diff options
author | paulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-13 02:48:59 +0000 |
---|---|---|
committer | paulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-13 02:48:59 +0000 |
commit | cdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea (patch) | |
tree | c9e3f5a89a3d9733ea75b97153ef2be4e8425aa3 /chrome/browser/download/download_manager.h | |
parent | 431838df78d6e3cd06794a45cf0243be32149c7c (diff) | |
download | chromium_src-cdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea.zip chromium_src-cdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea.tar.gz chromium_src-cdaa86594dcdd5fc4ccac5dbf63a5e4dbfcdb8ea.tar.bz2 |
Move the download code to new directories:
browser/download/
browser/views/
Review URL: http://codereview.chromium.org/2826
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2166 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/download/download_manager.h')
-rw-r--r-- | chrome/browser/download/download_manager.h | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/chrome/browser/download/download_manager.h b/chrome/browser/download/download_manager.h new file mode 100644 index 0000000..0ab3dc1 --- /dev/null +++ b/chrome/browser/download/download_manager.h @@ -0,0 +1,483 @@ +// Copyright (c) 2006-2008 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. +// +// Each download is represented by a DownloadItem, and all DownloadItems +// are owned by the DownloadManager which maintains a global list of all +// downloads. DownloadItems are created when a user initiates a download, +// and exist for the duration of the browser life time. +// +// 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: +// DownloadItem::Observer: +// - allows observers to receive notifications about one download from start +// to completion +// 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__ + +#include <string> +#include <map> +#include <set> +#include <vector> + +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/observer_list.h" +#include "base/ref_counted.h" +#include "chrome/browser/cancelable_request.h" +#include "chrome/browser/history/download_types.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/shell_dialogs.h" +#include "chrome/common/pref_member.h" + +class DownloadFileManager; +class DownloadItem; +class DownloadItemView; +class DownloadManager; +class GURL; +class MessageLoop; +class PrefService; +class Profile; +class ResourceDispatcherHost; +class URLRequestContext; +class WebContents; + +namespace base { +class Thread; +} + +// DownloadItem ---------------------------------------------------------------- + +// One DownloadItem per download. This is the model class that stores all the +// state for a download. Multiple views, such as a tab's download shelf and the +// Destination tab's download view, may refer to a given DownloadItem. +class DownloadItem { + public: + enum DownloadState { + IN_PROGRESS, + COMPLETE, + CANCELLED, + REMOVING + }; + + // Interface that observers of a particular download must implement in order + // to receive updates to the download's status. + class Observer { + public: + virtual void OnDownloadUpdated(DownloadItem* download) = 0; + }; + + // Constructing from persistent store: + DownloadItem(const DownloadCreateInfo& info); + + // Constructing from user action: + DownloadItem(int32 download_id, + const std::wstring& path, + const std::wstring& url, + const Time start_time, + int64 download_size, + int render_process_id, + int request_id); + + ~DownloadItem(); + + void Init(bool start_timer); + + // Public API + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Notify our observers periodically + void UpdateObservers(); + + // Received a new chunk of data + void Update(int64 bytes_so_far); + + // Cancel the download operation. We need to distinguish between cancels at + // exit (DownloadManager destructor) from user interface initiated cancels + // because at exit, the history system may not exist, and any updates to it + // require AddRef'ing the DownloadManager in the destructor which results in + // a DCHECK failure. Set 'update_history' to false when canceling from at + // exit to prevent this crash. This may result in a difference between the + // downloaded file's size on disk, and what the history system's last record + // of it is. At worst, we'll end up re-downloading a small portion of the file + // when resuming a download (assuming the server supports byte ranges). + void Cancel(bool update_history); + + // Download operation completed + void Finished(int64 size); + + // The user wants to remove the download from the views and history. This + // operation does not delete the file on the disk. + void Remove(); + + // Start/stop sending periodic updates to our observers + void StartProgressTimer(); + void StopProgressTimer(); + + // Simple calculation of the amount of time remaining to completion. Fills + // |*remaining| with the amount of time remaining if successful. Fails and + // returns false if we do not have the number of bytes or the speed so can + // not estimate. + bool TimeRemaining(TimeDelta* remaining) const; + + // Simple speed estimate in bytes/s + int64 CurrentSpeed() const; + + // Rough percent complete, -1 means we don't know (since we didn't receive a + // total size). + int PercentComplete() const; + + // Update the download's path, the actual file is renamed on the download + // thread. + void Rename(const std::wstring& full_path); + + // Allow the user to temporarily pause a download or resume a paused download. + void TogglePause(); + + // Accessors + DownloadState state() const { return state_; } + std::wstring full_path() const { return full_path_; } + std::wstring file_name() const { return file_name_; } + std::wstring url() const { return url_; } + int64 total_bytes() const { return total_bytes_; } + void set_total_bytes(int64 total_bytes) { total_bytes_ = total_bytes; } + int64 received_bytes() const { return received_bytes_; } + int32 id() const { return id_; } + Time start_time() const { return start_time_; } + void set_db_handle(int64 handle) { db_handle_ = handle; } + int64 db_handle() const { return db_handle_; } + DownloadManager* manager() const { return manager_; } + void set_manager(DownloadManager* manager) { manager_ = manager; } + bool is_paused() const { return is_paused_; } + void set_is_paused(bool pause) { is_paused_ = pause; } + bool open_when_complete() const { return open_when_complete_; } + void set_open_when_complete(bool open) { open_when_complete_ = open; } + int render_process_id() const { return render_process_id_; } + int request_id() const { return request_id_; } + + private: + // Internal helper for maintaining consistent received and total sizes. + void UpdateSize(int64 size); + + // Request ID assigned by the ResourceDispatcherHost. + int32 id_; + + // Full path to the downloaded file + std::wstring full_path_; + + // Short display version of the file + std::wstring file_name_; + + // The URL from whence we came, for display + std::wstring url_; + + // Total bytes expected + int64 total_bytes_; + + // Current received bytes + int64 received_bytes_; + + // Start time for calculating remaining time + uintptr_t start_tick_; + + // The current state of this download + DownloadState state_; + + // The views of this item in the download shelf and download tab + ObserverList<Observer> observers_; + + // Time the download was started + Time start_time_; + + // Our persistent store handle + int64 db_handle_; + + // Timer for regularly updating our observers + base::RepeatingTimer<DownloadItem> update_timer_; + + // Our owning object + DownloadManager* manager_; + + // In progress downloads may be paused by the user, we note it here + bool is_paused_; + + // A flag for indicating if the download should be opened at completion. + bool open_when_complete_; + + // For canceling or pausing requests. + int render_process_id_; + int request_id_; + + DISALLOW_EVIL_CONSTRUCTORS(DownloadItem); +}; + + +// DownloadManager ------------------------------------------------------------- + +// Browser's download manager: manages all downloads and destination view. +class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, + public SelectFileDialog::Listener { + // For testing. + friend class DownloadManagerTest; + + public: + DownloadManager(); + ~DownloadManager(); + + static void RegisterUserPrefs(PrefService* prefs); + + // 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; + + // A callback once the DownloadManager has retrieved the requested set of + // downloads. The DownloadManagerObserver must copy the vector, but does not + // own the individual DownloadItems, when this call is made. + virtual void SetDownloads(std::vector<DownloadItem*>& downloads) = 0; + }; + + // Public API + + // Begin a search for all downloads matching 'search_text'. If 'search_text' + // is empty, return all known downloads. The results are returned in the + // 'SetDownloads' observer callback. + void GetDownloads(Observer* observer, + const std::wstring& search_text); + + // Returns true if initialized properly. + bool Init(Profile* profile); + + // Schedule a query of the history service to retrieve all downloads. + void QueryHistoryForDownloads(); + + // Notifications sent from the download thread to the UI thread + void StartDownload(DownloadCreateInfo* info); + void UpdateDownload(int32 download_id, int64 size); + void DownloadFinished(int32 download_id, int64 size); + + // Helper method for cancelling the network request associated with a + // download. + static void CancelDownloadRequest(int render_process_id, int request_id); + + // 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); + + // 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 Time remove_begin, const 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 Time remove_begin); + + // Download the object at the URL. Used in cases such as "Save Link As..." + void DownloadUrl(const GURL& url, + const GURL& referrer, + WebContents* web_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); + void OnSearchComplete(HistoryService::Handle handle, + std::vector<int64>* results); + + // Show or Open a download via the Windows shell. + void ShowDownloadInShell(const DownloadItem* download); + void OpenDownloadInShell(const DownloadItem* download, HWND parent_window); + + // The number of in progress (including paused) downloads. + int in_progress_count() const { + return static_cast<int>(in_progress_.size()); + } + + std::wstring download_path() { return *download_path_; } + + // Registers this file extension for automatic opening upon download + // completion if 'open' is true, or prevents the extension from automatic + // opening if 'open' is false. + void OpenFilesOfExtension(const std::wstring& extension, bool open); + + // Tests if a file type should be opened automatically. + bool ShouldOpenFileExtension(const std::wstring& extension); + + // Tests if we think the server means for this mime_type to be executable. + static bool IsExecutableMimeType(const std::string& mime_type); + + // Tests if a file type is considered executable. + bool IsExecutable(const std::wstring& extension); + + // Resets the automatic open preference. + void ResetAutoOpenFiles(); + + // Returns true if there are automatic handlers registered for any file + // types. + bool HasAutoOpenFileTypesRegistered() const; + + // Overridden from SelectFileDialog::Listener: + virtual void FileSelected(const std::wstring& path, void* params); + virtual void FileSelectionCanceled(void* params); + + private: + // Shutdown the download manager. This call is needed only after Init. + void Shutdown(); + + // 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); + + // 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 ContinueStartDownload(DownloadCreateInfo* info, + const std::wstring& target_path); + + // Update the history service for a particular download. + void UpdateHistoryForDownload(DownloadItem* download); + void RemoveDownloadFromHistory(DownloadItem* download); + void RemoveDownloadsFromHistoryBetween(const Time remove_begin, + const Time remove_before); + + // Inform the notification service of download starts and stops. + void NotifyAboutDownloadStart(); + void NotifyAboutDownloadStop(); + + // Create an extension based on the file name and mime type. + void GenerateExtension(const std::wstring& file_name, + const std::string& mime_type, + std::wstring* generated_extension); + + // Create a file name based on the response from the server. + void GenerateFilename(DownloadCreateInfo* info, std::wstring* generated_name); + + // Persist the automatic opening preference. + void SaveAutoOpens(); + + // Runs the network cancel on the IO thread. + static void OnCancelDownloadRequest(ResourceDispatcherHost* rdh, + int render_process_id, + int request_id); + + // Runs the pause on the IO thread. + static void OnPauseDownloadRequest(ResourceDispatcherHost* rdh, + int render_process_id, + int request_id, + bool pause); + + // 'downloads_' is map of all downloads in this profile. The key is the handle + // returned by the history system, which is unique across sessions. This map + // owns all the DownloadItems once they have been created in the history + // system. + // + // '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. This map + // does not own the DownloadItems. + // + // When a download is created through a user action, the corresponding + // DownloadItem* is 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 'downloads_' map. When the + // download is complete, it is removed from 'in_progress_'. Downloads from + // past sessions read from a persisted state from the history system are + // placed directly into 'downloads_' since they have valid handles in the + // history system. + typedef base::hash_map<int64, DownloadItem*> DownloadMap; + DownloadMap downloads_; + DownloadMap in_progress_; + + // 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<URLRequestContext> request_context_; + + // Used for history service request management. + CancelableRequestConsumerT<Observer*, 0> cancelable_consumer_; + + // Non-owning pointer for handling file writing on the download_thread_. + DownloadFileManager* file_manager_; + + // A pointer to the main UI loop. + MessageLoop* ui_loop_; + + // A pointer to the file thread's loop. The file thread lives longer than + // the DownloadManager, so this is safe to cache. + MessageLoop* file_loop_; + + // User preferences + BooleanPrefMember prompt_for_download_; + StringPrefMember download_path_; + + // 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. + std::wstring last_download_path_; + + // Set of file extensions to open at download completion. + std::set<std::wstring> auto_open_; + + // Set of file extensions that are executables and shouldn't be auto opened. + std::set<std::wstring> exe_types_; + + // Keep track of downloads that are completed before the user selects the + // destination, so that observers are appropriately notified of completion + // after this determination is made. + // The map is of download_id->remaining size (bytes), both of which are + // required when calling DownloadFinished. + typedef std::map<int32, int64> PendingFinishedMap; + PendingFinishedMap pending_finished_downloads_; + + // The "Save As" dialog box used to ask the user where a file should be + // saved. + scoped_refptr<SelectFileDialog> select_file_dialog_; + + DISALLOW_EVIL_CONSTRUCTORS(DownloadManager); +}; + + +#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_H__ |