| diff --git chrome/browser/file_select_helper.cc chrome/browser/file_select_helper.cc |
| index 3f5042600416e..25c23b1a0f00d 100644 |
| --- chrome/browser/file_select_helper.cc |
| +++ chrome/browser/file_select_helper.cc |
| @@ -20,6 +20,7 @@ |
| #include "base/threading/hang_watcher.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| +#include "cef/libcef/features/runtime.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/enterprise/connectors/common.h" |
| #include "chrome/browser/platform_util.h" |
| @@ -256,6 +257,13 @@ void FileSelectHelper::OnListFile( |
| void FileSelectHelper::LaunchConfirmationDialog( |
| const base::FilePath& path, |
| std::vector<ui::SelectedFileInfo> selected_files) { |
| + if (cef::IsAlloyRuntimeEnabled() || run_from_cef_) { |
| + // Don't show the upload confirmation dialog with the Alloy runtime, or |
| + // when triggered via CEF (initially or recursively). |
| + ConvertToFileChooserFileInfoList(selected_files); |
| + return; |
| + } |
| + |
| ShowFolderUploadConfirmationDialog( |
| path, |
| base::BindOnce(&FileSelectHelper::ConvertToFileChooserFileInfoList, this), |
| @@ -340,6 +348,12 @@ void FileSelectHelper::PerformContentAnalysisIfNeeded( |
| if (AbortIfWebContentsDestroyed()) |
| return; |
| |
| + // Don't trigger creation of a AccountConsistencyModeManager (see issue #3401) |
| + if (cef::IsAlloyRuntimeEnabled()) { |
| + NotifyListenerAndEnd(std::move(list)); |
| + return; |
| + } |
| + |
| #if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS) |
| enterprise_connectors::ContentAnalysisDelegate::Data data; |
| if (enterprise_connectors::ContentAnalysisDelegate::IsEnabled( |
| @@ -470,7 +484,8 @@ void FileSelectHelper::DontAbortOnMissingWebContentsForTesting() { |
| |
| std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> |
| FileSelectHelper::GetFileTypesFromAcceptType( |
| - const std::vector<std::u16string>& accept_types) { |
| + const std::vector<std::u16string>& accept_types, |
| + bool run_from_cef) { |
| auto base_file_type = std::make_unique<ui::SelectFileDialog::FileTypeInfo>(); |
| if (accept_types.empty()) |
| return base_file_type; |
| @@ -483,17 +498,24 @@ FileSelectHelper::GetFileTypesFromAcceptType( |
| std::vector<base::FilePath::StringType>* extensions = |
| &file_type->extensions.back(); |
| |
| + // Create individual filters for each accept type. |
| + std::vector<std::vector<base::FilePath::StringType>> all_extensions; |
| + std::vector<std::u16string> all_overrides; |
| + |
| // Find the corresponding extensions. |
| int valid_type_count = 0; |
| int description_id = 0; |
| for (const auto& accept_type : accept_types) { |
| + std::vector<base::FilePath::StringType> current_extensions; |
| + description_id = 0; |
| + |
| size_t old_extension_size = extensions->size(); |
| if (accept_type[0] == '.') { |
| // If the type starts with a period it is assumed to be a file extension |
| // so we just have to add it to the list. |
| base::FilePath::StringType ext = |
| base::FilePath::FromUTF16Unsafe(accept_type).value(); |
| - extensions->push_back(ext.substr(1)); |
| + current_extensions.push_back(ext.substr(1)); |
| } else { |
| if (!base::IsStringASCII(accept_type)) |
| continue; |
| @@ -504,10 +526,18 @@ FileSelectHelper::GetFileTypesFromAcceptType( |
| description_id = IDS_AUDIO_FILES; |
| else if (ascii_type == "video/*") |
| description_id = IDS_VIDEO_FILES; |
| - |
| - net::GetExtensionsForMimeType(ascii_type, extensions); |
| + net::GetExtensionsForMimeType(ascii_type, ¤t_extensions); |
| } |
| |
| + if (!current_extensions.empty()) { |
| + all_extensions.push_back(current_extensions); |
| + all_overrides.push_back(description_id != 0 ? |
| + l10n_util::GetStringUTF16(description_id) : |
| + std::u16string()); |
| + |
| + extensions->insert(extensions->end(), current_extensions.begin(), |
| + current_extensions.end()); |
| + } |
| if (extensions->size() > old_extension_size) |
| valid_type_count++; |
| } |
| @@ -532,6 +562,15 @@ FileSelectHelper::GetFileTypesFromAcceptType( |
| l10n_util::GetStringUTF16(description_id)); |
| } |
| |
| + if (run_from_cef && all_extensions.size() > 1) { |
| + // Insert filters for the specific accept types at the beginning. |
| + file_type->extensions.insert(file_type->extensions.begin(), |
| + all_extensions.begin(), all_extensions.end()); |
| + file_type->extension_description_overrides.insert( |
| + file_type->extension_description_overrides.begin(), |
| + all_overrides.begin(), all_overrides.end()); |
| + } |
| + |
| return file_type; |
| } |
| |
| @@ -539,7 +578,8 @@ FileSelectHelper::GetFileTypesFromAcceptType( |
| void FileSelectHelper::RunFileChooser( |
| content::RenderFrameHost* render_frame_host, |
| scoped_refptr<content::FileSelectListener> listener, |
| - const FileChooserParams& params) { |
| + const FileChooserParams& params, |
| + bool run_from_cef) { |
| Profile* profile = Profile::FromBrowserContext( |
| render_frame_host->GetProcess()->GetBrowserContext()); |
| |
| @@ -558,6 +598,7 @@ void FileSelectHelper::RunFileChooser( |
| // message. |
| scoped_refptr<FileSelectHelper> file_select_helper( |
| new FileSelectHelper(profile)); |
| + file_select_helper->run_from_cef_ = run_from_cef; |
| file_select_helper->RunFileChooser(render_frame_host, std::move(listener), |
| params.Clone()); |
| } |
| @@ -609,7 +650,8 @@ void FileSelectHelper::RunFileChooser( |
| } |
| |
| void FileSelectHelper::GetFileTypesInThreadPool(FileChooserParamsPtr params) { |
| - select_file_types_ = GetFileTypesFromAcceptType(params->accept_types); |
| + select_file_types_ = GetFileTypesFromAcceptType(params->accept_types, |
| + run_from_cef_); |
| select_file_types_->allowed_paths = |
| params->need_local_path ? ui::SelectFileDialog::FileTypeInfo::NATIVE_PATH |
| : ui::SelectFileDialog::FileTypeInfo::ANY_PATH; |
| diff --git chrome/browser/file_select_helper.h chrome/browser/file_select_helper.h |
| index 57dae0b3670ae..85eeda4cbaa5b 100644 |
| --- chrome/browser/file_select_helper.h |
| +++ chrome/browser/file_select_helper.h |
| @@ -62,7 +62,8 @@ class FileSelectHelper : public base::RefCountedThreadSafe< |
| static void RunFileChooser( |
| content::RenderFrameHost* render_frame_host, |
| scoped_refptr<content::FileSelectListener> listener, |
| - const blink::mojom::FileChooserParams& params); |
| + const blink::mojom::FileChooserParams& params, |
| + bool run_from_cef = false); |
| |
| // Enumerates all the files in directory. |
| static void EnumerateDirectory( |
| @@ -268,7 +269,8 @@ class FileSelectHelper : public base::RefCountedThreadSafe< |
| // |accept_types| contains only valid lowercased MIME types or file extensions |
| // beginning with a period (.). |
| static std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> |
| - GetFileTypesFromAcceptType(const std::vector<std::u16string>& accept_types); |
| + GetFileTypesFromAcceptType(const std::vector<std::u16string>& accept_types, |
| + bool run_from_cef); |
| |
| // Check the accept type is valid. It is expected to be all lower case with |
| // no whitespace. |
| @@ -329,6 +331,9 @@ class FileSelectHelper : public base::RefCountedThreadSafe< |
| // Set to false in unit tests since there is no WebContents. |
| bool abort_on_missing_web_contents_in_tests_ = true; |
| |
| + // Set to true if this dialog was triggered via CEF. |
| + bool run_from_cef_ = false; |
| + |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| base::WeakPtrFactory<FileSelectHelper> weak_ptr_factory_{this}; |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |
| diff --git chrome/browser/ui/chrome_select_file_policy.h chrome/browser/ui/chrome_select_file_policy.h |
| index 49272553c7c53..5ba90c9a06ecf 100644 |
| --- chrome/browser/ui/chrome_select_file_policy.h |
| +++ chrome/browser/ui/chrome_select_file_policy.h |
| @@ -30,6 +30,8 @@ class ChromeSelectFilePolicy : public ui::SelectFilePolicy { |
| // Returns true if local state allows showing file pickers. |
| static bool FileSelectDialogsAllowed(); |
| |
| + content::WebContents* source_contents() const { return source_contents_; } |
| + |
| private: |
| raw_ptr<content::WebContents, AcrossTasksDanglingUntriaged> source_contents_; |
| }; |
| diff --git ui/shell_dialogs/execute_select_file_win.cc ui/shell_dialogs/execute_select_file_win.cc |
| index 101e91826023b..35456ffad43f3 100644 |
| --- ui/shell_dialogs/execute_select_file_win.cc |
| +++ ui/shell_dialogs/execute_select_file_win.cc |
| @@ -297,9 +297,7 @@ bool ExecuteSelectSingleFile(HWND owner, |
| const std::vector<FileFilterSpec>& filter, |
| int* filter_index, |
| std::vector<base::FilePath>* paths) { |
| - // Note: The title is not passed down for historical reasons. |
| - // TODO(pmonette): Figure out if it's a worthwhile improvement. |
| - return RunOpenFileDialog(owner, std::u16string(), std::u16string(), |
| + return RunOpenFileDialog(owner, title, std::u16string(), |
| default_path, filter, 0, filter_index, paths); |
| } |
| |
| @@ -311,14 +309,13 @@ bool ExecuteSelectMultipleFile(HWND owner, |
| std::vector<base::FilePath>* paths) { |
| DWORD dialog_options = FOS_ALLOWMULTISELECT; |
| |
| - // Note: The title is not passed down for historical reasons. |
| - // TODO(pmonette): Figure out if it's a worthwhile improvement. |
| - return RunOpenFileDialog(owner, std::u16string(), std::u16string(), |
| + return RunOpenFileDialog(owner, title, std::u16string(), |
| default_path, filter, dialog_options, filter_index, |
| paths); |
| } |
| |
| bool ExecuteSaveFile(HWND owner, |
| + const std::u16string& title, |
| const base::FilePath& default_path, |
| const std::vector<FileFilterSpec>& filter, |
| const std::wstring& def_ext, |
| @@ -331,9 +328,7 @@ bool ExecuteSaveFile(HWND owner, |
| |
| DWORD dialog_options = FOS_OVERWRITEPROMPT; |
| |
| - // Note: The title is not passed down for historical reasons. |
| - // TODO(pmonette): Figure out if it's a worthwhile improvement. |
| - return RunSaveFileDialog(owner, std::u16string(), default_path, filter, |
| + return RunSaveFileDialog(owner, title, default_path, filter, |
| dialog_options, def_ext, filter_index, path); |
| } |
| |
| @@ -358,7 +353,7 @@ void ExecuteSelectFile( |
| break; |
| case SelectFileDialog::SELECT_SAVEAS_FILE: { |
| base::FilePath path; |
| - if (ExecuteSaveFile(owner, default_path, filter, default_extension, |
| + if (ExecuteSaveFile(owner, title, default_path, filter, default_extension, |
| &file_type_index, &path)) { |
| paths.push_back(std::move(path)); |
| } |
| diff --git ui/shell_dialogs/select_file_dialog.cc ui/shell_dialogs/select_file_dialog.cc |
| index e2c00b2ec1532..a2e8753766597 100644 |
| --- ui/shell_dialogs/select_file_dialog.cc |
| +++ ui/shell_dialogs/select_file_dialog.cc |
| @@ -88,8 +88,10 @@ void SelectFileDialog::SetFactory( |
| // static |
| scoped_refptr<SelectFileDialog> SelectFileDialog::Create( |
| Listener* listener, |
| - std::unique_ptr<ui::SelectFilePolicy> policy) { |
| - if (dialog_factory_) |
| + std::unique_ptr<ui::SelectFilePolicy> policy, |
| + bool run_from_cef) { |
| + // Avoid reentrancy of the CEF factory. |
| + if (dialog_factory_ && (!run_from_cef || !dialog_factory_->IsCefFactory())) |
| return dialog_factory_->Create(listener, std::move(policy)); |
| return CreateSelectFileDialog(listener, std::move(policy)); |
| } |
| diff --git ui/shell_dialogs/select_file_dialog.h ui/shell_dialogs/select_file_dialog.h |
| index 65f0342389117..c4b79bc0dab91 100644 |
| --- ui/shell_dialogs/select_file_dialog.h |
| +++ ui/shell_dialogs/select_file_dialog.h |
| @@ -116,7 +116,8 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog |
| // is refcounted and uses a background thread. |
| static scoped_refptr<SelectFileDialog> Create( |
| Listener* listener, |
| - std::unique_ptr<SelectFilePolicy> policy); |
| + std::unique_ptr<SelectFilePolicy> policy, |
| + bool run_from_cef = false); |
| |
| SelectFileDialog(const SelectFileDialog&) = delete; |
| SelectFileDialog& operator=(const SelectFileDialog&) = delete; |
| @@ -213,6 +214,19 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog |
| const GURL* caller = nullptr); |
| bool HasMultipleFileTypeChoices(); |
| |
| + // Match the types used by CefWindowHandle. |
| +#if BUILDFLAG(IS_MAC) |
| + using WidgetType = void*; |
| + static constexpr WidgetType kNullWidget = nullptr; |
| +#else |
| + using WidgetType = gfx::AcceleratedWidget; |
| + static constexpr WidgetType kNullWidget = gfx::kNullAcceleratedWidget; |
| +#endif |
| + |
| + void set_owning_widget(WidgetType widget) { |
| + owning_widget_ = widget; |
| + } |
| + |
| protected: |
| friend class base::RefCountedThreadSafe<SelectFileDialog>; |
| |
| @@ -238,6 +252,11 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog |
| // The listener to be notified of selection completion. |
| raw_ptr<Listener> listener_; |
| |
| + std::unique_ptr<SelectFilePolicy> select_file_policy_; |
| + |
| + // Support override of the |owning_window| value. |
| + WidgetType owning_widget_ = kNullWidget; |
| + |
| private: |
| // Tests if the file selection dialog can be displayed by |
| // testing if the AllowFileSelectionDialogs-Policy is |
| @@ -250,8 +269,6 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog |
| |
| // Returns true if the dialog has multiple file type choices. |
| virtual bool HasMultipleFileTypeChoicesImpl() = 0; |
| - |
| - std::unique_ptr<SelectFilePolicy> select_file_policy_; |
| }; |
| |
| SelectFileDialog* CreateSelectFileDialog( |
| diff --git ui/shell_dialogs/select_file_dialog_factory.h ui/shell_dialogs/select_file_dialog_factory.h |
| index c7acd9b05fbb8..3e95e4125fa24 100644 |
| --- ui/shell_dialogs/select_file_dialog_factory.h |
| +++ ui/shell_dialogs/select_file_dialog_factory.h |
| @@ -24,6 +24,8 @@ class SHELL_DIALOGS_EXPORT SelectFileDialogFactory { |
| virtual SelectFileDialog* Create( |
| ui::SelectFileDialog::Listener* listener, |
| std::unique_ptr<ui::SelectFilePolicy> policy) = 0; |
| + |
| + virtual bool IsCefFactory() const { return false; } |
| }; |
| |
| } // namespace ui |
| diff --git ui/shell_dialogs/select_file_dialog_mac.mm ui/shell_dialogs/select_file_dialog_mac.mm |
| index 0b8aaa3c0e4f0..fe01d3db2eabe 100644 |
| --- ui/shell_dialogs/select_file_dialog_mac.mm |
| +++ ui/shell_dialogs/select_file_dialog_mac.mm |
| @@ -102,6 +102,10 @@ void SelectFileDialogImpl::SelectFileImpl( |
| mojo_window->CreateSelectFileDialog(std::move(receiver)); |
| } else { |
| NSWindow* ns_window = gfx_window.GetNativeNSWindow(); |
| + if (!ns_window && owning_widget_) { |
| + NSView* view = ((__bridge NSView*)owning_widget_); |
| + ns_window = [view window]; |
| + } |
| mojo::MakeSelfOwnedReceiver( |
| std::make_unique<remote_cocoa::SelectFileDialogBridge>(ns_window), |
| std::move(receiver)); |
| diff --git ui/shell_dialogs/select_file_dialog_win.cc ui/shell_dialogs/select_file_dialog_win.cc |
| index 04aa920d91675..93ea4988839cf 100644 |
| --- ui/shell_dialogs/select_file_dialog_win.cc |
| +++ ui/shell_dialogs/select_file_dialog_win.cc |
| @@ -252,6 +252,8 @@ void SelectFileDialogImpl::SelectFileImpl( |
| HWND owner = owning_window && owning_window->GetRootWindow() |
| ? owning_window->GetHost()->GetAcceleratedWidget() |
| : nullptr; |
| + if (!owner) |
| + owner = owning_widget_; |
| |
| std::unique_ptr<RunState> run_state = BeginRun(owner); |
| |