2000-03-22 10:43:43 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
2012-05-21 15:12:37 +04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2000-03-22 10:43:43 +03:00
|
|
|
|
2011-12-15 01:22:28 +04:00
|
|
|
#include "nsFilePicker.h"
|
|
|
|
|
|
|
|
#include <shlobj.h>
|
|
|
|
#include <shlwapi.h>
|
|
|
|
#include <cderr.h>
|
|
|
|
|
2023-02-23 00:05:24 +03:00
|
|
|
#include "mozilla/Assertions.h"
|
2018-12-13 16:17:14 +03:00
|
|
|
#include "mozilla/BackgroundHangMonitor.h"
|
Bug 1691589 - Reduce reliance on GeckoProfiler.h when only labels (and maybe markers) are needed - r=necko-reviewers,geckoview-reviewers,sg,agi,florian
There are no code changes, only #include changes.
It was a fairly mechanical process: Search for all "AUTO_PROFILER_LABEL", and in each file, if only labels are used, convert "GeckoProfiler.h" into "ProfilerLabels.h" (or just add that last one where needed).
In some files, there were also some marker calls but no other profiler-related calls, in these cases "GeckoProfiler.h" was replaced with both "ProfilerLabels.h" and "ProfilerMarkers.h", which still helps in reducing the use of the all-encompassing "GeckoProfiler.h".
Differential Revision: https://phabricator.services.mozilla.com/D104588
2021-02-16 07:44:19 +03:00
|
|
|
#include "mozilla/ProfilerLabels.h"
|
2015-10-30 21:35:28 +03:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2013-11-22 07:35:42 +04:00
|
|
|
#include "mozilla/WindowsVersion.h"
|
2001-09-29 12:28:41 +04:00
|
|
|
#include "nsReadableUtils.h"
|
2001-06-22 02:02:47 +04:00
|
|
|
#include "nsNetUtil.h"
|
2003-02-24 23:15:48 +03:00
|
|
|
#include "nsWindow.h"
|
2002-09-07 09:23:45 +04:00
|
|
|
#include "nsEnumeratorUtils.h"
|
2002-05-15 22:55:21 +04:00
|
|
|
#include "nsCRT.h"
|
2002-07-03 04:55:47 +04:00
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsToolkit.h"
|
2012-01-04 14:21:44 +04:00
|
|
|
#include "WinUtils.h"
|
2012-04-14 03:49:11 +04:00
|
|
|
#include "nsPIDOMWindow.h"
|
2012-01-04 14:21:44 +04:00
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
#include "mozilla/widget/filedialog/WinFileDialogCommands.h"
|
|
|
|
|
2015-10-30 21:35:28 +03:00
|
|
|
using mozilla::UniquePtr;
|
2002-07-03 04:55:47 +04:00
|
|
|
|
2020-11-16 22:37:09 +03:00
|
|
|
using namespace mozilla::widget;
|
2002-02-02 02:58:55 +03:00
|
|
|
|
2020-11-16 22:37:09 +03:00
|
|
|
UniquePtr<char16_t[], nsFilePicker::FreeDeleter>
|
|
|
|
nsFilePicker::sLastUsedUnicodeDirectory;
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2002-02-20 10:50:52 +03:00
|
|
|
#define MAX_EXTENSION_LENGTH 10
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Helper classes
|
|
|
|
|
|
|
|
// Manages matching PickerOpen/PickerClosed calls on the parent widget.
|
|
|
|
class AutoWidgetPickerState {
|
|
|
|
public:
|
|
|
|
explicit AutoWidgetPickerState(nsIWidget* aWidget)
|
|
|
|
: mWindow(static_cast<nsWindow*>(aWidget)) {
|
|
|
|
PickerState(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
~AutoWidgetPickerState() { PickerState(false); }
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
private:
|
|
|
|
void PickerState(bool aFlag) {
|
|
|
|
if (mWindow) {
|
|
|
|
if (aFlag)
|
|
|
|
mWindow->PickerOpen();
|
|
|
|
else
|
|
|
|
mWindow->PickerClosed();
|
|
|
|
}
|
|
|
|
}
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsWindow> mWindow;
|
2011-12-15 01:22:16 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsIFilePicker
|
|
|
|
|
2020-11-16 22:37:09 +03:00
|
|
|
nsFilePicker::nsFilePicker() : mSelectedType(1) {}
|
2000-03-22 10:43:43 +03:00
|
|
|
|
2014-04-27 11:06:00 +04:00
|
|
|
NS_IMPL_ISUPPORTS(nsFilePicker, nsIFilePicker)
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_IMETHODIMP nsFilePicker::Init(mozIDOMWindowProxy* aParent,
|
2023-02-23 00:05:24 +03:00
|
|
|
const nsAString& aTitle,
|
|
|
|
nsIFilePicker::Mode aMode) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(aParent);
|
2013-10-08 22:48:02 +04:00
|
|
|
nsIDocShell* docShell = window ? window->GetDocShell() : nullptr;
|
2012-04-09 23:53:46 +04:00
|
|
|
mLoadContext = do_QueryInterface(docShell);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-04-09 23:53:46 +04:00
|
|
|
return nsBaseFilePicker::Init(aParent, aTitle, aMode);
|
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2011-12-15 01:22:28 +04:00
|
|
|
/*
|
|
|
|
* Folder picker invocation
|
|
|
|
*/
|
|
|
|
|
2012-07-03 18:38:09 +04:00
|
|
|
/*
|
2016-12-23 05:13:31 +03:00
|
|
|
* Show a folder picker.
|
|
|
|
*
|
2012-07-03 18:38:09 +04:00
|
|
|
* @param aInitialDir The initial directory, the last used directory will be
|
|
|
|
* used if left blank.
|
|
|
|
* @return true if a file was selected successfully.
|
|
|
|
*/
|
2016-12-23 05:13:31 +03:00
|
|
|
bool nsFilePicker::ShowFolderPicker(const nsString& aInitialDir) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IFileOpenDialog> dialog;
|
2020-11-16 22:37:09 +03:00
|
|
|
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr,
|
|
|
|
CLSCTX_INPROC_SERVER, IID_IFileOpenDialog,
|
|
|
|
getter_AddRefs(dialog)))) {
|
2011-12-15 01:22:28 +04:00
|
|
|
return false;
|
2012-07-03 18:38:09 +04:00
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
namespace fd = ::mozilla::widget::filedialog;
|
|
|
|
nsTArray<fd::Command> commands = {
|
|
|
|
fd::SetOptions(FOS_PICKFOLDERS),
|
|
|
|
fd::SetTitle(mTitle),
|
|
|
|
};
|
2016-08-24 02:07:21 +03:00
|
|
|
|
|
|
|
if (!mOkButtonLabel.IsEmpty()) {
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetOkButtonLabel(mOkButtonLabel));
|
2016-08-24 02:07:21 +03:00
|
|
|
}
|
|
|
|
|
2012-02-17 04:36:04 +04:00
|
|
|
if (!aInitialDir.IsEmpty()) {
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetFolder(aInitialDir));
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
{
|
|
|
|
if (NS_FAILED(fd::ApplyCommands(dialog, commands))) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
ScopedRtlShimWindow shim(mParentWidget.get());
|
|
|
|
mozilla::BackgroundHangMonitor().NotifyWait();
|
2012-02-17 04:36:04 +04:00
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
if (FAILED(dialog->Show(shim.get()))) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-11-16 22:37:09 +03:00
|
|
|
}
|
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
auto result = fd::GetFolderResults(dialog.get());
|
|
|
|
if (result.isErr()) {
|
|
|
|
return false;
|
2012-02-17 04:36:04 +04:00
|
|
|
}
|
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
mUnicodeFile = result.unwrap();
|
|
|
|
return true;
|
2012-02-17 04:36:04 +04:00
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* File open and save picker invocation
|
|
|
|
*/
|
|
|
|
|
2012-07-03 18:38:09 +04:00
|
|
|
/*
|
2016-12-23 05:13:31 +03:00
|
|
|
* Show a file picker.
|
|
|
|
*
|
2012-07-03 18:38:09 +04:00
|
|
|
* @param aInitialDir The initial directory, the last used directory will be
|
|
|
|
* used if left blank.
|
|
|
|
* @return true if a file was selected successfully.
|
|
|
|
*/
|
2016-12-23 05:13:31 +03:00
|
|
|
bool nsFilePicker::ShowFilePicker(const nsString& aInitialDir) {
|
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
|
|
|
AUTO_PROFILER_LABEL("nsFilePicker::ShowFilePicker", OTHER);
|
2016-11-15 21:36:01 +03:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<IFileDialog> dialog;
|
2011-12-15 01:22:28 +04:00
|
|
|
if (mMode != modeSave) {
|
2020-11-16 22:37:09 +03:00
|
|
|
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr,
|
|
|
|
CLSCTX_INPROC_SERVER, IID_IFileOpenDialog,
|
|
|
|
getter_AddRefs(dialog)))) {
|
2011-12-15 01:22:28 +04:00
|
|
|
return false;
|
2012-07-03 18:38:09 +04:00
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
} else {
|
2020-11-16 22:37:09 +03:00
|
|
|
if (FAILED(CoCreateInstance(CLSID_FileSaveDialog, nullptr,
|
|
|
|
CLSCTX_INPROC_SERVER, IID_IFileSaveDialog,
|
|
|
|
getter_AddRefs(dialog)))) {
|
2011-12-15 01:22:28 +04:00
|
|
|
return false;
|
2012-07-03 18:38:09 +04:00
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
namespace fd = ::mozilla::widget::filedialog;
|
|
|
|
nsTArray<fd::Command> commands;
|
2011-12-15 01:22:28 +04:00
|
|
|
// options
|
2023-05-19 01:29:53 +03:00
|
|
|
{
|
|
|
|
FILEOPENDIALOGOPTIONS fos = 0;
|
|
|
|
fos |= FOS_SHAREAWARE | FOS_OVERWRITEPROMPT | FOS_FORCEFILESYSTEM;
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
// Handle add to recent docs settings
|
|
|
|
if (IsPrivacyModeEnabled() || !mAddToRecentDocs) {
|
|
|
|
fos |= FOS_DONTADDTORECENT;
|
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
// 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;
|
|
|
|
|
|
|
|
case modeGetFolder:
|
|
|
|
MOZ_ASSERT(false, "file-picker opened in directory-picker mode");
|
|
|
|
return false;
|
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetOptions(fos));
|
2020-11-16 22:37:09 +03:00
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
|
|
|
|
// initial strings
|
|
|
|
|
|
|
|
// title
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetTitle(mTitle));
|
2011-12-15 01:22:28 +04:00
|
|
|
|
|
|
|
// default filename
|
|
|
|
if (!mDefaultFilename.IsEmpty()) {
|
2022-05-09 22:27:08 +03:00
|
|
|
// Prevent the shell from expanding environment variables by removing
|
|
|
|
// the % characters that are used to delimit them.
|
|
|
|
nsAutoString sanitizedFilename(mDefaultFilename);
|
|
|
|
sanitizedFilename.ReplaceChar('%', '_');
|
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetFileName(sanitizedFilename));
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2011-12-15 01:22:28 +04:00
|
|
|
// default extension to append to new files
|
|
|
|
if (!mDefaultExtension.IsEmpty()) {
|
2023-02-27 21:01:10 +03:00
|
|
|
// We don't want environment variables expanded in the extension either.
|
|
|
|
nsAutoString sanitizedExtension(mDefaultExtension);
|
|
|
|
sanitizedExtension.ReplaceChar('%', '_');
|
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetDefaultExtension(sanitizedExtension));
|
2011-12-15 01:22:28 +04:00
|
|
|
} else if (IsDefaultPathHtml()) {
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetDefaultExtension(u"html"_ns));
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// initial location
|
2012-02-17 04:36:04 +04:00
|
|
|
if (!aInitialDir.IsEmpty()) {
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetFolder(aInitialDir));
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// filter types and the default index
|
2023-05-19 01:29:53 +03:00
|
|
|
if (!mFilterList.IsEmpty()) {
|
2023-05-19 01:29:53 +03:00
|
|
|
nsTArray<fd::ComDlgFilterSpec> fileTypes;
|
2023-05-19 01:29:53 +03:00
|
|
|
for (auto const& filter : mFilterList) {
|
2023-05-19 01:29:53 +03:00
|
|
|
fileTypes.EmplaceBack(filter.title, filter.filter);
|
2020-11-16 22:37:09 +03:00
|
|
|
}
|
2023-05-19 01:29:53 +03:00
|
|
|
commands.AppendElement(fd::SetFileTypes(std::move(fileTypes)));
|
|
|
|
commands.AppendElement(fd::SetFileTypeIndex(mSelectedType));
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// display
|
2011-12-15 01:22:28 +04:00
|
|
|
{
|
2023-05-19 01:29:53 +03:00
|
|
|
if (NS_FAILED(fd::ApplyCommands(dialog, commands))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-05-11 04:13:05 +03:00
|
|
|
ScopedRtlShimWindow shim(mParentWidget.get());
|
2011-12-15 01:22:28 +04:00
|
|
|
AutoWidgetPickerState awps(mParentWidget);
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2018-12-13 16:17:14 +03:00
|
|
|
mozilla::BackgroundHangMonitor().NotifyWait();
|
2023-05-11 04:13:05 +03:00
|
|
|
if (FAILED(dialog->Show(shim.get()))) {
|
2011-12-15 01:22:28 +04:00
|
|
|
return false;
|
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// results
|
2023-05-19 01:29:53 +03:00
|
|
|
auto result_ = fd::GetFileResults(dialog.get());
|
|
|
|
if (result_.isErr()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto result = result_.unwrap();
|
2011-12-15 01:22:28 +04:00
|
|
|
|
2012-01-03 18:59:29 +04:00
|
|
|
// Remember what filter type the user selected
|
2023-05-19 01:29:53 +03:00
|
|
|
mSelectedType = result.selectedFileTypeIndex();
|
|
|
|
|
|
|
|
auto const& paths = result.paths();
|
2012-01-03 18:59:29 +04:00
|
|
|
|
2011-12-15 01:22:28 +04:00
|
|
|
// single selection
|
|
|
|
if (mMode != modeOpenMultiple) {
|
2023-05-19 01:29:53 +03:00
|
|
|
if (!paths.IsEmpty()) {
|
|
|
|
MOZ_ASSERT(paths.Length() == 1);
|
|
|
|
mUnicodeFile = paths[0];
|
|
|
|
return true;
|
|
|
|
}
|
2011-12-15 01:22:28 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-05-19 01:29:53 +03:00
|
|
|
// multiple selection
|
|
|
|
for (auto const& str : paths) {
|
|
|
|
nsCOMPtr<nsIFile> file;
|
|
|
|
if (NS_SUCCEEDED(NS_NewLocalFile(str, false, getter_AddRefs(file)))) {
|
|
|
|
mFiles.AppendObject(file);
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2011-12-15 01:22:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsIFilePicker impl.
|
|
|
|
|
2023-02-23 00:05:23 +03:00
|
|
|
nsresult nsFilePicker::ShowW(nsIFilePicker::ResultCode* aReturnVal) {
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aReturnVal);
|
|
|
|
|
|
|
|
*aReturnVal = returnCancel;
|
|
|
|
|
|
|
|
nsAutoString initialDir;
|
|
|
|
if (mDisplayDirectory) mDisplayDirectory->GetPath(initialDir);
|
|
|
|
|
|
|
|
// If no display directory, re-use the last one.
|
|
|
|
if (initialDir.IsEmpty()) {
|
|
|
|
// Allocate copy of last used dir.
|
2020-11-16 22:37:09 +03:00
|
|
|
initialDir = sLastUsedUnicodeDirectory.get();
|
2003-02-24 23:15:48 +03:00
|
|
|
}
|
|
|
|
|
2011-12-16 19:10:16 +04:00
|
|
|
// Clear previous file selections
|
2011-12-15 01:22:16 +04:00
|
|
|
mUnicodeFile.Truncate();
|
2011-12-16 19:10:16 +04:00
|
|
|
mFiles.Clear();
|
2011-12-15 01:22:16 +04:00
|
|
|
|
2016-07-02 01:42:32 +03:00
|
|
|
// On Win10, the picker doesn't support per-monitor DPI, so we open it
|
|
|
|
// with our context set temporarily to system-dpi-aware
|
|
|
|
WinUtils::AutoSystemDpiAware dpiAwareness;
|
|
|
|
|
2016-12-23 05:13:31 +03:00
|
|
|
bool result = false;
|
2012-07-03 18:38:09 +04:00
|
|
|
if (mMode == modeGetFolder) {
|
2016-12-23 05:13:31 +03:00
|
|
|
result = ShowFolderPicker(initialDir);
|
2012-07-03 18:38:09 +04:00
|
|
|
} else {
|
2016-12-23 05:13:31 +03:00
|
|
|
result = ShowFilePicker(initialDir);
|
2012-07-03 18:38:09 +04:00
|
|
|
}
|
2011-12-15 01:22:16 +04:00
|
|
|
|
|
|
|
// exit, and return returnCancel in aReturnVal
|
|
|
|
if (!result) return NS_OK;
|
|
|
|
|
|
|
|
RememberLastUsedDirectory();
|
|
|
|
|
2023-02-23 00:05:23 +03:00
|
|
|
nsIFilePicker::ResultCode retValue = returnOK;
|
2011-12-15 01:22:16 +04:00
|
|
|
if (mMode == modeSave) {
|
|
|
|
// Windows does not return resultReplace, we must check if file
|
|
|
|
// already exists.
|
2020-11-16 22:37:09 +03:00
|
|
|
nsCOMPtr<nsIFile> file;
|
|
|
|
nsresult rv = NS_NewLocalFile(mUnicodeFile, false, getter_AddRefs(file));
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
bool flag = false;
|
2020-11-16 22:37:09 +03:00
|
|
|
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(file->Exists(&flag)) && flag) {
|
2011-12-15 01:22:16 +04:00
|
|
|
retValue = returnReplace;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*aReturnVal = retValue;
|
2002-07-03 04:55:47 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2023-02-23 00:05:23 +03:00
|
|
|
nsresult nsFilePicker::Show(nsIFilePicker::ResultCode* aReturnVal) {
|
|
|
|
return ShowW(aReturnVal);
|
|
|
|
}
|
2000-03-23 10:41:17 +03:00
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
2012-06-06 06:08:30 +04:00
|
|
|
nsFilePicker::GetFile(nsIFile** aFile) {
|
2000-04-11 02:08:19 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aFile);
|
2012-07-30 18:20:58 +04:00
|
|
|
*aFile = nullptr;
|
2000-04-11 02:08:19 +04:00
|
|
|
|
2002-07-03 04:55:47 +04:00
|
|
|
if (mUnicodeFile.IsEmpty()) return NS_OK;
|
2000-03-22 10:43:43 +03:00
|
|
|
|
2020-11-16 22:37:09 +03:00
|
|
|
nsCOMPtr<nsIFile> file;
|
|
|
|
nsresult rv = NS_NewLocalFile(mUnicodeFile, false, getter_AddRefs(file));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2000-03-22 10:43:43 +03:00
|
|
|
|
2020-11-16 22:37:09 +03:00
|
|
|
file.forget(aFile);
|
2000-03-22 10:43:43 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFilePicker::GetFileURL(nsIURI** aFileURL) {
|
2012-07-30 18:20:58 +04:00
|
|
|
*aFileURL = nullptr;
|
2012-06-06 06:08:30 +04:00
|
|
|
nsCOMPtr<nsIFile> file;
|
2008-02-26 19:12:17 +03:00
|
|
|
nsresult rv = GetFile(getter_AddRefs(file));
|
|
|
|
if (!file) return rv;
|
2000-04-05 03:50:41 +04:00
|
|
|
|
2008-02-26 19:12:17 +03:00
|
|
|
return NS_NewFileURI(aFileURL, file);
|
2000-04-05 03:50:41 +04:00
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFilePicker::GetFiles(nsISimpleEnumerator** aFiles) {
|
2002-09-07 09:23:45 +04:00
|
|
|
NS_ENSURE_ARG_POINTER(aFiles);
|
2018-08-19 07:06:32 +03:00
|
|
|
return NS_NewArrayEnumerator(aFiles, mFiles, NS_GET_IID(nsIFile));
|
2002-09-07 09:23:45 +04:00
|
|
|
}
|
|
|
|
|
2000-03-22 10:43:43 +03:00
|
|
|
// Get the file + path
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
2012-09-03 19:25:08 +04:00
|
|
|
nsBaseWinFilePicker::SetDefaultString(const nsAString& aString) {
|
2011-12-15 01:22:28 +04:00
|
|
|
mDefaultFilePath = aString;
|
2002-02-12 06:57:39 +03:00
|
|
|
|
2011-12-15 01:22:28 +04:00
|
|
|
// First, make sure the file name is not too long.
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nameLength;
|
Bug 1772006 - Part 5: Simplify and move the string searching APIs from ns[T]StringObsolete, r=xpcom-reviewers,necko-reviewers,eeejay,dragana,barret
The biggest set of APIs from ns[T]StringObsolete which are still heavily used
are the string searching APIs. It appears the intention was for these to be
replaced by the `FindInReadable` APIs, however that doesn't appear to have
happened.
In addition, the APIs have some quirks around their handling of mixed character
widths. These APIs generally supported both narrow strings and the native
string type, probably because char16_t string literals weren't available until
c++11. Finally they also used easy-to-confuse unlabeled boolean and integer
optional arguments to control behaviour.
These patches do the following major changes to the searching APIs:
1. The ASCII case-insensitive search method was split out as
LowerCaseFindASCII, rather than using a boolean. This should be less
error-prone and more explicit, and allows the method to continue to use
narrow string literals for all string types (as only ASCII is supported).
2. The other [R]Find methods were restricted to only support arguments with
matching character types. I considered adding a FindASCII method which would
use narrow string literals for both wide and narrow strings but it would've
been the same amount of work as changing all of the literals to unicode
literals.
This ends up being the bulk of the changes in the patch.
3. All find methods were re-implemented using std::basic_string_view's find
algorithm or stl algorithms to reduce code complexity, and avoid the need to
carry around the logic from nsStringObsolete.cpp.
4. The implementations were moved to nsTStringRepr.cpp.
5. An overload of Find was added to try to catch callers which previously
called `Find(..., false)` or `Find(..., true)` to set case-sensitivity, due
to booleans normally implicitly coercing to `index_type`. This should
probably be removed at some point, but may be useful during the transition.
Differential Revision: https://phabricator.services.mozilla.com/D148300
2022-07-30 03:12:48 +03:00
|
|
|
int32_t nameIndex = mDefaultFilePath.RFind(u"\\");
|
2002-02-12 06:57:39 +03:00
|
|
|
if (nameIndex == kNotFound)
|
|
|
|
nameIndex = 0;
|
|
|
|
else
|
|
|
|
nameIndex++;
|
2011-12-15 01:22:28 +04:00
|
|
|
nameLength = mDefaultFilePath.Length() - nameIndex;
|
|
|
|
mDefaultFilename.Assign(Substring(mDefaultFilePath, nameIndex));
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2009-01-05 21:17:44 +03:00
|
|
|
if (nameLength > MAX_PATH) {
|
Bug 1772006 - Part 5: Simplify and move the string searching APIs from ns[T]StringObsolete, r=xpcom-reviewers,necko-reviewers,eeejay,dragana,barret
The biggest set of APIs from ns[T]StringObsolete which are still heavily used
are the string searching APIs. It appears the intention was for these to be
replaced by the `FindInReadable` APIs, however that doesn't appear to have
happened.
In addition, the APIs have some quirks around their handling of mixed character
widths. These APIs generally supported both narrow strings and the native
string type, probably because char16_t string literals weren't available until
c++11. Finally they also used easy-to-confuse unlabeled boolean and integer
optional arguments to control behaviour.
These patches do the following major changes to the searching APIs:
1. The ASCII case-insensitive search method was split out as
LowerCaseFindASCII, rather than using a boolean. This should be less
error-prone and more explicit, and allows the method to continue to use
narrow string literals for all string types (as only ASCII is supported).
2. The other [R]Find methods were restricted to only support arguments with
matching character types. I considered adding a FindASCII method which would
use narrow string literals for both wide and narrow strings but it would've
been the same amount of work as changing all of the literals to unicode
literals.
This ends up being the bulk of the changes in the patch.
3. All find methods were re-implemented using std::basic_string_view's find
algorithm or stl algorithms to reduce code complexity, and avoid the need to
carry around the logic from nsStringObsolete.cpp.
4. The implementations were moved to nsTStringRepr.cpp.
5. An overload of Find was added to try to catch callers which previously
called `Find(..., false)` or `Find(..., true)` to set case-sensitivity, due
to booleans normally implicitly coercing to `index_type`. This should
probably be removed at some point, but may be useful during the transition.
Differential Revision: https://phabricator.services.mozilla.com/D148300
2022-07-30 03:12:48 +03:00
|
|
|
int32_t extIndex = mDefaultFilePath.RFind(u".");
|
2011-12-15 01:22:28 +04:00
|
|
|
if (extIndex == kNotFound) extIndex = mDefaultFilePath.Length();
|
2002-02-12 06:57:39 +03:00
|
|
|
|
2011-12-15 01:22:28 +04:00
|
|
|
// Let's try to shave the needed characters from the name part.
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t charsToRemove = nameLength - MAX_PATH;
|
2002-02-12 06:57:39 +03:00
|
|
|
if (extIndex - nameIndex >= charsToRemove) {
|
2011-12-15 01:22:28 +04:00
|
|
|
mDefaultFilePath.Cut(extIndex - charsToRemove, charsToRemove);
|
2002-02-12 06:57:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:28 +04:00
|
|
|
// Then, we need to replace illegal characters. At this stage, we cannot
|
|
|
|
// replace the backslash as the string might represent a file path.
|
Bug 1772006 - Part 5: Simplify and move the string searching APIs from ns[T]StringObsolete, r=xpcom-reviewers,necko-reviewers,eeejay,dragana,barret
The biggest set of APIs from ns[T]StringObsolete which are still heavily used
are the string searching APIs. It appears the intention was for these to be
replaced by the `FindInReadable` APIs, however that doesn't appear to have
happened.
In addition, the APIs have some quirks around their handling of mixed character
widths. These APIs generally supported both narrow strings and the native
string type, probably because char16_t string literals weren't available until
c++11. Finally they also used easy-to-confuse unlabeled boolean and integer
optional arguments to control behaviour.
These patches do the following major changes to the searching APIs:
1. The ASCII case-insensitive search method was split out as
LowerCaseFindASCII, rather than using a boolean. This should be less
error-prone and more explicit, and allows the method to continue to use
narrow string literals for all string types (as only ASCII is supported).
2. The other [R]Find methods were restricted to only support arguments with
matching character types. I considered adding a FindASCII method which would
use narrow string literals for both wide and narrow strings but it would've
been the same amount of work as changing all of the literals to unicode
literals.
This ends up being the bulk of the changes in the patch.
3. All find methods were re-implemented using std::basic_string_view's find
algorithm or stl algorithms to reduce code complexity, and avoid the need to
carry around the logic from nsStringObsolete.cpp.
4. The implementations were moved to nsTStringRepr.cpp.
5. An overload of Find was added to try to catch callers which previously
called `Find(..., false)` or `Find(..., true)` to set case-sensitivity, due
to booleans normally implicitly coercing to `index_type`. This should
probably be removed at some point, but may be useful during the transition.
Differential Revision: https://phabricator.services.mozilla.com/D148300
2022-07-30 03:12:48 +03:00
|
|
|
mDefaultFilePath.ReplaceChar(u"" FILE_ILLEGAL_CHARACTERS, u'-');
|
|
|
|
mDefaultFilename.ReplaceChar(u"" FILE_ILLEGAL_CHARACTERS, u'-');
|
2002-02-12 06:57:39 +03:00
|
|
|
|
2000-03-22 10:43:43 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
2012-09-03 19:25:08 +04:00
|
|
|
nsBaseWinFilePicker::GetDefaultString(nsAString& aString) {
|
2000-03-22 10:43:43 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2002-02-20 10:50:52 +03:00
|
|
|
// The default extension to use for files
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
2012-09-03 19:25:08 +04:00
|
|
|
nsBaseWinFilePicker::GetDefaultExtension(nsAString& aExtension) {
|
2004-04-22 03:38:22 +04:00
|
|
|
aExtension = mDefaultExtension;
|
2002-02-20 10:50:52 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
2012-09-03 19:25:08 +04:00
|
|
|
nsBaseWinFilePicker::SetDefaultExtension(const nsAString& aExtension) {
|
2002-02-20 10:50:52 +03:00
|
|
|
mDefaultExtension = aExtension;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-12-12 07:17:26 +03:00
|
|
|
// Set the filter index
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsFilePicker::GetFilterIndex(int32_t* aFilterIndex) {
|
2001-12-12 07:17:26 +03:00
|
|
|
// Windows' filter index is 1-based, we use a 0-based system.
|
|
|
|
*aFilterIndex = mSelectedType - 1;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsFilePicker::SetFilterIndex(int32_t aFilterIndex) {
|
2001-12-12 07:17:26 +03:00
|
|
|
// Windows' filter index is 1-based, we use a 0-based system.
|
|
|
|
mSelectedType = aFilterIndex + 1;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
void nsFilePicker::InitNative(nsIWidget* aParent, const nsAString& aTitle) {
|
2003-02-24 23:15:48 +03:00
|
|
|
mParentWidget = aParent;
|
2004-02-10 13:15:37 +03:00
|
|
|
mTitle.Assign(aTitle);
|
2000-03-22 13:26:22 +03:00
|
|
|
}
|
2000-08-25 06:17:53 +04:00
|
|
|
|
2011-12-15 01:22:28 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter) {
|
2023-05-19 01:29:53 +03:00
|
|
|
nsString sanitizedFilter(aFilter);
|
2023-03-20 23:55:56 +03:00
|
|
|
sanitizedFilter.ReplaceChar('%', '_');
|
2023-05-19 01:29:53 +03:00
|
|
|
|
|
|
|
if (sanitizedFilter == u"..apps"_ns) {
|
|
|
|
sanitizedFilter = u"*.exe;*.com"_ns;
|
|
|
|
} else {
|
|
|
|
sanitizedFilter.StripWhitespace();
|
|
|
|
if (sanitizedFilter == u"*"_ns) {
|
|
|
|
sanitizedFilter = u"*.*"_ns;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mFilterList.AppendElement(
|
|
|
|
Filter{.title = nsString(aTitle), .filter = std::move(sanitizedFilter)});
|
2000-08-25 06:17:53 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-08-19 21:55:03 +04:00
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
void nsFilePicker::RememberLastUsedDirectory() {
|
2020-11-16 22:37:09 +03:00
|
|
|
if (IsPrivacyModeEnabled()) {
|
|
|
|
// Don't remember the directory if private browsing was in effect
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFile> file;
|
|
|
|
if (NS_FAILED(NS_NewLocalFile(mUnicodeFile, false, getter_AddRefs(file)))) {
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_WARNING("RememberLastUsedDirectory failed to init file path.");
|
|
|
|
return;
|
2011-08-19 21:55:03 +04:00
|
|
|
}
|
2011-12-15 01:22:16 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIFile> dir;
|
|
|
|
nsAutoString newDir;
|
|
|
|
if (NS_FAILED(file->GetParent(getter_AddRefs(dir))) ||
|
2018-10-03 22:52:01 +03:00
|
|
|
!(mDisplayDirectory = dir) ||
|
2011-12-15 01:22:16 +04:00
|
|
|
NS_FAILED(mDisplayDirectory->GetPath(newDir)) || newDir.IsEmpty()) {
|
|
|
|
NS_WARNING("RememberLastUsedDirectory failed to get parent directory.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-11-16 22:37:09 +03:00
|
|
|
sLastUsedUnicodeDirectory.reset(ToNewUnicode(newDir));
|
2011-08-19 21:55:03 +04:00
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
bool nsFilePicker::IsPrivacyModeEnabled() {
|
2012-04-09 23:53:46 +04:00
|
|
|
return mLoadContext && mLoadContext->UsePrivateBrowsing();
|
2011-12-15 01:22:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool nsFilePicker::IsDefaultPathLink() {
|
2011-12-15 01:22:28 +04:00
|
|
|
NS_ConvertUTF16toUTF8 ext(mDefaultFilePath);
|
2011-12-15 01:22:16 +04:00
|
|
|
ext.Trim(" .", false, true); // watch out for trailing space and dots
|
|
|
|
ToLowerCase(ext);
|
2023-05-19 01:29:53 +03:00
|
|
|
return StringEndsWith(ext, ".lnk"_ns) || StringEndsWith(ext, ".pif"_ns) ||
|
|
|
|
StringEndsWith(ext, ".url"_ns);
|
2011-08-19 21:55:03 +04:00
|
|
|
}
|
|
|
|
|
2011-12-15 01:22:16 +04:00
|
|
|
bool nsFilePicker::IsDefaultPathHtml() {
|
Bug 1772006 - Part 5: Simplify and move the string searching APIs from ns[T]StringObsolete, r=xpcom-reviewers,necko-reviewers,eeejay,dragana,barret
The biggest set of APIs from ns[T]StringObsolete which are still heavily used
are the string searching APIs. It appears the intention was for these to be
replaced by the `FindInReadable` APIs, however that doesn't appear to have
happened.
In addition, the APIs have some quirks around their handling of mixed character
widths. These APIs generally supported both narrow strings and the native
string type, probably because char16_t string literals weren't available until
c++11. Finally they also used easy-to-confuse unlabeled boolean and integer
optional arguments to control behaviour.
These patches do the following major changes to the searching APIs:
1. The ASCII case-insensitive search method was split out as
LowerCaseFindASCII, rather than using a boolean. This should be less
error-prone and more explicit, and allows the method to continue to use
narrow string literals for all string types (as only ASCII is supported).
2. The other [R]Find methods were restricted to only support arguments with
matching character types. I considered adding a FindASCII method which would
use narrow string literals for both wide and narrow strings but it would've
been the same amount of work as changing all of the literals to unicode
literals.
This ends up being the bulk of the changes in the patch.
3. All find methods were re-implemented using std::basic_string_view's find
algorithm or stl algorithms to reduce code complexity, and avoid the need to
carry around the logic from nsStringObsolete.cpp.
4. The implementations were moved to nsTStringRepr.cpp.
5. An overload of Find was added to try to catch callers which previously
called `Find(..., false)` or `Find(..., true)` to set case-sensitivity, due
to booleans normally implicitly coercing to `index_type`. This should
probably be removed at some point, but may be useful during the transition.
Differential Revision: https://phabricator.services.mozilla.com/D148300
2022-07-30 03:12:48 +03:00
|
|
|
int32_t extIndex = mDefaultFilePath.RFind(u".");
|
2011-12-15 01:22:16 +04:00
|
|
|
if (extIndex >= 0) {
|
|
|
|
nsAutoString ext;
|
2011-12-15 01:22:28 +04:00
|
|
|
mDefaultFilePath.Right(ext, mDefaultFilePath.Length() - extIndex);
|
2011-12-15 01:22:16 +04:00
|
|
|
if (ext.LowerCaseEqualsLiteral(".htm") ||
|
|
|
|
ext.LowerCaseEqualsLiteral(".html") ||
|
|
|
|
ext.LowerCaseEqualsLiteral(".shtml"))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|