Bug 1294903: Modify file and folder pickers to ensure that the background MTA thread is running if we're on Windows 7; r?jimm draft
authorAaron Klotz <aklotz@mozilla.com>
Tue, 15 Nov 2016 11:36:01 -0700
changeset 439277 dcd266ffc6c073edcee493200796c1f1f931cdef
parent 439276 1889d9571d123a0df5471f9c6e9fbc6323d9f85e
child 537121 07022f2211b293397a374de9f41207f0ab774634
push id35953
push useraklotz@mozilla.com
push dateTue, 15 Nov 2016 18:36:56 +0000
reviewersjimm
bugs1294903
milestone52.0a1
Bug 1294903: Modify file and folder pickers to ensure that the background MTA thread is running if we're on Windows 7; r?jimm MozReview-Commit-ID: LrbkeLMrgcS
widget/windows/nsFilePicker.cpp
--- a/widget/windows/nsFilePicker.cpp
+++ b/widget/windows/nsFilePicker.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsFilePicker.h"
 
 #include <shlobj.h>
 #include <shlwapi.h>
 #include <cderr.h>
 
+#include "mozilla/mscom/EnsureMTA.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WindowsVersion.h"
 #include "nsReadableUtils.h"
 #include "nsNetUtil.h"
 #include "nsWindow.h"
 #include "nsILoadContext.h"
 #include "nsIServiceManager.h"
 #include "nsIURL.h"
@@ -23,17 +24,19 @@
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsToolkit.h"
 #include "WinUtils.h"
 #include "nsPIDOMWindow.h"
 #include "GeckoProfiler.h"
 
 using mozilla::IsVistaOrLater;
+using mozilla::IsWin8OrLater;
 using mozilla::MakeUnique;
+using mozilla::mscom::EnsureMTA;
 using mozilla::UniquePtr;
 using namespace mozilla::widget;
 
 char16_t *nsFilePicker::mLastUsedUnicodeDirectory;
 char nsFilePicker::mLastUsedDirectory[MAX_PATH+1] = { 0 };
 
 static const wchar_t kDialogPtrProp[] = L"DialogPtrProperty";
 static const DWORD kDialogTimerID = 9999;
@@ -572,16 +575,25 @@ nsFilePicker::ShowXPFolderPicker(const n
  *                      used if left blank.
  * @param aWasInitError Out parameter will hold true if there was an error
  *                      before the folder picker is shown.
  * @return true if a file was selected successfully.
 */
 bool
 nsFilePicker::ShowFolderPicker(const nsString& aInitialDir, bool &aWasInitError)
 {
+  if (!IsWin8OrLater()) {
+    // Some Windows 7 users are experiencing a race condition when some dlls
+    // that are loaded by the file picker cause a crash while attempting to shut
+    // down the COM multithreaded apartment. By instantiating EnsureMTA, we hold
+    // an additional reference to the MTA that should prevent this race, since
+    // the MTA will remain alive until shutdown.
+    EnsureMTA ensureMTA;
+  }
+
   RefPtr<IFileOpenDialog> dialog;
   if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC,
                               IID_IFileOpenDialog,
                               getter_AddRefs(dialog)))) {
     aWasInitError = true;
     return false;
   }
   aWasInitError = false;
@@ -870,16 +882,26 @@ nsFilePicker::ShowXPFilePicker(const nsS
  * @param aWasInitError Out parameter will hold true if there was an error
  *                      before the file picker is shown.
  * @return true if a file was selected successfully.
 */
 bool
 nsFilePicker::ShowFilePicker(const nsString& aInitialDir, bool &aWasInitError)
 {
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
+
+  if (!IsWin8OrLater()) {
+    // Some Windows 7 users are experiencing a race condition when some dlls
+    // that are loaded by the file picker cause a crash while attempting to shut
+    // down the COM multithreaded apartment. By instantiating EnsureMTA, we hold
+    // an additional reference to the MTA that should prevent this race, since
+    // the MTA will remain alive until shutdown.
+    EnsureMTA ensureMTA;
+  }
+
   RefPtr<IFileDialog> dialog;
   if (mMode != modeSave) {
     if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC,
                                 IID_IFileOpenDialog,
                                 getter_AddRefs(dialog)))) {
       aWasInitError = true;
       return false;
     }