file_select_helper.h 8.4 KB

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