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