file_select_helper.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright (c) 2021 Microsoft. All rights reserved.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #ifndef ELECTRON_SHELL_BROWSER_FILE_SELECT_HELPER_H_
  5. #define ELECTRON_SHELL_BROWSER_FILE_SELECT_HELPER_H_
  6. #include <map>
  7. #include <memory>
  8. #include <string>
  9. #include <vector>
  10. #include "base/compiler_specific.h"
  11. #include "base/scoped_observation.h"
  12. #include "build/build_config.h"
  13. #include "content/public/browser/browser_thread.h"
  14. #include "content/public/browser/render_widget_host.h"
  15. #include "content/public/browser/render_widget_host_observer.h"
  16. #include "content/public/browser/web_contents_observer.h"
  17. #include "net/base/directory_lister.h"
  18. #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
  19. #include "ui/shell_dialogs/select_file_dialog.h"
  20. namespace content {
  21. class FileSelectListener;
  22. class WebContents;
  23. } // namespace content
  24. namespace ui {
  25. struct SelectedFileInfo;
  26. }
  27. // This class handles file-selection requests coming from renderer processes.
  28. // It implements both the initialisation and listener functions for
  29. // file-selection dialogs.
  30. //
  31. // Since FileSelectHelper listens to observations of a widget, it needs to live
  32. // on and be destroyed on the UI thread. References to FileSelectHelper may be
  33. // passed on to other threads.
  34. class FileSelectHelper : public base::RefCountedThreadSafe<
  35. FileSelectHelper,
  36. content::BrowserThread::DeleteOnUIThread>,
  37. public ui::SelectFileDialog::Listener,
  38. public content::WebContentsObserver,
  39. public content::RenderWidgetHostObserver,
  40. private net::DirectoryLister::DirectoryListerDelegate {
  41. public:
  42. // disable copy
  43. FileSelectHelper(const FileSelectHelper&) = delete;
  44. FileSelectHelper& operator=(const FileSelectHelper&) = delete;
  45. // Show the file chooser dialog.
  46. static void RunFileChooser(
  47. content::RenderFrameHost* render_frame_host,
  48. scoped_refptr<content::FileSelectListener> listener,
  49. const blink::mojom::FileChooserParams& params);
  50. // Enumerates all the files in directory.
  51. static void EnumerateDirectory(
  52. content::WebContents* tab,
  53. scoped_refptr<content::FileSelectListener> listener,
  54. const base::FilePath& path);
  55. private:
  56. friend class base::RefCountedThreadSafe<FileSelectHelper>;
  57. friend class base::DeleteHelper<FileSelectHelper>;
  58. friend struct content::BrowserThread::DeleteOnThread<
  59. content::BrowserThread::UI>;
  60. FileSelectHelper();
  61. ~FileSelectHelper() override;
  62. void RunFileChooser(content::RenderFrameHost* render_frame_host,
  63. scoped_refptr<content::FileSelectListener> listener,
  64. blink::mojom::FileChooserParamsPtr params);
  65. void GetFileTypesInThreadPool(blink::mojom::FileChooserParamsPtr params);
  66. void GetSanitizedFilenameOnUIThread(
  67. blink::mojom::FileChooserParamsPtr params);
  68. void RunFileChooserOnUIThread(const base::FilePath& default_path,
  69. blink::mojom::FileChooserParamsPtr params);
  70. // Cleans up and releases this instance. This must be called after the last
  71. // callback is received from the file chooser dialog.
  72. void RunFileChooserEnd();
  73. // SelectFileDialog::Listener overrides.
  74. void FileSelected(const base::FilePath& path,
  75. int index,
  76. void* params) override;
  77. void FileSelectedWithExtraInfo(const ui::SelectedFileInfo& file,
  78. int index,
  79. void* params) override;
  80. void MultiFilesSelected(const std::vector<base::FilePath>& files,
  81. void* params) override;
  82. void MultiFilesSelectedWithExtraInfo(
  83. const std::vector<ui::SelectedFileInfo>& files,
  84. void* params) override;
  85. void FileSelectionCanceled(void* params) override;
  86. // content::RenderWidgetHostObserver overrides.
  87. void RenderWidgetHostDestroyed(
  88. content::RenderWidgetHost* widget_host) override;
  89. // content::WebContentsObserver overrides.
  90. void RenderFrameHostChanged(content::RenderFrameHost* old_host,
  91. content::RenderFrameHost* new_host) override;
  92. void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
  93. void WebContentsDestroyed() override;
  94. void EnumerateDirectoryImpl(
  95. content::WebContents* tab,
  96. scoped_refptr<content::FileSelectListener> listener,
  97. const base::FilePath& path);
  98. // Kicks off a new directory enumeration.
  99. void StartNewEnumeration(const base::FilePath& path);
  100. // net::DirectoryLister::DirectoryListerDelegate overrides.
  101. void OnListFile(
  102. const net::DirectoryLister::DirectoryListerData& data) override;
  103. void OnListDone(int error) override;
  104. void LaunchConfirmationDialog(
  105. const base::FilePath& path,
  106. std::vector<ui::SelectedFileInfo> selected_files);
  107. // Cleans up and releases this instance. This must be called after the last
  108. // callback is received from the enumeration code.
  109. void EnumerateDirectoryEnd();
  110. #if BUILDFLAG(IS_MAC)
  111. // Must be called from a MayBlock() task. Each selected file that is a package
  112. // will be zipped, and the zip will be passed to the render view host in place
  113. // of the package.
  114. void ProcessSelectedFilesMac(const std::vector<ui::SelectedFileInfo>& files);
  115. // Saves the paths of |zipped_files| for later deletion. Passes |files| to the
  116. // render view host.
  117. void ProcessSelectedFilesMacOnUIThread(
  118. const std::vector<ui::SelectedFileInfo>& files,
  119. const std::vector<base::FilePath>& zipped_files);
  120. // Zips the package at |path| into a temporary destination. Returns the
  121. // temporary destination, if the zip was successful. Otherwise returns an
  122. // empty path.
  123. static base::FilePath ZipPackage(const base::FilePath& path);
  124. #endif // BUILDFLAG(IS_MAC)
  125. void ConvertToFileChooserFileInfoList(
  126. const std::vector<ui::SelectedFileInfo>& files);
  127. // Checks to see if scans are required for the specified files.
  128. void PerformContentAnalysisIfNeeded(
  129. std::vector<blink::mojom::FileChooserFileInfoPtr> list);
  130. // Finish the PerformContentAnalysisIfNeeded() handling after the
  131. // deep scanning checks have been performed. Deep scanning may change the
  132. // list of files chosen by the user, so the list of files passed here may be
  133. // a subset of of the files passed to PerformContentAnalysisIfNeeded().
  134. void NotifyListenerAndEnd(
  135. std::vector<blink::mojom::FileChooserFileInfoPtr> list);
  136. // Schedules the deletion of the files in |temporary_files_| and clears the
  137. // vector.
  138. void DeleteTemporaryFiles();
  139. // Cleans up when the initiator of the file chooser is no longer valid.
  140. void CleanUp();
  141. // Calls RunFileChooserEnd() if the webcontents was destroyed. Returns true
  142. // if the file chooser operation shouldn't proceed.
  143. bool AbortIfWebContentsDestroyed();
  144. void SetFileSelectListenerForTesting(
  145. scoped_refptr<content::FileSelectListener> listener);
  146. // Helper method to get allowed extensions for select file dialog from
  147. // the specified accept types as defined in the spec:
  148. // http://whatwg.org/html/number-state.html#attr-input-accept
  149. // |accept_types| contains only valid lowercased MIME types or file extensions
  150. // beginning with a period (.).
  151. static std::unique_ptr<ui::SelectFileDialog::FileTypeInfo>
  152. GetFileTypesFromAcceptType(const std::vector<std::u16string>& accept_types);
  153. // Check the accept type is valid. It is expected to be all lower case with
  154. // no whitespace.
  155. static bool IsAcceptTypeValid(const std::string& accept_type);
  156. // Get a sanitized filename suitable for use as a default filename.
  157. static base::FilePath GetSanitizedFileName(
  158. const base::FilePath& suggested_path);
  159. // The RenderFrameHost and WebContents for the page showing a file dialog
  160. // (may only be one such dialog).
  161. content::RenderFrameHost* render_frame_host_;
  162. content::WebContents* web_contents_;
  163. // |listener_| receives the result of the FileSelectHelper.
  164. scoped_refptr<content::FileSelectListener> listener_;
  165. // Dialog box used for choosing files to upload from file form fields.
  166. scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
  167. std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> select_file_types_;
  168. // The type of file dialog last shown. This is SELECT_NONE if an
  169. // instance is created through the public EnumerateDirectory().
  170. ui::SelectFileDialog::Type dialog_type_;
  171. // The mode of file dialog last shown.
  172. blink::mojom::FileChooserParams::Mode dialog_mode_;
  173. // The enumeration root directory for EnumerateDirectory() and
  174. // RunFileChooser with kUploadFolder.
  175. base::FilePath base_dir_;
  176. // Maintain an active directory enumeration. These could come from the file
  177. // select dialog or from drag-and-drop of directories. There could not be
  178. // more than one going on at a time.
  179. struct ActiveDirectoryEnumeration;
  180. std::unique_ptr<ActiveDirectoryEnumeration> directory_enumeration_;
  181. base::ScopedObservation<content::RenderWidgetHost,
  182. content::RenderWidgetHostObserver>
  183. observation_{this};
  184. // Temporary files only used on OSX. This class is responsible for deleting
  185. // these files when they are no longer needed.
  186. std::vector<base::FilePath> temporary_files_;
  187. };
  188. #endif // ELECTRON_SHELL_BROWSER_FILE_SELECT_HELPER_H_