/* * Show a folder picker. * * @param aInitialDir The initial directory, the last used directory will be * used if left blank. * @return true if a file was selected successfully. */ bool nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) { 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)))) { return false; } // hook up event callbacks dialog->Advise(this, &mFDECookie); // options FILEOPENDIALOGOPTIONS fos = FOS_PICKFOLDERS; dialog->SetOptions(fos); // initial strings dialog->SetTitle(mTitle.get()); if (!mOkButtonLabel.IsEmpty()) { dialog->SetOkButtonLabel(mOkButtonLabel.get()); } if (!aInitialDir.IsEmpty()) { RefPtr<IShellItem> folder; if (SUCCEEDED( WinUtils::SHCreateItemFromParsingName(aInitialDir.get(), nullptr, IID_IShellItem, getter_AddRefs(folder)))) { dialog->SetFolder(folder); } } AutoDestroyTmpWindow adtw((HWND)(mParentWidget.get() ? mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr)); // display RefPtr<IShellItem> item; if (FAILED(dialog->Show(adtw.get())) || FAILED(dialog->GetResult(getter_AddRefs(item))) || !item) { dialog->Unadvise(mFDECookie); return false; } dialog->Unadvise(mFDECookie); // results // If the user chose a Win7 Library, resolve to the library's // default save folder. RefPtr<IShellItem> folderPath; RefPtr<IShellLibrary> shellLib; CoCreateInstance(CLSID_ShellLibrary, nullptr, CLSCTX_INPROC, IID_IShellLibrary, getter_AddRefs(shellLib)); if (shellLib && SUCCEEDED(shellLib->LoadLibraryFromItem(item, STGM_READ)) && SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem, getter_AddRefs(folderPath)))) { item.swap(folderPath); } // get the folder's file system path return WinUtils::GetShellItemPath(item, mUnicodeFile); }
/* * Show a file picker. * * @param aInitialDir The initial directory, the last used directory will be * used if left blank. * @return true if a file was selected successfully. */ bool nsFilePicker::ShowFilePicker(const nsString& aInitialDir) { 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)))) { return false; } } else { if (FAILED(CoCreateInstance(CLSID_FileSaveDialog, nullptr, CLSCTX_INPROC, IID_IFileSaveDialog, getter_AddRefs(dialog)))) { return false; } } // hook up event callbacks dialog->Advise(this, &mFDECookie); // options FILEOPENDIALOGOPTIONS fos = 0; fos |= FOS_SHAREAWARE | FOS_OVERWRITEPROMPT | FOS_FORCEFILESYSTEM; // Handle add to recent docs settings if (IsPrivacyModeEnabled() || !mAddToRecentDocs) { fos |= FOS_DONTADDTORECENT; } // Msdn claims FOS_NOCHANGEDIR is not needed. We'll add this // just in case. AutoRestoreWorkingPath arw; // mode specific switch(mMode) { case modeOpen: fos |= FOS_FILEMUSTEXIST; break; case modeOpenMultiple: fos |= FOS_FILEMUSTEXIST | FOS_ALLOWMULTISELECT; break; case modeSave: fos |= FOS_NOREADONLYRETURN; // Don't follow shortcuts when saving a shortcut, this can be used // to trick users (bug 271732) if (IsDefaultPathLink()) fos |= FOS_NODEREFERENCELINKS; break; } dialog->SetOptions(fos); // initial strings // title dialog->SetTitle(mTitle.get()); // default filename if (!mDefaultFilename.IsEmpty()) { dialog->SetFileName(mDefaultFilename.get()); } NS_NAMED_LITERAL_STRING(htmExt, "html"); // default extension to append to new files if (!mDefaultExtension.IsEmpty()) { dialog->SetDefaultExtension(mDefaultExtension.get()); } else if (IsDefaultPathHtml()) { dialog->SetDefaultExtension(htmExt.get()); } // initial location if (!aInitialDir.IsEmpty()) { RefPtr<IShellItem> folder; if (SUCCEEDED( WinUtils::SHCreateItemFromParsingName(aInitialDir.get(), nullptr, IID_IShellItem, getter_AddRefs(folder)))) { dialog->SetFolder(folder); } } // filter types and the default index if (!mComFilterList.IsEmpty()) { dialog->SetFileTypes(mComFilterList.Length(), mComFilterList.get()); dialog->SetFileTypeIndex(mSelectedType); } // display { AutoDestroyTmpWindow adtw((HWND)(mParentWidget.get() ? mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr)); AutoTimerCallbackCancel atcc(this, PickerCallbackTimerFunc); AutoWidgetPickerState awps(mParentWidget); if (FAILED(dialog->Show(adtw.get()))) { dialog->Unadvise(mFDECookie); return false; } dialog->Unadvise(mFDECookie); } // results // Remember what filter type the user selected UINT filterIdxResult; if (SUCCEEDED(dialog->GetFileTypeIndex(&filterIdxResult))) { mSelectedType = (int16_t)filterIdxResult; } // single selection if (mMode != modeOpenMultiple) { RefPtr<IShellItem> item; if (FAILED(dialog->GetResult(getter_AddRefs(item))) || !item) return false; return WinUtils::GetShellItemPath(item, mUnicodeFile); } // multiple selection RefPtr<IFileOpenDialog> openDlg; dialog->QueryInterface(IID_IFileOpenDialog, getter_AddRefs(openDlg)); if (!openDlg) { // should not happen return false; } RefPtr<IShellItemArray> items; if (FAILED(openDlg->GetResults(getter_AddRefs(items))) || !items) { return false; } DWORD count = 0; items->GetCount(&count); for (unsigned int idx = 0; idx < count; idx++) { RefPtr<IShellItem> item; nsAutoString str; if (SUCCEEDED(items->GetItemAt(idx, getter_AddRefs(item)))) { if (!WinUtils::GetShellItemPath(item, str)) continue; nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1"); if (file && NS_SUCCEEDED(file->InitWithPath(str))) mFiles.AppendObject(file); } } return true; }
/* * Show a folder picker post Windows XP * * @param aInitialDir The initial directory, the last used directory will be * 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) { RefPtr<IFileOpenDialog> dialog; if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC, IID_IFileOpenDialog, getter_AddRefs(dialog)))) { aWasInitError = true; return false; } aWasInitError = false; // hook up event callbacks dialog->Advise(this, &mFDECookie); // options FILEOPENDIALOGOPTIONS fos = FOS_PICKFOLDERS; dialog->SetOptions(fos); // initial strings dialog->SetTitle(mTitle.get()); if (!aInitialDir.IsEmpty()) { RefPtr<IShellItem> folder; if (SUCCEEDED( WinUtils::SHCreateItemFromParsingName(aInitialDir.get(), nullptr, IID_IShellItem, getter_AddRefs(folder)))) { dialog->SetFolder(folder); } } AutoDestroyTmpWindow adtw((HWND)(mParentWidget.get() ? mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr)); // display RefPtr<IShellItem> item; if (FAILED(dialog->Show(adtw.get())) || FAILED(dialog->GetResult(getter_AddRefs(item))) || !item) { dialog->Unadvise(mFDECookie); return false; } dialog->Unadvise(mFDECookie); // results // If the user chose a Win7 Library, resolve to the library's // default save folder. RefPtr<IShellItem> folderPath; RefPtr<IShellLibrary> shellLib; CoCreateInstance(CLSID_ShellLibrary, nullptr, CLSCTX_INPROC, IID_IShellLibrary, getter_AddRefs(shellLib)); if (shellLib && SUCCEEDED(shellLib->LoadLibraryFromItem(item, STGM_READ)) && SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem, getter_AddRefs(folderPath)))) { item.swap(folderPath); } // get the folder's file system path return WinUtils::GetShellItemPath(item, mUnicodeFile); }