Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Unified Diff: chrome/browser/download/download_file_manager.cc

Issue 7618048: Move the core download files to content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/download/download_file_manager.cc
===================================================================
--- chrome/browser/download/download_file_manager.cc (revision 96793)
+++ chrome/browser/download/download_file_manager.cc (working copy)
@@ -1,404 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/download/download_file_manager.h"
-
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/task.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/download/download_create_info.h"
-#include "chrome/browser/download/download_manager.h"
-#include "chrome/browser/download/download_request_handle.h"
-#include "chrome/browser/download/download_util.h"
-#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "chrome/common/pref_names.h"
-#include "content/browser/browser_thread.h"
-#include "content/browser/renderer_host/resource_dispatcher_host.h"
-#include "content/browser/tab_contents/tab_contents.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/io_buffer.h"
-
-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() {
- DCHECK(downloads_.empty());
-}
-
-void DownloadFileManager::Shutdown() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(this, &DownloadFileManager::OnShutdown));
-}
-
-void DownloadFileManager::OnShutdown() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- StopUpdateTimer();
- STLDeleteValues(&downloads_);
-}
-
-void DownloadFileManager::CreateDownloadFile(DownloadCreateInfo* info,
- DownloadManager* download_manager,
- bool get_hash) {
- DCHECK(info);
- VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString();
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- // Life of |info| ends here. No more references to it after this method.
- scoped_ptr<DownloadCreateInfo> infop(info);
-
- scoped_ptr<DownloadFile>
- download_file(new DownloadFile(info, download_manager));
- if (!download_file->Initialize(get_hash)) {
- info->request_handle.CancelRequest();
- return;
- }
-
- int32 id = info->download_id;
- DCHECK(GetDownloadFile(id) == NULL);
- downloads_[id] = download_file.release();
-
- // The file is now ready, we can un-pause the request and start saving data.
- info->request_handle.ResumeRequest();
-
- StartUpdateTimer();
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(download_manager,
- &DownloadManager::StartDownload, id));
-}
-
-DownloadFile* DownloadFileManager::GetDownloadFile(int id) {
- DownloadFileMap::iterator it = downloads_.find(id);
- return it == downloads_.end() ? NULL : it->second;
-}
-
-void DownloadFileManager::StartUpdateTimer() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- if (!update_timer_.IsRunning()) {
- update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs),
- this, &DownloadFileManager::UpdateInProgressDownloads);
- }
-}
-
-void DownloadFileManager::StopUpdateTimer() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- update_timer_.Stop();
-}
-
-void DownloadFileManager::UpdateInProgressDownloads() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- for (DownloadFileMap::iterator i = downloads_.begin();
- i != downloads_.end(); ++i) {
- int id = i->first;
- DownloadFile* download_file = i->second;
- DownloadManager* manager = download_file->GetDownloadManager();
- if (manager) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(manager, &DownloadManager::UpdateDownload,
- id, download_file->bytes_so_far()));
- }
- }
-}
-
-// Called on the IO thread once the ResourceDispatcherHost has decided that a
-// request is a download.
-int DownloadFileManager::GetNextId() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- return next_id_++;
-}
-
-void DownloadFileManager::StartDownload(DownloadCreateInfo* info) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(info);
-
- DownloadManager* manager = info->request_handle.GetDownloadManager();
- if (!manager) {
- info->request_handle.CancelRequest();
- delete info;
- return;
- }
-
- // TODO(phajdan.jr): fix the duplication of path info below.
- info->path = info->save_info.file_path;
-
- manager->CreateDownloadItem(info);
-
-#if defined(ENABLE_SAFE_BROWSING)
- bool hash_needed = manager->profile()->GetPrefs()->GetBoolean(
- prefs::kSafeBrowsingEnabled) &&
- g_browser_process->safe_browsing_service()->DownloadBinHashNeeded();
-#else
- bool hash_needed = false;
-#endif
-
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile,
- info, make_scoped_refptr(manager), hash_needed));
-}
-
-// 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(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- std::vector<DownloadBuffer::Contents> contents;
- {
- base::AutoLock auto_lock(buffer->lock);
- contents.swap(buffer->contents);
- }
-
- DownloadFile* download_file = GetDownloadFile(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_file)
- download_file->AppendDataToFile(data->data(), data_len);
- data->Release();
- }
-}
-
-void DownloadFileManager::OnResponseCompleted(
- int id,
- DownloadBuffer* buffer,
- int os_error,
- const std::string& security_info) {
- VLOG(20) << __FUNCTION__ << "()" << " id = " << id
- << " os_error = " << os_error
- << " security_info = \"" << security_info << "\"";
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- delete buffer;
- DownloadFile* download_file = GetDownloadFile(id);
- if (!download_file)
- return;
-
- download_file->Finish();
-
- DownloadManager* download_manager = download_file->GetDownloadManager();
- if (!download_manager) {
- CancelDownload(id);
- return;
- }
-
- std::string hash;
- if (!download_file->GetSha256Hash(&hash))
- hash.clear();
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(
- download_manager, &DownloadManager::OnResponseCompleted,
- id, download_file->bytes_so_far(), os_error, hash));
- // We need to keep the download around until the UI thread has finalized
- // the name.
-}
-
-// 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) {
- VLOG(20) << __FUNCTION__ << "()" << " id = " << id;
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- DownloadFileMap::iterator it = downloads_.find(id);
- if (it == downloads_.end())
- return;
-
- DownloadFile* download_file = it->second;
- VLOG(20) << __FUNCTION__ << "()"
- << " download_file = " << download_file->DebugString();
- download_file->Cancel();
-
- EraseDownload(id);
-}
-
-void DownloadFileManager::CompleteDownload(int id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- if (!ContainsKey(downloads_, id))
- return;
-
- DownloadFile* download_file = downloads_[id];
-
- VLOG(20) << " " << __FUNCTION__ << "()"
- << " id = " << id
- << " download_file = " << download_file->DebugString();
-
- download_file->Detach();
-
- EraseDownload(id);
-}
-
-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)->id());
- delete *i;
- }
-}
-
-// Actions from the UI thread and run on the download thread
-
-// The DownloadManager in the UI thread has provided an intermediate .crdownload
-// name for the download specified by 'id'. Rename the in progress download.
-//
-// There are 2 possible rename cases where this method can be called:
-// 1. tmp -> foo.crdownload (not final, safe)
-// 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous)
-void DownloadFileManager::RenameInProgressDownloadFile(
- int id, const FilePath& full_path) {
- VLOG(20) << __FUNCTION__ << "()" << " id = " << id
- << " full_path = \"" << full_path.value() << "\"";
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- DownloadFile* download_file = GetDownloadFile(id);
- if (!download_file)
- return;
-
- VLOG(20) << __FUNCTION__ << "()"
- << " download_file = " << download_file->DebugString();
-
- if (!download_file->Rename(full_path)) {
- // Error. Between the time the UI thread generated 'full_path' to the time
- // this code runs, something happened that prevents us from renaming.
- CancelDownloadOnRename(id);
- }
-}
-
-// The DownloadManager in the UI thread has provided a final name for the
-// download specified by 'id'. Rename the download that's in the process
-// of completing.
-//
-// There are 2 possible rename cases where this method can be called:
-// 1. foo.crdownload -> foo (final, safe)
-// 2. Unconfirmed.xxx.crdownload -> xxx (final, validated)
-void DownloadFileManager::RenameCompletingDownloadFile(
- int id, const FilePath& full_path, bool overwrite_existing_file) {
- VLOG(20) << __FUNCTION__ << "()" << " id = " << id
- << " overwrite_existing_file = " << overwrite_existing_file
- << " full_path = \"" << full_path.value() << "\"";
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- DownloadFile* download_file = GetDownloadFile(id);
- if (!download_file)
- return;
-
- DCHECK(download_file->GetDownloadManager());
- DownloadManager* download_manager = download_file->GetDownloadManager();
-
- VLOG(20) << __FUNCTION__ << "()"
- << " download_file = " << download_file->DebugString();
-
- int uniquifier = 0;
- FilePath new_path = full_path;
- if (!overwrite_existing_file) {
- // Make our name unique at this point, as if a dangerous file is
- // downloading and a 2nd download is started for a file with the same
- // name, they would have the same path. This is because we uniquify
- // the name on download start, and at that time the first file does
- // not exists yet, so the second file gets the same name.
- // This should not happen in the SAFE case, and we check for that in the UI
- // thread.
- uniquifier = download_util::GetUniquePathNumber(new_path);
- if (uniquifier > 0) {
- download_util::AppendNumberToPath(&new_path, uniquifier);
- }
- }
-
- // Rename the file, overwriting if necessary.
- if (!download_file->Rename(new_path)) {
- // Error. Between the time the UI thread generated 'full_path' to the time
- // this code runs, something happened that prevents us from renaming.
- CancelDownloadOnRename(id);
- return;
- }
-
-#if defined(OS_MACOSX)
- // Done here because we only want to do this once; see
- // http://crbug.com/13120 for details.
- download_file->AnnotateWithSourceInformation();
-#endif
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(
- download_manager, &DownloadManager::OnDownloadRenamedToFinalName, id,
- new_path, uniquifier));
-}
-
-// Called only from RenameInProgressDownloadFile and
-// RenameCompletingDownloadFile on the FILE thread.
-void DownloadFileManager::CancelDownloadOnRename(int id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- DownloadFile* download_file = GetDownloadFile(id);
- if (!download_file)
- return;
-
- DownloadManager* download_manager = download_file->GetDownloadManager();
- if (!download_manager) {
- // Without a download manager, we can't cancel the request normally, so we
- // need to do it here. The normal path will also update the download
- // history before cancelling the request.
- download_file->CancelDownloadRequest();
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(download_manager,
- &DownloadManager::DownloadCancelled, id));
-}
-
-void DownloadFileManager::EraseDownload(int id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- if (!ContainsKey(downloads_, id))
- return;
-
- DownloadFile* download_file = downloads_[id];
-
- VLOG(20) << " " << __FUNCTION__ << "()"
- << " id = " << id
- << " download_file = " << download_file->DebugString();
-
- downloads_.erase(id);
-
- delete download_file;
-
- if (downloads_.empty())
- StopUpdateTimer();
-}

Powered by Google App Engine
This is Rietveld 408576698