summaryrefslogtreecommitdiffstats
path: root/content/browser/download/download_file_manager.cc
diff options
context:
space:
mode:
authorrdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-24 17:01:21 +0000
committerrdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-24 17:01:21 +0000
commitee26796967de038f855e7260e3e10b8a7bae6c15 (patch)
treefccf63d0226b684b8f99b313df00cb1a9e8e8224 /content/browser/download/download_file_manager.cc
parent658f9ca69a0c2187948618b55a9453068052838d (diff)
downloadchromium_src-ee26796967de038f855e7260e3e10b8a7bae6c15.zip
chromium_src-ee26796967de038f855e7260e3e10b8a7bae6c15.tar.gz
chromium_src-ee26796967de038f855e7260e3e10b8a7bae6c15.tar.bz2
Revert 153221 - Remove DownloadFileManager in favor of direct ownership of DownloadFiles.
This CL is equivalent to CLs http://codereview.chromium.org/10799005 and http://codereview.chromium.org/10836293, which were previous attempts to land the same functionality. TBR=jam@chromium.org BUG=123998 Review URL: https://chromiumcodereview.appspot.com/10823406 TBR=rdsmith@chromium.org Review URL: https://chromiumcodereview.appspot.com/10878054 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@153229 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/download/download_file_manager.cc')
-rw-r--r--content/browser/download/download_file_manager.cc227
1 files changed, 227 insertions, 0 deletions
diff --git a/content/browser/download/download_file_manager.cc b/content/browser/download/download_file_manager.cc
new file mode 100644
index 0000000..7bebd92
--- /dev/null
+++ b/content/browser/download/download_file_manager.cc
@@ -0,0 +1,227 @@
+// Copyright (c) 2012 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 "content/browser/download/download_file_manager.h"
+
+#include <set>
+#include <string>
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/utf_string_conversions.h"
+#include "content/browser/download/base_file.h"
+#include "content/browser/download/download_create_info.h"
+#include "content/browser/download/download_file_impl.h"
+#include "content/browser/download/download_interrupt_reasons_impl.h"
+#include "content/browser/download/download_request_handle.h"
+#include "content/browser/download/download_stats.h"
+#include "content/browser/power_save_blocker.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/browser/download_manager_delegate.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/io_buffer.h"
+
+using content::BrowserThread;
+using content::DownloadFile;
+using content::DownloadId;
+using content::DownloadManager;
+
+namespace {
+
+class DownloadFileFactoryImpl
+ : public DownloadFileManager::DownloadFileFactory {
+ public:
+ DownloadFileFactoryImpl() {}
+
+ virtual content::DownloadFile* CreateFile(
+ DownloadCreateInfo* info,
+ scoped_ptr<content::ByteStreamReader> stream,
+ DownloadManager* download_manager,
+ bool calculate_hash,
+ const net::BoundNetLog& bound_net_log) OVERRIDE;
+};
+
+DownloadFile* DownloadFileFactoryImpl::CreateFile(
+ DownloadCreateInfo* info,
+ scoped_ptr<content::ByteStreamReader> stream,
+ DownloadManager* download_manager,
+ bool calculate_hash,
+ const net::BoundNetLog& bound_net_log) {
+ return new DownloadFileImpl(
+ info, stream.Pass(), new DownloadRequestHandle(info->request_handle),
+ download_manager, calculate_hash,
+ scoped_ptr<content::PowerSaveBlocker>(
+ new content::PowerSaveBlocker(
+ content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ "Download in progress")).Pass(),
+ bound_net_log);
+}
+
+} // namespace
+
+DownloadFileManager::DownloadFileManager(DownloadFileFactory* factory)
+ : download_file_factory_(factory) {
+ if (download_file_factory_ == NULL)
+ download_file_factory_.reset(new DownloadFileFactoryImpl);
+}
+
+DownloadFileManager::~DownloadFileManager() {
+ DCHECK(downloads_.empty());
+}
+
+void DownloadFileManager::Shutdown() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DownloadFileManager::OnShutdown, this));
+}
+
+void DownloadFileManager::OnShutdown() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ STLDeleteValues(&downloads_);
+}
+
+void DownloadFileManager::CreateDownloadFile(
+ scoped_ptr<DownloadCreateInfo> info,
+ scoped_ptr<content::ByteStreamReader> stream,
+ scoped_refptr<DownloadManager> download_manager, bool get_hash,
+ const net::BoundNetLog& bound_net_log,
+ const CreateDownloadFileCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(info.get());
+ VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString();
+
+ scoped_ptr<DownloadFile> download_file(download_file_factory_->CreateFile(
+ info.get(), stream.Pass(), download_manager, get_hash, bound_net_log));
+
+ content::DownloadInterruptReason interrupt_reason(
+ download_file->Initialize());
+ if (interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NONE) {
+ DCHECK(GetDownloadFile(info->download_id) == NULL);
+ downloads_[info->download_id] = download_file.release();
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, interrupt_reason));
+}
+
+DownloadFile* DownloadFileManager::GetDownloadFile(
+ DownloadId global_id) {
+ DownloadFileMap::iterator it = downloads_.find(global_id);
+ return it == downloads_.end() ? NULL : it->second;
+}
+
+// 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(DownloadId global_id) {
+ VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DownloadFileMap::iterator it = downloads_.find(global_id);
+ if (it == downloads_.end())
+ return;
+
+ DownloadFile* download_file = it->second;
+ VLOG(20) << __FUNCTION__ << "()"
+ << " download_file = " << download_file->DebugString();
+ download_file->Cancel();
+
+ EraseDownload(global_id);
+}
+
+void DownloadFileManager::CompleteDownload(
+ DownloadId global_id, const base::Closure& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ if (!ContainsKey(downloads_, global_id))
+ return;
+
+ DownloadFile* download_file = downloads_[global_id];
+
+ VLOG(20) << " " << __FUNCTION__ << "()"
+ << " id = " << global_id
+ << " download_file = " << download_file->DebugString();
+
+ // Done here on Windows so that anti-virus scanners invoked by
+ // the attachment service actually see the data; see
+ // http://crbug.com/127999.
+ // Done here for mac because we only want to do this once; see
+ // http://crbug.com/13120 for details.
+ // Other platforms don't currently do source annotation.
+ download_file->AnnotateWithSourceInformation();
+
+ download_file->Detach();
+
+ EraseDownload(global_id);
+
+ // Notify our caller we've let it go.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
+}
+
+void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(manager);
+
+ std::set<DownloadFile*> to_remove;
+
+ for (DownloadFileMap::iterator i = downloads_.begin();
+ i != downloads_.end(); ++i) {
+ DownloadFile* download_file = i->second;
+ if (download_file->GetDownloadManager() == manager) {
+ download_file->CancelDownloadRequest();
+ to_remove.insert(download_file);
+ }
+ }
+
+ for (std::set<DownloadFile*>::iterator i = to_remove.begin();
+ i != to_remove.end(); ++i) {
+ downloads_.erase((*i)->GlobalId());
+ delete *i;
+ }
+}
+
+// Actions from the UI thread and run on the download thread
+
+void DownloadFileManager::RenameDownloadFile(
+ DownloadId global_id,
+ const FilePath& full_path,
+ bool overwrite_existing_file,
+ const RenameCompletionCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DownloadFile* download_file = GetDownloadFile(global_id);
+ if (!download_file) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
+ FilePath()));
+ return;
+ }
+
+ download_file->Rename(full_path, overwrite_existing_file, callback);
+}
+
+int DownloadFileManager::NumberOfActiveDownloads() const {
+ return downloads_.size();
+}
+
+void DownloadFileManager::EraseDownload(DownloadId global_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ if (!ContainsKey(downloads_, global_id))
+ return;
+
+ DownloadFile* download_file = downloads_[global_id];
+
+ VLOG(20) << " " << __FUNCTION__ << "()"
+ << " id = " << global_id
+ << " download_file = " << download_file->DebugString();
+
+ downloads_.erase(global_id);
+
+ delete download_file;
+}