1 // Copyright (c) 2012 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 CHROME_BROWSER_EXTENSIONS_API_DOWNLOADS_DOWNLOADS_API_H_ 6 #define CHROME_BROWSER_EXTENSIONS_API_DOWNLOADS_DOWNLOADS_API_H_ 7 8 #include <memory> 9 #include <set> 10 #include <string> 11 12 #include "base/files/file_path.h" 13 #include "base/macros.h" 14 #include "base/scoped_observer.h" 15 #include "base/time/time.h" 16 #include "chrome/browser/download/download_danger_prompt.h" 17 #include "chrome/common/extensions/api/downloads.h" 18 #include "components/download/content/public/all_download_item_notifier.h" 19 #include "components/download/public/common/download_path_reservation_tracker.h" 20 #include "content/public/browser/download_manager.h" 21 #include "extensions/browser/event_router.h" 22 #include "extensions/browser/extension_function.h" 23 #include "extensions/browser/extension_registry.h" 24 #include "extensions/browser/extension_registry_observer.h" 25 #include "extensions/browser/warning_set.h" 26 27 class DownloadFileIconExtractor; 28 class DownloadOpenPrompt; 29 class Profile; 30 31 // Functions in the chrome.downloads namespace facilitate 32 // controlling downloads from extensions. See the full API doc at 33 // http://goo.gl/6hO1n 34 35 namespace download_extension_errors { 36 37 // Errors that can be returned through chrome.runtime.lastError.message. 38 extern const char kEmptyFile[]; 39 extern const char kFileAlreadyDeleted[]; 40 extern const char kFileNotRemoved[]; 41 extern const char kIconNotFound[]; 42 extern const char kInvalidDangerType[]; 43 extern const char kInvalidFilename[]; 44 extern const char kInvalidFilter[]; 45 extern const char kInvalidHeaderName[]; 46 extern const char kInvalidHeaderValue[]; 47 extern const char kInvalidHeaderUnsafe[]; 48 extern const char kInvalidId[]; 49 extern const char kInvalidOrderBy[]; 50 extern const char kInvalidQueryLimit[]; 51 extern const char kInvalidState[]; 52 extern const char kInvalidURL[]; 53 extern const char kInvisibleContext[]; 54 extern const char kNotComplete[]; 55 extern const char kNotDangerous[]; 56 extern const char kNotInProgress[]; 57 extern const char kNotResumable[]; 58 extern const char kOpenPermission[]; 59 extern const char kShelfDisabled[]; 60 extern const char kShelfPermission[]; 61 extern const char kTooManyListeners[]; 62 extern const char kUnexpectedDeterminer[]; 63 extern const char kUserGesture[]; 64 65 } // namespace download_extension_errors 66 67 namespace extensions { 68 69 class DownloadedByExtension : public base::SupportsUserData::Data { 70 public: 71 static DownloadedByExtension* Get(download::DownloadItem* item); 72 73 DownloadedByExtension(download::DownloadItem* item, 74 const std::string& id, 75 const std::string& name); 76 id()77 const std::string& id() const { return id_; } name()78 const std::string& name() const { return name_; } 79 80 private: 81 static const char kKey[]; 82 83 std::string id_; 84 std::string name_; 85 86 DISALLOW_COPY_AND_ASSIGN(DownloadedByExtension); 87 }; 88 89 class DownloadsDownloadFunction : public ExtensionFunction { 90 public: 91 DECLARE_EXTENSION_FUNCTION("downloads.download", DOWNLOADS_DOWNLOAD) 92 DownloadsDownloadFunction(); 93 ResponseAction Run() override; 94 95 protected: 96 ~DownloadsDownloadFunction() override; 97 98 private: 99 void OnStarted(const base::FilePath& creator_suggested_filename, 100 extensions::api::downloads::FilenameConflictAction 101 creator_conflict_action, 102 download::DownloadItem* item, 103 download::DownloadInterruptReason interrupt_reason); 104 105 DISALLOW_COPY_AND_ASSIGN(DownloadsDownloadFunction); 106 }; 107 108 class DownloadsSearchFunction : public ExtensionFunction { 109 public: 110 DECLARE_EXTENSION_FUNCTION("downloads.search", DOWNLOADS_SEARCH) 111 DownloadsSearchFunction(); 112 ResponseAction Run() override; 113 114 protected: 115 ~DownloadsSearchFunction() override; 116 117 private: 118 DISALLOW_COPY_AND_ASSIGN(DownloadsSearchFunction); 119 }; 120 121 class DownloadsPauseFunction : public ExtensionFunction { 122 public: 123 DECLARE_EXTENSION_FUNCTION("downloads.pause", DOWNLOADS_PAUSE) 124 DownloadsPauseFunction(); 125 ResponseAction Run() override; 126 127 protected: 128 ~DownloadsPauseFunction() override; 129 130 private: 131 DISALLOW_COPY_AND_ASSIGN(DownloadsPauseFunction); 132 }; 133 134 class DownloadsResumeFunction : public ExtensionFunction { 135 public: 136 DECLARE_EXTENSION_FUNCTION("downloads.resume", DOWNLOADS_RESUME) 137 DownloadsResumeFunction(); 138 ResponseAction Run() override; 139 140 protected: 141 ~DownloadsResumeFunction() override; 142 143 private: 144 DISALLOW_COPY_AND_ASSIGN(DownloadsResumeFunction); 145 }; 146 147 class DownloadsCancelFunction : public ExtensionFunction { 148 public: 149 DECLARE_EXTENSION_FUNCTION("downloads.cancel", DOWNLOADS_CANCEL) 150 DownloadsCancelFunction(); 151 ResponseAction Run() override; 152 153 protected: 154 ~DownloadsCancelFunction() override; 155 156 private: 157 DISALLOW_COPY_AND_ASSIGN(DownloadsCancelFunction); 158 }; 159 160 class DownloadsEraseFunction : public ExtensionFunction { 161 public: 162 DECLARE_EXTENSION_FUNCTION("downloads.erase", DOWNLOADS_ERASE) 163 DownloadsEraseFunction(); 164 ResponseAction Run() override; 165 166 protected: 167 ~DownloadsEraseFunction() override; 168 169 private: 170 DISALLOW_COPY_AND_ASSIGN(DownloadsEraseFunction); 171 }; 172 173 class DownloadsRemoveFileFunction : public ExtensionFunction { 174 public: 175 DECLARE_EXTENSION_FUNCTION("downloads.removeFile", DOWNLOADS_REMOVEFILE) 176 DownloadsRemoveFileFunction(); 177 ResponseAction Run() override; 178 179 protected: 180 ~DownloadsRemoveFileFunction() override; 181 182 private: 183 void Done(bool success); 184 185 DISALLOW_COPY_AND_ASSIGN(DownloadsRemoveFileFunction); 186 }; 187 188 class DownloadsAcceptDangerFunction : public ExtensionFunction { 189 public: 190 typedef base::Callback<void(DownloadDangerPrompt*)> OnPromptCreatedCallback; OnPromptCreatedForTesting(OnPromptCreatedCallback * callback)191 static void OnPromptCreatedForTesting( 192 OnPromptCreatedCallback* callback) { 193 on_prompt_created_ = callback; 194 } 195 196 DECLARE_EXTENSION_FUNCTION("downloads.acceptDanger", DOWNLOADS_ACCEPTDANGER) 197 DownloadsAcceptDangerFunction(); 198 ResponseAction Run() override; 199 200 protected: 201 ~DownloadsAcceptDangerFunction() override; 202 void DangerPromptCallback(int download_id, 203 DownloadDangerPrompt::Action action); 204 205 private: 206 void PromptOrWait(int download_id, int retries); 207 208 static OnPromptCreatedCallback* on_prompt_created_; 209 DISALLOW_COPY_AND_ASSIGN(DownloadsAcceptDangerFunction); 210 }; 211 212 class DownloadsShowFunction : public ExtensionFunction { 213 public: 214 DECLARE_EXTENSION_FUNCTION("downloads.show", DOWNLOADS_SHOW) 215 DownloadsShowFunction(); 216 ResponseAction Run() override; 217 218 protected: 219 ~DownloadsShowFunction() override; 220 221 private: 222 DISALLOW_COPY_AND_ASSIGN(DownloadsShowFunction); 223 }; 224 225 class DownloadsShowDefaultFolderFunction : public ExtensionFunction { 226 public: 227 DECLARE_EXTENSION_FUNCTION( 228 "downloads.showDefaultFolder", DOWNLOADS_SHOWDEFAULTFOLDER) 229 DownloadsShowDefaultFolderFunction(); 230 ResponseAction Run() override; 231 232 protected: 233 ~DownloadsShowDefaultFolderFunction() override; 234 235 private: 236 DISALLOW_COPY_AND_ASSIGN(DownloadsShowDefaultFolderFunction); 237 }; 238 239 class DownloadsOpenFunction : public ExtensionFunction { 240 public: 241 DECLARE_EXTENSION_FUNCTION("downloads.open", DOWNLOADS_OPEN) 242 DownloadsOpenFunction(); 243 ResponseAction Run() override; 244 245 typedef base::OnceCallback<void(DownloadOpenPrompt*)> OnPromptCreatedCallback; set_on_prompt_created_cb_for_testing(OnPromptCreatedCallback * on_prompt_created_cb)246 static void set_on_prompt_created_cb_for_testing( 247 OnPromptCreatedCallback* on_prompt_created_cb) { 248 on_prompt_created_cb_ = on_prompt_created_cb; 249 } 250 251 protected: 252 ~DownloadsOpenFunction() override; 253 254 private: 255 void OpenPromptDone(int download_id, bool accept); 256 257 static OnPromptCreatedCallback* on_prompt_created_cb_; 258 259 DISALLOW_COPY_AND_ASSIGN(DownloadsOpenFunction); 260 }; 261 262 class DownloadsSetShelfEnabledFunction : public ExtensionFunction { 263 public: 264 DECLARE_EXTENSION_FUNCTION("downloads.setShelfEnabled", 265 DOWNLOADS_SETSHELFENABLED) 266 DownloadsSetShelfEnabledFunction(); 267 ResponseAction Run() override; 268 269 protected: 270 ~DownloadsSetShelfEnabledFunction() override; 271 272 private: 273 DISALLOW_COPY_AND_ASSIGN(DownloadsSetShelfEnabledFunction); 274 }; 275 276 class DownloadsGetFileIconFunction : public ExtensionFunction { 277 public: 278 DECLARE_EXTENSION_FUNCTION("downloads.getFileIcon", DOWNLOADS_GETFILEICON) 279 DownloadsGetFileIconFunction(); 280 ResponseAction Run() override; 281 void SetIconExtractorForTesting(DownloadFileIconExtractor* extractor); 282 283 protected: 284 ~DownloadsGetFileIconFunction() override; 285 286 private: 287 void OnIconURLExtracted(const std::string& url); 288 base::FilePath path_; 289 std::unique_ptr<DownloadFileIconExtractor> icon_extractor_; 290 DISALLOW_COPY_AND_ASSIGN(DownloadsGetFileIconFunction); 291 }; 292 293 // Observes a single DownloadManager and many DownloadItems and dispatches 294 // onCreated and onErased events. 295 class ExtensionDownloadsEventRouter 296 : public extensions::EventRouter::Observer, 297 public extensions::ExtensionRegistryObserver, 298 public download::AllDownloadItemNotifier::Observer { 299 public: 300 typedef base::Callback<void( 301 const base::FilePath& changed_filename, 302 download::DownloadPathReservationTracker::FilenameConflictAction)> 303 FilenameChangedCallback; 304 305 static void SetDetermineFilenameTimeoutSecondsForTesting(int s); 306 307 // The logic for how to handle conflicting filename suggestions from multiple 308 // extensions is split out here for testing. 309 static void DetermineFilenameInternal( 310 const base::FilePath& filename, 311 extensions::api::downloads::FilenameConflictAction conflict_action, 312 const std::string& suggesting_extension_id, 313 const base::Time& suggesting_install_time, 314 const std::string& incumbent_extension_id, 315 const base::Time& incumbent_install_time, 316 std::string* winner_extension_id, 317 base::FilePath* determined_filename, 318 extensions::api::downloads::FilenameConflictAction* 319 determined_conflict_action, 320 extensions::WarningSet* warnings); 321 322 // A downloads.onDeterminingFilename listener has returned. If the extension 323 // wishes to override the download's filename, then |filename| will be 324 // non-empty. |filename| will be interpreted as a relative path, appended to 325 // the default downloads directory. If the extension wishes to overwrite any 326 // existing files, then |overwrite| will be true. Returns true on success, 327 // false otherwise. 328 static bool DetermineFilename( 329 content::BrowserContext* browser_context, 330 bool include_incognito, 331 const std::string& ext_id, 332 int download_id, 333 const base::FilePath& filename, 334 extensions::api::downloads::FilenameConflictAction conflict_action, 335 std::string* error); 336 337 explicit ExtensionDownloadsEventRouter( 338 Profile* profile, content::DownloadManager* manager); 339 ~ExtensionDownloadsEventRouter() override; 340 341 void SetShelfEnabled(const extensions::Extension* extension, bool enabled); 342 bool IsShelfEnabled() const; 343 344 // Called by ChromeDownloadManagerDelegate during the filename determination 345 // process, allows extensions to change the item's target filename. If no 346 // extension wants to change the target filename, then |no_change| will be 347 // called and the filename determination process will continue as normal. If 348 // an extension wants to change the target filename, then |change| will be 349 // called with the new filename and a flag indicating whether the new file 350 // should overwrite any old files of the same name. 351 void OnDeterminingFilename(download::DownloadItem* item, 352 const base::FilePath& suggested_path, 353 const base::Closure& no_change, 354 const FilenameChangedCallback& change); 355 356 // AllDownloadItemNotifier::Observer. 357 void OnDownloadCreated(content::DownloadManager* manager, 358 download::DownloadItem* download_item) override; 359 void OnDownloadUpdated(content::DownloadManager* manager, 360 download::DownloadItem* download_item) override; 361 void OnDownloadRemoved(content::DownloadManager* manager, 362 download::DownloadItem* download_item) override; 363 364 // extensions::EventRouter::Observer. 365 void OnListenerRemoved(const extensions::EventListenerInfo& details) override; 366 367 // Used for testing. 368 struct DownloadsNotificationSource { 369 std::string event_name; 370 Profile* profile; 371 }; 372 373 void CheckForHistoryFilesRemoval(); 374 375 private: 376 void DispatchEvent(events::HistogramValue histogram_value, 377 const std::string& event_name, 378 bool include_incognito, 379 Event::WillDispatchCallback will_dispatch_callback, 380 std::unique_ptr<base::Value> json_arg); 381 382 // extensions::ExtensionRegistryObserver. 383 void OnExtensionUnloaded(content::BrowserContext* browser_context, 384 const extensions::Extension* extension, 385 extensions::UnloadedExtensionReason reason) override; 386 387 Profile* profile_; 388 download::AllDownloadItemNotifier notifier_; 389 std::set<const extensions::Extension*> shelf_disabling_extensions_; 390 391 base::Time last_checked_removal_; 392 393 // Listen to extension unloaded notifications. 394 ScopedObserver<extensions::ExtensionRegistry, 395 extensions::ExtensionRegistryObserver> 396 extension_registry_observer_{this}; 397 398 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouter); 399 }; 400 401 } // namespace extensions 402 403 #endif // CHROME_BROWSER_EXTENSIONS_API_DOWNLOADS_DOWNLOADS_API_H_ 404