download_file_manager.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_file_manager.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
8201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/logging.h"
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stl_util-inl.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h"
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/browser_thread.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_manager.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_util.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/history/download_create_info.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/chrome_url_request_context.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/platform_util.h"
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/safe_browsing/safe_browsing_service.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_util.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h"
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/io_buffer.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Throttle updates to the UI thread so that a fast moving download doesn't
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// cause it to become unresponsive (in milliseconds).
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kUpdatePeriodMs = 500;
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickDownloadManager* DownloadManagerForRenderViewHost(int render_process_id,
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                  int render_view_id) {
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TabContents* contents = tab_util::GetTabContentsByID(render_process_id,
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                       render_view_id);
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (contents) {
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    Profile* profile = contents->profile();
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (profile)
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return profile->GetDownloadManager();
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return NULL;
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh)
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : next_id_(0),
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      resource_dispatcher_host_(rdh) {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadFileManager::~DownloadFileManager() {
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(downloads_.empty());
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::Shutdown() {
60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::FILE, FROM_HERE,
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(this, &DownloadFileManager::OnShutdown));
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::OnShutdown() {
67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  StopUpdateTimer();
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  STLDeleteValues(&downloads_);
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DownloadFileManager::CreateDownloadFile(DownloadCreateInfo* info,
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                             DownloadManager* download_manager,
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                             bool get_hash) {
75201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString();
76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<DownloadFile>
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      download_file(new DownloadFile(info, download_manager));
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!download_file->Initialize(get_hash)) {
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::IO, FROM_HERE,
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableFunction(&download_util::CancelDownloadRequest,
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            resource_dispatcher_host_,
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            info->child_id,
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            info->request_id));
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete info;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(GetDownloadFile(info->download_id) == NULL);
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  downloads_[info->download_id] = download_file.release();
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(phajdan.jr): fix the duplication of path info below.
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  info->path = info->save_info.file_path;
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // The file is now ready, we can un-pause the request and start saving data.
97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::IO, FROM_HERE,
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewRunnableMethod(this, &DownloadFileManager::ResumeDownloadRequest,
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        info->child_id, info->request_id));
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StartUpdateTimer();
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::UI, FROM_HERE,
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewRunnableMethod(download_manager,
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        &DownloadManager::StartDownload, info));
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadFileManager::ResumeDownloadRequest(int child_id, int request_id) {
111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This balances the pause in DownloadResourceHandler::OnResponseStarted.
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  resource_dispatcher_host_->PauseRequest(child_id, request_id, false);
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadFile* DownloadFileManager::GetDownloadFile(int id) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadFileMap::iterator it = downloads_.find(id);
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return it == downloads_.end() ? NULL : it->second;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::StartUpdateTimer() {
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!update_timer_.IsRunning()) {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdatePeriodMs),
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        this, &DownloadFileManager::UpdateInProgressDownloads);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::StopUpdateTimer() {
131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  update_timer_.Stop();
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::UpdateInProgressDownloads() {
136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (DownloadFileMap::iterator i = downloads_.begin();
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i != downloads_.end(); ++i) {
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int id = i->first;
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DownloadFile* download_file = i->second;
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DownloadManager* manager = download_file->GetDownloadManager();
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (manager) {
143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          NewRunnableMethod(manager, &DownloadManager::UpdateDownload,
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            id, download_file->bytes_so_far()));
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Called on the IO thread once the ResourceDispatcherHost has decided that a
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// request is a download.
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint DownloadFileManager::GetNextId() {
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return next_id_++;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::StartDownload(DownloadCreateInfo* info) {
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(info);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DownloadManager* manager = DownloadManagerForRenderViewHost(
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      info->child_id, info->render_view_id);
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!manager) {
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::IO, FROM_HERE,
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableFunction(&download_util::CancelDownloadRequest,
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            resource_dispatcher_host_,
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            info->child_id,
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            info->request_id));
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete info;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  manager->CreateDownloadItem(info);
17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool hash_needed = resource_dispatcher_host_->safe_browsing_service()->
17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      DownloadBinHashNeeded();
17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile,
18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        info, make_scoped_refptr(manager), hash_needed));
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We don't forward an update to the UI thread here, since we want to throttle
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the UI update rate via a periodic timer. If the user has cancelled the
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// download (in the UI thread), we may receive a few more updates before the IO
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// thread gets the cancel message: we just delete the data since the
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DownloadFile has been deleted.
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) {
190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<DownloadBuffer::Contents> contents;
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::AutoLock auto_lock(buffer->lock);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    contents.swap(buffer->contents);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadFile* download = GetDownloadFile(id);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < contents.size(); ++i) {
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net::IOBuffer* data = contents[i].first;
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int data_len = contents[i].second;
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (download)
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      download->AppendDataToFile(data->data(), data_len);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data->Release();
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadFileManager::OnResponseCompleted(int id, DownloadBuffer* buffer) {
208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " id = " << id;
209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete buffer;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadFileMap::iterator it = downloads_.find(id);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it != downloads_.end()) {
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DownloadFile* download = it->second;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download->Finish();
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DownloadManager* download_manager = download->GetDownloadManager();
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (download_manager) {
218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::PostTask(
219731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          BrowserThread::UI, FROM_HERE,
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          NewRunnableMethod(
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              download_manager, &DownloadManager::OnAllDataSaved,
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              id, download->bytes_so_far()));
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We need to keep the download around until the UI thread has finalized
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the name.
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (download->path_renamed()) {
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      downloads_.erase(it);
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete download;
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (downloads_.empty())
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    StopUpdateTimer();
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This method will be sent via a user action, or shutdown on the UI thread, and
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// run on the download thread. Since this message has been sent from the UI
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// thread, the download may have already completed and won't exist in our map.
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::CancelDownload(int id) {
241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " id = " << id;
242731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadFileMap::iterator it = downloads_.find(id);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it != downloads_.end()) {
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DownloadFile* download = it->second;
246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    VLOG(20) << __FUNCTION__ << "()"
247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             << " download = " << download->DebugString();
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download->Cancel();
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (download->path_renamed()) {
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      downloads_.erase(it);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete download;
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (downloads_.empty())
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    StopUpdateTimer();
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) {
261731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(manager);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::set<DownloadFile*> to_remove;
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (DownloadFileMap::iterator i = downloads_.begin();
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i != downloads_.end(); ++i) {
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DownloadFile* download_file = i->second;
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (download_file->GetDownloadManager() == manager) {
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      download_file->CancelDownloadRequest(resource_dispatcher_host_);
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      to_remove.insert(download_file);
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (std::set<DownloadFile*>::iterator i = to_remove.begin();
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i != to_remove.end(); ++i) {
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    downloads_.erase((*i)->id());
2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    delete *i;
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Actions from the UI thread and run on the download thread
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The DownloadManager in the UI thread has provided an intermediate .crdownload
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// name for the download specified by 'id'. Rename the in progress download.
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::OnIntermediateDownloadName(
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int id, const FilePath& full_path, DownloadManager* download_manager)
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{
289201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " id = " << id
290201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           << " full_path = \"" << full_path.value() << "\"";
291731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadFileMap::iterator it = downloads_.find(id);
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == downloads_.end())
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadFile* download = it->second;
297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " download = " << download->DebugString();
298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!download->Rename(full_path, false /* is_final_rename */)) {
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Error. Between the time the UI thread generated 'full_path' to the time
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // this code runs, something happened that prevents us from renaming.
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CancelDownloadOnRename(id);
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The DownloadManager in the UI thread has provided a final name for the
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// download specified by 'id'. Rename the in progress download, and remove it
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// from our table if it has been completed or cancelled already.
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |need_delete_crdownload| indicates if we explicitly delete an intermediate
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// .crdownload file or not.
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There are 3 possible rename cases where this method can be called:
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 1. tmp -> foo            (need_delete_crdownload=T)
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 2. foo.crdownload -> foo (need_delete_crdownload=F)
31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// 3. tmp-> Unconfirmed.xxx.crdownload (need_delete_crdownload=F)
315513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid DownloadFileManager::OnFinalDownloadName(
316513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int id, const FilePath& full_path, bool need_delete_crdownload,
317513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    DownloadManager* download_manager) {
318201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " id = " << id
319201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           << " full_path = \"" << full_path.value() << "\""
320201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           << " need_delete_crdownload = " << need_delete_crdownload;
321731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DownloadFile* download = GetDownloadFile(id);
3243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!download)
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
326201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " download = " << download->DebugString();
327513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (download->Rename(full_path, true /* is_final_rename */)) {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Done here because we only want to do this once; see
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // http://crbug.com/13120 for details.
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download->AnnotateWithSourceInformation();
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
333731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
334731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::UI, FROM_HERE,
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(
336513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch            download_manager, &DownloadManager::DownloadRenamedToFinalName, id,
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            full_path));
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Error. Between the time the UI thread generated 'full_path' to the time
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // this code runs, something happened that prevents us from renaming.
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CancelDownloadOnRename(id);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (need_delete_crdownload)
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download->DeleteCrDownload();
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the download has completed before we got this final name, we remove it
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // from our in progress map.
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!download->in_progress()) {
3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    downloads_.erase(id);
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete download;
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (downloads_.empty())
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    StopUpdateTimer();
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Called only from OnFinalDownloadName or OnIntermediateDownloadName
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// on the FILE thread.
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadFileManager::CancelDownloadOnRename(int id) {
361731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DownloadFile* download = GetDownloadFile(id);
3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!download)
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DownloadManager* download_manager = download->GetDownloadManager();
3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!download_manager) {
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download->CancelDownloadRequest(resource_dispatcher_host_);
3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::UI, FROM_HERE,
3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewRunnableMethod(download_manager,
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        &DownloadManager::DownloadCancelled, id));
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
378