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 23class DownloadFileIconExtractor; 24class DownloadQuery; 25 26namespace content { 27class ResourceContext; 28class ResourceDispatcherHost; 29} 30 31namespace extensions { 32class 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 39namespace download_extension_errors { 40 41// Errors that can be returned through chrome.runtime.lastError.message. 42extern const char kEmptyFile[]; 43extern const char kFileAlreadyDeleted[]; 44extern const char kFileNotRemoved[]; 45extern const char kIconNotFound[]; 46extern const char kInvalidDangerType[]; 47extern const char kInvalidFilename[]; 48extern const char kInvalidFilter[]; 49extern const char kInvalidHeaderName[]; 50extern const char kInvalidHeaderValue[]; 51extern const char kInvalidHeaderUnsafe[]; 52extern const char kInvalidId[]; 53extern const char kInvalidOrderBy[]; 54extern const char kInvalidQueryLimit[]; 55extern const char kInvalidState[]; 56extern const char kInvalidURL[]; 57extern const char kInvisibleContext[]; 58extern const char kNotComplete[]; 59extern const char kNotDangerous[]; 60extern const char kNotInProgress[]; 61extern const char kNotResumable[]; 62extern const char kOpenPermission[]; 63extern const char kShelfDisabled[]; 64extern const char kShelfPermission[]; 65extern const char kTooManyListeners[]; 66extern const char kUnexpectedDeterminer[]; 67extern const char kUserGesture[]; 68 69} // namespace download_extension_errors 70 71namespace extensions { 72 73class 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 81 const std::string& id() const { return id_; } 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 93class 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 112class 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 125class 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 138class 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 151class 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 164class 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 177class 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 192class DownloadsAcceptDangerFunction : public ChromeAsyncExtensionFunction { 193 public: 194 typedef base::Callback<void(DownloadDangerPrompt*)> OnPromptCreatedCallback; 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 216class 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 229class 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 243class 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 256class 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 270class 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 283class 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. 302class 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