select_file_dialog.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_H_
  5. #define UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_H_
  6. #include <memory>
  7. #include <string>
  8. #include <vector>
  9. #include "base/files/file_path.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/memory/ref_counted.h"
  12. #include "ui/gfx/native_widget_types.h"
  13. #include "ui/shell_dialogs/base_shell_dialog.h"
  14. #include "ui/shell_dialogs/shell_dialogs_export.h"
  15. namespace ui {
  16. class SelectFileDialogFactory;
  17. class SelectFilePolicy;
  18. struct SelectedFileInfo;
  19. // Shows a dialog box for selecting a file or a folder.
  20. class SHELL_DIALOGS_EXPORT SelectFileDialog
  21. : public base::RefCountedThreadSafe<SelectFileDialog>,
  22. public BaseShellDialog {
  23. public:
  24. enum Type {
  25. SELECT_NONE,
  26. // For opening a folder.
  27. SELECT_FOLDER,
  28. // Like SELECT_FOLDER, but the dialog UI should explicitly show it's
  29. // specifically for "upload".
  30. SELECT_UPLOAD_FOLDER,
  31. // Like SELECT_FOLDER, but folder creation is disabled, if possible.
  32. SELECT_EXISTING_FOLDER,
  33. // For saving into a file, allowing a nonexistent file to be selected.
  34. SELECT_SAVEAS_FILE,
  35. // For opening a file.
  36. SELECT_OPEN_FILE,
  37. // Like SELECT_OPEN_FILE, but allowing multiple files to open.
  38. SELECT_OPEN_MULTI_FILE
  39. };
  40. // An interface implemented by a Listener object wishing to know about the
  41. // the result of the Select File/Folder action. These callbacks must be
  42. // re-entrant.
  43. class SHELL_DIALOGS_EXPORT Listener {
  44. public:
  45. // Notifies the Listener that a file/folder selection has been made. The
  46. // file/folder path is in |path|. |params| is contextual passed to
  47. // SelectFile. |index| specifies the index of the filter passed to the
  48. // the initial call to SelectFile.
  49. virtual void FileSelected(const base::FilePath& path,
  50. int index, void* params) = 0;
  51. // Similar to FileSelected() but takes SelectedFileInfo instead of
  52. // base::FilePath. Used for passing extra information (ex. display name).
  53. //
  54. // If not overridden, calls FileSelected() with path from |file|.
  55. virtual void FileSelectedWithExtraInfo(
  56. const SelectedFileInfo& file,
  57. int index,
  58. void* params);
  59. // Notifies the Listener that many files have been selected. The
  60. // files are in |files|. |params| is contextual passed to SelectFile.
  61. virtual void MultiFilesSelected(
  62. const std::vector<base::FilePath>& files, void* params) {}
  63. // Similar to MultiFilesSelected() but takes SelectedFileInfo instead of
  64. // base::FilePath. Used for passing extra information (ex. display name).
  65. //
  66. // If not overridden, calls MultiFilesSelected() with paths from |files|.
  67. virtual void MultiFilesSelectedWithExtraInfo(
  68. const std::vector<SelectedFileInfo>& files,
  69. void* params);
  70. // Notifies the Listener that the file/folder selection was aborted (via
  71. // the user canceling or closing the selection dialog box, for example).
  72. // |params| is contextual passed to SelectFile.
  73. virtual void FileSelectionCanceled(void* params) {}
  74. protected:
  75. virtual ~Listener() = default;
  76. };
  77. // Sets the factory that creates SelectFileDialog objects, overriding default
  78. // behaviour.
  79. //
  80. // This is optional and should only be used by components that have to live
  81. // elsewhere in the tree due to layering violations. (For example, because of
  82. // a dependency on chrome's extension system.)
  83. static void SetFactory(SelectFileDialogFactory* factory);
  84. // Creates a dialog box helper. This is an inexpensive wrapper around the
  85. // platform-native file selection dialog. |policy| is an optional class that
  86. // can prevent showing a dialog.
  87. //
  88. // The lifetime of the Listener is not managed by this class. The calling
  89. // code should call always ListenerDestroyed() (on the base class
  90. // BaseShellDialog) when the listener is destroyed since the SelectFileDialog
  91. // is refcounted and uses a background thread.
  92. static scoped_refptr<SelectFileDialog> Create(
  93. Listener* listener,
  94. std::unique_ptr<SelectFilePolicy> policy);
  95. SelectFileDialog(const SelectFileDialog&) = delete;
  96. SelectFileDialog& operator=(const SelectFileDialog&) = delete;
  97. // Holds information about allowed extensions on a file save dialog.
  98. struct SHELL_DIALOGS_EXPORT FileTypeInfo {
  99. FileTypeInfo();
  100. FileTypeInfo(const FileTypeInfo& other);
  101. ~FileTypeInfo();
  102. // A list of allowed extensions. For example, it might be
  103. //
  104. // { { "htm", "html" }, { "txt" } }
  105. //
  106. // Only pass more than one extension in the inner vector if the extensions
  107. // are equivalent. Do NOT include leading periods.
  108. std::vector<std::vector<base::FilePath::StringType>> extensions;
  109. // Overrides the system descriptions of the specified extensions. Entries
  110. // correspond to |extensions|; if left blank the system descriptions will
  111. // be used.
  112. std::vector<std::u16string> extension_description_overrides;
  113. // Specifies whether there will be a filter added for all files (i.e. *.*).
  114. bool include_all_files = false;
  115. // Some implementations by default hide the extension of a file, in
  116. // particular in a save file dialog. If this is set to true, where
  117. // supported, the save file dialog will instead keep the file extension
  118. // visible.
  119. bool keep_extension_visible = false;
  120. // Specifies which type of paths the caller can handle.
  121. enum AllowedPaths {
  122. // Any type of path, whether on a local/native volume or a remote/virtual
  123. // volume. Excludes files that can only be opened by URL; for those use
  124. // ANY_PATH_OR_URL below.
  125. ANY_PATH,
  126. // Set when the caller cannot handle virtual volumes (e.g. File System
  127. // Provider [FSP] volumes like "File System for Dropbox"). When opening
  128. // files, the dialog will create a native replica of the file and return
  129. // its path. When saving files, the dialog will hide virtual volumes.
  130. NATIVE_PATH,
  131. // Set when the caller can open files via URL. For example, when opening a
  132. // .gdoc file from Google Drive the file is opened by navigating to a
  133. // docs.google.com URL.
  134. ANY_PATH_OR_URL
  135. };
  136. AllowedPaths allowed_paths = NATIVE_PATH;
  137. };
  138. // Returns a file path with a base name at most 255 characters long. This
  139. // is the limit on Windows and Linux, and on Windows the system file
  140. // selection dialog will fail to open if the file name exceeds 255 characters.
  141. static base::FilePath GetShortenedFilePath(const base::FilePath& path);
  142. // Selects a File.
  143. // Before doing anything this function checks if FileBrowsing is forbidden
  144. // by Policy. If so, it tries to show an InfoBar and behaves as though no File
  145. // was selected (the user clicked `Cancel` immediately).
  146. // Otherwise it will start displaying the dialog box. This will also
  147. // block the calling window until the dialog box is complete. The listener
  148. // associated with this object will be notified when the selection is
  149. // complete.
  150. // |type| is the type of file dialog to be shown, see Type enumeration above.
  151. // |title| is the title to be displayed in the dialog. If this string is
  152. // empty, the default title is used.
  153. // |default_path| is the default path and suggested file name to be shown in
  154. // the dialog. This only works for SELECT_SAVEAS_FILE and SELECT_OPEN_FILE.
  155. // Can be an empty string to indicate the platform default.
  156. // |file_types| holds the information about the file types allowed. Pass NULL
  157. // to get no special behavior
  158. // |file_type_index| is the 1-based index into the file type list in
  159. // |file_types|. Specify 0 if you don't need to specify extension behavior.
  160. // |default_extension| is the default extension to add to the file if the
  161. // user doesn't type one. This should NOT include the '.'. On Windows, if
  162. // you specify this you must also specify |file_types|.
  163. // |owning_window| is the window the dialog is modal to, or NULL for a
  164. // modeless dialog.
  165. // |params| is data from the calling context which will be passed through to
  166. // the listener. Can be NULL.
  167. // NOTE: only one instance of any shell dialog can be shown per owning_window
  168. // at a time (for obvious reasons).
  169. void SelectFile(Type type,
  170. const std::u16string& title,
  171. const base::FilePath& default_path,
  172. const FileTypeInfo* file_types,
  173. int file_type_index,
  174. const base::FilePath::StringType& default_extension,
  175. gfx::NativeWindow owning_window,
  176. void* params);
  177. bool HasMultipleFileTypeChoices();
  178. protected:
  179. friend class base::RefCountedThreadSafe<SelectFileDialog>;
  180. explicit SelectFileDialog(Listener* listener,
  181. std::unique_ptr<SelectFilePolicy> policy);
  182. ~SelectFileDialog() override;
  183. // Displays the actual file-selection dialog.
  184. // This is overridden in the platform-specific descendants of FileSelectDialog
  185. // and gets called from SelectFile after testing the
  186. // AllowFileSelectionDialogs-Policy.
  187. virtual void SelectFileImpl(
  188. Type type,
  189. const std::u16string& title,
  190. const base::FilePath& default_path,
  191. const FileTypeInfo* file_types,
  192. int file_type_index,
  193. const base::FilePath::StringType& default_extension,
  194. gfx::NativeWindow owning_window,
  195. void* params) = 0;
  196. // The listener to be notified of selection completion.
  197. raw_ptr<Listener> listener_;
  198. private:
  199. // Tests if the file selection dialog can be displayed by
  200. // testing if the AllowFileSelectionDialogs-Policy is
  201. // either unset or set to true.
  202. bool CanOpenSelectFileDialog();
  203. // Informs the |listener_| that the file selection dialog was canceled. Moved
  204. // to a function for being able to post it to the message loop.
  205. void CancelFileSelection(void* params);
  206. // Returns true if the dialog has multiple file type choices.
  207. virtual bool HasMultipleFileTypeChoicesImpl() = 0;
  208. std::unique_ptr<SelectFilePolicy> select_file_policy_;
  209. };
  210. SelectFileDialog* CreateSelectFileDialog(
  211. SelectFileDialog::Listener* listener,
  212. std::unique_ptr<SelectFilePolicy> policy);
  213. } // namespace ui
  214. #endif // UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_H_