blob: cbae7650a487a1f79ead83bb2e803206ac6a7f26 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit09911bf2008-07-26 23:55:294//
5// The DownloadManager object manages the process of downloading, including
6// updates to the history system and providing the information for displaying
7// the downloads view in the Destinations tab. There is one DownloadManager per
8// active profile in Chrome.
9//
10// Each download is represented by a DownloadItem, and all DownloadItems
11// are owned by the DownloadManager which maintains a global list of all
12// downloads. DownloadItems are created when a user initiates a download,
13// and exist for the duration of the browser life time.
14//
15// Download observers:
16// Objects that are interested in notifications about new downloads, or progress
17// updates for a given download must implement one of the download observer
18// interfaces:
19// DownloadItem::Observer:
20// - allows observers to receive notifications about one download from start
21// to completion
22// DownloadManager::Observer:
23// - allows observers, primarily views, to be notified when changes to the
24// set of all downloads (such as new downloads, or deletes) occur
25// Use AddObserver() / RemoveObserver() on the appropriate download object to
26// receive state updates.
27//
28// Download state persistence:
29// The DownloadManager uses the history service for storing persistent
30// information about the state of all downloads. The history system maintains a
31// separate table for this called 'downloads'. At the point that the
32// DownloadManager is constructed, we query the history service for the state of
33// all persisted downloads.
34
[email protected]cdaa8652008-09-13 02:48:5935#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H__
36#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H__
initial.commit09911bf2008-07-26 23:55:2937
38#include <string>
initial.commit09911bf2008-07-26 23:55:2939#include <map>
40#include <set>
41#include <vector>
42
43#include "base/basictypes.h"
[email protected]23144032008-09-08 20:51:3044#include "base/hash_tables.h"
initial.commit09911bf2008-07-26 23:55:2945#include "base/observer_list.h"
46#include "base/ref_counted.h"
47#include "chrome/browser/cancelable_request.h"
48#include "chrome/browser/history/download_types.h"
49#include "chrome/browser/history/history.h"
50#include "chrome/browser/shell_dialogs.h"
51#include "chrome/common/pref_member.h"
initial.commit09911bf2008-07-26 23:55:2952
53class DownloadFileManager;
54class DownloadItem;
55class DownloadItemView;
56class DownloadManager;
[email protected]46072d42008-07-28 14:49:3557class GURL;
initial.commit09911bf2008-07-26 23:55:2958class MessageLoop;
59class PrefService;
60class Profile;
61class ResourceDispatcherHost;
initial.commit09911bf2008-07-26 23:55:2962class URLRequestContext;
63class WebContents;
64
[email protected]ab820df2008-08-26 05:55:1065namespace base {
66class Thread;
67}
initial.commit09911bf2008-07-26 23:55:2968
69// DownloadItem ----------------------------------------------------------------
70
71// One DownloadItem per download. This is the model class that stores all the
72// state for a download. Multiple views, such as a tab's download shelf and the
73// Destination tab's download view, may refer to a given DownloadItem.
74class DownloadItem {
75 public:
76 enum DownloadState {
77 IN_PROGRESS,
78 COMPLETE,
79 CANCELLED,
80 REMOVING
81 };
82
[email protected]9ccbb372008-10-10 18:50:3283 enum SafetyState {
84 SAFE = 0,
85 DANGEROUS,
86 DANGEROUS_BUT_VALIDATED // Dangerous but the user confirmed the download.
87 };
88
initial.commit09911bf2008-07-26 23:55:2989 // Interface that observers of a particular download must implement in order
90 // to receive updates to the download's status.
91 class Observer {
92 public:
93 virtual void OnDownloadUpdated(DownloadItem* download) = 0;
94 };
95
96 // Constructing from persistent store:
97 DownloadItem(const DownloadCreateInfo& info);
98
99 // Constructing from user action:
100 DownloadItem(int32 download_id,
101 const std::wstring& path,
[email protected]7a256ea2008-10-17 17:34:16102 int path_uniquifier,
initial.commit09911bf2008-07-26 23:55:29103 const std::wstring& url,
[email protected]9ccbb372008-10-10 18:50:32104 const std::wstring& original_name,
initial.commit09911bf2008-07-26 23:55:29105 const Time start_time,
106 int64 download_size,
107 int render_process_id,
[email protected]9ccbb372008-10-10 18:50:32108 int request_id,
109 bool is_dangerous);
initial.commit09911bf2008-07-26 23:55:29110
111 ~DownloadItem();
112
113 void Init(bool start_timer);
114
115 // Public API
116
117 void AddObserver(Observer* observer);
118 void RemoveObserver(Observer* observer);
119
120 // Notify our observers periodically
121 void UpdateObservers();
122
123 // Received a new chunk of data
124 void Update(int64 bytes_so_far);
125
126 // Cancel the download operation. We need to distinguish between cancels at
127 // exit (DownloadManager destructor) from user interface initiated cancels
128 // because at exit, the history system may not exist, and any updates to it
129 // require AddRef'ing the DownloadManager in the destructor which results in
130 // a DCHECK failure. Set 'update_history' to false when canceling from at
131 // exit to prevent this crash. This may result in a difference between the
132 // downloaded file's size on disk, and what the history system's last record
133 // of it is. At worst, we'll end up re-downloading a small portion of the file
134 // when resuming a download (assuming the server supports byte ranges).
135 void Cancel(bool update_history);
136
[email protected]9ccbb372008-10-10 18:50:32137 // Download operation completed.
initial.commit09911bf2008-07-26 23:55:29138 void Finished(int64 size);
139
[email protected]9ccbb372008-10-10 18:50:32140 // The user wants to remove the download from the views and history. If
141 // |delete_file| is true, the file is deleted on the disk.
142 void Remove(bool delete_file);
initial.commit09911bf2008-07-26 23:55:29143
144 // Start/stop sending periodic updates to our observers
145 void StartProgressTimer();
146 void StopProgressTimer();
147
148 // Simple calculation of the amount of time remaining to completion. Fills
149 // |*remaining| with the amount of time remaining if successful. Fails and
150 // returns false if we do not have the number of bytes or the speed so can
151 // not estimate.
152 bool TimeRemaining(TimeDelta* remaining) const;
153
154 // Simple speed estimate in bytes/s
155 int64 CurrentSpeed() const;
156
157 // Rough percent complete, -1 means we don't know (since we didn't receive a
158 // total size).
159 int PercentComplete() const;
160
161 // Update the download's path, the actual file is renamed on the download
162 // thread.
163 void Rename(const std::wstring& full_path);
164
165 // Allow the user to temporarily pause a download or resume a paused download.
166 void TogglePause();
167
168 // Accessors
169 DownloadState state() const { return state_; }
initial.commit09911bf2008-07-26 23:55:29170 std::wstring file_name() const { return file_name_; }
[email protected]9ccbb372008-10-10 18:50:32171 void set_file_name(const std::wstring& name) { file_name_ = name; }
172 std::wstring full_path() const { return full_path_; }
173 void set_full_path(const std::wstring& path) { full_path_ = path; }
[email protected]7a256ea2008-10-17 17:34:16174 int path_uniquifier() const { return path_uniquifier_; }
175 void set_path_uniquifier(int uniquifier) { path_uniquifier_ = uniquifier; }
initial.commit09911bf2008-07-26 23:55:29176 std::wstring url() const { return url_; }
177 int64 total_bytes() const { return total_bytes_; }
178 void set_total_bytes(int64 total_bytes) { total_bytes_ = total_bytes; }
179 int64 received_bytes() const { return received_bytes_; }
180 int32 id() const { return id_; }
181 Time start_time() const { return start_time_; }
182 void set_db_handle(int64 handle) { db_handle_ = handle; }
183 int64 db_handle() const { return db_handle_; }
184 DownloadManager* manager() const { return manager_; }
185 void set_manager(DownloadManager* manager) { manager_ = manager; }
186 bool is_paused() const { return is_paused_; }
187 void set_is_paused(bool pause) { is_paused_ = pause; }
188 bool open_when_complete() const { return open_when_complete_; }
189 void set_open_when_complete(bool open) { open_when_complete_ = open; }
190 int render_process_id() const { return render_process_id_; }
191 int request_id() const { return request_id_; }
[email protected]9ccbb372008-10-10 18:50:32192 SafetyState safety_state() const { return safety_state_; }
193 void set_safety_state(SafetyState safety_state) {
194 safety_state_ = safety_state;
195 }
196 std::wstring original_name() const { return original_name_; }
197 void set_original_name(const std::wstring& name) { original_name_ = name; }
198
199 // Returns the file-name that should be reported to the user, which is
[email protected]7a256ea2008-10-17 17:34:16200 // file_name_ for safe downloads and original_name_ for dangerous ones with
201 // the uniquifier number.
[email protected]9ccbb372008-10-10 18:50:32202 std::wstring GetFileName() const;
initial.commit09911bf2008-07-26 23:55:29203
204 private:
205 // Internal helper for maintaining consistent received and total sizes.
206 void UpdateSize(int64 size);
207
208 // Request ID assigned by the ResourceDispatcherHost.
209 int32 id_;
210
211 // Full path to the downloaded file
212 std::wstring full_path_;
213
[email protected]7a256ea2008-10-17 17:34:16214 // A number that should be appended to the path to make it unique, or 0 if the
215 // path should be used as is.
216 int path_uniquifier_;
217
initial.commit09911bf2008-07-26 23:55:29218 // Short display version of the file
219 std::wstring file_name_;
220
221 // The URL from whence we came, for display
222 std::wstring url_;
223
224 // Total bytes expected
225 int64 total_bytes_;
226
227 // Current received bytes
228 int64 received_bytes_;
229
230 // Start time for calculating remaining time
231 uintptr_t start_tick_;
232
233 // The current state of this download
234 DownloadState state_;
235
236 // The views of this item in the download shelf and download tab
237 ObserverList<Observer> observers_;
238
239 // Time the download was started
240 Time start_time_;
241
242 // Our persistent store handle
243 int64 db_handle_;
244
[email protected]2d316662008-09-03 18:18:14245 // Timer for regularly updating our observers
246 base::RepeatingTimer<DownloadItem> update_timer_;
initial.commit09911bf2008-07-26 23:55:29247
248 // Our owning object
249 DownloadManager* manager_;
250
251 // In progress downloads may be paused by the user, we note it here
252 bool is_paused_;
253
254 // A flag for indicating if the download should be opened at completion.
255 bool open_when_complete_;
256
[email protected]9ccbb372008-10-10 18:50:32257 // Whether the download is considered potentially safe or dangerous
258 // (executable files are typically considered dangerous).
259 SafetyState safety_state_;
260
261 // Dangerous download are given temporary names until the user approves them.
262 // This stores their original name.
263 std::wstring original_name_;
264
initial.commit09911bf2008-07-26 23:55:29265 // For canceling or pausing requests.
266 int render_process_id_;
267 int request_id_;
268
269 DISALLOW_EVIL_CONSTRUCTORS(DownloadItem);
270};
271
272
273// DownloadManager -------------------------------------------------------------
274
275// Browser's download manager: manages all downloads and destination view.
276class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>,
277 public SelectFileDialog::Listener {
278 // For testing.
279 friend class DownloadManagerTest;
280
281 public:
282 DownloadManager();
283 ~DownloadManager();
284
285 static void RegisterUserPrefs(PrefService* prefs);
286
287 // Interface to implement for observers that wish to be informed of changes
288 // to the DownloadManager's collection of downloads.
289 class Observer {
290 public:
291 // New or deleted download, observers should query us for the current set
292 // of downloads.
293 virtual void ModelChanged() = 0;
294
295 // A callback once the DownloadManager has retrieved the requested set of
296 // downloads. The DownloadManagerObserver must copy the vector, but does not
297 // own the individual DownloadItems, when this call is made.
298 virtual void SetDownloads(std::vector<DownloadItem*>& downloads) = 0;
299 };
300
301 // Public API
302
303 // Begin a search for all downloads matching 'search_text'. If 'search_text'
304 // is empty, return all known downloads. The results are returned in the
305 // 'SetDownloads' observer callback.
306 void GetDownloads(Observer* observer,
307 const std::wstring& search_text);
308
309 // Returns true if initialized properly.
310 bool Init(Profile* profile);
311
312 // Schedule a query of the history service to retrieve all downloads.
313 void QueryHistoryForDownloads();
314
315 // Notifications sent from the download thread to the UI thread
316 void StartDownload(DownloadCreateInfo* info);
317 void UpdateDownload(int32 download_id, int64 size);
318 void DownloadFinished(int32 download_id, int64 size);
319
320 // Helper method for cancelling the network request associated with a
321 // download.
322 static void CancelDownloadRequest(int render_process_id, int request_id);
323
324 // Called from a view when a user clicks a UI button or link.
325 void DownloadCancelled(int32 download_id);
326 void PauseDownload(int32 download_id, bool pause);
327 void RemoveDownload(int64 download_handle);
328
329 // Remove downloads after remove_begin (inclusive) and before remove_end
330 // (exclusive). You may pass in null Time values to do an unbounded delete
331 // in either direction.
332 int RemoveDownloadsBetween(const Time remove_begin, const Time remove_end);
333
334 // Remove downloads will delete all downloads that have a timestamp that is
335 // the same or more recent than |remove_begin|. The number of downloads
336 // deleted is returned back to the caller.
337 int RemoveDownloads(const Time remove_begin);
338
339 // Download the object at the URL. Used in cases such as "Save Link As..."
340 void DownloadUrl(const GURL& url,
341 const GURL& referrer,
342 WebContents* web_contents);
343
344 // Allow objects to observe the download creation process.
345 void AddObserver(Observer* observer);
346
347 // Remove a download observer from ourself.
348 void RemoveObserver(Observer* observer);
349
350 // Methods called on completion of a query sent to the history system.
351 void OnQueryDownloadEntriesComplete(
352 std::vector<DownloadCreateInfo>* entries);
353 void OnCreateDownloadEntryComplete(DownloadCreateInfo info, int64 db_handle);
354 void OnSearchComplete(HistoryService::Handle handle,
355 std::vector<int64>* results);
356
357 // Show or Open a download via the Windows shell.
358 void ShowDownloadInShell(const DownloadItem* download);
359 void OpenDownloadInShell(const DownloadItem* download, HWND parent_window);
360
361 // The number of in progress (including paused) downloads.
362 int in_progress_count() const {
363 return static_cast<int>(in_progress_.size());
364 }
365
366 std::wstring download_path() { return *download_path_; }
367
368 // Registers this file extension for automatic opening upon download
369 // completion if 'open' is true, or prevents the extension from automatic
370 // opening if 'open' is false.
371 void OpenFilesOfExtension(const std::wstring& extension, bool open);
372
373 // Tests if a file type should be opened automatically.
374 bool ShouldOpenFileExtension(const std::wstring& extension);
375
376 // Tests if we think the server means for this mime_type to be executable.
377 static bool IsExecutableMimeType(const std::string& mime_type);
378
379 // Tests if a file type is considered executable.
380 bool IsExecutable(const std::wstring& extension);
381
382 // Resets the automatic open preference.
383 void ResetAutoOpenFiles();
384
385 // Returns true if there are automatic handlers registered for any file
386 // types.
387 bool HasAutoOpenFileTypesRegistered() const;
388
389 // Overridden from SelectFileDialog::Listener:
390 virtual void FileSelected(const std::wstring& path, void* params);
391 virtual void FileSelectionCanceled(void* params);
392
[email protected]9ccbb372008-10-10 18:50:32393 // Deletes the specified path on the file thread.
394 void DeleteDownload(const std::wstring& path);
395
396 // Called when the user has validated the donwload of a dangerous file.
397 void DangerousDownloadValidated(DownloadItem* download);
398
initial.commit09911bf2008-07-26 23:55:29399 private:
400 // Shutdown the download manager. This call is needed only after Init.
401 void Shutdown();
402
403 // Called on the download thread to check whether the suggested file path
404 // exists. We don't check if the file exists on the UI thread to avoid UI
405 // stalls from interacting with the file system.
406 void CheckIfSuggestedPathExists(DownloadCreateInfo* info);
407
408 // Called on the UI thread once the DownloadManager has determined whether the
409 // suggested file path exists.
410 void OnPathExistenceAvailable(DownloadCreateInfo* info);
411
412 // Called back after a target path for the file to be downloaded to has been
413 // determined, either automatically based on the suggested file name, or by
414 // the user in a Save As dialog box.
415 void ContinueStartDownload(DownloadCreateInfo* info,
416 const std::wstring& target_path);
417
418 // Update the history service for a particular download.
419 void UpdateHistoryForDownload(DownloadItem* download);
420 void RemoveDownloadFromHistory(DownloadItem* download);
421 void RemoveDownloadsFromHistoryBetween(const Time remove_begin,
422 const Time remove_before);
423
424 // Inform the notification service of download starts and stops.
425 void NotifyAboutDownloadStart();
426 void NotifyAboutDownloadStop();
427
428 // Create an extension based on the file name and mime type.
429 void GenerateExtension(const std::wstring& file_name,
430 const std::string& mime_type,
431 std::wstring* generated_extension);
432
433 // Create a file name based on the response from the server.
434 void GenerateFilename(DownloadCreateInfo* info, std::wstring* generated_name);
435
436 // Persist the automatic opening preference.
437 void SaveAutoOpens();
438
439 // Runs the network cancel on the IO thread.
440 static void OnCancelDownloadRequest(ResourceDispatcherHost* rdh,
441 int render_process_id,
442 int request_id);
443
444 // Runs the pause on the IO thread.
445 static void OnPauseDownloadRequest(ResourceDispatcherHost* rdh,
446 int render_process_id,
447 int request_id,
448 bool pause);
449
[email protected]9ccbb372008-10-10 18:50:32450 // Performs the last steps required when a download has been completed.
451 // It is necessary to break down the flow when a download is finished as
452 // dangerous downloads are downloaded to temporary files that need to be
453 // renamed on the file thread first.
454 // Invoked on the UI thread.
455 void ContinueDownloadFinished(DownloadItem* download);
456
457 // Renames a finished dangerous download from its temporary file name to its
458 // real file name.
459 // Invoked on the file thread.
460 void ProceedWithFinishedDangerousDownload(int64 download_handle,
461 const std::wstring& path,
462 const std::wstring& original_name);
463
464 // Invoked on the UI thread when a dangerous downloaded file has been renamed.
465 void DangerousDownloadRenamed(int64 download_handle,
466 bool success,
[email protected]7a256ea2008-10-17 17:34:16467 const std::wstring& new_path,
468 int new_path_uniquifier);
[email protected]9ccbb372008-10-10 18:50:32469
470 // Checks whether a file represents a risk if downloaded.
471 bool IsDangerous(const std::wstring& file_name);
472
473 // Changes the paths and file name of the specified |download|, propagating
474 // the change to the history system.
475 void RenameDownload(DownloadItem* download, const std::wstring& new_path);
476
initial.commit09911bf2008-07-26 23:55:29477 // 'downloads_' is map of all downloads in this profile. The key is the handle
478 // returned by the history system, which is unique across sessions. This map
479 // owns all the DownloadItems once they have been created in the history
480 // system.
481 //
482 // 'in_progress_' is a map of all downloads that are in progress and that have
483 // not yet received a valid history handle. The key is the ID assigned by the
484 // ResourceDispatcherHost, which is unique for the current session. This map
485 // does not own the DownloadItems.
486 //
[email protected]9ccbb372008-10-10 18:50:32487 // 'dangerous_finished_' is a map of dangerous download that have finished
488 // but were not yet approved by the user. Similarly to in_progress_, the key
489 // is the ID assigned by the ResourceDispatcherHost and the map does not own
490 // the DownloadItems. It is used on shutdown to delete completed downloads
491 // that have not been approved.
492 //
initial.commit09911bf2008-07-26 23:55:29493 // When a download is created through a user action, the corresponding
494 // DownloadItem* is placed in 'in_progress_' and remains there until it has
495 // received a valid handle from the history system. Once it has a valid
496 // handle, the DownloadItem* is placed in the 'downloads_' map. When the
497 // download is complete, it is removed from 'in_progress_'. Downloads from
498 // past sessions read from a persisted state from the history system are
499 // placed directly into 'downloads_' since they have valid handles in the
500 // history system.
[email protected]23144032008-09-08 20:51:30501 typedef base::hash_map<int64, DownloadItem*> DownloadMap;
initial.commit09911bf2008-07-26 23:55:29502 DownloadMap downloads_;
503 DownloadMap in_progress_;
[email protected]9ccbb372008-10-10 18:50:32504 DownloadMap dangerous_finished_;
initial.commit09911bf2008-07-26 23:55:29505
506 // True if the download manager has been initialized and requires a shutdown.
507 bool shutdown_needed_;
508
509 // Observers that want to be notified of changes to the set of downloads.
510 ObserverList<Observer> observers_;
511
512 // The current active profile.
513 Profile* profile_;
514 scoped_refptr<URLRequestContext> request_context_;
515
516 // Used for history service request management.
517 CancelableRequestConsumerT<Observer*, 0> cancelable_consumer_;
518
519 // Non-owning pointer for handling file writing on the download_thread_.
520 DownloadFileManager* file_manager_;
521
522 // A pointer to the main UI loop.
523 MessageLoop* ui_loop_;
524
525 // A pointer to the file thread's loop. The file thread lives longer than
526 // the DownloadManager, so this is safe to cache.
527 MessageLoop* file_loop_;
528
529 // User preferences
530 BooleanPrefMember prompt_for_download_;
531 StringPrefMember download_path_;
532
533 // The user's last choice for download directory. This is only used when the
534 // user wants us to prompt for a save location for each download.
535 std::wstring last_download_path_;
536
537 // Set of file extensions to open at download completion.
538 std::set<std::wstring> auto_open_;
539
540 // Set of file extensions that are executables and shouldn't be auto opened.
541 std::set<std::wstring> exe_types_;
542
543 // Keep track of downloads that are completed before the user selects the
544 // destination, so that observers are appropriately notified of completion
545 // after this determination is made.
546 // The map is of download_id->remaining size (bytes), both of which are
547 // required when calling DownloadFinished.
548 typedef std::map<int32, int64> PendingFinishedMap;
549 PendingFinishedMap pending_finished_downloads_;
550
551 // The "Save As" dialog box used to ask the user where a file should be
552 // saved.
553 scoped_refptr<SelectFileDialog> select_file_dialog_;
554
555 DISALLOW_EVIL_CONSTRUCTORS(DownloadManager);
556};
557
558
[email protected]cdaa8652008-09-13 02:48:59559#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H__