• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
id()81   const std::string& id() const { return id_; }
name()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;
OnPromptCreatedForTesting(OnPromptCreatedCallback * callback)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