зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1833450 - [3/4] Windows nsFilePicker: convert to use IPC-able Command structs r=gstoll,handyman
Convert `nsFilePicker` to use the `Command` structs introduced in the first commit in this patchset. No functional changes -- this should be a straight reorganization of internal code. Additionally, remove from `WinUtils` the now-unused function `GetShellItemPath`, whose functionality has been moved into `Command`'s associated functions' translation unit. (This function was added to WinUtils in 2012 as part of supporting the Windows Vista file picker (bug 718374). It's not overtly filepicker-specific, but in the past eleven years, no other code has ever used it.) Differential Revision: https://phabricator.services.mozilla.com/D178204
This commit is contained in:
Родитель
7e4941fcde
Коммит
d65140658c
|
@ -1225,16 +1225,6 @@ int32_t FaviconHelper::GetICOCacheSecondsTimeout() {
|
|||
return icoReCacheSecondsTimeout;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool WinUtils::GetShellItemPath(IShellItem* aItem, nsString& aResultString) {
|
||||
NS_ENSURE_TRUE(aItem, false);
|
||||
LPWSTR str = nullptr;
|
||||
if (FAILED(aItem->GetDisplayName(SIGDN_FILESYSPATH, &str))) return false;
|
||||
aResultString.Assign(str);
|
||||
CoTaskMemFree(str);
|
||||
return !aResultString.IsEmpty();
|
||||
}
|
||||
|
||||
/* static */
|
||||
LayoutDeviceIntRegion WinUtils::ConvertHRGNToRegion(HRGN aRgn) {
|
||||
NS_ASSERTION(aRgn, "Don't pass NULL region here");
|
||||
|
|
|
@ -466,16 +466,6 @@ class WinUtils {
|
|||
|
||||
static bool GetIsMouseFromTouch(EventMessage aEventType);
|
||||
|
||||
/**
|
||||
* GetShellItemPath return the file or directory path of a shell item.
|
||||
* Internally calls IShellItem's GetDisplayName.
|
||||
*
|
||||
* aItem the shell item containing the path.
|
||||
* aResultString the resulting string path.
|
||||
* returns true if a path was retreived.
|
||||
*/
|
||||
static bool GetShellItemPath(IShellItem* aItem, nsString& aResultString);
|
||||
|
||||
/**
|
||||
* ConvertHRGNToRegion converts a Windows HRGN to an LayoutDeviceIntRegion.
|
||||
*
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "WinUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
#include "mozilla/widget/filedialog/WinFileDialogCommands.h"
|
||||
|
||||
using mozilla::UniquePtr;
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
@ -95,67 +97,40 @@ bool nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// options
|
||||
FILEOPENDIALOGOPTIONS fos = FOS_PICKFOLDERS;
|
||||
HRESULT hr = dialog->SetOptions(fos);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// initial strings
|
||||
hr = dialog->SetTitle(mTitle.get());
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
namespace fd = ::mozilla::widget::filedialog;
|
||||
nsTArray<fd::Command> commands = {
|
||||
fd::SetOptions(FOS_PICKFOLDERS),
|
||||
fd::SetTitle(mTitle),
|
||||
};
|
||||
|
||||
if (!mOkButtonLabel.IsEmpty()) {
|
||||
hr = dialog->SetOkButtonLabel(mOkButtonLabel.get());
|
||||
if (FAILED(hr)) {
|
||||
commands.AppendElement(fd::SetOkButtonLabel(mOkButtonLabel));
|
||||
}
|
||||
|
||||
if (!aInitialDir.IsEmpty()) {
|
||||
commands.AppendElement(fd::SetFolder(aInitialDir));
|
||||
}
|
||||
|
||||
{
|
||||
if (NS_FAILED(fd::ApplyCommands(dialog, commands))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedRtlShimWindow shim(mParentWidget.get());
|
||||
mozilla::BackgroundHangMonitor().NotifyWait();
|
||||
|
||||
if (FAILED(dialog->Show(shim.get()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aInitialDir.IsEmpty()) {
|
||||
RefPtr<IShellItem> folder;
|
||||
if (SUCCEEDED(SHCreateItemFromParsingName(aInitialDir.get(), nullptr,
|
||||
IID_IShellItem,
|
||||
getter_AddRefs(folder)))) {
|
||||
hr = dialog->SetFolder(folder);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScopedRtlShimWindow shim(mParentWidget.get());
|
||||
|
||||
// display
|
||||
mozilla::BackgroundHangMonitor().NotifyWait();
|
||||
RefPtr<IShellItem> item;
|
||||
if (FAILED(dialog->Show(shim.get())) ||
|
||||
FAILED(dialog->GetResult(getter_AddRefs(item))) || !item) {
|
||||
auto result = fd::GetFolderResults(dialog.get());
|
||||
if (result.isErr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// results
|
||||
|
||||
// If the user chose a Win7 Library, resolve to the library's
|
||||
// default save folder.
|
||||
RefPtr<IShellItem> folderPath;
|
||||
RefPtr<IShellLibrary> shellLib;
|
||||
if (FAILED(CoCreateInstance(CLSID_ShellLibrary, nullptr, CLSCTX_INPROC_SERVER,
|
||||
IID_IShellLibrary, getter_AddRefs(shellLib)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
mUnicodeFile = result.unwrap();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -187,50 +162,47 @@ bool nsFilePicker::ShowFilePicker(const nsString& aInitialDir) {
|
|||
}
|
||||
}
|
||||
|
||||
namespace fd = ::mozilla::widget::filedialog;
|
||||
nsTArray<fd::Command> commands;
|
||||
// options
|
||||
{
|
||||
FILEOPENDIALOGOPTIONS fos = 0;
|
||||
fos |= FOS_SHAREAWARE | FOS_OVERWRITEPROMPT | FOS_FORCEFILESYSTEM;
|
||||
|
||||
FILEOPENDIALOGOPTIONS fos = 0;
|
||||
fos |= FOS_SHAREAWARE | FOS_OVERWRITEPROMPT | FOS_FORCEFILESYSTEM;
|
||||
// Handle add to recent docs settings
|
||||
if (IsPrivacyModeEnabled() || !mAddToRecentDocs) {
|
||||
fos |= FOS_DONTADDTORECENT;
|
||||
}
|
||||
|
||||
// Handle add to recent docs settings
|
||||
if (IsPrivacyModeEnabled() || !mAddToRecentDocs) {
|
||||
fos |= FOS_DONTADDTORECENT;
|
||||
}
|
||||
// mode specific
|
||||
switch (mMode) {
|
||||
case modeOpen:
|
||||
fos |= FOS_FILEMUSTEXIST;
|
||||
break;
|
||||
|
||||
// mode specific
|
||||
switch (mMode) {
|
||||
case modeOpen:
|
||||
fos |= FOS_FILEMUSTEXIST;
|
||||
break;
|
||||
case modeOpenMultiple:
|
||||
fos |= FOS_FILEMUSTEXIST | FOS_ALLOWMULTISELECT;
|
||||
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;
|
||||
|
||||
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;
|
||||
case modeGetFolder:
|
||||
MOZ_ASSERT(false, "file-picker opened in directory-picker mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
case modeGetFolder:
|
||||
MOZ_ASSERT(false, "file-picker opened in directory-picker mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = dialog->SetOptions(fos);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
commands.AppendElement(fd::SetOptions(fos));
|
||||
}
|
||||
|
||||
// initial strings
|
||||
|
||||
// title
|
||||
hr = dialog->SetTitle(mTitle.get());
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
commands.AppendElement(fd::SetTitle(mTitle));
|
||||
|
||||
// default filename
|
||||
if (!mDefaultFilename.IsEmpty()) {
|
||||
|
@ -239,10 +211,7 @@ bool nsFilePicker::ShowFilePicker(const nsString& aInitialDir) {
|
|||
nsAutoString sanitizedFilename(mDefaultFilename);
|
||||
sanitizedFilename.ReplaceChar('%', '_');
|
||||
|
||||
hr = dialog->SetFileName(sanitizedFilename.get());
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
commands.AppendElement(fd::SetFileName(sanitizedFilename));
|
||||
}
|
||||
|
||||
// default extension to append to new files
|
||||
|
@ -251,49 +220,32 @@ bool nsFilePicker::ShowFilePicker(const nsString& aInitialDir) {
|
|||
nsAutoString sanitizedExtension(mDefaultExtension);
|
||||
sanitizedExtension.ReplaceChar('%', '_');
|
||||
|
||||
hr = dialog->SetDefaultExtension(sanitizedExtension.get());
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
commands.AppendElement(fd::SetDefaultExtension(sanitizedExtension));
|
||||
} else if (IsDefaultPathHtml()) {
|
||||
hr = dialog->SetDefaultExtension(L"html");
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
commands.AppendElement(fd::SetDefaultExtension(u"html"_ns));
|
||||
}
|
||||
|
||||
// initial location
|
||||
if (!aInitialDir.IsEmpty()) {
|
||||
RefPtr<IShellItem> folder;
|
||||
if (SUCCEEDED(SHCreateItemFromParsingName(aInitialDir.get(), nullptr,
|
||||
IID_IShellItem,
|
||||
getter_AddRefs(folder)))) {
|
||||
hr = dialog->SetFolder(folder);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
commands.AppendElement(fd::SetFolder(aInitialDir));
|
||||
}
|
||||
|
||||
// filter types and the default index
|
||||
if (!mFilterList.IsEmpty()) {
|
||||
std::vector<COMDLG_FILTERSPEC> filterSpecs;
|
||||
nsTArray<fd::ComDlgFilterSpec> fileTypes;
|
||||
for (auto const& filter : mFilterList) {
|
||||
filterSpecs.push_back({filter.title.get(), filter.filter.get()});
|
||||
}
|
||||
hr = dialog->SetFileTypes(filterSpecs.size(), filterSpecs.data());
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
hr = dialog->SetFileTypeIndex(mSelectedType);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
fileTypes.EmplaceBack(filter.title, filter.filter);
|
||||
}
|
||||
commands.AppendElement(fd::SetFileTypes(std::move(fileTypes)));
|
||||
commands.AppendElement(fd::SetFileTypeIndex(mSelectedType));
|
||||
}
|
||||
|
||||
// display
|
||||
|
||||
{
|
||||
if (NS_FAILED(fd::ApplyCommands(dialog, commands))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedRtlShimWindow shim(mParentWidget.get());
|
||||
AutoWidgetPickerState awps(mParentWidget);
|
||||
|
||||
|
@ -304,44 +256,32 @@ bool nsFilePicker::ShowFilePicker(const nsString& aInitialDir) {
|
|||
}
|
||||
|
||||
// results
|
||||
auto result_ = fd::GetFileResults(dialog.get());
|
||||
if (result_.isErr()) {
|
||||
return false;
|
||||
}
|
||||
auto result = result_.unwrap();
|
||||
|
||||
// Remember what filter type the user selected
|
||||
UINT filterIdxResult;
|
||||
if (SUCCEEDED(dialog->GetFileTypeIndex(&filterIdxResult))) {
|
||||
mSelectedType = (int16_t)filterIdxResult;
|
||||
}
|
||||
mSelectedType = result.selectedFileTypeIndex();
|
||||
|
||||
auto const& paths = result.paths();
|
||||
|
||||
// single selection
|
||||
if (mMode != modeOpenMultiple) {
|
||||
RefPtr<IShellItem> item;
|
||||
if (FAILED(dialog->GetResult(getter_AddRefs(item))) || !item) return false;
|
||||
return WinUtils::GetShellItemPath(item, mUnicodeFile);
|
||||
if (!paths.IsEmpty()) {
|
||||
MOZ_ASSERT(paths.Length() == 1);
|
||||
mUnicodeFile = paths[0];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (NS_SUCCEEDED(NS_NewLocalFile(str, false, getter_AddRefs(file)))) {
|
||||
mFiles.AppendObject(file);
|
||||
}
|
||||
for (auto const& str : paths) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
if (NS_SUCCEEDED(NS_NewLocalFile(str, false, getter_AddRefs(file)))) {
|
||||
mFiles.AppendObject(file);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
Загрузка…
Ссылка в новой задаче