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