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