1 // Copyright (c) 2011 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 // Download observers: 11 // Objects that are interested in notifications about new downloads, or progress 12 // updates for a given download must implement one of the download observer 13 // interfaces: 14 // DownloadManager::Observer: 15 // - allows observers, primarily views, to be notified when changes to the 16 // set of all downloads (such as new downloads, or deletes) occur 17 // Use AddObserver() / RemoveObserver() on the appropriate download object to 18 // receive state updates. 19 // 20 // Download state persistence: 21 // The DownloadManager uses the history service for storing persistent 22 // information about the state of all downloads. The history system maintains a 23 // separate table for this called 'downloads'. At the point that the 24 // DownloadManager is constructed, we query the history service for the state of 25 // all persisted downloads. 26 27 #ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H_ 28 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H_ 29 #pragma once 30 31 #include <map> 32 #include <set> 33 #include <string> 34 #include <vector> 35 36 #include "base/basictypes.h" 37 #include "base/file_path.h" 38 #include "base/gtest_prod_util.h" 39 #include "base/memory/ref_counted.h" 40 #include "base/memory/weak_ptr.h" 41 #include "base/observer_list.h" 42 #include "base/scoped_ptr.h" 43 #include "base/time.h" 44 #include "chrome/browser/download/download_status_updater_delegate.h" 45 #include "chrome/browser/ui/shell_dialogs.h" 46 #include "content/browser/browser_thread.h" 47 48 class DownloadFileManager; 49 class DownloadHistory; 50 class DownloadItem; 51 class DownloadPrefs; 52 class DownloadStatusUpdater; 53 class GURL; 54 class Profile; 55 class ResourceDispatcherHost; 56 class TabContents; 57 struct DownloadCreateInfo; 58 struct DownloadSaveInfo; 59 60 namespace net { 61 class URLRequestContextGetter; 62 } 63 64 // Browser's download manager: manages all downloads and destination view. 65 class DownloadManager 66 : public base::RefCountedThreadSafe<DownloadManager, 67 BrowserThread::DeleteOnUIThread>, 68 public DownloadStatusUpdaterDelegate, 69 public SelectFileDialog::Listener { 70 public: 71 explicit DownloadManager(DownloadStatusUpdater* status_updater); 72 73 // Shutdown the download manager. Must be called before destruction. 74 void Shutdown(); 75 76 // Interface to implement for observers that wish to be informed of changes 77 // to the DownloadManager's collection of downloads. 78 class Observer { 79 public: 80 // New or deleted download, observers should query us for the current set 81 // of downloads. 82 virtual void ModelChanged() = 0; 83 84 // Called when the DownloadManager is being destroyed to prevent Observers 85 // from calling back to a stale pointer. 86 virtual void ManagerGoingDown() {} 87 88 // Called immediately after the DownloadManager puts up a select file 89 // dialog. 90 // |id| indicates which download opened the dialog. 91 virtual void SelectFileDialogDisplayed(int32 id) {} 92 93 protected: 94 virtual ~Observer() {} 95 }; 96 97 // Return all temporary downloads that reside in the specified directory. 98 void GetTemporaryDownloads(const FilePath& dir_path, 99 std::vector<DownloadItem*>* result); 100 101 // Return all non-temporary downloads in the specified directory that are 102 // are in progress or have completed. 103 void GetAllDownloads(const FilePath& dir_path, 104 std::vector<DownloadItem*>* result); 105 106 // Return all non-temporary downloads in the specified directory that are 107 // in-progress (including dangerous downloads waiting for user confirmation). 108 void GetCurrentDownloads(const FilePath& dir_path, 109 std::vector<DownloadItem*>* result); 110 111 // Returns all non-temporary downloads matching |query|. Empty query matches 112 // everything. 113 void SearchDownloads(const string16& query, 114 std::vector<DownloadItem*>* result); 115 116 // Returns true if initialized properly. 117 bool Init(Profile* profile); 118 119 // Notifications sent from the download thread to the UI thread 120 void StartDownload(DownloadCreateInfo* info); 121 void UpdateDownload(int32 download_id, int64 size); 122 // |hash| is sha256 hash for the downloaded file. It is empty when the hash 123 // is not available. 124 void OnResponseCompleted(int32 download_id, int64 size, int os_error, 125 const std::string& hash); 126 127 // Called from a view when a user clicks a UI button or link. 128 void DownloadCancelled(int32 download_id); 129 void PauseDownload(int32 download_id, bool pause); 130 void RemoveDownload(int64 download_handle); 131 132 // Determine if the download is ready for completion, i.e. has had 133 // all data saved, and completed the filename determination and 134 // history insertion. 135 bool IsDownloadReadyForCompletion(DownloadItem* download); 136 137 // If all pre-requisites have been met, complete download processing, i.e. 138 // do internal cleanup, file rename, and potentially auto-open. 139 // (Dangerous downloads still may block on user acceptance after this 140 // point.) 141 void MaybeCompleteDownload(DownloadItem* download); 142 143 // Called when the download is renamed to its final name. 144 // |uniquifier| is a number used to make unique names for the file. It is 145 // only valid for the DANGEROUS_BUT_VALIDATED state of the download item. 146 void OnDownloadRenamedToFinalName(int download_id, 147 const FilePath& full_path, 148 int uniquifier); 149 150 // Remove downloads after remove_begin (inclusive) and before remove_end 151 // (exclusive). You may pass in null Time values to do an unbounded delete 152 // in either direction. 153 int RemoveDownloadsBetween(const base::Time remove_begin, 154 const base::Time remove_end); 155 156 // Remove downloads will delete all downloads that have a timestamp that is 157 // the same or more recent than |remove_begin|. The number of downloads 158 // deleted is returned back to the caller. 159 int RemoveDownloads(const base::Time remove_begin); 160 161 // Remove all downloads will delete all downloads. The number of downloads 162 // deleted is returned back to the caller. 163 int RemoveAllDownloads(); 164 165 // Final download manager transition for download: Update the download 166 // history and remove the download from |active_downloads_|. 167 void DownloadCompleted(int32 download_id); 168 169 // Called when a Save Page As download is started. Transfers ownership 170 // of |download_item| to the DownloadManager. 171 void SavePageAsDownloadStarted(DownloadItem* download_item); 172 173 // Download the object at the URL. Used in cases such as "Save Link As..." 174 void DownloadUrl(const GURL& url, 175 const GURL& referrer, 176 const std::string& referrer_encoding, 177 TabContents* tab_contents); 178 179 // Download the object at the URL and save it to the specified path. The 180 // download is treated as the temporary download and thus will not appear 181 // in the download history. Used in cases such as drag and drop. 182 void DownloadUrlToFile(const GURL& url, 183 const GURL& referrer, 184 const std::string& referrer_encoding, 185 const DownloadSaveInfo& save_info, 186 TabContents* tab_contents); 187 188 // Allow objects to observe the download creation process. 189 void AddObserver(Observer* observer); 190 191 // Remove a download observer from ourself. 192 void RemoveObserver(Observer* observer); 193 194 // Methods called on completion of a query sent to the history system. 195 void OnQueryDownloadEntriesComplete( 196 std::vector<DownloadCreateInfo>* entries); 197 void OnCreateDownloadEntryComplete( 198 DownloadCreateInfo info, int64 db_handle); 199 200 // Display a new download in the appropriate browser UI. 201 void ShowDownloadInBrowser(const DownloadCreateInfo& info, 202 DownloadItem* download); 203 204 // The number of in progress (including paused) downloads. 205 int in_progress_count() const { 206 return static_cast<int>(in_progress_.size()); 207 } 208 209 Profile* profile() { return profile_; } 210 211 DownloadHistory* download_history() { return download_history_.get(); } 212 213 DownloadPrefs* download_prefs() { return download_prefs_.get(); } 214 215 // Creates the download item. Must be called on the UI thread. 216 void CreateDownloadItem(DownloadCreateInfo* info); 217 218 // Clears the last download path, used to initialize "save as" dialogs. 219 void ClearLastDownloadPath(); 220 221 // Tests if a file type should be opened automatically. 222 bool ShouldOpenFileBasedOnExtension(const FilePath& path) const; 223 224 // Overridden from DownloadStatusUpdaterDelegate: 225 virtual bool IsDownloadProgressKnown(); 226 virtual int64 GetInProgressDownloadCount(); 227 virtual int64 GetReceivedDownloadBytes(); 228 virtual int64 GetTotalDownloadBytes(); 229 230 // Overridden from SelectFileDialog::Listener: 231 virtual void FileSelected(const FilePath& path, int index, void* params); 232 virtual void FileSelectionCanceled(void* params); 233 234 // Called when the user has validated the download of a dangerous file. 235 void DangerousDownloadValidated(DownloadItem* download); 236 237 // Callback function after url is checked with safebrowsing service. 238 void CheckDownloadUrlDone(DownloadCreateInfo* info, bool is_dangerous_url); 239 240 // Callback function after download file hash is checked with safebrowsing 241 // service. 242 void CheckDownloadHashDone(int32 download_id, bool is_dangerous_hash); 243 244 private: 245 // For testing. 246 friend class DownloadManagerTest; 247 friend class MockDownloadManager; 248 249 // This class is used to let an incognito DownloadManager observe changes to 250 // a normal DownloadManager, to propagate ModelChanged() calls from the parent 251 // DownloadManager to the observers of the incognito DownloadManager. 252 class OtherDownloadManagerObserver : public Observer { 253 public: 254 explicit OtherDownloadManagerObserver( 255 DownloadManager* observing_download_manager); 256 virtual ~OtherDownloadManagerObserver(); 257 258 // Observer interface. 259 virtual void ModelChanged(); 260 virtual void ManagerGoingDown(); 261 262 private: 263 // The incognito download manager. 264 DownloadManager* observing_download_manager_; 265 266 // The original profile's download manager. 267 DownloadManager* observed_download_manager_; 268 }; 269 270 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; 271 friend class DeleteTask<DownloadManager>; 272 friend class OtherDownloadManagerObserver; 273 274 ~DownloadManager(); 275 276 // Called on the download thread to check whether the suggested file path 277 // exists. We don't check if the file exists on the UI thread to avoid UI 278 // stalls from interacting with the file system. 279 void CheckIfSuggestedPathExists(DownloadCreateInfo* info, 280 const FilePath& default_path); 281 282 // Called on the UI thread once the DownloadManager has determined whether the 283 // suggested file path exists. 284 void OnPathExistenceAvailable(DownloadCreateInfo* info); 285 286 // Called back after a target path for the file to be downloaded to has been 287 // determined, either automatically based on the suggested file name, or by 288 // the user in a Save As dialog box. 289 void AttachDownloadItem(DownloadCreateInfo* info); 290 291 // Download cancel helper function. 292 void DownloadCancelledInternal(int download_id, 293 int render_process_id, 294 int request_id); 295 296 // All data has been downloaded. 297 // |hash| is sha256 hash for the downloaded file. It is empty when the hash 298 // is not available. 299 void OnAllDataSaved(int32 download_id, int64 size, const std::string& hash); 300 301 // An error occurred in the download. 302 void OnDownloadError(int32 download_id, int64 size, int os_error); 303 304 // Updates the app icon about the overall download progress. 305 void UpdateAppIcon(); 306 307 // Makes the ResourceDispatcherHost pause/un-pause a download request. 308 // Called on the IO thread. 309 void PauseDownloadRequest(ResourceDispatcherHost* rdh, 310 int render_process_id, 311 int request_id, 312 bool pause); 313 314 // Inform observers that the model has changed. 315 void NotifyModelChanged(); 316 317 DownloadItem* GetDownloadItem(int id); 318 319 // Debugging routine to confirm relationship between below 320 // containers; no-op if NDEBUG. 321 void AssertContainersConsistent() const; 322 323 // |downloads_| is the owning set for all downloads known to the 324 // DownloadManager. This includes downloads started by the user in 325 // this session, downloads initialized from the history system, and 326 // "save page as" downloads. All other DownloadItem containers in 327 // the DownloadManager are maps; they do not own the DownloadItems. 328 // Note that this is the only place (with any functional implications; 329 // see save_page_as_downloads_ below) that "save page as" downloads are 330 // kept, as the DownloadManager's only job is to hold onto those 331 // until destruction. 332 // 333 // |history_downloads_| is map of all downloads in this profile. The key 334 // is the handle returned by the history system, which is unique 335 // across sessions. 336 // 337 // |active_downloads_| is a map of all downloads that are currently being 338 // processed. The key is the ID assigned by the ResourceDispatcherHost, 339 // which is unique for the current session. 340 // 341 // |in_progress_| is a map of all downloads that are in progress and that have 342 // not yet received a valid history handle. The key is the ID assigned by the 343 // ResourceDispatcherHost, which is unique for the current session. 344 // 345 // |save_page_as_downloads_| (if defined) is a collection of all the 346 // downloads the "save page as" system has given to us to hold onto 347 // until we are destroyed. It is only used for debugging. 348 // 349 // When a download is created through a user action, the corresponding 350 // DownloadItem* is placed in |active_downloads_| and remains there until the 351 // download is in a terminal state (COMPLETE or CANCELLED). It is also 352 // placed in |in_progress_| and remains there until it has received a 353 // valid handle from the history system. Once it has a valid handle, the 354 // DownloadItem* is placed in the |history_downloads_| map. When the 355 // download reaches a terminal state, it is removed from |in_progress_|. 356 // Downloads from past sessions read from a persisted state from the 357 // history system are placed directly into |history_downloads_| since 358 // they have valid handles in the history system. 359 typedef std::set<DownloadItem*> DownloadSet; 360 typedef base::hash_map<int64, DownloadItem*> DownloadMap; 361 362 DownloadSet downloads_; 363 DownloadMap history_downloads_; 364 DownloadMap in_progress_; 365 DownloadMap active_downloads_; 366 #if !defined(NDEBUG) 367 DownloadSet save_page_as_downloads_; 368 #endif 369 370 // True if the download manager has been initialized and requires a shutdown. 371 bool shutdown_needed_; 372 373 // Observers that want to be notified of changes to the set of downloads. 374 ObserverList<Observer> observers_; 375 376 // The current active profile. 377 Profile* profile_; 378 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 379 380 scoped_ptr<DownloadHistory> download_history_; 381 382 scoped_ptr<DownloadPrefs> download_prefs_; 383 384 // Non-owning pointer for handling file writing on the download_thread_. 385 DownloadFileManager* file_manager_; 386 387 // Non-owning pointer for updating the download status. 388 base::WeakPtr<DownloadStatusUpdater> status_updater_; 389 390 // The user's last choice for download directory. This is only used when the 391 // user wants us to prompt for a save location for each download. 392 FilePath last_download_path_; 393 394 // The "Save As" dialog box used to ask the user where a file should be 395 // saved. 396 scoped_refptr<SelectFileDialog> select_file_dialog_; 397 398 scoped_ptr<OtherDownloadManagerObserver> other_download_manager_observer_; 399 400 DISALLOW_COPY_AND_ASSIGN(DownloadManager); 401 }; 402 403 #endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H_ 404