Bug 731307 - Async filepicker widget implementation. r=roc. sr=mounir
authorBrian R. Bondy <netzen@gmail.com>
Fri, 17 Aug 2012 11:35:01 -0400
changeset 108119 fccf7aeabfe96647c8155b3e7a4100731cf5556d
parent 108118 b16ef09f140c65e1a6983e83505b536f14b952c0
child 108120 d6d44f461483ccf73cf5b2bc6e137b3836352c79
push id1490
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 18:29:50 +0000
treeherdermozilla-beta@f335e7dacdc1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, mounir
bugs731307
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 731307 - Async filepicker widget implementation. r=roc. sr=mounir
widget/xpwidgets/nsBaseFilePicker.cpp
widget/xpwidgets/nsBaseFilePicker.h
--- a/widget/xpwidgets/nsBaseFilePicker.cpp
+++ b/widget/xpwidgets/nsBaseFilePicker.cpp
@@ -15,24 +15,63 @@
 #include "nsIStringBundle.h"
 #include "nsXPIDLString.h"
 #include "nsIServiceManager.h"
 #include "nsCOMArray.h"
 #include "nsIFile.h"
 #include "nsEnumeratorUtils.h"
 #include "mozilla/Services.h"
 #include "WidgetUtils.h"
+#include "nsThreadUtils.h"
 
 #include "nsBaseFilePicker.h"
 
 using namespace mozilla::widget;
 
 #define FILEPICKER_TITLES "chrome://global/locale/filepicker.properties"
 #define FILEPICKER_FILTERS "chrome://global/content/filepicker.properties"
 
+/**
+ * A runnable to dispatch from the main thread to the main thread to display
+ * the file picker while letting the showAsync method return right away.
+*/
+class AsyncShowFilePicker : public nsRunnable
+{
+public:
+  AsyncShowFilePicker(nsIFilePicker *aFilePicker,
+                      nsIFilePickerShownCallback *aCallback) :
+    mFilePicker(aFilePicker),
+    mCallback(aCallback)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    NS_ASSERTION(NS_IsMainThread(),
+                 "AsyncShowFilePicker should be on the main thread!");
+
+    // It's possible that some widget implementations require GUI operations
+    // to be on the main thread, so that's why we're not dispatching to another
+    // thread and calling back to the main after it's done.
+    PRInt16 result;
+    nsresult rv = mFilePicker->Show(&result);
+    if (NS_FAILED(rv)) {
+      NS_ERROR("FilePicker's Show() implementation failed!");
+      mCallback->Done(nsIFilePicker::returnCancel);
+      return NS_OK;
+    }
+
+    return mCallback->Done(result);
+  }
+
+private:
+  nsRefPtr<nsIFilePicker> mFilePicker;
+  nsRefPtr<nsIFilePickerShownCallback> mCallback;
+};
+
 nsBaseFilePicker::nsBaseFilePicker() :
   mAddToRecentDocs(true)
 {
 
 }
 
 nsBaseFilePicker::~nsBaseFilePicker()
 {
@@ -48,16 +87,23 @@ NS_IMETHODIMP nsBaseFilePicker::Init(nsI
   nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent);
   NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
 
   InitNative(widget, aTitle, aMode);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsBaseFilePicker::Open(nsIFilePickerShownCallback *aCallback)
+{
+  nsCOMPtr<nsIRunnable> filePickerEvent =
+    new AsyncShowFilePicker(this, aCallback);
+  return NS_DispatchToMainThread(filePickerEvent);
+}
 
 NS_IMETHODIMP
 nsBaseFilePicker::AppendFilters(PRInt32 aFilterMask)
 {
   nsCOMPtr<nsIStringBundleService> stringService =
     mozilla::services::GetStringBundleService();
   if (!stringService)
     return NS_ERROR_FAILURE;
--- a/widget/xpwidgets/nsBaseFilePicker.h
+++ b/widget/xpwidgets/nsBaseFilePicker.h
@@ -22,16 +22,17 @@ class nsBaseFilePicker : public nsIFileP
 public:
   nsBaseFilePicker(); 
   virtual ~nsBaseFilePicker();
 
   NS_IMETHOD Init(nsIDOMWindow *aParent,
                   const nsAString& aTitle,
                   PRInt16 aMode);
 
+  NS_IMETHOD Open(nsIFilePickerShownCallback *aCallback);
   NS_IMETHOD AppendFilters(PRInt32 filterMask);
   NS_IMETHOD GetFilterIndex(PRInt32 *aFilterIndex);
   NS_IMETHOD SetFilterIndex(PRInt32 aFilterIndex);
   NS_IMETHOD GetFiles(nsISimpleEnumerator **aFiles);
 #ifdef BASEFILEPICKER_HAS_DISPLAYDIRECTORY 
   NS_IMETHOD GetDisplayDirectory(nsIFile * *aDisplayDirectory);
   NS_IMETHOD SetDisplayDirectory(nsIFile * aDisplayDirectory);
 #endif