| OLD | NEW |
| (Empty) |
| 1 // 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. | |
| 4 // | |
| 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 | |
| 35 #ifndef CHROME_BROWSER_DOWNLOAD_MANAGER_H__ | |
| 36 #define CHROME_BROWSER_DOWNLOAD_MANAGER_H__ | |
| 37 | |
| 38 #include <string> | |
| 39 #include <map> | |
| 40 #include <set> | |
| 41 #include <vector> | |
| 42 | |
| 43 #include "base/basictypes.h" | |
| 44 #include "base/hash_tables.h" | |
| 45 #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" | |
| 52 | |
| 53 class DownloadFileManager; | |
| 54 class DownloadItem; | |
| 55 class DownloadItemView; | |
| 56 class DownloadManager; | |
| 57 class GURL; | |
| 58 class MessageLoop; | |
| 59 class PrefService; | |
| 60 class Profile; | |
| 61 class ResourceDispatcherHost; | |
| 62 class URLRequestContext; | |
| 63 class WebContents; | |
| 64 | |
| 65 namespace base { | |
| 66 class Thread; | |
| 67 } | |
| 68 | |
| 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. | |
| 74 class DownloadItem { | |
| 75 public: | |
| 76 enum DownloadState { | |
| 77 IN_PROGRESS, | |
| 78 COMPLETE, | |
| 79 CANCELLED, | |
| 80 REMOVING | |
| 81 }; | |
| 82 | |
| 83 // Interface that observers of a particular download must implement in order | |
| 84 // to receive updates to the download's status. | |
| 85 class Observer { | |
| 86 public: | |
| 87 virtual void OnDownloadUpdated(DownloadItem* download) = 0; | |
| 88 }; | |
| 89 | |
| 90 // Constructing from persistent store: | |
| 91 DownloadItem(const DownloadCreateInfo& info); | |
| 92 | |
| 93 // Constructing from user action: | |
| 94 DownloadItem(int32 download_id, | |
| 95 const std::wstring& path, | |
| 96 const std::wstring& url, | |
| 97 const Time start_time, | |
| 98 int64 download_size, | |
| 99 int render_process_id, | |
| 100 int request_id); | |
| 101 | |
| 102 ~DownloadItem(); | |
| 103 | |
| 104 void Init(bool start_timer); | |
| 105 | |
| 106 // Public API | |
| 107 | |
| 108 void AddObserver(Observer* observer); | |
| 109 void RemoveObserver(Observer* observer); | |
| 110 | |
| 111 // Notify our observers periodically | |
| 112 void UpdateObservers(); | |
| 113 | |
| 114 // Received a new chunk of data | |
| 115 void Update(int64 bytes_so_far); | |
| 116 | |
| 117 // Cancel the download operation. We need to distinguish between cancels at | |
| 118 // exit (DownloadManager destructor) from user interface initiated cancels | |
| 119 // because at exit, the history system may not exist, and any updates to it | |
| 120 // require AddRef'ing the DownloadManager in the destructor which results in | |
| 121 // a DCHECK failure. Set 'update_history' to false when canceling from at | |
| 122 // exit to prevent this crash. This may result in a difference between the | |
| 123 // downloaded file's size on disk, and what the history system's last record | |
| 124 // of it is. At worst, we'll end up re-downloading a small portion of the file | |
| 125 // when resuming a download (assuming the server supports byte ranges). | |
| 126 void Cancel(bool update_history); | |
| 127 | |
| 128 // Download operation completed | |
| 129 void Finished(int64 size); | |
| 130 | |
| 131 // The user wants to remove the download from the views and history. This | |
| 132 // operation does not delete the file on the disk. | |
| 133 void Remove(); | |
| 134 | |
| 135 // Start/stop sending periodic updates to our observers | |
| 136 void StartProgressTimer(); | |
| 137 void StopProgressTimer(); | |
| 138 | |
| 139 // Simple calculation of the amount of time remaining to completion. Fills | |
| 140 // |*remaining| with the amount of time remaining if successful. Fails and | |
| 141 // returns false if we do not have the number of bytes or the speed so can | |
| 142 // not estimate. | |
| 143 bool TimeRemaining(TimeDelta* remaining) const; | |
| 144 | |
| 145 // Simple speed estimate in bytes/s | |
| 146 int64 CurrentSpeed() const; | |
| 147 | |
| 148 // Rough percent complete, -1 means we don't know (since we didn't receive a | |
| 149 // total size). | |
| 150 int PercentComplete() const; | |
| 151 | |
| 152 // Update the download's path, the actual file is renamed on the download | |
| 153 // thread. | |
| 154 void Rename(const std::wstring& full_path); | |
| 155 | |
| 156 // Allow the user to temporarily pause a download or resume a paused download. | |
| 157 void TogglePause(); | |
| 158 | |
| 159 // Accessors | |
| 160 DownloadState state() const { return state_; } | |
| 161 std::wstring full_path() const { return full_path_; } | |
| 162 std::wstring file_name() const { return file_name_; } | |
| 163 std::wstring url() const { return url_; } | |
| 164 int64 total_bytes() const { return total_bytes_; } | |
| 165 void set_total_bytes(int64 total_bytes) { total_bytes_ = total_bytes; } | |
| 166 int64 received_bytes() const { return received_bytes_; } | |
| 167 int32 id() const { return id_; } | |
| 168 Time start_time() const { return start_time_; } | |
| 169 void set_db_handle(int64 handle) { db_handle_ = handle; } | |
| 170 int64 db_handle() const { return db_handle_; } | |
| 171 DownloadManager* manager() const { return manager_; } | |
| 172 void set_manager(DownloadManager* manager) { manager_ = manager; } | |
| 173 bool is_paused() const { return is_paused_; } | |
| 174 void set_is_paused(bool pause) { is_paused_ = pause; } | |
| 175 bool open_when_complete() const { return open_when_complete_; } | |
| 176 void set_open_when_complete(bool open) { open_when_complete_ = open; } | |
| 177 int render_process_id() const { return render_process_id_; } | |
| 178 int request_id() const { return request_id_; } | |
| 179 | |
| 180 private: | |
| 181 // Internal helper for maintaining consistent received and total sizes. | |
| 182 void UpdateSize(int64 size); | |
| 183 | |
| 184 // Request ID assigned by the ResourceDispatcherHost. | |
| 185 int32 id_; | |
| 186 | |
| 187 // Full path to the downloaded file | |
| 188 std::wstring full_path_; | |
| 189 | |
| 190 // Short display version of the file | |
| 191 std::wstring file_name_; | |
| 192 | |
| 193 // The URL from whence we came, for display | |
| 194 std::wstring url_; | |
| 195 | |
| 196 // Total bytes expected | |
| 197 int64 total_bytes_; | |
| 198 | |
| 199 // Current received bytes | |
| 200 int64 received_bytes_; | |
| 201 | |
| 202 // Start time for calculating remaining time | |
| 203 uintptr_t start_tick_; | |
| 204 | |
| 205 // The current state of this download | |
| 206 DownloadState state_; | |
| 207 | |
| 208 // The views of this item in the download shelf and download tab | |
| 209 ObserverList<Observer> observers_; | |
| 210 | |
| 211 // Time the download was started | |
| 212 Time start_time_; | |
| 213 | |
| 214 // Our persistent store handle | |
| 215 int64 db_handle_; | |
| 216 | |
| 217 // Timer for regularly updating our observers | |
| 218 base::RepeatingTimer<DownloadItem> update_timer_; | |
| 219 | |
| 220 // Our owning object | |
| 221 DownloadManager* manager_; | |
| 222 | |
| 223 // In progress downloads may be paused by the user, we note it here | |
| 224 bool is_paused_; | |
| 225 | |
| 226 // A flag for indicating if the download should be opened at completion. | |
| 227 bool open_when_complete_; | |
| 228 | |
| 229 // For canceling or pausing requests. | |
| 230 int render_process_id_; | |
| 231 int request_id_; | |
| 232 | |
| 233 DISALLOW_EVIL_CONSTRUCTORS(DownloadItem); | |
| 234 }; | |
| 235 | |
| 236 | |
| 237 // DownloadManager ------------------------------------------------------------- | |
| 238 | |
| 239 // Browser's download manager: manages all downloads and destination view. | |
| 240 class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, | |
| 241 public SelectFileDialog::Listener { | |
| 242 // For testing. | |
| 243 friend class DownloadManagerTest; | |
| 244 | |
| 245 public: | |
| 246 DownloadManager(); | |
| 247 ~DownloadManager(); | |
| 248 | |
| 249 static void RegisterUserPrefs(PrefService* prefs); | |
| 250 | |
| 251 // Interface to implement for observers that wish to be informed of changes | |
| 252 // to the DownloadManager's collection of downloads. | |
| 253 class Observer { | |
| 254 public: | |
| 255 // New or deleted download, observers should query us for the current set | |
| 256 // of downloads. | |
| 257 virtual void ModelChanged() = 0; | |
| 258 | |
| 259 // A callback once the DownloadManager has retrieved the requested set of | |
| 260 // downloads. The DownloadManagerObserver must copy the vector, but does not | |
| 261 // own the individual DownloadItems, when this call is made. | |
| 262 virtual void SetDownloads(std::vector<DownloadItem*>& downloads) = 0; | |
| 263 }; | |
| 264 | |
| 265 // Public API | |
| 266 | |
| 267 // Begin a search for all downloads matching 'search_text'. If 'search_text' | |
| 268 // is empty, return all known downloads. The results are returned in the | |
| 269 // 'SetDownloads' observer callback. | |
| 270 void GetDownloads(Observer* observer, | |
| 271 const std::wstring& search_text); | |
| 272 | |
| 273 // Returns true if initialized properly. | |
| 274 bool Init(Profile* profile); | |
| 275 | |
| 276 // Schedule a query of the history service to retrieve all downloads. | |
| 277 void QueryHistoryForDownloads(); | |
| 278 | |
| 279 // Notifications sent from the download thread to the UI thread | |
| 280 void StartDownload(DownloadCreateInfo* info); | |
| 281 void UpdateDownload(int32 download_id, int64 size); | |
| 282 void DownloadFinished(int32 download_id, int64 size); | |
| 283 | |
| 284 // Helper method for cancelling the network request associated with a | |
| 285 // download. | |
| 286 static void CancelDownloadRequest(int render_process_id, int request_id); | |
| 287 | |
| 288 // Called from a view when a user clicks a UI button or link. | |
| 289 void DownloadCancelled(int32 download_id); | |
| 290 void PauseDownload(int32 download_id, bool pause); | |
| 291 void RemoveDownload(int64 download_handle); | |
| 292 | |
| 293 // Remove downloads after remove_begin (inclusive) and before remove_end | |
| 294 // (exclusive). You may pass in null Time values to do an unbounded delete | |
| 295 // in either direction. | |
| 296 int RemoveDownloadsBetween(const Time remove_begin, const Time remove_end); | |
| 297 | |
| 298 // Remove downloads will delete all downloads that have a timestamp that is | |
| 299 // the same or more recent than |remove_begin|. The number of downloads | |
| 300 // deleted is returned back to the caller. | |
| 301 int RemoveDownloads(const Time remove_begin); | |
| 302 | |
| 303 // Download the object at the URL. Used in cases such as "Save Link As..." | |
| 304 void DownloadUrl(const GURL& url, | |
| 305 const GURL& referrer, | |
| 306 WebContents* web_contents); | |
| 307 | |
| 308 // Allow objects to observe the download creation process. | |
| 309 void AddObserver(Observer* observer); | |
| 310 | |
| 311 // Remove a download observer from ourself. | |
| 312 void RemoveObserver(Observer* observer); | |
| 313 | |
| 314 // Methods called on completion of a query sent to the history system. | |
| 315 void OnQueryDownloadEntriesComplete( | |
| 316 std::vector<DownloadCreateInfo>* entries); | |
| 317 void OnCreateDownloadEntryComplete(DownloadCreateInfo info, int64 db_handle); | |
| 318 void OnSearchComplete(HistoryService::Handle handle, | |
| 319 std::vector<int64>* results); | |
| 320 | |
| 321 // Show or Open a download via the Windows shell. | |
| 322 void ShowDownloadInShell(const DownloadItem* download); | |
| 323 void OpenDownloadInShell(const DownloadItem* download, HWND parent_window); | |
| 324 | |
| 325 // The number of in progress (including paused) downloads. | |
| 326 int in_progress_count() const { | |
| 327 return static_cast<int>(in_progress_.size()); | |
| 328 } | |
| 329 | |
| 330 std::wstring download_path() { return *download_path_; } | |
| 331 | |
| 332 // Registers this file extension for automatic opening upon download | |
| 333 // completion if 'open' is true, or prevents the extension from automatic | |
| 334 // opening if 'open' is false. | |
| 335 void OpenFilesOfExtension(const std::wstring& extension, bool open); | |
| 336 | |
| 337 // Tests if a file type should be opened automatically. | |
| 338 bool ShouldOpenFileExtension(const std::wstring& extension); | |
| 339 | |
| 340 // Tests if we think the server means for this mime_type to be executable. | |
| 341 static bool IsExecutableMimeType(const std::string& mime_type); | |
| 342 | |
| 343 // Tests if a file type is considered executable. | |
| 344 bool IsExecutable(const std::wstring& extension); | |
| 345 | |
| 346 // Resets the automatic open preference. | |
| 347 void ResetAutoOpenFiles(); | |
| 348 | |
| 349 // Returns true if there are automatic handlers registered for any file | |
| 350 // types. | |
| 351 bool HasAutoOpenFileTypesRegistered() const; | |
| 352 | |
| 353 // Overridden from SelectFileDialog::Listener: | |
| 354 virtual void FileSelected(const std::wstring& path, void* params); | |
| 355 virtual void FileSelectionCanceled(void* params); | |
| 356 | |
| 357 private: | |
| 358 // Shutdown the download manager. This call is needed only after Init. | |
| 359 void Shutdown(); | |
| 360 | |
| 361 // Called on the download thread to check whether the suggested file path | |
| 362 // exists. We don't check if the file exists on the UI thread to avoid UI | |
| 363 // stalls from interacting with the file system. | |
| 364 void CheckIfSuggestedPathExists(DownloadCreateInfo* info); | |
| 365 | |
| 366 // Called on the UI thread once the DownloadManager has determined whether the | |
| 367 // suggested file path exists. | |
| 368 void OnPathExistenceAvailable(DownloadCreateInfo* info); | |
| 369 | |
| 370 // Called back after a target path for the file to be downloaded to has been | |
| 371 // determined, either automatically based on the suggested file name, or by | |
| 372 // the user in a Save As dialog box. | |
| 373 void ContinueStartDownload(DownloadCreateInfo* info, | |
| 374 const std::wstring& target_path); | |
| 375 | |
| 376 // Update the history service for a particular download. | |
| 377 void UpdateHistoryForDownload(DownloadItem* download); | |
| 378 void RemoveDownloadFromHistory(DownloadItem* download); | |
| 379 void RemoveDownloadsFromHistoryBetween(const Time remove_begin, | |
| 380 const Time remove_before); | |
| 381 | |
| 382 // Inform the notification service of download starts and stops. | |
| 383 void NotifyAboutDownloadStart(); | |
| 384 void NotifyAboutDownloadStop(); | |
| 385 | |
| 386 // Create an extension based on the file name and mime type. | |
| 387 void GenerateExtension(const std::wstring& file_name, | |
| 388 const std::string& mime_type, | |
| 389 std::wstring* generated_extension); | |
| 390 | |
| 391 // Create a file name based on the response from the server. | |
| 392 void GenerateFilename(DownloadCreateInfo* info, std::wstring* generated_name); | |
| 393 | |
| 394 // Persist the automatic opening preference. | |
| 395 void SaveAutoOpens(); | |
| 396 | |
| 397 // Runs the network cancel on the IO thread. | |
| 398 static void OnCancelDownloadRequest(ResourceDispatcherHost* rdh, | |
| 399 int render_process_id, | |
| 400 int request_id); | |
| 401 | |
| 402 // Runs the pause on the IO thread. | |
| 403 static void OnPauseDownloadRequest(ResourceDispatcherHost* rdh, | |
| 404 int render_process_id, | |
| 405 int request_id, | |
| 406 bool pause); | |
| 407 | |
| 408 // 'downloads_' is map of all downloads in this profile. The key is the handle | |
| 409 // returned by the history system, which is unique across sessions. This map | |
| 410 // owns all the DownloadItems once they have been created in the history | |
| 411 // system. | |
| 412 // | |
| 413 // 'in_progress_' is a map of all downloads that are in progress and that have | |
| 414 // not yet received a valid history handle. The key is the ID assigned by the | |
| 415 // ResourceDispatcherHost, which is unique for the current session. This map | |
| 416 // does not own the DownloadItems. | |
| 417 // | |
| 418 // When a download is created through a user action, the corresponding | |
| 419 // DownloadItem* is placed in 'in_progress_' and remains there until it has | |
| 420 // received a valid handle from the history system. Once it has a valid | |
| 421 // handle, the DownloadItem* is placed in the 'downloads_' map. When the | |
| 422 // download is complete, it is removed from 'in_progress_'. Downloads from | |
| 423 // past sessions read from a persisted state from the history system are | |
| 424 // placed directly into 'downloads_' since they have valid handles in the | |
| 425 // history system. | |
| 426 typedef base::hash_map<int64, DownloadItem*> DownloadMap; | |
| 427 DownloadMap downloads_; | |
| 428 DownloadMap in_progress_; | |
| 429 | |
| 430 // True if the download manager has been initialized and requires a shutdown. | |
| 431 bool shutdown_needed_; | |
| 432 | |
| 433 // Observers that want to be notified of changes to the set of downloads. | |
| 434 ObserverList<Observer> observers_; | |
| 435 | |
| 436 // The current active profile. | |
| 437 Profile* profile_; | |
| 438 scoped_refptr<URLRequestContext> request_context_; | |
| 439 | |
| 440 // Used for history service request management. | |
| 441 CancelableRequestConsumerT<Observer*, 0> cancelable_consumer_; | |
| 442 | |
| 443 // Non-owning pointer for handling file writing on the download_thread_. | |
| 444 DownloadFileManager* file_manager_; | |
| 445 | |
| 446 // A pointer to the main UI loop. | |
| 447 MessageLoop* ui_loop_; | |
| 448 | |
| 449 // A pointer to the file thread's loop. The file thread lives longer than | |
| 450 // the DownloadManager, so this is safe to cache. | |
| 451 MessageLoop* file_loop_; | |
| 452 | |
| 453 // User preferences | |
| 454 BooleanPrefMember prompt_for_download_; | |
| 455 StringPrefMember download_path_; | |
| 456 | |
| 457 // The user's last choice for download directory. This is only used when the | |
| 458 // user wants us to prompt for a save location for each download. | |
| 459 std::wstring last_download_path_; | |
| 460 | |
| 461 // Set of file extensions to open at download completion. | |
| 462 std::set<std::wstring> auto_open_; | |
| 463 | |
| 464 // Set of file extensions that are executables and shouldn't be auto opened. | |
| 465 std::set<std::wstring> exe_types_; | |
| 466 | |
| 467 // Keep track of downloads that are completed before the user selects the | |
| 468 // destination, so that observers are appropriately notified of completion | |
| 469 // after this determination is made. | |
| 470 // The map is of download_id->remaining size (bytes), both of which are | |
| 471 // required when calling DownloadFinished. | |
| 472 typedef std::map<int32, int64> PendingFinishedMap; | |
| 473 PendingFinishedMap pending_finished_downloads_; | |
| 474 | |
| 475 // The "Save As" dialog box used to ask the user where a file should be | |
| 476 // saved. | |
| 477 scoped_refptr<SelectFileDialog> select_file_dialog_; | |
| 478 | |
| 479 DISALLOW_EVIL_CONSTRUCTORS(DownloadManager); | |
| 480 }; | |
| 481 | |
| 482 | |
| 483 #endif // CHROME_BROWSER_DOWNLOAD_MANAGER_H__ | |
| OLD | NEW |