1 // Copyright 2017 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 5 #ifndef EXTENSIONS_BROWSER_API_FILE_SYSTEM_FILE_SYSTEM_API_H_ 6 #define EXTENSIONS_BROWSER_API_FILE_SYSTEM_FILE_SYSTEM_API_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/files/file.h" 13 #include "base/files/file_path.h" 14 #include "base/macros.h" 15 #include "base/values.h" 16 #include "build/build_config.h" 17 #include "extensions/browser/extension_function.h" 18 #include "extensions/common/api/file_system.h" 19 #include "ui/shell_dialogs/select_file_dialog.h" 20 21 namespace content { 22 class WebContents; 23 } // namespace content 24 25 namespace extensions { 26 class ExtensionPrefs; 27 28 namespace file_system_api { 29 30 // Methods to get and set the path of the directory containing the last file 31 // chosen by the user in response to a chrome.fileSystem.chooseEntry() call for 32 // the given extension. 33 34 // Returns an empty path on failure. 35 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs, 36 const std::string& extension_id); 37 38 void SetLastChooseEntryDirectory(ExtensionPrefs* prefs, 39 const std::string& extension_id, 40 const base::FilePath& path); 41 42 } // namespace file_system_api 43 44 class FileSystemGetDisplayPathFunction : public ExtensionFunction { 45 public: 46 DECLARE_EXTENSION_FUNCTION("fileSystem.getDisplayPath", 47 FILESYSTEM_GETDISPLAYPATH) 48 49 protected: ~FileSystemGetDisplayPathFunction()50 ~FileSystemGetDisplayPathFunction() override {} 51 ResponseAction Run() override; 52 }; 53 54 class FileSystemEntryFunction : public ExtensionFunction { 55 protected: 56 FileSystemEntryFunction(); 57 ~FileSystemEntryFunction()58 ~FileSystemEntryFunction() override {} 59 60 // This is called when writable file entries are being returned. The function 61 // will ensure the files exist, creating them if necessary, and also check 62 // that none of the files are links. If it succeeds it proceeds to 63 // RegisterFileSystemsAndSendResponse, otherwise to HandleWritableFileError. 64 void PrepareFilesForWritableApp(const std::vector<base::FilePath>& path); 65 66 // This will finish the choose file process. This is either called directly 67 // from FilesSelected, or from WritableFileChecker. It is called on the UI 68 // thread. 69 void RegisterFileSystemsAndSendResponse( 70 const std::vector<base::FilePath>& path); 71 72 // Creates a result dictionary. 73 std::unique_ptr<base::DictionaryValue> CreateResult(); 74 75 // Adds an entry to the result dictionary. 76 void AddEntryToResult(const base::FilePath& path, 77 const std::string& id_override, 78 base::DictionaryValue* result); 79 80 // called on the UI thread if there is a problem checking a writable file. 81 void HandleWritableFileError(const base::FilePath& error_path); 82 83 // Whether multiple entries have been requested. 84 bool multiple_; 85 86 // Whether a directory has been requested. 87 bool is_directory_; 88 }; 89 90 class FileSystemGetWritableEntryFunction : public FileSystemEntryFunction { 91 public: 92 DECLARE_EXTENSION_FUNCTION("fileSystem.getWritableEntry", 93 FILESYSTEM_GETWRITABLEENTRY) 94 95 protected: ~FileSystemGetWritableEntryFunction()96 ~FileSystemGetWritableEntryFunction() override {} 97 ResponseAction Run() override; 98 99 private: 100 void CheckPermissionAndSendResponse(); 101 void SetIsDirectoryAsync(); 102 103 // The path to the file for which a writable entry has been requested. 104 base::FilePath path_; 105 }; 106 107 class FileSystemIsWritableEntryFunction : public ExtensionFunction { 108 public: 109 DECLARE_EXTENSION_FUNCTION("fileSystem.isWritableEntry", 110 FILESYSTEM_ISWRITABLEENTRY) 111 112 protected: ~FileSystemIsWritableEntryFunction()113 ~FileSystemIsWritableEntryFunction() override {} 114 ResponseAction Run() override; 115 }; 116 117 class FileSystemChooseEntryFunction : public FileSystemEntryFunction { 118 public: 119 // Allow picker UI to be skipped in testing. 120 static void SkipPickerAndAlwaysSelectPathForTest(base::FilePath* path); 121 static void SkipPickerAndAlwaysSelectPathsForTest( 122 std::vector<base::FilePath>* paths); 123 static void SkipPickerAndSelectSuggestedPathForTest(); 124 static void SkipPickerAndAlwaysCancelForTest(); 125 static void StopSkippingPickerForTest(); 126 // Allow directory access confirmation UI to be skipped in testing. 127 static void SkipDirectoryConfirmationForTest(); 128 static void AutoCancelDirectoryConfirmationForTest(); 129 static void StopSkippingDirectoryConfirmationForTest(); 130 // Call this with the directory for test file paths. On Chrome OS, accessed 131 // path needs to be explicitly registered for smooth integration with Google 132 // Drive support. 133 static void RegisterTempExternalFileSystemForTest(const std::string& name, 134 const base::FilePath& path); 135 DECLARE_EXTENSION_FUNCTION("fileSystem.chooseEntry", FILESYSTEM_CHOOSEENTRY) 136 137 typedef std::vector<api::file_system::AcceptOption> AcceptOptions; 138 139 static void BuildFileTypeInfo( 140 ui::SelectFileDialog::FileTypeInfo* file_type_info, 141 const base::FilePath::StringType& suggested_extension, 142 const AcceptOptions* accepts, 143 const bool* acceptsAllTypes); 144 static void BuildSuggestion(const std::string* opt_name, 145 base::FilePath* suggested_name, 146 base::FilePath::StringType* suggested_extension); 147 148 protected: ~FileSystemChooseEntryFunction()149 ~FileSystemChooseEntryFunction() override {} 150 ResponseAction Run() override; 151 void ShowPicker(const ui::SelectFileDialog::FileTypeInfo& file_type_info, 152 ui::SelectFileDialog::Type picker_type); 153 154 private: 155 void SetInitialPathAndShowPicker( 156 const base::FilePath& previous_path, 157 const base::FilePath& suggested_name, 158 const ui::SelectFileDialog::FileTypeInfo& file_type_info, 159 ui::SelectFileDialog::Type picker_type, 160 bool is_path_non_native_directory); 161 162 // FilesSelected and FileSelectionCanceled are called by the file picker. 163 void FilesSelected(const std::vector<base::FilePath>& paths); 164 void FileSelectionCanceled(); 165 166 // Check if the chosen directory is or is an ancestor of a sensitive 167 // directory. If so, calls ConfirmSensitiveDirectoryAccess. Otherwise, calls 168 // OnDirectoryAccessConfirmed. 169 void ConfirmDirectoryAccessAsync(bool non_native_path, 170 const std::vector<base::FilePath>& paths, 171 content::WebContents* web_contents); 172 173 // Shows a dialog to confirm whether the user wants to open the directory. 174 // Calls OnDirectoryAccessConfirmed or FileSelectionCanceled. 175 void ConfirmSensitiveDirectoryAccess(const std::vector<base::FilePath>& paths, 176 content::WebContents* web_contents); 177 178 void OnDirectoryAccessConfirmed(const std::vector<base::FilePath>& paths); 179 180 base::FilePath initial_path_; 181 }; 182 183 class FileSystemRetainEntryFunction : public ExtensionFunction { 184 public: 185 DECLARE_EXTENSION_FUNCTION("fileSystem.retainEntry", FILESYSTEM_RETAINENTRY) 186 187 protected: ~FileSystemRetainEntryFunction()188 ~FileSystemRetainEntryFunction() override {} 189 ResponseAction Run() override; 190 191 private: 192 // Retains the file entry referenced by |entry_id| in apps::SavedFilesService. 193 // |entry_id| must refer to an entry in an isolated file system. |path| is a 194 // path of the entry. |file_info| is base::File::Info of the entry if it can 195 // be obtained. 196 void RetainFileEntry(const std::string& entry_id, 197 const base::FilePath& path, 198 std::unique_ptr<base::File::Info> file_info); 199 }; 200 201 class FileSystemIsRestorableFunction : public ExtensionFunction { 202 public: 203 DECLARE_EXTENSION_FUNCTION("fileSystem.isRestorable", FILESYSTEM_ISRESTORABLE) 204 205 protected: ~FileSystemIsRestorableFunction()206 ~FileSystemIsRestorableFunction() override {} 207 ResponseAction Run() override; 208 }; 209 210 class FileSystemRestoreEntryFunction : public FileSystemEntryFunction { 211 public: 212 DECLARE_EXTENSION_FUNCTION("fileSystem.restoreEntry", FILESYSTEM_RESTOREENTRY) 213 214 protected: ~FileSystemRestoreEntryFunction()215 ~FileSystemRestoreEntryFunction() override {} 216 ResponseAction Run() override; 217 }; 218 219 #if !defined(OS_CHROMEOS) 220 // Stub for non Chrome OS operating systems. 221 class FileSystemRequestFileSystemFunction : public ExtensionFunction { 222 public: 223 DECLARE_EXTENSION_FUNCTION("fileSystem.requestFileSystem", 224 FILESYSTEM_REQUESTFILESYSTEM) 225 226 protected: ~FileSystemRequestFileSystemFunction()227 ~FileSystemRequestFileSystemFunction() override {} 228 229 // ExtensionFunction overrides. 230 ExtensionFunction::ResponseAction Run() override; 231 }; 232 233 // Stub for non Chrome OS operating systems. 234 class FileSystemGetVolumeListFunction : public ExtensionFunction { 235 public: 236 DECLARE_EXTENSION_FUNCTION("fileSystem.getVolumeList", 237 FILESYSTEM_GETVOLUMELIST) 238 239 protected: ~FileSystemGetVolumeListFunction()240 ~FileSystemGetVolumeListFunction() override {} 241 242 // ExtensionFunction overrides. 243 ExtensionFunction::ResponseAction Run() override; 244 }; 245 246 #else 247 // Requests a file system for the specified volume id. 248 class FileSystemRequestFileSystemFunction : public ExtensionFunction { 249 public: 250 DECLARE_EXTENSION_FUNCTION("fileSystem.requestFileSystem", 251 FILESYSTEM_REQUESTFILESYSTEM) 252 FileSystemRequestFileSystemFunction(); 253 254 protected: 255 ~FileSystemRequestFileSystemFunction() override; 256 257 // ExtensionFunction overrides. 258 ExtensionFunction::ResponseAction Run() override; 259 260 private: 261 // Called when a user grants or rejects permissions for the file system 262 // access. 263 void OnGotFileSystem(const std::string& id, const std::string& path); 264 void OnError(const std::string& error); 265 }; 266 267 // Requests a list of available volumes. 268 class FileSystemGetVolumeListFunction : public ExtensionFunction { 269 public: 270 DECLARE_EXTENSION_FUNCTION("fileSystem.getVolumeList", 271 FILESYSTEM_GETVOLUMELIST) 272 FileSystemGetVolumeListFunction(); 273 274 protected: 275 ~FileSystemGetVolumeListFunction() override; 276 277 // ExtensionFunction overrides. 278 ExtensionFunction::ResponseAction Run() override; 279 280 private: 281 void OnGotVolumeList(const std::vector<api::file_system::Volume>& volumes); 282 void OnError(const std::string& error); 283 }; 284 #endif 285 286 } // namespace extensions 287 288 #endif // EXTENSIONS_BROWSER_API_FILE_SYSTEM_FILE_SYSTEM_API_H_ 289