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
--- 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;
}