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/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 
     79   const std::string& id() const { return id_; }
     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;
    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