• 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/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 
id()79   const std::string& id() const { return id_; }
name()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;
OnPromptCreatedForTesting(OnPromptCreatedCallback * callback)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