summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/automation/automation_provider.cc2
-rw-r--r--chrome/browser/automation/automation_provider_observers.cc1
-rw-r--r--chrome/browser/automation/automation_provider_observers.h13
-rw-r--r--chrome/browser/browser.cc1
-rw-r--r--chrome/browser/browser_process_impl.cc2
-rw-r--r--chrome/browser/cocoa/download_item_cell.mm1
-rw-r--r--chrome/browser/cocoa/download_item_controller.mm1
-rw-r--r--chrome/browser/cocoa/download_item_mac.h1
-rw-r--r--chrome/browser/cocoa/download_item_mac.mm1
-rw-r--r--chrome/browser/cocoa/download_shelf_controller.mm3
-rw-r--r--chrome/browser/cocoa/download_util_mac.mm1
-rw-r--r--chrome/browser/dom_ui/downloads_dom_handler.cc1
-rw-r--r--chrome/browser/dom_ui/downloads_dom_handler.h1
-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
-rw-r--r--chrome/browser/gtk/custom_drag.cc2
-rw-r--r--chrome/browser/gtk/download_item_gtk.cc1
-rw-r--r--chrome/browser/gtk/download_item_gtk.h2
-rw-r--r--chrome/browser/gtk/download_shelf_gtk.cc1
-rw-r--r--chrome/browser/history/download_database.cc2
-rw-r--r--chrome/browser/history/history_unittest.cc2
-rw-r--r--chrome/browser/renderer_host/download_resource_handler.cc5
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.cc2
-rw-r--r--chrome/browser/views/download_item_view.h1
-rw-r--r--chrome/browser/views/download_shelf_view.cc1
-rw-r--r--chrome/chrome_browser.gypi5
-rw-r--r--chrome/test/ui_test_utils.cc1
41 files changed, 1327 insertions, 1257 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 18b7d7b..0597f69 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -47,7 +47,7 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/dom_operation_notification_details.h"
#include "chrome/browser/debugger/devtools_manager.h"
-#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_shelf.h"
#include "chrome/browser/download/save_package.h"
#include "chrome/browser/extensions/crx_installer.h"
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index a60883d..194410e 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/automation/automation_provider_json.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/dom_operation_notification_details.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/save_package.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_process_manager.h"
diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h
index 21e87c0..08d9e08 100644
--- a/chrome/browser/automation/automation_provider_observers.h
+++ b/chrome/browser/automation/automation_provider_observers.h
@@ -11,6 +11,7 @@
#include "chrome/browser/bookmarks/bookmark_model_observer.h"
#include "chrome/browser/browsing_data_remover.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/importer/importer.h"
#include "chrome/browser/importer/importer_data_types.h"
@@ -553,8 +554,8 @@ class AutomationProviderBookmarkModelObserver : BookmarkModelObserver {
// When asked for pending downloads, the DownloadManager places
// results in a DownloadManager::Observer.
-class AutomationProviderDownloadManagerObserver :
- public DownloadManager::Observer {
+class AutomationProviderDownloadManagerObserver
+ : public DownloadManager::Observer {
public:
AutomationProviderDownloadManagerObserver() : DownloadManager::Observer() {}
virtual ~AutomationProviderDownloadManagerObserver() {}
@@ -616,8 +617,8 @@ class AutomationProviderHistoryObserver {
};
// Allows the automation provider to wait for import queries to finish.
-class AutomationProviderImportSettingsObserver :
- public ImporterHost::Observer {
+class AutomationProviderImportSettingsObserver
+ : public ImporterHost::Observer {
public:
AutomationProviderImportSettingsObserver(
AutomationProvider* provider,
@@ -652,8 +653,8 @@ class AutomationProviderGetPasswordsObserver :
};
// Allows the automation provider to wait for clearing browser data to finish.
-class AutomationProviderBrowsingDataObserver :
- public BrowsingDataRemover::Observer {
+class AutomationProviderBrowsingDataObserver
+ : public BrowsingDataRemover::Observer {
public:
AutomationProviderBrowsingDataObserver(
AutomationProvider* provider,
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 1e30d39..364c599 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -37,6 +37,7 @@
#include "chrome/browser/debugger/devtools_window.h"
#include "chrome/browser/dock_info.h"
#include "chrome/browser/dom_ui/filebrowse_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_shelf.h"
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index f84b3f3..bee3eaf 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -22,7 +22,7 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/debugger/debugger_wrapper.h"
#include "chrome/browser/debugger/devtools_manager.h"
-#include "chrome/browser/download/download_file.h"
+#include "chrome/browser/download/download_file_manager.h"
#include "chrome/browser/download/save_file_manager.h"
#include "chrome/browser/first_run.h"
#include "chrome/browser/google_url_tracker.h"
diff --git a/chrome/browser/cocoa/download_item_cell.mm b/chrome/browser/cocoa/download_item_cell.mm
index c9843aba..8ae9fd9 100644
--- a/chrome/browser/cocoa/download_item_cell.mm
+++ b/chrome/browser/cocoa/download_item_cell.mm
@@ -12,6 +12,7 @@
#import "chrome/browser/cocoa/download_item_cell.h"
#import "chrome/browser/cocoa/image_utils.h"
#import "chrome/browser/cocoa/themed_window.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/cocoa/download_item_controller.mm b/chrome/browser/cocoa/download_item_controller.mm
index 61b0aa3..00e2110 100644
--- a/chrome/browser/cocoa/download_item_controller.mm
+++ b/chrome/browser/cocoa/download_item_controller.mm
@@ -18,6 +18,7 @@
#import "chrome/browser/cocoa/download_shelf_controller.h"
#import "chrome/browser/cocoa/themed_window.h"
#import "chrome/browser/cocoa/ui_localizer.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_shelf.h"
#include "chrome/browser/download/download_util.h"
diff --git a/chrome/browser/cocoa/download_item_mac.h b/chrome/browser/cocoa/download_item_mac.h
index a54abe4..91a8702 100644
--- a/chrome/browser/cocoa/download_item_mac.h
+++ b/chrome/browser/cocoa/download_item_mac.h
@@ -10,6 +10,7 @@
#include "base/scoped_nsobject.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/cancelable_request.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/icon_manager.h"
diff --git a/chrome/browser/cocoa/download_item_mac.mm b/chrome/browser/cocoa/download_item_mac.mm
index 7bc3b25..b2aae2c 100644
--- a/chrome/browser/cocoa/download_item_mac.mm
+++ b/chrome/browser/cocoa/download_item_mac.mm
@@ -8,6 +8,7 @@
#include "chrome/browser/browser_process.h"
#import "chrome/browser/cocoa/download_item_controller.h"
#include "chrome/browser/cocoa/download_util_mac.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_item_model.h"
#include "skia/ext/skia_utils_mac.h"
diff --git a/chrome/browser/cocoa/download_shelf_controller.mm b/chrome/browser/cocoa/download_shelf_controller.mm
index 53501c3..7fa1bf9 100644
--- a/chrome/browser/cocoa/download_shelf_controller.mm
+++ b/chrome/browser/cocoa/download_shelf_controller.mm
@@ -17,6 +17,7 @@
#include "chrome/browser/cocoa/download_shelf_mac.h"
#import "chrome/browser/cocoa/download_shelf_view.h"
#import "chrome/browser/cocoa/hyperlink_button_cell.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/profile.h"
#include "grit/generated_resources.h"
@@ -90,7 +91,7 @@ const NSTimeInterval kDownloadShelfCloseDuration = 0.12;
selector:@selector(viewFrameDidChange:)
name:NSViewFrameDidChangeNotification
object:[self view]];
-
+
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
NSImage* favicon = rb.GetNSImageNamed(IDR_DOWNLOADS_FAVICON);
DCHECK(favicon);
diff --git a/chrome/browser/cocoa/download_util_mac.mm b/chrome/browser/cocoa/download_util_mac.mm
index 75a75ec..9364520 100644
--- a/chrome/browser/cocoa/download_util_mac.mm
+++ b/chrome/browser/cocoa/download_util_mac.mm
@@ -8,6 +8,7 @@
#include "base/sys_string_conversions.h"
#import "chrome/browser/cocoa/dock_icon.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_manager.h"
#include "gfx/native_widget_types.h"
#include "skia/ext/skia_utils_mac.h"
diff --git a/chrome/browser/dom_ui/downloads_dom_handler.cc b/chrome/browser/dom_ui/downloads_dom_handler.cc
index c637b47..126a8be 100644
--- a/chrome/browser/dom_ui/downloads_dom_handler.cc
+++ b/chrome/browser/dom_ui/downloads_dom_handler.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
#include "chrome/browser/dom_ui/fileicon_source.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/profile.h"
diff --git a/chrome/browser/dom_ui/downloads_dom_handler.h b/chrome/browser/dom_ui/downloads_dom_handler.h
index 7eba4c2..99af1f5 100644
--- a/chrome/browser/dom_ui/downloads_dom_handler.h
+++ b/chrome/browser/dom_ui/downloads_dom_handler.h
@@ -8,6 +8,7 @@
#include <vector>
#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_manager.h"
class Value;
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"
diff --git a/chrome/browser/gtk/custom_drag.cc b/chrome/browser/gtk/custom_drag.cc
index 282e316..9eb3b85 100644
--- a/chrome/browser/gtk/custom_drag.cc
+++ b/chrome/browser/gtk/custom_drag.cc
@@ -6,7 +6,7 @@
#include "app/gtk_dnd_util.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/gtk/bookmark_utils_gtk.h"
#include "gfx/gtk_util.h"
#include "googleurl/src/gurl.h"
diff --git a/chrome/browser/gtk/download_item_gtk.cc b/chrome/browser/gtk/download_item_gtk.cc
index e7a8ddc..6744af0 100644
--- a/chrome/browser/gtk/download_item_gtk.cc
+++ b/chrome/browser/gtk/download_item_gtk.cc
@@ -17,6 +17,7 @@
#include "base/time.h"
#include "chrome/browser/browser.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/browser/download/download_shelf.h"
diff --git a/chrome/browser/gtk/download_item_gtk.h b/chrome/browser/gtk/download_item_gtk.h
index a701d99..1b793dc 100644
--- a/chrome/browser/gtk/download_item_gtk.h
+++ b/chrome/browser/gtk/download_item_gtk.h
@@ -13,7 +13,7 @@
#include "app/gtk_signal.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
-#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/icon_manager.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
diff --git a/chrome/browser/gtk/download_shelf_gtk.cc b/chrome/browser/gtk/download_shelf_gtk.cc
index f7ef409..a6c2a69 100644
--- a/chrome/browser/gtk/download_shelf_gtk.cc
+++ b/chrome/browser/gtk/download_shelf_gtk.cc
@@ -7,6 +7,7 @@
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "chrome/browser/browser.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/gtk/browser_window_gtk.h"
diff --git a/chrome/browser/history/download_database.cc b/chrome/browser/history/download_database.cc
index 26780ad..aa3dbde 100644
--- a/chrome/browser/history/download_database.cc
+++ b/chrome/browser/history/download_database.cc
@@ -12,7 +12,7 @@
#include "base/file_path.h"
#include "base/utf_string_conversions.h"
#include "build/build_config.h"
-#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/history/download_types.h"
// Download schema:
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc
index 24b4119..c8db05a 100644
--- a/chrome/browser/history/history_unittest.cc
+++ b/chrome/browser/history/history_unittest.cc
@@ -32,7 +32,7 @@
#include "base/string_util.h"
#include "base/task.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_database.h"
diff --git a/chrome/browser/renderer_host/download_resource_handler.cc b/chrome/browser/renderer_host/download_resource_handler.cc
index 73d9cec..0b45695 100644
--- a/chrome/browser/renderer_host/download_resource_handler.cc
+++ b/chrome/browser/renderer_host/download_resource_handler.cc
@@ -6,8 +6,9 @@
#include "base/logging.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/download/download_file_manager.h"
+#include "chrome/browser/history/download_types.h"
#include "chrome/browser/renderer_host/global_request_id.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/common/resource_response.h"
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc
index eab9da82..cca59a1 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc
@@ -17,7 +17,7 @@
#include "chrome/browser/cert_store.h"
#include "chrome/browser/child_process_security_policy.h"
#include "chrome/browser/cross_site_request_manager.h"
-#include "chrome/browser/download/download_file.h"
+#include "chrome/browser/download/download_file_manager.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/download/download_request_limiter.h"
#include "chrome/browser/download/save_file_manager.h"
diff --git a/chrome/browser/views/download_item_view.h b/chrome/browser/views/download_item_view.h
index 366dc1c..ffede2c 100644
--- a/chrome/browser/views/download_item_view.h
+++ b/chrome/browser/views/download_item_view.h
@@ -24,6 +24,7 @@
#include "base/time.h"
#include "base/timer.h"
#include "chrome/browser/cancelable_request.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/icon_manager.h"
#include "gfx/font.h"
diff --git a/chrome/browser/views/download_shelf_view.cc b/chrome/browser/views/download_shelf_view.cc
index d727d43..f0c37f1 100644
--- a/chrome/browser/views/download_shelf_view.cc
+++ b/chrome/browser/views/download_shelf_view.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_theme_provider.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/tab_contents/navigation_entry.h"
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 7da139b..dde71ad 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1136,6 +1136,10 @@
'browser/download/download_exe.cc',
'browser/download/download_file.cc',
'browser/download/download_file.h',
+ 'browser/download/download_file_manager.cc',
+ 'browser/download/download_file_manager.h',
+ 'browser/download/download_item.cc',
+ 'browser/download/download_item.h',
'browser/download/download_item_model.cc',
'browser/download/download_item_model.h',
'browser/download/download_manager.cc',
@@ -1147,6 +1151,7 @@
'browser/download/download_shelf.cc',
'browser/download/download_shelf.h',
'browser/download/download_started_animation.h',
+ 'browser/download/download_types.h',
'browser/download/download_util.cc',
'browser/download/download_util.h',
'browser/download/drag_download_file.cc',
diff --git a/chrome/test/ui_test_utils.cc b/chrome/test/ui_test_utils.cc
index f9f2d04..c464229 100644
--- a/chrome/test/ui_test_utils.cc
+++ b/chrome/test/ui_test_utils.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/dom_operation_notification_details.h"
+#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"