| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // The DownloadManager object manages the process of downloading, including |
| // updates to the history system and providing the information for displaying |
| // the downloads view in the Destinations tab. There is one DownloadManager per |
| // active profile in Chrome. |
| // |
| // Download observers: |
| // Objects that are interested in notifications about new downloads, or progress |
| // updates for a given download must implement one of the download observer |
| // interfaces: |
| // DownloadManager::Observer: |
| // - allows observers, primarily views, to be notified when changes to the |
| // set of all downloads (such as new downloads, or deletes) occur |
| // Use AddObserver() / RemoveObserver() on the appropriate download object to |
| // receive state updates. |
| // |
| // Download state persistence: |
| // The DownloadManager uses the history service for storing persistent |
| // information about the state of all downloads. The history system maintains a |
| // separate table for this called 'downloads'. At the point that the |
| // DownloadManager is constructed, we query the history service for the state of |
| // all persisted downloads. |
| |
| #ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H_ |
| #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H_ |
| #pragma once |
| |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/basictypes.h" |
| #include "base/file_path.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/scoped_ptr.h" |
| #include "base/time.h" |
| #include "chrome/browser/download/download_status_updater_delegate.h" |
| #include "chrome/browser/ui/shell_dialogs.h" |
| #include "content/browser/browser_thread.h" |
| |
| class DownloadFileManager; |
| class DownloadHistory; |
| class DownloadItem; |
| class DownloadPrefs; |
| class DownloadStatusUpdater; |
| class GURL; |
| class Profile; |
| class ResourceDispatcherHost; |
| class TabContents; |
| struct DownloadCreateInfo; |
| struct DownloadSaveInfo; |
| |
| namespace net { |
| class URLRequestContextGetter; |
| } |
| |
| // Browser's download manager: manages all downloads and destination view. |
| class DownloadManager |
| : public base::RefCountedThreadSafe<DownloadManager, |
| BrowserThread::DeleteOnUIThread>, |
| public DownloadStatusUpdaterDelegate, |
| public SelectFileDialog::Listener { |
| public: |
| explicit DownloadManager(DownloadStatusUpdater* status_updater); |
| |
| // Shutdown the download manager. Must be called before destruction. |
| void Shutdown(); |
| |
| // Interface to implement for observers that wish to be informed of changes |
| // to the DownloadManager's collection of downloads. |
| class Observer { |
| public: |
| // New or deleted download, observers should query us for the current set |
| // of downloads. |
| virtual void ModelChanged() = 0; |
| |
| // Called when the DownloadManager is being destroyed to prevent Observers |
| // from calling back to a stale pointer. |
| virtual void ManagerGoingDown() {} |
| |
| // Called immediately after the DownloadManager puts up a select file |
| // dialog. |
| // |id| indicates which download opened the dialog. |
| virtual void SelectFileDialogDisplayed(int32 id) {} |
| |
| protected: |
| virtual ~Observer() {} |
| }; |
| |
| // Return all temporary downloads that reside in the specified directory. |
| void GetTemporaryDownloads(const FilePath& dir_path, |
| std::vector<DownloadItem*>* result); |
| |
| // Return all non-temporary downloads in the specified directory that are |
| // are in progress or have completed. |
| void GetAllDownloads(const FilePath& dir_path, |
| std::vector<DownloadItem*>* result); |
| |
| // Return all non-temporary downloads in the specified directory that are |
| // in-progress (including dangerous downloads waiting for user confirmation). |
| void GetCurrentDownloads(const FilePath& dir_path, |
| std::vector<DownloadItem*>* result); |
| |
| // Returns all non-temporary downloads matching |query|. Empty query matches |
| // everything. |
| void SearchDownloads(const string16& query, |
| std::vector<DownloadItem*>* result); |
| |
| // Returns true if initialized properly. |
| bool Init(Profile* profile); |
| |
| // Notifications sent from the download thread to the UI thread |
| void StartDownload(DownloadCreateInfo* info); |
| void UpdateDownload(int32 download_id, int64 size); |
| // |hash| is sha256 hash for the downloaded file. It is empty when the hash |
| // is not available. |
| void OnResponseCompleted(int32 download_id, int64 size, int os_error, |
| const std::string& hash); |
| |
| // Called from a view when a user clicks a UI button or link. |
| void DownloadCancelled(int32 download_id); |
| void PauseDownload(int32 download_id, bool pause); |
| void RemoveDownload(int64 download_handle); |
| |
| // Determine if the download is ready for completion, i.e. has had |
| // all data saved, and completed the filename determination and |
| // history insertion. |
| bool IsDownloadReadyForCompletion(DownloadItem* download); |
| |
| // If all pre-requisites have been met, complete download processing, i.e. |
| // do internal cleanup, file rename, and potentially auto-open. |
| // (Dangerous downloads still may block on user acceptance after this |
| // point.) |
| void MaybeCompleteDownload(DownloadItem* download); |
| |
| // Called when the download is renamed to its final name. |
| // |uniquifier| is a number used to make unique names for the file. It is |
| // only valid for the DANGEROUS_BUT_VALIDATED state of the download item. |
| void OnDownloadRenamedToFinalName(int download_id, |
| const FilePath& full_path, |
| int uniquifier); |
| |
| // Remove downloads after remove_begin (inclusive) and before remove_end |
| // (exclusive). You may pass in null Time values to do an unbounded delete |
| // in either direction. |
| int RemoveDownloadsBetween(const base::Time remove_begin, |
| const base::Time remove_end); |
| |
| // Remove downloads will delete all downloads that have a timestamp that is |
| // the same or more recent than |remove_begin|. The number of downloads |
| // deleted is returned back to the caller. |
| int RemoveDownloads(const base::Time remove_begin); |
| |
| // Remove all downloads will delete all downloads. The number of downloads |
| // deleted is returned back to the caller. |
| int RemoveAllDownloads(); |
| |
| // Final download manager transition for download: Update the download |
| // history and remove the download from |active_downloads_|. |
| void DownloadCompleted(int32 download_id); |
| |
| // Called when a Save Page As download is started. Transfers ownership |
| // of |download_item| to the DownloadManager. |
| void SavePageAsDownloadStarted(DownloadItem* download_item); |
| |
| // Download the object at the URL. Used in cases such as "Save Link As..." |
| void DownloadUrl(const GURL& url, |
| const GURL& referrer, |
| const std::string& referrer_encoding, |
| TabContents* tab_contents); |
| |
| // Download the object at the URL and save it to the specified path. The |
| // download is treated as the temporary download and thus will not appear |
| // in the download history. Used in cases such as drag and drop. |
| void DownloadUrlToFile(const GURL& url, |
| const GURL& referrer, |
| const std::string& referrer_encoding, |
| const DownloadSaveInfo& save_info, |
| TabContents* tab_contents); |
| |
| // Allow objects to observe the download creation process. |
| void AddObserver(Observer* observer); |
| |
| // Remove a download observer from ourself. |
| void RemoveObserver(Observer* observer); |
| |
| // Methods called on completion of a query sent to the history system. |
| void OnQueryDownloadEntriesComplete( |
| std::vector<DownloadCreateInfo>* entries); |
| void OnCreateDownloadEntryComplete( |
| DownloadCreateInfo info, int64 db_handle); |
| |
| // Display a new download in the appropriate browser UI. |
| void ShowDownloadInBrowser(const DownloadCreateInfo& info, |
| DownloadItem* download); |
| |
| // The number of in progress (including paused) downloads. |
| int in_progress_count() const { |
| return static_cast<int>(in_progress_.size()); |
| } |
| |
| Profile* profile() { return profile_; } |
| |
| DownloadHistory* download_history() { return download_history_.get(); } |
| |
| DownloadPrefs* download_prefs() { return download_prefs_.get(); } |
| |
| // Creates the download item. Must be called on the UI thread. |
| void CreateDownloadItem(DownloadCreateInfo* info); |
| |
| // Clears the last download path, used to initialize "save as" dialogs. |
| void ClearLastDownloadPath(); |
| |
| // Tests if a file type should be opened automatically. |
| bool ShouldOpenFileBasedOnExtension(const FilePath& path) const; |
| |
| // Overridden from DownloadStatusUpdaterDelegate: |
| virtual bool IsDownloadProgressKnown(); |
| virtual int64 GetInProgressDownloadCount(); |
| virtual int64 GetReceivedDownloadBytes(); |
| virtual int64 GetTotalDownloadBytes(); |
| |
| // Overridden from SelectFileDialog::Listener: |
| virtual void FileSelected(const FilePath& path, int index, void* params); |
| virtual void FileSelectionCanceled(void* params); |
| |
| // Called when the user has validated the download of a dangerous file. |
| void DangerousDownloadValidated(DownloadItem* download); |
| |
| // Callback function after url is checked with safebrowsing service. |
| void CheckDownloadUrlDone(DownloadCreateInfo* info, bool is_dangerous_url); |
| |
| // Callback function after download file hash is checked with safebrowsing |
| // service. |
| void CheckDownloadHashDone(int32 download_id, bool is_dangerous_hash); |
| |
| private: |
| // For testing. |
| friend class DownloadManagerTest; |
| friend class MockDownloadManager; |
| |
| // This class is used to let an incognito DownloadManager observe changes to |
| // a normal DownloadManager, to propagate ModelChanged() calls from the parent |
| // DownloadManager to the observers of the incognito DownloadManager. |
| class OtherDownloadManagerObserver : public Observer { |
| public: |
| explicit OtherDownloadManagerObserver( |
| DownloadManager* observing_download_manager); |
| virtual ~OtherDownloadManagerObserver(); |
| |
| // Observer interface. |
| virtual void ModelChanged(); |
| virtual void ManagerGoingDown(); |
| |
| private: |
| // The incognito download manager. |
| DownloadManager* observing_download_manager_; |
| |
| // The original profile's download manager. |
| DownloadManager* observed_download_manager_; |
| }; |
| |
| friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; |
| friend class DeleteTask<DownloadManager>; |
| friend class OtherDownloadManagerObserver; |
| |
| ~DownloadManager(); |
| |
| // Called on the download thread to check whether the suggested file path |
| // exists. We don't check if the file exists on the UI thread to avoid UI |
| // stalls from interacting with the file system. |
| void CheckIfSuggestedPathExists(DownloadCreateInfo* info, |
| const FilePath& default_path); |
| |
| // Called on the UI thread once the DownloadManager has determined whether the |
| // suggested file path exists. |
| void OnPathExistenceAvailable(DownloadCreateInfo* info); |
| |
| // Called back after a target path for the file to be downloaded to has been |
| // determined, either automatically based on the suggested file name, or by |
| // the user in a Save As dialog box. |
| void AttachDownloadItem(DownloadCreateInfo* info); |
| |
| // Download cancel helper function. |
| void DownloadCancelledInternal(int download_id, |
| int render_process_id, |
| int request_id); |
| |
| // All data has been downloaded. |
| // |hash| is sha256 hash for the downloaded file. It is empty when the hash |
| // is not available. |
| void OnAllDataSaved(int32 download_id, int64 size, const std::string& hash); |
| |
| // An error occurred in the download. |
| void OnDownloadError(int32 download_id, int64 size, int os_error); |
| |
| // Updates the app icon about the overall download progress. |
| void UpdateAppIcon(); |
| |
| // Makes the ResourceDispatcherHost pause/un-pause a download request. |
| // Called on the IO thread. |
| void PauseDownloadRequest(ResourceDispatcherHost* rdh, |
| int render_process_id, |
| int request_id, |
| bool pause); |
| |
| // Inform observers that the model has changed. |
| void NotifyModelChanged(); |
| |
| DownloadItem* GetDownloadItem(int id); |
| |
| // Debugging routine to confirm relationship between below |
| // containers; no-op if NDEBUG. |
| void AssertContainersConsistent() const; |
| |
| // |downloads_| is the owning set for all downloads known to the |
| // DownloadManager. This includes downloads started by the user in |
| // this session, downloads initialized from the history system, and |
| // "save page as" downloads. All other DownloadItem containers in |
| // the DownloadManager are maps; they do not own the DownloadItems. |
| // Note that this is the only place (with any functional implications; |
| // see save_page_as_downloads_ below) that "save page as" downloads are |
| // kept, as the DownloadManager's only job is to hold onto those |
| // until destruction. |
| // |
| // |history_downloads_| is map of all downloads in this profile. The key |
| // is the handle returned by the history system, which is unique |
| // across sessions. |
| // |
| // |active_downloads_| is a map of all downloads that are currently being |
| // processed. The key is the ID assigned by the ResourceDispatcherHost, |
| // which is unique for the current session. |
| // |
| // |in_progress_| is a map of all downloads that are in progress and that have |
| // not yet received a valid history handle. The key is the ID assigned by the |
| // ResourceDispatcherHost, which is unique for the current session. |
| // |
| // |save_page_as_downloads_| (if defined) is a collection of all the |
| // downloads the "save page as" system has given to us to hold onto |
| // until we are destroyed. It is only used for debugging. |
| // |
| // When a download is created through a user action, the corresponding |
| // DownloadItem* is placed in |active_downloads_| and remains there until the |
| // download is in a terminal state (COMPLETE or CANCELLED). It is also |
| // placed in |in_progress_| and remains there until it has received a |
| // valid handle from the history system. Once it has a valid handle, the |
| // DownloadItem* is placed in the |history_downloads_| map. When the |
| // download reaches a terminal state, it is removed from |in_progress_|. |
| // Downloads from past sessions read from a persisted state from the |
| // history system are placed directly into |history_downloads_| since |
| // they have valid handles in the history system. |
| typedef std::set<DownloadItem*> DownloadSet; |
| typedef base::hash_map<int64, DownloadItem*> DownloadMap; |
| |
| DownloadSet downloads_; |
| DownloadMap history_downloads_; |
| DownloadMap in_progress_; |
| DownloadMap active_downloads_; |
| #if !defined(NDEBUG) |
| DownloadSet save_page_as_downloads_; |
| #endif |
| |
| // True if the download manager has been initialized and requires a shutdown. |
| bool shutdown_needed_; |
| |
| // Observers that want to be notified of changes to the set of downloads. |
| ObserverList<Observer> observers_; |
| |
| // The current active profile. |
| Profile* profile_; |
| scoped_refptr<net::URLRequestContextGetter> request_context_getter_; |
| |
| scoped_ptr<DownloadHistory> download_history_; |
| |
| scoped_ptr<DownloadPrefs> download_prefs_; |
| |
| // Non-owning pointer for handling file writing on the download_thread_. |
| DownloadFileManager* file_manager_; |
| |
| // Non-owning pointer for updating the download status. |
| base::WeakPtr<DownloadStatusUpdater> status_updater_; |
| |
| // The user's last choice for download directory. This is only used when the |
| // user wants us to prompt for a save location for each download. |
| FilePath last_download_path_; |
| |
| // The "Save As" dialog box used to ask the user where a file should be |
| // saved. |
| scoped_refptr<SelectFileDialog> select_file_dialog_; |
| |
| scoped_ptr<OtherDownloadManagerObserver> other_download_manager_observer_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DownloadManager); |
| }; |
| |
| #endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H_ |