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/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