summaryrefslogtreecommitdiffstats
path: root/chrome/browser/download
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-16 21:41:16 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-16 21:41:16 +0000
commit6c69796dfc4e3c4fe1c6c0d7c561d3f17a3e18a9 (patch)
tree18375c7ebd926415dbc1371de37e5945528c6b30 /chrome/browser/download
parentaa561d95543b80f81781e2c332b271a044c134c6 (diff)
downloadchromium_src-6c69796dfc4e3c4fe1c6c0d7c561d3f17a3e18a9.zip
chromium_src-6c69796dfc4e3c4fe1c6c0d7c561d3f17a3e18a9.tar.gz
chromium_src-6c69796dfc4e3c4fe1c6c0d7c561d3f17a3e18a9.tar.bz2
Download code cleanup: split big files into smaller one.
It's hard to find things in the download directory. DownloadFile and DownloadFileManager were bundled together. Similarly for DownloadItem and DownloadManager, which was much less intuitive. Some 3-5 line structs were also in one bag with something else. I extracted them to their own small file. TEST=unit_tests, browser_tests, ui_tests BUG=48913 Review URL: http://codereview.chromium.org/2806054 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52749 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/download')
-rw-r--r--chrome/browser/download/download_file.cc501
-rw-r--r--chrome/browser/download/download_file.h201
-rw-r--r--chrome/browser/download/download_file_manager.cc507
-rw-r--r--chrome/browser/download/download_file_manager.h183
-rw-r--r--chrome/browser/download/download_item.cc235
-rw-r--r--chrome/browser/download/download_item.h299
-rw-r--r--chrome/browser/download/download_item_model.cc2
-rw-r--r--chrome/browser/download/download_manager.cc262
-rw-r--r--chrome/browser/download/download_manager.h294
-rw-r--r--chrome/browser/download/download_manager_unittest.cc1
-rw-r--r--chrome/browser/download/download_shelf.cc1
-rw-r--r--chrome/browser/download/download_types.h37
-rw-r--r--chrome/browser/download/download_util.cc1
-rw-r--r--chrome/browser/download/drag_download_file.cc2
-rw-r--r--chrome/browser/download/drag_download_file.h3
-rw-r--r--chrome/browser/download/save_package.cc1
16 files changed, 1289 insertions, 1241 deletions
diff --git a/chrome/browser/download/download_file.cc b/chrome/browser/download/download_file.cc
index 521a5c8..81d80b4 100644
--- a/chrome/browser/download/download_file.cc
+++ b/chrome/browser/download/download_file.cc
@@ -1,30 +1,15 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
#include "chrome/browser/download/download_file.h"
#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/stl_util-inl.h"
-#include "base/task.h"
-#include "base/thread.h"
-#include "base/utf_string_conversions.h"
#include "build/build_config.h"
-#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/download/download_util.h"
-#include "chrome/browser/net/chrome_url_request_context.h"
-#include "chrome/browser/platform_util.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
-#include "chrome/browser/tab_contents/tab_util.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/chrome_paths.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_util.h"
-#include "net/url_request/url_request_context.h"
+#include "chrome/browser/history/download_types.h"
+#include "net/base/net_errors.h"
#if defined(OS_WIN)
#include "app/win_util.h"
@@ -33,12 +18,6 @@
#include "chrome/browser/cocoa/file_metadata.h"
#endif
-// Throttle updates to the UI thread so that a fast moving download doesn't
-// cause it to become unresponsive (in milliseconds).
-static const int kUpdatePeriodMs = 500;
-
-// DownloadFile implementation -------------------------------------------------
-
DownloadFile::DownloadFile(const DownloadCreateInfo* info)
: file_stream_(info->save_info.file_stream),
source_url_(info->url),
@@ -187,477 +166,3 @@ void DownloadFile::AnnotateWithSourceInformation() {
referrer_url_);
#endif
}
-
-// DownloadFileManager implementation ------------------------------------------
-
-DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh)
- : next_id_(0),
- resource_dispatcher_host_(rdh) {
-}
-
-DownloadFileManager::~DownloadFileManager() {
- // Check for clean shutdown.
- DCHECK(downloads_.empty());
- ui_progress_.clear();
-}
-
-// Called during the browser shutdown process to clean up any state (open files,
-// timers) that live on the download_thread_.
-void DownloadFileManager::Shutdown() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- StopUpdateTimer();
- ChromeThread::PostTask(
- ChromeThread::FILE, FROM_HERE,
- NewRunnableMethod(this, &DownloadFileManager::OnShutdown));
-}
-
-// Cease download thread operations.
-void DownloadFileManager::OnShutdown() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- // Delete any partial downloads during shutdown.
- for (DownloadFileMap::iterator it = downloads_.begin();
- it != downloads_.end(); ++it) {
- DownloadFile* download = it->second;
- if (download->in_progress())
- download->Cancel();
- delete download;
- }
- downloads_.clear();
-}
-
-// Initiate a request for URL to be downloaded. Called from UI thread,
-// runs on IO thread.
-void DownloadFileManager::OnDownloadUrl(
- const GURL& url,
- const GURL& referrer,
- const std::string& referrer_charset,
- const DownloadSaveInfo& save_info,
- int render_process_host_id,
- int render_view_id,
- URLRequestContextGetter* request_context_getter) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-
- URLRequestContext* context = request_context_getter->GetURLRequestContext();
- context->set_referrer_charset(referrer_charset);
-
- resource_dispatcher_host_->BeginDownload(url,
- referrer,
- save_info,
- render_process_host_id,
- render_view_id,
- context);
-}
-
-// Notifications sent from the download thread and run on the UI thread.
-
-// Lookup the DownloadManager for this TabContents' profile and inform it of
-// a new download.
-// TODO(paulg): When implementing download restart via the Downloads tab,
-// there will be no 'render_process_id' or 'render_view_id'.
-void DownloadFileManager::OnStartDownload(DownloadCreateInfo* info) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- DownloadManager* manager = DownloadManagerFromRenderIds(info->child_id,
- info->render_view_id);
- if (!manager) {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
- resource_dispatcher_host_,
- info->child_id,
- info->request_id));
- delete info;
- return;
- }
-
- StartUpdateTimer();
-
- // Add the download manager to our request maps for future updates. We want to
- // be able to cancel all in progress downloads when a DownloadManager is
- // deleted, such as when a profile is closed. We also want to be able to look
- // up the DownloadManager associated with a given request without having to
- // rely on using tab information, since a tab may be closed while a download
- // initiated from that tab is still in progress.
- DownloadRequests& downloads = requests_[manager];
- downloads.insert(info->download_id);
-
- // TODO(paulg): The manager will exist when restarts are implemented.
- DownloadManagerMap::iterator dit = managers_.find(info->download_id);
- if (dit == managers_.end())
- managers_[info->download_id] = manager;
- else
- NOTREACHED();
-
- // StartDownload will clean up |info|.
- manager->StartDownload(info);
-}
-
-// Update the Download Manager with the finish state, and remove the request
-// tracking entries.
-void DownloadFileManager::OnDownloadFinished(int id,
- int64 bytes_so_far) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- DownloadManager* manager = LookupManager(id);
- if (manager)
- manager->DownloadFinished(id, bytes_so_far);
- RemoveDownload(id, manager);
- RemoveDownloadFromUIProgress(id);
-}
-
-// Lookup one in-progress download.
-DownloadFile* DownloadFileManager::LookupDownload(int id) {
- DownloadFileMap::iterator it = downloads_.find(id);
- return it == downloads_.end() ? NULL : it->second;
-}
-
-// The UI progress is updated on the file thread and removed on the UI thread.
-void DownloadFileManager::RemoveDownloadFromUIProgress(int id) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- AutoLock lock(progress_lock_);
- if (ui_progress_.find(id) != ui_progress_.end())
- ui_progress_.erase(id);
-}
-
-// Throttle updates to the UI thread by only posting update notifications at a
-// regularly controlled interval.
-void DownloadFileManager::StartUpdateTimer() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- if (!update_timer_.IsRunning()) {
- update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs),
- this, &DownloadFileManager::UpdateInProgressDownloads);
- }
-}
-
-void DownloadFileManager::StopUpdateTimer() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- update_timer_.Stop();
-}
-
-// Our periodic timer has fired so send the UI thread updates on all in progress
-// downloads.
-void DownloadFileManager::UpdateInProgressDownloads() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- AutoLock lock(progress_lock_);
- ProgressMap::iterator it = ui_progress_.begin();
- for (; it != ui_progress_.end(); ++it) {
- const int id = it->first;
- DownloadManager* manager = LookupManager(id);
- if (manager)
- manager->UpdateDownload(id, it->second);
- }
-}
-
-// Called on the IO thread once the ResourceDispatcherHost has decided that a
-// request is a download.
-int DownloadFileManager::GetNextId() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- return next_id_++;
-}
-
-// Notifications sent from the IO thread and run on the download thread:
-
-// The IO thread created 'info', but the download thread (this method) uses it
-// to create a DownloadFile, then passes 'info' to the UI thread where it is
-// finally consumed and deleted.
-void DownloadFileManager::StartDownload(DownloadCreateInfo* info) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- DCHECK(info);
-
- DownloadFile* download = new DownloadFile(info);
- if (!download->Initialize()) {
- // Couldn't open, cancel the operation. The UI thread does not yet know
- // about this download so we have to clean up 'info'. We need to get back
- // to the IO thread to cancel the network request and CancelDownloadRequest
- // on the UI thread is the safe way to do that.
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
- resource_dispatcher_host_,
- info->child_id,
- info->request_id));
- delete info;
- delete download;
- return;
- }
-
- DCHECK(LookupDownload(info->download_id) == NULL);
- downloads_[info->download_id] = download;
- info->path = download->full_path();
- {
- AutoLock lock(progress_lock_);
- ui_progress_[info->download_id] = info->received_bytes;
- }
-
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &DownloadFileManager::OnStartDownload, info));
-}
-
-// We don't forward an update to the UI thread here, since we want to throttle
-// the UI update rate via a periodic timer. If the user has cancelled the
-// download (in the UI thread), we may receive a few more updates before the IO
-// thread gets the cancel message: we just delete the data since the
-// DownloadFile has been deleted.
-void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- std::vector<DownloadBuffer::Contents> contents;
- {
- AutoLock auto_lock(buffer->lock);
- contents.swap(buffer->contents);
- }
-
- DownloadFile* download = LookupDownload(id);
- for (size_t i = 0; i < contents.size(); ++i) {
- net::IOBuffer* data = contents[i].first;
- const int data_len = contents[i].second;
- if (download)
- download->AppendDataToFile(data->data(), data_len);
- data->Release();
- }
-
- if (download) {
- AutoLock lock(progress_lock_);
- ui_progress_[download->id()] = download->bytes_so_far();
- }
-}
-
-void DownloadFileManager::DownloadFinished(int id, DownloadBuffer* buffer) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- delete buffer;
- DownloadFileMap::iterator it = downloads_.find(id);
- if (it != downloads_.end()) {
- DownloadFile* download = it->second;
- download->set_in_progress(false);
-
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(
- this, &DownloadFileManager::OnDownloadFinished,
- id, download->bytes_so_far()));
-
- // We need to keep the download around until the UI thread has finalized
- // the name.
- if (download->path_renamed()) {
- downloads_.erase(it);
- delete download;
- }
- }
-
- if (downloads_.empty())
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
-}
-
-// This method will be sent via a user action, or shutdown on the UI thread, and
-// run on the download thread. Since this message has been sent from the UI
-// thread, the download may have already completed and won't exist in our map.
-void DownloadFileManager::CancelDownload(int id) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- DownloadFileMap::iterator it = downloads_.find(id);
- if (it != downloads_.end()) {
- DownloadFile* download = it->second;
- download->set_in_progress(false);
-
- download->Cancel();
-
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(
- this, &DownloadFileManager::RemoveDownloadFromUIProgress,
- download->id()));
-
- if (download->path_renamed()) {
- downloads_.erase(it);
- delete download;
- }
- }
-
- if (downloads_.empty()) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
- }
-}
-
-void DownloadFileManager::DownloadUrl(
- const GURL& url,
- const GURL& referrer,
- const std::string& referrer_charset,
- const DownloadSaveInfo& save_info,
- int render_process_host_id,
- int render_view_id,
- URLRequestContextGetter* request_context_getter) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableMethod(this,
- &DownloadFileManager::OnDownloadUrl,
- url,
- referrer,
- referrer_charset,
- save_info,
- render_process_host_id,
- render_view_id,
- request_context_getter));
-}
-
-// Relate a download ID to its owning DownloadManager.
-DownloadManager* DownloadFileManager::LookupManager(int download_id) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- DownloadManagerMap::iterator it = managers_.find(download_id);
- if (it != managers_.end())
- return it->second;
- return NULL;
-}
-
-// Utility function for look up table maintenance, called on the UI thread.
-// A manager may have multiple downloads in progress, so we just look up the
-// one download (id) and remove it from the set, and remove the set if it
-// becomes empty.
-void DownloadFileManager::RemoveDownload(int id, DownloadManager* manager) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- if (manager) {
- RequestMap::iterator it = requests_.find(manager);
- if (it != requests_.end()) {
- DownloadRequests& downloads = it->second;
- DownloadRequests::iterator rit = downloads.find(id);
- if (rit != downloads.end())
- downloads.erase(rit);
- if (downloads.empty())
- requests_.erase(it);
- }
- }
-
- // A download can only have one manager, so remove it if it exists.
- DownloadManagerMap::iterator dit = managers_.find(id);
- if (dit != managers_.end())
- managers_.erase(dit);
-}
-
-// Utility function for converting request IDs to a TabContents. Must be called
-// only on the UI thread since Profile operations may create UI objects, such as
-// the first call to profile->GetDownloadManager().
-// static
-DownloadManager* DownloadFileManager::DownloadManagerFromRenderIds(
- int render_process_id, int render_view_id) {
- TabContents* contents = tab_util::GetTabContentsByID(render_process_id,
- render_view_id);
- if (contents) {
- Profile* profile = contents->profile();
- if (profile)
- return profile->GetDownloadManager();
- }
-
- return NULL;
-}
-
-// Called by DownloadManagers in their destructor, and only on the UI thread.
-void DownloadFileManager::RemoveDownloadManager(DownloadManager* manager) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- DCHECK(manager);
- RequestMap::iterator it = requests_.find(manager);
- if (it == requests_.end())
- return;
-
- const DownloadRequests& requests = it->second;
- DownloadRequests::const_iterator i = requests.begin();
- for (; i != requests.end(); ++i) {
- DownloadManagerMap::iterator dit = managers_.find(*i);
- if (dit != managers_.end()) {
- DCHECK(dit->second == manager);
- managers_.erase(dit);
- }
- }
-
- requests_.erase(it);
-}
-
-// Actions from the UI thread and run on the download thread
-
-// Open a download, or show it in a file explorer window. We run on this
-// thread to avoid blocking the UI with (potentially) slow Shell operations.
-// TODO(paulg): File 'stat' operations.
-#if !defined(OS_MACOSX)
-void DownloadFileManager::OnShowDownloadInShell(const FilePath& full_path) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- platform_util::ShowItemInFolder(full_path);
-}
-#endif
-
-// Launches the selected download using ShellExecute 'open' verb. For windows,
-// if there is a valid parent window, the 'safer' version will be used which can
-// display a modal dialog asking for user consent on dangerous files.
-#if !defined(OS_MACOSX)
-void DownloadFileManager::OnOpenDownloadInShell(const FilePath& full_path,
- const GURL& url,
- gfx::NativeView parent_window) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
-#if defined(OS_WIN)
- if (NULL != parent_window) {
- win_util::SaferOpenItemViaShell(parent_window, L"", full_path,
- UTF8ToWide(url.spec()));
- return;
- }
-#endif
- platform_util::OpenItem(full_path);
-}
-#endif // OS_MACOSX
-
-// The DownloadManager in the UI thread has provided a final name for the
-// download specified by 'id'. Rename the in progress download, and remove it
-// from our table if it has been completed or cancelled already.
-void DownloadFileManager::OnFinalDownloadName(int id,
- const FilePath& full_path,
- DownloadManager* manager) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- DownloadFileMap::iterator it = downloads_.find(id);
- if (it == downloads_.end())
- return;
-
- file_util::CreateDirectory(full_path.DirName());
-
- DownloadFile* download = it->second;
- if (download->Rename(full_path)) {
-#if defined(OS_MACOSX)
- // Done here because we only want to do this once; see
- // http://crbug.com/13120 for details.
- download->AnnotateWithSourceInformation();
-#endif
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(
- manager, &DownloadManager::DownloadRenamedToFinalName, id,
- full_path));
- } else {
- // Error. Between the time the UI thread generated 'full_path' to the time
- // this code runs, something happened that prevents us from renaming.
- DownloadManagerMap::iterator dmit = managers_.find(download->id());
- if (dmit != managers_.end()) {
- DownloadManager* dlm = dmit->second;
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(dlm, &DownloadManager::DownloadCancelled, id));
- } else {
- ChromeThread::PostTask(
- ChromeThread::IO, FROM_HERE,
- NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
- resource_dispatcher_host_,
- download->child_id(),
- download->request_id()));
- }
- }
-
- // If the download has completed before we got this final name, we remove it
- // from our in progress map.
- if (!download->in_progress()) {
- downloads_.erase(it);
- delete download;
- }
-
- if (downloads_.empty()) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
- }
-}
-
diff --git a/chrome/browser/download/download_file.h b/chrome/browser/download/download_file.h
index b905d83..97057a6 100644
--- a/chrome/browser/download/download_file.h
+++ b/chrome/browser/download/download_file.h
@@ -1,42 +1,6 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
-//
-// Objects that handle file operations for downloads, on the download thread.
-//
-// The DownloadFileManager owns a set of DownloadFile objects, each of which
-// represent one in progress download and performs the disk IO for that
-// download. The DownloadFileManager itself is a singleton object owned by the
-// ResourceDispatcherHost.
-//
-// The DownloadFileManager uses the file_thread for performing file write
-// operations, in order to avoid disk activity on either the IO (network) thread
-// and the UI thread. It coordinates the notifications from the network and UI.
-//
-// A typical download operation involves multiple threads:
-//
-// Updating an in progress download
-// io_thread
-// |----> data ---->|
-// file_thread (writes to disk)
-// |----> stats ---->|
-// ui_thread (feedback for user and
-// updates to history)
-//
-// Cancel operations perform the inverse order when triggered by a user action:
-// ui_thread (user click)
-// |----> cancel command ---->|
-// file_thread (close file)
-// |----> cancel command ---->|
-// io_thread (stops net IO
-// for download)
-//
-// The DownloadFileManager tracks download requests, mapping from a download
-// ID (unique integer created in the IO thread) to the DownloadManager for the
-// tab (profile) where the download was initiated. In the event of a tab closure
-// during a download, the DownloadFileManager will continue to route data to the
-// appropriate DownloadManager. In progress downloads are cancelled for a
-// DownloadManager that exits (such as when closing a profile).
#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_FILE_H_
#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_FILE_H_
@@ -49,48 +13,11 @@
#include "base/file_path.h"
#include "base/hash_tables.h"
#include "base/linked_ptr.h"
-#include "base/lock.h"
-#include "base/ref_counted.h"
-#include "base/timer.h"
+#include "chrome/browser/download/download_types.h"
#include "chrome/browser/power_save_blocker.h"
-#include "gfx/native_widget_types.h"
#include "googleurl/src/gurl.h"
-#include "net/base/file_stream.h"
-namespace net {
-class IOBuffer;
-}
struct DownloadCreateInfo;
-class DownloadManager;
-class ResourceDispatcherHost;
-class URLRequestContextGetter;
-
-// DownloadBuffer --------------------------------------------------------------
-
-// This container is created and populated on the io_thread, and passed to the
-// file_thread for writing. In order to avoid flooding the file_thread with too
-// many small write messages, each write is appended to the DownloadBuffer while
-// waiting for the task to run on the file_thread. Access to the write buffers
-// is synchronized via the lock. Each entry in 'contents' represents one data
-// buffer and its size in bytes.
-
-struct DownloadBuffer {
- Lock lock;
- typedef std::pair<net::IOBuffer*, int> Contents;
- std::vector<Contents> contents;
-};
-
-// DownloadSaveInfo ------------------------------------------------------------
-
-// Holds the information about how to save a download file.
-struct DownloadSaveInfo {
- FilePath file_path;
- linked_ptr<net::FileStream> file_stream;
-
- DownloadSaveInfo() { }
-};
-
-// DownloadFile ----------------------------------------------------------------
// These objects live exclusively on the download thread and handle the writing
// operations for one download. These objects live only for the duration that
@@ -175,128 +102,4 @@ class DownloadFile {
DISALLOW_COPY_AND_ASSIGN(DownloadFile);
};
-
-// DownloadFileManager ---------------------------------------------------------
-
-// Manages all in progress downloads.
-class DownloadFileManager
- : public base::RefCountedThreadSafe<DownloadFileManager> {
- public:
- explicit DownloadFileManager(ResourceDispatcherHost* rdh);
-
- // Called on shutdown on the UI thread.
- void Shutdown();
-
- // Called on the IO thread
- int GetNextId();
-
- // Handlers for notifications sent from the IO thread and run on the
- // download thread.
- void StartDownload(DownloadCreateInfo* info);
- void UpdateDownload(int id, DownloadBuffer* buffer);
- void CancelDownload(int id);
- void DownloadFinished(int id, DownloadBuffer* buffer);
-
- // Download the URL. Called on the UI thread and forwarded to the
- // ResourceDispatcherHost on the IO thread.
- void DownloadUrl(const GURL& url,
- const GURL& referrer,
- const std::string& referrer_charset,
- const DownloadSaveInfo& save_info,
- int render_process_host_id,
- int render_view_id,
- URLRequestContextGetter* request_context_getter);
-
- // Called on the UI thread to remove a download item or manager.
- void RemoveDownloadManager(DownloadManager* manager);
- void RemoveDownload(int id, DownloadManager* manager);
-
-#if !defined(OS_MACOSX)
- // The open and show methods run on the file thread, which does not work on
- // Mac OS X (which uses the UI thread for opens).
-
- // Handler for shell operations sent from the UI to the download thread.
- void OnShowDownloadInShell(const FilePath& full_path);
-
- // Handler to open or execute a downloaded file.
- void OnOpenDownloadInShell(const FilePath& full_path,
- const GURL& url,
- gfx::NativeView parent_window);
-#endif
-
- // The download manager has provided a final name for a download. Sent from
- // the UI thread and run on the download thread.
- void OnFinalDownloadName(int id, const FilePath& full_path,
- DownloadManager* download_manager);
-
- private:
- friend class base::RefCountedThreadSafe<DownloadFileManager>;
-
- ~DownloadFileManager();
-
- // Timer helpers for updating the UI about the current progress of a download.
- void StartUpdateTimer();
- void StopUpdateTimer();
- void UpdateInProgressDownloads();
-
- // Clean up helper that runs on the download thread.
- void OnShutdown();
-
- // Run on the IO thread to initiate the download of a URL.
- void OnDownloadUrl(const GURL& url,
- const GURL& referrer,
- const std::string& referrer_charset,
- const DownloadSaveInfo& save_info,
- int render_process_host_id,
- int render_view_id,
- URLRequestContextGetter* request_context_getter);
-
- // Handlers for notifications sent from the download thread and run on
- // the UI thread.
- void OnStartDownload(DownloadCreateInfo* info);
- void OnDownloadFinished(int id, int64 bytes_so_far);
-
- // Called only on UI thread to get the DownloadManager for a tab's profile.
- static DownloadManager* DownloadManagerFromRenderIds(int render_process_id,
- int review_view_id);
- DownloadManager* LookupManager(int download_id);
-
- // Called only on the download thread.
- DownloadFile* LookupDownload(int id);
-
- // Called on the UI thread to remove a download from the UI progress table.
- void RemoveDownloadFromUIProgress(int id);
-
- // Unique ID for each DownloadFile.
- int next_id_;
-
- // A map of all in progress downloads.
- typedef base::hash_map<int, DownloadFile*> DownloadFileMap;
- DownloadFileMap downloads_;
-
- // Throttle updates to the UI thread.
- base::RepeatingTimer<DownloadFileManager> update_timer_;
-
- ResourceDispatcherHost* resource_dispatcher_host_;
-
- // Tracking which DownloadManager to send data to, called only on UI thread.
- // DownloadManagerMap maps download IDs to their DownloadManager.
- typedef base::hash_map<int, DownloadManager*> DownloadManagerMap;
- DownloadManagerMap managers_;
-
- // RequestMap maps a DownloadManager to all in-progress download IDs.
- // Called only on the UI thread.
- typedef base::hash_set<int> DownloadRequests;
- typedef std::map<DownloadManager*, DownloadRequests> RequestMap;
- RequestMap requests_;
-
- // Used for progress updates on the UI thread, mapping download->id() to bytes
- // received so far. Written to by the file thread and read by the UI thread.
- typedef base::hash_map<int, int64> ProgressMap;
- ProgressMap ui_progress_;
- Lock progress_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(DownloadFileManager);
-};
-
#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_FILE_H_
diff --git a/chrome/browser/download/download_file_manager.cc b/chrome/browser/download/download_file_manager.cc
new file mode 100644
index 0000000..90a95f4
--- /dev/null
+++ b/chrome/browser/download/download_file_manager.cc
@@ -0,0 +1,507 @@
+// Copyright (c) 2010 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.
+
+#include "chrome/browser/download/download_file_manager.h"
+
+#include "base/file_util.h"
+#include "base/task.h"
+#include "base/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/history/download_types.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "googleurl/src/gurl.h"
+
+#if defined(OS_WIN)
+#include "app/win_util.h"
+#include "chrome/common/win_safe_util.h"
+#elif defined(OS_MACOSX)
+#include "chrome/browser/cocoa/file_metadata.h"
+#endif
+
+namespace {
+
+// Throttle updates to the UI thread so that a fast moving download doesn't
+// cause it to become unresponsive (in milliseconds).
+const int kUpdatePeriodMs = 500;
+
+} // namespace
+
+DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh)
+ : next_id_(0),
+ resource_dispatcher_host_(rdh) {
+}
+
+DownloadFileManager::~DownloadFileManager() {
+ // Check for clean shutdown.
+ DCHECK(downloads_.empty());
+ ui_progress_.clear();
+}
+
+// Called during the browser shutdown process to clean up any state (open files,
+// timers) that live on the download_thread_.
+void DownloadFileManager::Shutdown() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ StopUpdateTimer();
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &DownloadFileManager::OnShutdown));
+}
+
+// Cease download thread operations.
+void DownloadFileManager::OnShutdown() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ // Delete any partial downloads during shutdown.
+ for (DownloadFileMap::iterator it = downloads_.begin();
+ it != downloads_.end(); ++it) {
+ DownloadFile* download = it->second;
+ if (download->in_progress())
+ download->Cancel();
+ delete download;
+ }
+ downloads_.clear();
+}
+
+// Initiate a request for URL to be downloaded. Called from UI thread,
+// runs on IO thread.
+void DownloadFileManager::OnDownloadUrl(
+ const GURL& url,
+ const GURL& referrer,
+ const std::string& referrer_charset,
+ const DownloadSaveInfo& save_info,
+ int render_process_host_id,
+ int render_view_id,
+ URLRequestContextGetter* request_context_getter) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ URLRequestContext* context = request_context_getter->GetURLRequestContext();
+ context->set_referrer_charset(referrer_charset);
+
+ resource_dispatcher_host_->BeginDownload(url,
+ referrer,
+ save_info,
+ render_process_host_id,
+ render_view_id,
+ context);
+}
+
+// Notifications sent from the download thread and run on the UI thread.
+
+// Lookup the DownloadManager for this TabContents' profile and inform it of
+// a new download.
+// TODO(paulg): When implementing download restart via the Downloads tab,
+// there will be no 'render_process_id' or 'render_view_id'.
+void DownloadFileManager::OnStartDownload(DownloadCreateInfo* info) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ DownloadManager* manager = DownloadManagerFromRenderIds(info->child_id,
+ info->render_view_id);
+ if (!manager) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
+ resource_dispatcher_host_,
+ info->child_id,
+ info->request_id));
+ delete info;
+ return;
+ }
+
+ StartUpdateTimer();
+
+ // Add the download manager to our request maps for future updates. We want to
+ // be able to cancel all in progress downloads when a DownloadManager is
+ // deleted, such as when a profile is closed. We also want to be able to look
+ // up the DownloadManager associated with a given request without having to
+ // rely on using tab information, since a tab may be closed while a download
+ // initiated from that tab is still in progress.
+ DownloadRequests& downloads = requests_[manager];
+ downloads.insert(info->download_id);
+
+ // TODO(paulg): The manager will exist when restarts are implemented.
+ DownloadManagerMap::iterator dit = managers_.find(info->download_id);
+ if (dit == managers_.end())
+ managers_[info->download_id] = manager;
+ else
+ NOTREACHED();
+
+ // StartDownload will clean up |info|.
+ manager->StartDownload(info);
+}
+
+// Update the Download Manager with the finish state, and remove the request
+// tracking entries.
+void DownloadFileManager::OnDownloadFinished(int id,
+ int64 bytes_so_far) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ DownloadManager* manager = LookupManager(id);
+ if (manager)
+ manager->DownloadFinished(id, bytes_so_far);
+ RemoveDownload(id, manager);
+ RemoveDownloadFromUIProgress(id);
+}
+
+// Lookup one in-progress download.
+DownloadFile* DownloadFileManager::LookupDownload(int id) {
+ DownloadFileMap::iterator it = downloads_.find(id);
+ return it == downloads_.end() ? NULL : it->second;
+}
+
+// The UI progress is updated on the file thread and removed on the UI thread.
+void DownloadFileManager::RemoveDownloadFromUIProgress(int id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ AutoLock lock(progress_lock_);
+ if (ui_progress_.find(id) != ui_progress_.end())
+ ui_progress_.erase(id);
+}
+
+// Throttle updates to the UI thread by only posting update notifications at a
+// regularly controlled interval.
+void DownloadFileManager::StartUpdateTimer() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ if (!update_timer_.IsRunning()) {
+ update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs),
+ this, &DownloadFileManager::UpdateInProgressDownloads);
+ }
+}
+
+void DownloadFileManager::StopUpdateTimer() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ update_timer_.Stop();
+}
+
+// Our periodic timer has fired so send the UI thread updates on all in progress
+// downloads.
+void DownloadFileManager::UpdateInProgressDownloads() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ AutoLock lock(progress_lock_);
+ ProgressMap::iterator it = ui_progress_.begin();
+ for (; it != ui_progress_.end(); ++it) {
+ const int id = it->first;
+ DownloadManager* manager = LookupManager(id);
+ if (manager)
+ manager->UpdateDownload(id, it->second);
+ }
+}
+
+// Called on the IO thread once the ResourceDispatcherHost has decided that a
+// request is a download.
+int DownloadFileManager::GetNextId() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ return next_id_++;
+}
+
+// Notifications sent from the IO thread and run on the download thread:
+
+// The IO thread created 'info', but the download thread (this method) uses it
+// to create a DownloadFile, then passes 'info' to the UI thread where it is
+// finally consumed and deleted.
+void DownloadFileManager::StartDownload(DownloadCreateInfo* info) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ DCHECK(info);
+
+ DownloadFile* download = new DownloadFile(info);
+ if (!download->Initialize()) {
+ // Couldn't open, cancel the operation. The UI thread does not yet know
+ // about this download so we have to clean up 'info'. We need to get back
+ // to the IO thread to cancel the network request and CancelDownloadRequest
+ // on the UI thread is the safe way to do that.
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
+ resource_dispatcher_host_,
+ info->child_id,
+ info->request_id));
+ delete info;
+ delete download;
+ return;
+ }
+
+ DCHECK(LookupDownload(info->download_id) == NULL);
+ downloads_[info->download_id] = download;
+ info->path = download->full_path();
+ {
+ AutoLock lock(progress_lock_);
+ ui_progress_[info->download_id] = info->received_bytes;
+ }
+
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &DownloadFileManager::OnStartDownload, info));
+}
+
+// We don't forward an update to the UI thread here, since we want to throttle
+// the UI update rate via a periodic timer. If the user has cancelled the
+// download (in the UI thread), we may receive a few more updates before the IO
+// thread gets the cancel message: we just delete the data since the
+// DownloadFile has been deleted.
+void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ std::vector<DownloadBuffer::Contents> contents;
+ {
+ AutoLock auto_lock(buffer->lock);
+ contents.swap(buffer->contents);
+ }
+
+ DownloadFile* download = LookupDownload(id);
+ for (size_t i = 0; i < contents.size(); ++i) {
+ net::IOBuffer* data = contents[i].first;
+ const int data_len = contents[i].second;
+ if (download)
+ download->AppendDataToFile(data->data(), data_len);
+ data->Release();
+ }
+
+ if (download) {
+ AutoLock lock(progress_lock_);
+ ui_progress_[download->id()] = download->bytes_so_far();
+ }
+}
+
+void DownloadFileManager::DownloadFinished(int id, DownloadBuffer* buffer) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ delete buffer;
+ DownloadFileMap::iterator it = downloads_.find(id);
+ if (it != downloads_.end()) {
+ DownloadFile* download = it->second;
+ download->set_in_progress(false);
+
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &DownloadFileManager::OnDownloadFinished,
+ id, download->bytes_so_far()));
+
+ // We need to keep the download around until the UI thread has finalized
+ // the name.
+ if (download->path_renamed()) {
+ downloads_.erase(it);
+ delete download;
+ }
+ }
+
+ if (downloads_.empty())
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
+}
+
+// This method will be sent via a user action, or shutdown on the UI thread, and
+// run on the download thread. Since this message has been sent from the UI
+// thread, the download may have already completed and won't exist in our map.
+void DownloadFileManager::CancelDownload(int id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ DownloadFileMap::iterator it = downloads_.find(id);
+ if (it != downloads_.end()) {
+ DownloadFile* download = it->second;
+ download->set_in_progress(false);
+
+ download->Cancel();
+
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &DownloadFileManager::RemoveDownloadFromUIProgress,
+ download->id()));
+
+ if (download->path_renamed()) {
+ downloads_.erase(it);
+ delete download;
+ }
+ }
+
+ if (downloads_.empty()) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
+ }
+}
+
+void DownloadFileManager::DownloadUrl(
+ const GURL& url,
+ const GURL& referrer,
+ const std::string& referrer_charset,
+ const DownloadSaveInfo& save_info,
+ int render_process_host_id,
+ int render_view_id,
+ URLRequestContextGetter* request_context_getter) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this,
+ &DownloadFileManager::OnDownloadUrl,
+ url,
+ referrer,
+ referrer_charset,
+ save_info,
+ render_process_host_id,
+ render_view_id,
+ request_context_getter));
+}
+
+// Relate a download ID to its owning DownloadManager.
+DownloadManager* DownloadFileManager::LookupManager(int download_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ DownloadManagerMap::iterator it = managers_.find(download_id);
+ if (it != managers_.end())
+ return it->second;
+ return NULL;
+}
+
+// Utility function for look up table maintenance, called on the UI thread.
+// A manager may have multiple downloads in progress, so we just look up the
+// one download (id) and remove it from the set, and remove the set if it
+// becomes empty.
+void DownloadFileManager::RemoveDownload(int id, DownloadManager* manager) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ if (manager) {
+ RequestMap::iterator it = requests_.find(manager);
+ if (it != requests_.end()) {
+ DownloadRequests& downloads = it->second;
+ DownloadRequests::iterator rit = downloads.find(id);
+ if (rit != downloads.end())
+ downloads.erase(rit);
+ if (downloads.empty())
+ requests_.erase(it);
+ }
+ }
+
+ // A download can only have one manager, so remove it if it exists.
+ DownloadManagerMap::iterator dit = managers_.find(id);
+ if (dit != managers_.end())
+ managers_.erase(dit);
+}
+
+// Utility function for converting request IDs to a TabContents. Must be called
+// only on the UI thread since Profile operations may create UI objects, such as
+// the first call to profile->GetDownloadManager().
+// static
+DownloadManager* DownloadFileManager::DownloadManagerFromRenderIds(
+ int render_process_id, int render_view_id) {
+ TabContents* contents = tab_util::GetTabContentsByID(render_process_id,
+ render_view_id);
+ if (contents) {
+ Profile* profile = contents->profile();
+ if (profile)
+ return profile->GetDownloadManager();
+ }
+
+ return NULL;
+}
+
+// Called by DownloadManagers in their destructor, and only on the UI thread.
+void DownloadFileManager::RemoveDownloadManager(DownloadManager* manager) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ DCHECK(manager);
+ RequestMap::iterator it = requests_.find(manager);
+ if (it == requests_.end())
+ return;
+
+ const DownloadRequests& requests = it->second;
+ DownloadRequests::const_iterator i = requests.begin();
+ for (; i != requests.end(); ++i) {
+ DownloadManagerMap::iterator dit = managers_.find(*i);
+ if (dit != managers_.end()) {
+ DCHECK(dit->second == manager);
+ managers_.erase(dit);
+ }
+ }
+
+ requests_.erase(it);
+}
+
+// Actions from the UI thread and run on the download thread
+
+// Open a download, or show it in a file explorer window. We run on this
+// thread to avoid blocking the UI with (potentially) slow Shell operations.
+// TODO(paulg): File 'stat' operations.
+#if !defined(OS_MACOSX)
+void DownloadFileManager::OnShowDownloadInShell(const FilePath& full_path) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ platform_util::ShowItemInFolder(full_path);
+}
+#endif
+
+// Launches the selected download using ShellExecute 'open' verb. For windows,
+// if there is a valid parent window, the 'safer' version will be used which can
+// display a modal dialog asking for user consent on dangerous files.
+#if !defined(OS_MACOSX)
+void DownloadFileManager::OnOpenDownloadInShell(const FilePath& full_path,
+ const GURL& url,
+ gfx::NativeView parent_window) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+#if defined(OS_WIN)
+ if (NULL != parent_window) {
+ win_util::SaferOpenItemViaShell(parent_window, L"", full_path,
+ UTF8ToWide(url.spec()));
+ return;
+ }
+#endif
+ platform_util::OpenItem(full_path);
+}
+#endif // OS_MACOSX
+
+// The DownloadManager in the UI thread has provided a final name for the
+// download specified by 'id'. Rename the in progress download, and remove it
+// from our table if it has been completed or cancelled already.
+void DownloadFileManager::OnFinalDownloadName(int id,
+ const FilePath& full_path,
+ DownloadManager* manager) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ DownloadFileMap::iterator it = downloads_.find(id);
+ if (it == downloads_.end())
+ return;
+
+ file_util::CreateDirectory(full_path.DirName());
+
+ DownloadFile* download = it->second;
+ if (download->Rename(full_path)) {
+#if defined(OS_MACOSX)
+ // Done here because we only want to do this once; see
+ // http://crbug.com/13120 for details.
+ download->AnnotateWithSourceInformation();
+#endif
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ manager, &DownloadManager::DownloadRenamedToFinalName, id,
+ full_path));
+ } else {
+ // Error. Between the time the UI thread generated 'full_path' to the time
+ // this code runs, something happened that prevents us from renaming.
+ DownloadManagerMap::iterator dmit = managers_.find(download->id());
+ if (dmit != managers_.end()) {
+ DownloadManager* dlm = dmit->second;
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(dlm, &DownloadManager::DownloadCancelled, id));
+ } else {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableFunction(&DownloadManager::OnCancelDownloadRequest,
+ resource_dispatcher_host_,
+ download->child_id(),
+ download->request_id()));
+ }
+ }
+
+ // If the download has completed before we got this final name, we remove it
+ // from our in progress map.
+ if (!download->in_progress()) {
+ downloads_.erase(it);
+ delete download;
+ }
+
+ if (downloads_.empty()) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &DownloadFileManager::StopUpdateTimer));
+ }
+}
+
diff --git a/chrome/browser/download/download_file_manager.h b/chrome/browser/download/download_file_manager.h
new file mode 100644
index 0000000..f4c1a5e
--- /dev/null
+++ b/chrome/browser/download/download_file_manager.h
@@ -0,0 +1,183 @@
+// Copyright (c) 2010 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 DownloadFileManager owns a set of DownloadFile objects, each of which
+// represent one in progress download and performs the disk IO for that
+// download. The DownloadFileManager itself is a singleton object owned by the
+// ResourceDispatcherHost.
+//
+// The DownloadFileManager uses the file_thread for performing file write
+// operations, in order to avoid disk activity on either the IO (network) thread
+// and the UI thread. It coordinates the notifications from the network and UI.
+//
+// A typical download operation involves multiple threads:
+//
+// Updating an in progress download
+// io_thread
+// |----> data ---->|
+// file_thread (writes to disk)
+// |----> stats ---->|
+// ui_thread (feedback for user and
+// updates to history)
+//
+// Cancel operations perform the inverse order when triggered by a user action:
+// ui_thread (user click)
+// |----> cancel command ---->|
+// file_thread (close file)
+// |----> cancel command ---->|
+// io_thread (stops net IO
+// for download)
+//
+// The DownloadFileManager tracks download requests, mapping from a download
+// ID (unique integer created in the IO thread) to the DownloadManager for the
+// tab (profile) where the download was initiated. In the event of a tab closure
+// during a download, the DownloadFileManager will continue to route data to the
+// appropriate DownloadManager. In progress downloads are cancelled for a
+// DownloadManager that exits (such as when closing a profile).
+
+#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_FILE_MANAGER_H_
+#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_FILE_MANAGER_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/hash_tables.h"
+#include "base/lock.h"
+#include "base/ref_counted.h"
+#include "base/timer.h"
+#include "gfx/native_widget_types.h"
+
+struct DownloadBuffer;
+struct DownloadCreateInfo;
+struct DownloadSaveInfo;
+class DownloadFile;
+class DownloadManager;
+class FilePath;
+class GURL;
+class ResourceDispatcherHost;
+class URLRequestContextGetter;
+
+// Manages all in progress downloads.
+class DownloadFileManager
+ : public base::RefCountedThreadSafe<DownloadFileManager> {
+ public:
+ explicit DownloadFileManager(ResourceDispatcherHost* rdh);
+
+ // Called on shutdown on the UI thread.
+ void Shutdown();
+
+ // Called on the IO thread
+ int GetNextId();
+
+ // Handlers for notifications sent from the IO thread and run on the
+ // download thread.
+ void StartDownload(DownloadCreateInfo* info);
+ void UpdateDownload(int id, DownloadBuffer* buffer);
+ void CancelDownload(int id);
+ void DownloadFinished(int id, DownloadBuffer* buffer);
+
+ // Download the URL. Called on the UI thread and forwarded to the
+ // ResourceDispatcherHost on the IO thread.
+ void DownloadUrl(const GURL& url,
+ const GURL& referrer,
+ const std::string& referrer_charset,
+ const DownloadSaveInfo& save_info,
+ int render_process_host_id,
+ int render_view_id,
+ URLRequestContextGetter* request_context_getter);
+
+ // Called on the UI thread to remove a download item or manager.
+ void RemoveDownloadManager(DownloadManager* manager);
+ void RemoveDownload(int id, DownloadManager* manager);
+
+#if !defined(OS_MACOSX)
+ // The open and show methods run on the file thread, which does not work on
+ // Mac OS X (which uses the UI thread for opens).
+
+ // Handler for shell operations sent from the UI to the download thread.
+ void OnShowDownloadInShell(const FilePath& full_path);
+
+ // Handler to open or execute a downloaded file.
+ void OnOpenDownloadInShell(const FilePath& full_path,
+ const GURL& url,
+ gfx::NativeView parent_window);
+#endif
+
+ // The download manager has provided a final name for a download. Sent from
+ // the UI thread and run on the download thread.
+ void OnFinalDownloadName(int id, const FilePath& full_path,
+ DownloadManager* download_manager);
+
+ private:
+ friend class base::RefCountedThreadSafe<DownloadFileManager>;
+
+ ~DownloadFileManager();
+
+ // Timer helpers for updating the UI about the current progress of a download.
+ void StartUpdateTimer();
+ void StopUpdateTimer();
+ void UpdateInProgressDownloads();
+
+ // Clean up helper that runs on the download thread.
+ void OnShutdown();
+
+ // Run on the IO thread to initiate the download of a URL.
+ void OnDownloadUrl(const GURL& url,
+ const GURL& referrer,
+ const std::string& referrer_charset,
+ const DownloadSaveInfo& save_info,
+ int render_process_host_id,
+ int render_view_id,
+ URLRequestContextGetter* request_context_getter);
+
+ // Handlers for notifications sent from the download thread and run on
+ // the UI thread.
+ void OnStartDownload(DownloadCreateInfo* info);
+ void OnDownloadFinished(int id, int64 bytes_so_far);
+
+ // Called only on UI thread to get the DownloadManager for a tab's profile.
+ static DownloadManager* DownloadManagerFromRenderIds(int render_process_id,
+ int review_view_id);
+ DownloadManager* LookupManager(int download_id);
+
+ // Called only on the download thread.
+ DownloadFile* LookupDownload(int id);
+
+ // Called on the UI thread to remove a download from the UI progress table.
+ void RemoveDownloadFromUIProgress(int id);
+
+ // Unique ID for each DownloadFile.
+ int next_id_;
+
+ // A map of all in progress downloads.
+ typedef base::hash_map<int, DownloadFile*> DownloadFileMap;
+ DownloadFileMap downloads_;
+
+ // Throttle updates to the UI thread.
+ base::RepeatingTimer<DownloadFileManager> update_timer_;
+
+ ResourceDispatcherHost* resource_dispatcher_host_;
+
+ // Tracking which DownloadManager to send data to, called only on UI thread.
+ // DownloadManagerMap maps download IDs to their DownloadManager.
+ typedef base::hash_map<int, DownloadManager*> DownloadManagerMap;
+ DownloadManagerMap managers_;
+
+ // RequestMap maps a DownloadManager to all in-progress download IDs.
+ // Called only on the UI thread.
+ typedef base::hash_set<int> DownloadRequests;
+ typedef std::map<DownloadManager*, DownloadRequests> RequestMap;
+ RequestMap requests_;
+
+ // Used for progress updates on the UI thread, mapping download->id() to bytes
+ // received so far. Written to by the file thread and read by the UI thread.
+ typedef base::hash_map<int, int64> ProgressMap;
+ ProgressMap ui_progress_;
+ Lock progress_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadFileManager);
+};
+
+#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_FILE_MANAGER_H_
diff --git a/chrome/browser/download/download_item.cc b/chrome/browser/download/download_item.cc
new file mode 100644
index 0000000..d72b6d4
--- /dev/null
+++ b/chrome/browser/download/download_item.cc
@@ -0,0 +1,235 @@
+// Copyright (c) 2010 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.
+
+#include "chrome/browser/download/download_item.h"
+
+#include "base/logging.h"
+#include "base/timer.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/history/download_types.h"
+
+namespace {
+
+// Update frequency (milliseconds).
+const int kUpdateTimeMs = 1000;
+
+} // namespace
+
+// Constructor for reading from the history service.
+DownloadItem::DownloadItem(const DownloadCreateInfo& info)
+ : id_(-1),
+ full_path_(info.path),
+ url_(info.url),
+ referrer_url_(info.referrer_url),
+ mime_type_(info.mime_type),
+ original_mime_type_(info.original_mime_type),
+ total_bytes_(info.total_bytes),
+ received_bytes_(info.received_bytes),
+ start_tick_(base::TimeTicks()),
+ state_(static_cast<DownloadState>(info.state)),
+ start_time_(info.start_time),
+ db_handle_(info.db_handle),
+ manager_(NULL),
+ is_paused_(false),
+ open_when_complete_(false),
+ safety_state_(SAFE),
+ auto_opened_(false),
+ original_name_(info.original_name),
+ render_process_id_(-1),
+ request_id_(-1),
+ save_as_(false),
+ is_otr_(false),
+ is_extension_install_(info.is_extension_install),
+ name_finalized_(false),
+ is_temporary_(false) {
+ if (state_ == IN_PROGRESS)
+ state_ = CANCELLED;
+ Init(false /* don't start progress timer */);
+}
+
+// Constructor for DownloadItem created via user action in the main thread.
+DownloadItem::DownloadItem(int32 download_id,
+ const FilePath& path,
+ int path_uniquifier,
+ const GURL& url,
+ const GURL& referrer_url,
+ const std::string& mime_type,
+ const std::string& original_mime_type,
+ const FilePath& original_name,
+ const base::Time start_time,
+ int64 download_size,
+ int render_process_id,
+ int request_id,
+ bool is_dangerous,
+ bool save_as,
+ bool is_otr,
+ bool is_extension_install,
+ bool is_temporary)
+ : id_(download_id),
+ full_path_(path),
+ path_uniquifier_(path_uniquifier),
+ url_(url),
+ referrer_url_(referrer_url),
+ mime_type_(mime_type),
+ original_mime_type_(original_mime_type),
+ total_bytes_(download_size),
+ received_bytes_(0),
+ start_tick_(base::TimeTicks::Now()),
+ state_(IN_PROGRESS),
+ start_time_(start_time),
+ db_handle_(DownloadManager::kUninitializedHandle),
+ manager_(NULL),
+ is_paused_(false),
+ open_when_complete_(false),
+ safety_state_(is_dangerous ? DANGEROUS : SAFE),
+ auto_opened_(false),
+ original_name_(original_name),
+ render_process_id_(render_process_id),
+ request_id_(request_id),
+ save_as_(save_as),
+ is_otr_(is_otr),
+ is_extension_install_(is_extension_install),
+ name_finalized_(false),
+ is_temporary_(is_temporary) {
+ Init(true /* start progress timer */);
+}
+
+void DownloadItem::Init(bool start_timer) {
+ file_name_ = full_path_.BaseName();
+ if (start_timer)
+ StartProgressTimer();
+}
+
+DownloadItem::~DownloadItem() {
+ state_ = REMOVING;
+ UpdateObservers();
+}
+
+void DownloadItem::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void DownloadItem::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void DownloadItem::UpdateObservers() {
+ FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this));
+}
+
+void DownloadItem::NotifyObserversDownloadFileCompleted() {
+ FOR_EACH_OBSERVER(Observer, observers_, OnDownloadFileCompleted(this));
+}
+
+void DownloadItem::NotifyObserversDownloadOpened() {
+ FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this));
+}
+
+// If we've received more data than we were expecting (bad server info?), revert
+// to 'unknown size mode'.
+void DownloadItem::UpdateSize(int64 bytes_so_far) {
+ received_bytes_ = bytes_so_far;
+ if (received_bytes_ > total_bytes_)
+ total_bytes_ = 0;
+}
+
+// Updates from the download thread may have been posted while this download
+// was being cancelled in the UI thread, so we'll accept them unless we're
+// complete.
+void DownloadItem::Update(int64 bytes_so_far) {
+ if (state_ == COMPLETE) {
+ NOTREACHED();
+ return;
+ }
+ UpdateSize(bytes_so_far);
+ UpdateObservers();
+}
+
+// Triggered by a user action.
+void DownloadItem::Cancel(bool update_history) {
+ if (state_ != IN_PROGRESS) {
+ // Small downloads might be complete before this method has a chance to run.
+ return;
+ }
+ state_ = CANCELLED;
+ UpdateObservers();
+ StopProgressTimer();
+ if (update_history)
+ manager_->DownloadCancelled(id_);
+}
+
+void DownloadItem::Finished(int64 size) {
+ state_ = COMPLETE;
+ UpdateSize(size);
+ StopProgressTimer();
+}
+
+void DownloadItem::Remove(bool delete_on_disk) {
+ Cancel(true);
+ state_ = REMOVING;
+ if (delete_on_disk)
+ manager_->DeleteDownload(full_path_);
+ manager_->RemoveDownload(db_handle_);
+ // We have now been deleted.
+}
+
+void DownloadItem::StartProgressTimer() {
+ update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdateTimeMs), this,
+ &DownloadItem::UpdateObservers);
+}
+
+void DownloadItem::StopProgressTimer() {
+ update_timer_.Stop();
+}
+
+bool DownloadItem::TimeRemaining(base::TimeDelta* remaining) const {
+ if (total_bytes_ <= 0)
+ return false; // We never received the content_length for this download.
+
+ int64 speed = CurrentSpeed();
+ if (speed == 0)
+ return false;
+
+ *remaining =
+ base::TimeDelta::FromSeconds((total_bytes_ - received_bytes_) / speed);
+ return true;
+}
+
+int64 DownloadItem::CurrentSpeed() const {
+ base::TimeDelta diff = base::TimeTicks::Now() - start_tick_;
+ int64 diff_ms = diff.InMilliseconds();
+ return diff_ms == 0 ? 0 : received_bytes_ * 1000 / diff_ms;
+}
+
+int DownloadItem::PercentComplete() const {
+ int percent = -1;
+ if (total_bytes_ > 0)
+ percent = static_cast<int>(received_bytes_ * 100.0 / total_bytes_);
+ return percent;
+}
+
+void DownloadItem::Rename(const FilePath& full_path) {
+ DCHECK(!full_path.empty());
+ full_path_ = full_path;
+ file_name_ = full_path_.BaseName();
+}
+
+void DownloadItem::TogglePause() {
+ DCHECK(state_ == IN_PROGRESS);
+ manager_->PauseDownload(id_, !is_paused_);
+ is_paused_ = !is_paused_;
+ UpdateObservers();
+}
+
+FilePath DownloadItem::GetFileName() const {
+ if (safety_state_ == DownloadItem::SAFE)
+ return file_name_;
+ if (path_uniquifier_ > 0) {
+ FilePath name(original_name_);
+ download_util::AppendNumberToPath(&name, path_uniquifier_);
+ return name;
+ }
+ return original_name_;
+}
diff --git a/chrome/browser/download/download_item.h b/chrome/browser/download/download_item.h
new file mode 100644
index 0000000..1a1b627
--- /dev/null
+++ b/chrome/browser/download/download_item.h
@@ -0,0 +1,299 @@
+// Copyright (c) 2010 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.
+//
+// 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:
+// DownloadItem::Observer:
+// - allows observers to receive notifications about one download from start
+// to completion
+// Use AddObserver() / RemoveObserver() on the appropriate download object to
+// receive state updates.
+
+#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_H_
+#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/observer_list.h"
+#include "base/time.h"
+#include "base/timer.h"
+#include "googleurl/src/gurl.h"
+
+class DownloadManager;
+struct DownloadCreateInfo;
+
+// 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
+ };
+
+ enum SafetyState {
+ SAFE = 0,
+ DANGEROUS,
+ DANGEROUS_BUT_VALIDATED // Dangerous but the user confirmed the download.
+ };
+
+ // 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;
+
+ // Called when a downloaded file has been completed.
+ virtual void OnDownloadFileCompleted(DownloadItem* download) = 0;
+
+ // Called when a downloaded file has been opened.
+ virtual void OnDownloadOpened(DownloadItem* download) = 0;
+
+ protected:
+ virtual ~Observer() {}
+ };
+
+ // Constructing from persistent store:
+ explicit DownloadItem(const DownloadCreateInfo& info);
+
+ // Constructing from user action:
+ DownloadItem(int32 download_id,
+ const FilePath& path,
+ int path_uniquifier,
+ const GURL& url,
+ const GURL& referrer_url,
+ const std::string& mime_type,
+ const std::string& original_mime_type,
+ const FilePath& original_name,
+ const base::Time start_time,
+ int64 download_size,
+ int render_process_id,
+ int request_id,
+ bool is_dangerous,
+ bool save_as,
+ bool is_otr,
+ bool is_extension_install,
+ bool is_temporary);
+
+ ~DownloadItem();
+
+ void Init(bool start_timer);
+
+ // Public API
+
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ // Notifies our observers periodically.
+ void UpdateObservers();
+
+ // Notifies our observers the downloaded file has been completed.
+ void NotifyObserversDownloadFileCompleted();
+
+ // Notifies our observers the downloaded file has been opened.
+ void NotifyObserversDownloadOpened();
+
+ // 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. If
+ // |delete_file| is true, the file is deleted on the disk.
+ void Remove(bool delete_file);
+
+ // 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(base::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 FilePath& full_path);
+
+ // Allow the user to temporarily pause a download or resume a paused download.
+ void TogglePause();
+
+ // Accessors
+ DownloadState state() const { return state_; }
+ FilePath file_name() const { return file_name_; }
+ void set_file_name(const FilePath& name) { file_name_ = name; }
+ FilePath full_path() const { return full_path_; }
+ void set_full_path(const FilePath& path) { full_path_ = path; }
+ int path_uniquifier() const { return path_uniquifier_; }
+ void set_path_uniquifier(int uniquifier) { path_uniquifier_ = uniquifier; }
+ GURL url() const { return url_; }
+ GURL referrer_url() const { return referrer_url_; }
+ std::string mime_type() const { return mime_type_; }
+ std::string original_mime_type() const { return original_mime_type_; }
+ 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_; }
+ base::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_; }
+ SafetyState safety_state() const { return safety_state_; }
+ void set_safety_state(SafetyState safety_state) {
+ safety_state_ = safety_state;
+ }
+ bool auto_opened() { return auto_opened_; }
+ void set_auto_opened(bool auto_opened) { auto_opened_ = auto_opened; }
+ FilePath original_name() const { return original_name_; }
+ void set_original_name(const FilePath& name) { original_name_ = name; }
+ bool save_as() const { return save_as_; }
+ bool is_otr() const { return is_otr_; }
+ bool is_extension_install() const { return is_extension_install_; }
+ bool name_finalized() const { return name_finalized_; }
+ void set_name_finalized(bool name_finalized) {
+ name_finalized_ = name_finalized;
+ }
+ bool is_temporary() const { return is_temporary_; }
+ void set_is_temporary(bool is_temporary) { is_temporary_ = is_temporary; }
+
+ // Returns the file-name that should be reported to the user, which is
+ // file_name_ for safe downloads and original_name_ for dangerous ones with
+ // the uniquifier number.
+ FilePath GetFileName() const;
+
+ 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
+ FilePath full_path_;
+
+ // A number that should be appended to the path to make it unique, or 0 if the
+ // path should be used as is.
+ int path_uniquifier_;
+
+ // Short display version of the file
+ FilePath file_name_;
+
+ // The URL from whence we came.
+ GURL url_;
+
+ // The URL of the page that initiated the download.
+ GURL referrer_url_;
+
+ // The mimetype of the download
+ std::string mime_type_;
+
+ // The value of the content type header received when downloading
+ // this item. |mime_type_| may be different because of type sniffing.
+ std::string original_mime_type_;
+
+ // Total bytes expected
+ int64 total_bytes_;
+
+ // Current received bytes
+ int64 received_bytes_;
+
+ // Start time for calculating remaining time
+ base::TimeTicks 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
+ base::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_;
+
+ // Whether the download is considered potentially safe or dangerous
+ // (executable files are typically considered dangerous).
+ SafetyState safety_state_;
+
+ // Whether the download was auto-opened. We set this rather than using
+ // an observer as it's frequently possible for the download to be auto opened
+ // before the observer is added.
+ bool auto_opened_;
+
+ // Dangerous download are given temporary names until the user approves them.
+ // This stores their original name.
+ FilePath original_name_;
+
+ // For canceling or pausing requests.
+ int render_process_id_;
+ int request_id_;
+
+ // True if the item was downloaded as a result of 'save as...'
+ bool save_as_;
+
+ // True if the download was initiated in an incognito window.
+ bool is_otr_;
+
+ // True if the item was downloaded for an extension installation.
+ bool is_extension_install_;
+
+ // True if the filename is finalized.
+ bool name_finalized_;
+
+ // True if the item was downloaded temporarily.
+ bool is_temporary_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadItem);
+};
+
+#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_ITEM_H_
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index 2dc4c1e..457a34a 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -8,7 +8,7 @@
#include "base/i18n/number_formatting.h"
#include "base/i18n/rtl.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/save_package.h"
#include "chrome/common/time_format.h"
#include "grit/generated_resources.h"
diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc
index c43f18e..26d1d54 100644
--- a/chrome/browser/download/download_manager.cc
+++ b/chrome/browser/download/download_manager.cc
@@ -9,48 +9,39 @@
#include "base/callback.h"
#include "base/file_util.h"
#include "base/logging.h"
-#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/rand_util.h"
-#include "base/stl_util-inl.h"
-#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "base/task.h"
-#include "base/thread.h"
-#include "base/timer.h"
#include "build/build_config.h"
+#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
-#include "chrome/browser/download/download_file.h"
+#include "chrome/browser/download/download_file_manager.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_install_ui.h"
#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/history/download_types.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/platform_util.h"
-#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_util.h"
-#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/user_script.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "googleurl/src/gurl.h"
-#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/mime_util.h"
#include "net/base/net_util.h"
-#include "net/url_request/url_request_context.h"
#if defined(OS_WIN)
#include "app/win_util.h"
@@ -60,25 +51,6 @@
namespace {
-// Periodically update our observers.
-class DownloadItemUpdateTask : public Task {
- public:
- explicit DownloadItemUpdateTask(DownloadItem* item) : item_(item) {}
- void Run() { if (item_) item_->UpdateObservers(); }
-
- private:
- DownloadItem* item_;
-};
-
-// Update frequency (milliseconds).
-const int kUpdateTimeMs = 1000;
-
-// Our download table ID starts at 1, so we use 0 to represent a download that
-// has started, but has not yet had its data persisted in the table. We use fake
-// database handles in incognito mode starting at -1 and progressively getting
-// more negative.
-const int kUninitializedHandle = 0;
-
// Used to sort download items based on descending start time.
bool CompareStartTime(DownloadItem* first, DownloadItem* second) {
return first->start_time() > second->start_time();
@@ -94,226 +66,12 @@ void DeleteDownloadedFile(const FilePath& path) {
} // namespace
-// DownloadItem implementation -------------------------------------------------
-
-// Constructor for reading from the history service.
-DownloadItem::DownloadItem(const DownloadCreateInfo& info)
- : id_(-1),
- full_path_(info.path),
- url_(info.url),
- referrer_url_(info.referrer_url),
- mime_type_(info.mime_type),
- original_mime_type_(info.original_mime_type),
- total_bytes_(info.total_bytes),
- received_bytes_(info.received_bytes),
- start_tick_(base::TimeTicks()),
- state_(static_cast<DownloadState>(info.state)),
- start_time_(info.start_time),
- db_handle_(info.db_handle),
- manager_(NULL),
- is_paused_(false),
- open_when_complete_(false),
- safety_state_(SAFE),
- auto_opened_(false),
- original_name_(info.original_name),
- render_process_id_(-1),
- request_id_(-1),
- save_as_(false),
- is_otr_(false),
- is_extension_install_(info.is_extension_install),
- name_finalized_(false),
- is_temporary_(false) {
- if (state_ == IN_PROGRESS)
- state_ = CANCELLED;
- Init(false /* don't start progress timer */);
-}
-
-// Constructor for DownloadItem created via user action in the main thread.
-DownloadItem::DownloadItem(int32 download_id,
- const FilePath& path,
- int path_uniquifier,
- const GURL& url,
- const GURL& referrer_url,
- const std::string& mime_type,
- const std::string& original_mime_type,
- const FilePath& original_name,
- const base::Time start_time,
- int64 download_size,
- int render_process_id,
- int request_id,
- bool is_dangerous,
- bool save_as,
- bool is_otr,
- bool is_extension_install,
- bool is_temporary)
- : id_(download_id),
- full_path_(path),
- path_uniquifier_(path_uniquifier),
- url_(url),
- referrer_url_(referrer_url),
- mime_type_(mime_type),
- original_mime_type_(original_mime_type),
- total_bytes_(download_size),
- received_bytes_(0),
- start_tick_(base::TimeTicks::Now()),
- state_(IN_PROGRESS),
- start_time_(start_time),
- db_handle_(kUninitializedHandle),
- manager_(NULL),
- is_paused_(false),
- open_when_complete_(false),
- safety_state_(is_dangerous ? DANGEROUS : SAFE),
- auto_opened_(false),
- original_name_(original_name),
- render_process_id_(render_process_id),
- request_id_(request_id),
- save_as_(save_as),
- is_otr_(is_otr),
- is_extension_install_(is_extension_install),
- name_finalized_(false),
- is_temporary_(is_temporary) {
- Init(true /* start progress timer */);
-}
-
-void DownloadItem::Init(bool start_timer) {
- file_name_ = full_path_.BaseName();
- if (start_timer)
- StartProgressTimer();
-}
-
-DownloadItem::~DownloadItem() {
- state_ = REMOVING;
- UpdateObservers();
-}
-
-void DownloadItem::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void DownloadItem::RemoveObserver(Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void DownloadItem::UpdateObservers() {
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this));
-}
-
-void DownloadItem::NotifyObserversDownloadFileCompleted() {
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadFileCompleted(this));
-}
-
-void DownloadItem::NotifyObserversDownloadOpened() {
- FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this));
-}
-
-// If we've received more data than we were expecting (bad server info?), revert
-// to 'unknown size mode'.
-void DownloadItem::UpdateSize(int64 bytes_so_far) {
- received_bytes_ = bytes_so_far;
- if (received_bytes_ > total_bytes_)
- total_bytes_ = 0;
-}
-
-// Updates from the download thread may have been posted while this download
-// was being cancelled in the UI thread, so we'll accept them unless we're
-// complete.
-void DownloadItem::Update(int64 bytes_so_far) {
- if (state_ == COMPLETE) {
- NOTREACHED();
- return;
- }
- UpdateSize(bytes_so_far);
- UpdateObservers();
-}
-
-// Triggered by a user action.
-void DownloadItem::Cancel(bool update_history) {
- if (state_ != IN_PROGRESS) {
- // Small downloads might be complete before this method has a chance to run.
- return;
- }
- state_ = CANCELLED;
- UpdateObservers();
- StopProgressTimer();
- if (update_history)
- manager_->DownloadCancelled(id_);
-}
-
-void DownloadItem::Finished(int64 size) {
- state_ = COMPLETE;
- UpdateSize(size);
- StopProgressTimer();
-}
-
-void DownloadItem::Remove(bool delete_on_disk) {
- Cancel(true);
- state_ = REMOVING;
- if (delete_on_disk)
- manager_->DeleteDownload(full_path_);
- manager_->RemoveDownload(db_handle_);
- // We have now been deleted.
-}
-
-void DownloadItem::StartProgressTimer() {
- update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdateTimeMs), this,
- &DownloadItem::UpdateObservers);
-}
-
-void DownloadItem::StopProgressTimer() {
- update_timer_.Stop();
-}
-
-bool DownloadItem::TimeRemaining(base::TimeDelta* remaining) const {
- if (total_bytes_ <= 0)
- return false; // We never received the content_length for this download.
-
- int64 speed = CurrentSpeed();
- if (speed == 0)
- return false;
-
- *remaining =
- base::TimeDelta::FromSeconds((total_bytes_ - received_bytes_) / speed);
- return true;
-}
-
-int64 DownloadItem::CurrentSpeed() const {
- base::TimeDelta diff = base::TimeTicks::Now() - start_tick_;
- int64 diff_ms = diff.InMilliseconds();
- return diff_ms == 0 ? 0 : received_bytes_ * 1000 / diff_ms;
-}
-
-int DownloadItem::PercentComplete() const {
- int percent = -1;
- if (total_bytes_ > 0)
- percent = static_cast<int>(received_bytes_ * 100.0 / total_bytes_);
- return percent;
-}
-
-void DownloadItem::Rename(const FilePath& full_path) {
- DCHECK(!full_path.empty());
- full_path_ = full_path;
- file_name_ = full_path_.BaseName();
-}
-
-void DownloadItem::TogglePause() {
- DCHECK(state_ == IN_PROGRESS);
- manager_->PauseDownload(id_, !is_paused_);
- is_paused_ = !is_paused_;
- UpdateObservers();
-}
-
-FilePath DownloadItem::GetFileName() const {
- if (safety_state_ == DownloadItem::SAFE)
- return file_name_;
- if (path_uniquifier_ > 0) {
- FilePath name(original_name_);
- download_util::AppendNumberToPath(&name, path_uniquifier_);
- return name;
- }
- return original_name_;
-}
-
-// DownloadManager implementation ----------------------------------------------
+// Our download table ID starts at 1, so we use 0 to represent a download that
+// has started, but has not yet had its data persisted in the table. We use fake
+// database handles in incognito mode starting at -1 and progressively getting
+// more negative.
+// static
+const int DownloadManager::kUninitializedHandle = 0;
// static
void DownloadManager::RegisterUserPrefs(PrefService* prefs) {
diff --git a/chrome/browser/download/download_manager.h b/chrome/browser/download/download_manager.h
index ee9dff8..704012d 100644
--- a/chrome/browser/download/download_manager.h
+++ b/chrome/browser/download/download_manager.h
@@ -7,18 +7,10 @@
// 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
@@ -42,20 +34,16 @@
#include "base/basictypes.h"
#include "base/file_path.h"
-#include "base/hash_tables.h"
#include "base/observer_list.h"
#include "base/ref_counted.h"
#include "base/time.h"
-#include "base/timer.h"
#include "chrome/browser/cancelable_request.h"
-#include "chrome/browser/history/download_types.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/pref_member.h"
#include "chrome/browser/shell_dialogs.h"
class DownloadFileManager;
-class DownloadItemView;
-class DownloadManager;
+class DownloadItem;
class GURL;
class PrefService;
class Profile;
@@ -64,282 +52,6 @@ class URLRequestContextGetter;
class TabContents;
struct DownloadSaveInfo;
-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
- };
-
- enum SafetyState {
- SAFE = 0,
- DANGEROUS,
- DANGEROUS_BUT_VALIDATED // Dangerous but the user confirmed the download.
- };
-
- // 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;
-
- // Called when a downloaded file has been completed.
- virtual void OnDownloadFileCompleted(DownloadItem* download) = 0;
-
- // Called when a downloaded file has been opened.
- virtual void OnDownloadOpened(DownloadItem* download) = 0;
-
- protected:
- virtual ~Observer() {}
- };
-
- // Constructing from persistent store:
- explicit DownloadItem(const DownloadCreateInfo& info);
-
- // Constructing from user action:
- DownloadItem(int32 download_id,
- const FilePath& path,
- int path_uniquifier,
- const GURL& url,
- const GURL& referrer_url,
- const std::string& mime_type,
- const std::string& original_mime_type,
- const FilePath& original_name,
- const base::Time start_time,
- int64 download_size,
- int render_process_id,
- int request_id,
- bool is_dangerous,
- bool save_as,
- bool is_otr,
- bool is_extension_install,
- bool is_temporary);
-
- ~DownloadItem();
-
- void Init(bool start_timer);
-
- // Public API
-
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-
- // Notifies our observers periodically.
- void UpdateObservers();
-
- // Notifies our observers the downloaded file has been completed.
- void NotifyObserversDownloadFileCompleted();
-
- // Notifies our observers the downloaded file has been opened.
- void NotifyObserversDownloadOpened();
-
- // 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. If
- // |delete_file| is true, the file is deleted on the disk.
- void Remove(bool delete_file);
-
- // 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(base::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 FilePath& full_path);
-
- // Allow the user to temporarily pause a download or resume a paused download.
- void TogglePause();
-
- // Accessors
- DownloadState state() const { return state_; }
- FilePath file_name() const { return file_name_; }
- void set_file_name(const FilePath& name) { file_name_ = name; }
- FilePath full_path() const { return full_path_; }
- void set_full_path(const FilePath& path) { full_path_ = path; }
- int path_uniquifier() const { return path_uniquifier_; }
- void set_path_uniquifier(int uniquifier) { path_uniquifier_ = uniquifier; }
- GURL url() const { return url_; }
- GURL referrer_url() const { return referrer_url_; }
- std::string mime_type() const { return mime_type_; }
- std::string original_mime_type() const { return original_mime_type_; }
- 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_; }
- base::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_; }
- SafetyState safety_state() const { return safety_state_; }
- void set_safety_state(SafetyState safety_state) {
- safety_state_ = safety_state;
- }
- bool auto_opened() { return auto_opened_; }
- void set_auto_opened(bool auto_opened) { auto_opened_ = auto_opened; }
- FilePath original_name() const { return original_name_; }
- void set_original_name(const FilePath& name) { original_name_ = name; }
- bool save_as() const { return save_as_; }
- bool is_otr() const { return is_otr_; }
- bool is_extension_install() const { return is_extension_install_; }
- bool name_finalized() const { return name_finalized_; }
- void set_name_finalized(bool name_finalized) {
- name_finalized_ = name_finalized;
- }
- bool is_temporary() const { return is_temporary_; }
- void set_is_temporary(bool is_temporary) { is_temporary_ = is_temporary; }
-
- // Returns the file-name that should be reported to the user, which is
- // file_name_ for safe downloads and original_name_ for dangerous ones with
- // the uniquifier number.
- FilePath GetFileName() const;
-
- 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
- FilePath full_path_;
-
- // A number that should be appended to the path to make it unique, or 0 if the
- // path should be used as is.
- int path_uniquifier_;
-
- // Short display version of the file
- FilePath file_name_;
-
- // The URL from whence we came.
- GURL url_;
-
- // The URL of the page that initiated the download.
- GURL referrer_url_;
-
- // The mimetype of the download
- std::string mime_type_;
-
- // The value of the content type header received when downloading
- // this item. |mime_type_| may be different because of type sniffing.
- std::string original_mime_type_;
-
- // Total bytes expected
- int64 total_bytes_;
-
- // Current received bytes
- int64 received_bytes_;
-
- // Start time for calculating remaining time
- base::TimeTicks 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
- base::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_;
-
- // Whether the download is considered potentially safe or dangerous
- // (executable files are typically considered dangerous).
- SafetyState safety_state_;
-
- // Whether the download was auto-opened. We set this rather than using
- // an observer as it's frequently possible for the download to be auto opened
- // before the observer is added.
- bool auto_opened_;
-
- // Dangerous download are given temporary names until the user approves them.
- // This stores their original name.
- FilePath original_name_;
-
- // For canceling or pausing requests.
- int render_process_id_;
- int request_id_;
-
- // True if the item was downloaded as a result of 'save as...'
- bool save_as_;
-
- // True if the download was initiated in an incognito window.
- bool is_otr_;
-
- // True if the item was downloaded for an extension installation.
- bool is_extension_install_;
-
- // True if the filename is finalized.
- bool name_finalized_;
-
- // True if the item was downloaded temporarily.
- bool is_temporary_;
-
- DISALLOW_COPY_AND_ASSIGN(DownloadItem);
-};
-
-
-// DownloadManager -------------------------------------------------------------
-
// Browser's download manager: manages all downloads and destination view.
class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>,
public SelectFileDialog::Listener {
@@ -347,6 +59,10 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>,
friend class DownloadManagerTest;
public:
+ // A fake download table ID which representas a download that has started,
+ // but is not yet in the table.
+ static const int kUninitializedHandle;
+
DownloadManager();
static void RegisterUserPrefs(PrefService* prefs);
diff --git a/chrome/browser/download/download_manager_unittest.cc b/chrome/browser/download/download_manager_unittest.cc
index 5ff1786..c971115 100644
--- a/chrome/browser/download/download_manager_unittest.cc
+++ b/chrome/browser/download/download_manager_unittest.cc
@@ -8,6 +8,7 @@
#include "build/build_config.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/history/download_types.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc
index ec67f0e..fa6ab09 100644
--- a/chrome/browser/download/download_shelf.cc
+++ b/chrome/browser/download/download_shelf.cc
@@ -8,6 +8,7 @@
#include "base/file_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/dom_ui/downloads_ui.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/download/download_util.h"
diff --git a/chrome/browser/download/download_types.h b/chrome/browser/download/download_types.h
new file mode 100644
index 0000000..de8bfc8
--- /dev/null
+++ b/chrome/browser/download/download_types.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TYPES_H_
+#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TYPES_H_
+
+#include <vector>
+
+#include "base/file_path.h"
+#include "base/linked_ptr.h"
+#include "base/lock.h"
+#include "net/base/file_stream.h"
+
+namespace net {
+class IOBuffer;
+}
+
+// DownloadBuffer is created and populated on the IO thread, and passed to the
+// file thread for writing. In order to avoid flooding the file thread with too
+// many small write messages, each write is appended to the DownloadBuffer while
+// waiting for the task to run on the file thread. Access to the write buffers
+// is synchronized via the lock. Each entry in 'contents' represents one data
+// buffer and its size in bytes.
+struct DownloadBuffer {
+ Lock lock;
+ typedef std::pair<net::IOBuffer*, int> Contents;
+ std::vector<Contents> contents;
+};
+
+// Holds the information about how to save a download file.
+struct DownloadSaveInfo {
+ FilePath file_path;
+ linked_ptr<net::FileStream> file_stream;
+};
+
+#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TYPES_H_
diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc
index 591eb83..a3e064f 100644
--- a/chrome/browser/download/download_util.cc
+++ b/chrome/browser/download/download_util.cc
@@ -22,6 +22,7 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/common/chrome_paths.h"
diff --git a/chrome/browser/download/drag_download_file.cc b/chrome/browser/download/drag_download_file.cc
index 8267621..4b2b370 100644
--- a/chrome/browser/download/drag_download_file.cc
+++ b/chrome/browser/download/drag_download_file.cc
@@ -8,7 +8,7 @@
#include "base/message_loop.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/download/download_file.h"
-#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "net/base/file_stream.h"
diff --git a/chrome/browser/download/drag_download_file.h b/chrome/browser/download/drag_download_file.h
index 31064ec..4ea3cdf 100644
--- a/chrome/browser/download/drag_download_file.h
+++ b/chrome/browser/download/drag_download_file.h
@@ -9,13 +9,14 @@
#include "base/file_path.h"
#include "base/linked_ptr.h"
#include "chrome/browser/download/download_file.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_manager.h"
#include "googleurl/src/gurl.h"
class TabContents;
namespace net {
-class FileSteram;
+class FileStream;
}
class DragDownloadFile : public DownloadFileProvider,
diff --git a/chrome/browser/download/save_package.cc b/chrome/browser/download/save_package.cc
index a9a8a6f..7be57c2 100644
--- a/chrome/browser/download/save_package.cc
+++ b/chrome/browser/download/save_package.cc
@@ -17,6 +17,7 @@
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/download/download_shelf.h"