mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			353 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			353 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| diff --git chrome/browser/file_select_helper.cc chrome/browser/file_select_helper.cc
 | |
| index 447a91b9ac380..51593091b5fa6 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"
 | |
| @@ -245,6 +246,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),
 | |
| @@ -329,6 +337,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(
 | |
| @@ -459,7 +473,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;
 | |
| @@ -472,17 +487,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;
 | |
| @@ -493,10 +515,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++;
 | |
|    }
 | |
| @@ -521,6 +551,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;
 | |
|  }
 | |
|  
 | |
| @@ -528,7 +567,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());
 | |
|  
 | |
| @@ -547,6 +587,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());
 | |
|  }
 | |
| @@ -598,7 +639,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 7194323c36956..903cdf0c294fc 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(
 | |
| @@ -264,7 +265,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.
 | |
| @@ -325,6 +327,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 9361287ac3411..59567b485bf99 100644
 | |
| --- ui/shell_dialogs/execute_select_file_win.cc
 | |
| +++ ui/shell_dialogs/execute_select_file_win.cc
 | |
| @@ -360,9 +360,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);
 | |
|  }
 | |
|  
 | |
| @@ -374,14 +372,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,
 | |
| @@ -394,9 +391,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);
 | |
|  }
 | |
|  
 | |
| @@ -421,7 +416,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 68dd62159b686..e94831cd44a2d 100644
 | |
| --- ui/shell_dialogs/select_file_dialog.cc
 | |
| +++ ui/shell_dialogs/select_file_dialog.cc
 | |
| @@ -73,8 +73,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 9b12fae59c3cc..dfb534a6f06e6 100644
 | |
| --- ui/shell_dialogs/select_file_dialog.h
 | |
| +++ ui/shell_dialogs/select_file_dialog.h
 | |
| @@ -102,7 +102,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;
 | |
| @@ -199,6 +200,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>;
 | |
|  
 | |
| @@ -224,6 +238,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
 | |
| @@ -236,8 +255,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 bf99047fa53cf..0efdb76233331 100644
 | |
| --- ui/shell_dialogs/select_file_dialog_mac.mm
 | |
| +++ ui/shell_dialogs/select_file_dialog_mac.mm
 | |
| @@ -107,6 +107,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 cb1a0d203b448..307158e8117fe 100644
 | |
| --- ui/shell_dialogs/select_file_dialog_win.cc
 | |
| +++ ui/shell_dialogs/select_file_dialog_win.cc
 | |
| @@ -253,6 +253,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);
 | |
|  
 |