Home | History | Annotate | Download | only in downloads
      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 
     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 
     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;
    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