a24433149e8f701ab7a56ec8f4c4fbb57d2e76a4
[platform/framework/web/crosswalk.git] / src / chrome / browser / download / download_target_determiner.h
1 // Copyright 2013 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_DOWNLOAD_DOWNLOAD_TARGET_DETERMINER_H_
6 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TARGET_DETERMINER_H_
7
8 #include "base/files/file_path.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/weak_ptr.h"
12 #include "chrome/browser/common/cancelable_request.h"
13 #include "chrome/browser/download/download_path_reservation_tracker.h"
14 #include "chrome/browser/download/download_target_determiner_delegate.h"
15 #include "chrome/browser/download/download_target_info.h"
16 #include "content/public/browser/download_danger_type.h"
17 #include "content/public/browser/download_item.h"
18 #include "content/public/browser/download_manager_delegate.h"
19
20 class ChromeDownloadManagerDelegate;
21 class Profile;
22 class DownloadPrefs;
23
24 namespace content {
25 enum DownloadDangerType;
26 }
27
28 // Determines the target of the download.
29 //
30 // Terminology:
31 //   Virtual Path: A path representing the target of the download that may or
32 //     may not be a physical file path. E.g. if the target of the download is in
33 //     cloud storage, then the virtual path may be relative to a logical mount
34 //     point.
35 //
36 //   Local Path: A local file system path where the downloads system should
37 //     write the file to.
38 //
39 //   Intermediate Path: Where the data should be written to during the course of
40 //     the download. Once the download completes, the file could be renamed to
41 //     Local Path.
42 //
43 // DownloadTargetDeterminer is a self owned object that performs the work of
44 // determining the download target. It observes the DownloadItem and aborts the
45 // process if the download is removed. DownloadTargetDeterminerDelegate is
46 // responsible for providing external dependencies and prompting the user if
47 // necessary.
48 //
49 // The only public entrypoint is the static Start() method which creates an
50 // instance of DownloadTargetDeterminer.
51 class DownloadTargetDeterminer
52     : public content::DownloadItem::Observer {
53  public:
54   typedef base::Callback<void(scoped_ptr<DownloadTargetInfo>)>
55       CompletionCallback;
56
57   // Start the process of determing the target of |download|.
58   //
59   // |initial_virtual_path| if non-empty, defines the initial virtual path for
60   //   the target determination process. If one isn't specified, one will be
61   //   generated based on the response data specified in |download| and the
62   //   users' downloads directory.
63   //   Note: |initial_virtual_path| is only used if download has prompted the
64   //       user before and doesn't have a forced path.
65   // |download_prefs| is required and must outlive |download|. It is used for
66   //   determining the user's preferences regarding the default downloads
67   //   directory, prompting and auto-open behavior.
68   // |delegate| is required and must live until |callback| is invoked.
69   // |callback| will be scheduled asynchronously on the UI thread after download
70   //   determination is complete or after |download| is destroyed.
71   //
72   // Start() should be called on the UI thread.
73   static void Start(content::DownloadItem* download,
74                     const base::FilePath& initial_virtual_path,
75                     DownloadPrefs* download_prefs,
76                     DownloadTargetDeterminerDelegate* delegate,
77                     const CompletionCallback& callback);
78
79   // Returns a .crdownload intermediate path for the |suggested_path|.
80   static base::FilePath GetCrDownloadPath(const base::FilePath& suggested_path);
81
82  private:
83   // The main workflow is controlled via a set of state transitions. Each state
84   // has an associated handler. The handler for STATE_FOO is DoFoo. Each handler
85   // performs work, determines the next state to transition to and returns a
86   // Result indicating how the workflow should proceed. The loop ends when a
87   // handler returns COMPLETE.
88   enum State {
89     STATE_GENERATE_TARGET_PATH,
90     STATE_NOTIFY_EXTENSIONS,
91     STATE_RESERVE_VIRTUAL_PATH,
92     STATE_PROMPT_USER_FOR_DOWNLOAD_PATH,
93     STATE_DETERMINE_LOCAL_PATH,
94     STATE_DETERMINE_MIME_TYPE,
95     STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER,
96     STATE_CHECK_DOWNLOAD_URL,
97     STATE_CHECK_VISITED_REFERRER_BEFORE,
98     STATE_DETERMINE_INTERMEDIATE_PATH,
99     STATE_NONE,
100   };
101
102   // Result code returned by each step of the workflow below. Controls execution
103   // of DoLoop().
104   enum Result {
105     // Continue processing. next_state_ is required to not be STATE_NONE.
106     CONTINUE,
107
108     // The DoLoop() that invoked the handler should exit. This value is
109     // typically returned when the handler has invoked an asynchronous operation
110     // and is expecting a callback. If a handler returns this value, it has
111     // taken responsibility for ensuring that DoLoop() is invoked. It is
112     // possible that the handler has invoked another DoLoop() already.
113     QUIT_DOLOOP,
114
115     // Target determination is complete.
116     COMPLETE
117   };
118
119   // Used with IsDangerousFile to indicate whether the user has visited the
120   // referrer URL for the download prior to today.
121   enum PriorVisitsToReferrer {
122     NO_VISITS_TO_REFERRER,
123     VISITED_REFERRER,
124   };
125
126   // Construct a DownloadTargetDeterminer object. Constraints on the arguments
127   // are as per Start() above.
128   DownloadTargetDeterminer(content::DownloadItem* download,
129                            const base::FilePath& initial_virtual_path,
130                            DownloadPrefs* download_prefs,
131                            DownloadTargetDeterminerDelegate* delegate,
132                            const CompletionCallback& callback);
133
134   virtual ~DownloadTargetDeterminer();
135
136   // Invoke each successive handler until a handler returns QUIT_DOLOOP or
137   // COMPLETE. Note that as a result, this object might be deleted. So |this|
138   // should not be accessed after calling DoLoop().
139   void DoLoop();
140
141   // === Main workflow ===
142
143   // Generates an initial target path. This target is based only on the state of
144   // the download item.
145   // Next state:
146   // - STATE_NONE : If the download is not in progress, returns COMPLETE.
147   // - STATE_NOTIFY_EXTENSIONS : All other downloads.
148   Result DoGenerateTargetPath();
149
150   // Notifies downloads extensions. If any extension wishes to override the
151   // download filename, it will respond to the OnDeterminingFilename()
152   // notification.
153   // Next state:
154   // - STATE_RESERVE_VIRTUAL_PATH.
155   Result DoNotifyExtensions();
156
157   // Callback invoked after extensions are notified. Updates |virtual_path_| and
158   // |conflict_action_|.
159   void NotifyExtensionsDone(
160       const base::FilePath& new_path,
161       DownloadPathReservationTracker::FilenameConflictAction conflict_action);
162
163   // Invokes ReserveVirtualPath() on the delegate to acquire a reservation for
164   // the path. See DownloadPathReservationTracker.
165   // Next state:
166   // - STATE_PROMPT_USER_FOR_DOWNLOAD_PATH.
167   Result DoReserveVirtualPath();
168
169   // Callback invoked after the delegate aquires a path reservation.
170   void ReserveVirtualPathDone(const base::FilePath& path, bool verified);
171
172   // Presents a file picker to the user if necessary.
173   // Next state:
174   // - STATE_DETERMINE_LOCAL_PATH.
175   Result DoPromptUserForDownloadPath();
176
177   // Callback invoked after the file picker completes. Cancels the download if
178   // the user cancels the file picker.
179   void PromptUserForDownloadPathDone(const base::FilePath& virtual_path);
180
181   // Up until this point, the path that was used is considered to be a virtual
182   // path. This step determines the local file system path corresponding to this
183   // virtual path. The translation is done by invoking the DetermineLocalPath()
184   // method on the delegate.
185   // Next state:
186   // - STATE_DETERMINE_MIME_TYPE.
187   Result DoDetermineLocalPath();
188
189   // Callback invoked when the delegate has determined local path.
190   void DetermineLocalPathDone(const base::FilePath& local_path);
191
192   // Determine the MIME type corresponding to the local file path. This is only
193   // done if the local path and the virtual path was the same. I.e. The file is
194   // intended for the local file system. This restriction is there because the
195   // resulting MIME type is only valid for determining whether the browser can
196   // handle the download if it were opened via a file:// URL.
197   // Next state:
198   // - STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER.
199   Result DoDetermineMimeType();
200
201   // Callback invoked when the MIME type is available. Since determination of
202   // the MIME type can involve disk access, it is done in the blocking pool.
203   void DetermineMimeTypeDone(const std::string& mime_type);
204
205   // Determine if the file type can be handled safely by the browser if it were
206   // to be opened via a file:// URL.
207   // Next state:
208   // - STATE_CHECK_DOWNLOAD_URL.
209   Result DoDetermineIfHandledSafely();
210
211   // Callback invoked when a decision is available about whether the file type
212   // can be handled safely by the browser.
213   void DetermineIfHandledSafelyDone(bool is_handled_safely);
214
215   // Checks whether the downloaded URL is malicious. Invokes the
216   // DownloadProtectionService via the delegate.
217   // Next state:
218   // - STATE_CHECK_VISITED_REFERRER_BEFORE.
219   Result DoCheckDownloadUrl();
220
221   // Callback invoked after the delegate has checked the download URL. Sets the
222   // danger type of the download to |danger_type|.
223   void CheckDownloadUrlDone(content::DownloadDangerType danger_type);
224
225   // Checks if the user has visited the referrer URL of the download prior to
226   // today. The actual check is only performed if it would be needed to
227   // determine the danger type of the download.
228   // Next state:
229   // - STATE_DETERMINE_INTERMEDIATE_PATH.
230   Result DoCheckVisitedReferrerBefore();
231
232   // Callback invoked after completion of history check for prior visits to
233   // referrer URL.
234   void CheckVisitedReferrerBeforeDone(bool visited_referrer_before);
235
236   // Determines the intermediate path. Once this step completes, downloads
237   // target determination is complete. The determination assumes that the
238   // intermediate file will never be overwritten (always uniquified if needed).
239   // Next state:
240   // - STATE_NONE: Returns COMPLETE.
241   Result DoDetermineIntermediatePath();
242
243   // === End of main workflow ===
244
245   // Utilities:
246
247   void ScheduleCallbackAndDeleteSelf();
248
249   void CancelOnFailureAndDeleteSelf();
250
251   Profile* GetProfile();
252
253   // Determine whether to prompt the user for the download location. For regular
254   // downloads, this determination is based on the target disposition, auto-open
255   // behavior, among other factors. For an interrupted download, this
256   // determination will be based on the interrupt reason. It is assumed that
257   // download interruptions always occur after the first round of download
258   // target determination is complete.
259   bool ShouldPromptForDownload(const base::FilePath& filename) const;
260
261   // Returns true if the user has been prompted for this download at least once
262   // prior to this target determination operation. This method is only expected
263   // to return true for a resuming interrupted download that has prompted the
264   // user before interruption. The return value does not depend on whether the
265   // user will be or has been prompted during the current target determination
266   // operation.
267   bool HasPromptedForPath() const;
268
269   // Returns true if this download should show the "dangerous file" warning.
270   // Various factors are considered, such as the type of the file, whether a
271   // user action initiated the download, and whether the user has explicitly
272   // marked the file type as "auto open". Protected virtual for testing.
273   bool IsDangerousFile(PriorVisitsToReferrer visits);
274
275   // content::DownloadItem::Observer
276   virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE;
277
278   // state
279   State next_state_;
280   bool should_prompt_;
281   bool should_notify_extensions_;
282   bool create_target_directory_;
283   DownloadPathReservationTracker::FilenameConflictAction conflict_action_;
284   content::DownloadDangerType danger_type_;
285   base::FilePath virtual_path_;
286   base::FilePath local_path_;
287   base::FilePath intermediate_path_;
288   std::string mime_type_;
289   bool is_filetype_handled_safely_;
290
291   content::DownloadItem* download_;
292   const bool is_resumption_;
293   DownloadPrefs* download_prefs_;
294   DownloadTargetDeterminerDelegate* delegate_;
295   CompletionCallback completion_callback_;
296   CancelableRequestConsumer history_consumer_;
297
298   base::WeakPtrFactory<DownloadTargetDeterminer> weak_ptr_factory_;
299
300   DISALLOW_COPY_AND_ASSIGN(DownloadTargetDeterminer);
301 };
302
303 #endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TARGET_DETERMINER_H_