172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 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_manager.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/rand_util.h"
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stl_util-inl.h"
13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/stringprintf.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/sys_string_conversions.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h"
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/download/download_extensions.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_file_manager.h"
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/download/download_history.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_item.h"
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/download/download_prefs.h"
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/download/download_safe_browsing_client.h"
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/download/download_status_updater.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_util.h"
2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h"
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/history/download_create_info.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/chrome_url_request_context.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/platform_util.h"
3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_util.h"
334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h"
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_process_host.h"
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/resource_dispatcher_host.h"
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h"
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h"
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/mime_util.h"
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickDownloadManager::DownloadManager(DownloadStatusUpdater* status_updater)
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : shutdown_needed_(false),
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_(NULL),
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      file_manager_(NULL),
54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      status_updater_(status_updater->AsWeakPtr()) {
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (status_updater_)
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    status_updater_->AddDelegate(this);
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadManager::~DownloadManager() {
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(!shutdown_needed_);
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (status_updater_)
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    status_updater_->RemoveDelegate(this);
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::Shutdown() {
66201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()"
67201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           << " shutdown_needed_ = " << shutdown_needed_;
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!shutdown_needed_)
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  shutdown_needed_ = false;
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FOR_EACH_OBSERVER(Observer, observers_, ManagerGoingDown());
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (file_manager_) {
75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        NewRunnableMethod(file_manager_,
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          &DownloadFileManager::OnDownloadManagerShutdown,
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                          make_scoped_refptr(this)));
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  AssertContainersConsistent();
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Go through all downloads in downloads_.  Dangerous ones we need to
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // remove on disk, and in progress ones we need to cancel.
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (DownloadSet::iterator it = downloads_.begin(); it != downloads_.end();) {
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DownloadItem* download = *it;
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Save iterator from potential erases in this set done by called code.
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Iterators after an erasure point are still valid for lists and
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // associative containers such as sets.
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    it++;
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (download->safety_state() == DownloadItem::DANGEROUS &&
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        download->IsPartialDownload()) {
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // The user hasn't accepted it, so we need to remove it
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // from the disk.  This may or may not result in it being
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // removed from the DownloadManager queues and deleted
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // (specifically, DownloadManager::RemoveDownload only
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // removes and deletes it if it's known to the history service)
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // so the only thing we know after calling this function is that
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // the download was deleted if-and-only-if it was removed
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // from all queues.
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN);
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else if (download->IsPartialDownload()) {
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      download->Cancel(false);
10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      download_history_->UpdateEntry(download);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // At this point, all dangerous downloads have had their files removed
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // and all in progress downloads have been cancelled.  We can now delete
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // anything left.
11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  STLDeleteElements(&downloads_);
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // And clear all non-owning containers.
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  in_progress_.clear();
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  active_downloads_.clear();
11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if !defined(NDEBUG)
11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  save_page_as_downloads_.clear();
12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  file_manager_ = NULL;
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure the save as dialog doesn't notify us back if we're gone before
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // it returns.
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (select_file_dialog_.get())
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    select_file_dialog_->ListenerDestroyed();
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  download_history_.reset();
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  download_prefs_.reset();
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  request_context_getter_ = NULL;
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  shutdown_needed_ = false;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadManager::GetTemporaryDownloads(
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const FilePath& dir_path, std::vector<DownloadItem*>* result) {
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(result);
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (DownloadMap::iterator it = history_downloads_.begin();
14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       it != history_downloads_.end(); ++it) {
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (it->second->is_temporary() &&
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        it->second->full_path().DirName() == dir_path)
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      result->push_back(it->second);
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadManager::GetAllDownloads(
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const FilePath& dir_path, std::vector<DownloadItem*>* result) {
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(result);
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (DownloadMap::iterator it = history_downloads_.begin();
15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       it != history_downloads_.end(); ++it) {
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!it->second->is_temporary() &&
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (dir_path.empty() || it->second->full_path().DirName() == dir_path))
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      result->push_back(it->second);
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadManager::GetCurrentDownloads(
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const FilePath& dir_path, std::vector<DownloadItem*>* result) {
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(result);
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (DownloadMap::iterator it = history_downloads_.begin();
16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       it != history_downloads_.end(); ++it) {
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DownloadItem* item =it->second;
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Skip temporary items.
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (item->is_temporary())
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Skip items that have all their data, and are OK to save.
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!item->IsPartialDownload() &&
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        (item->safety_state() != DownloadItem::DANGEROUS))
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Skip items that don't match |dir_path|.
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If |dir_path| is empty, all remaining items match.
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path))
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      continue;
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result->push_back(item);
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If we have a parent profile, let it add its downloads to the results.
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Profile* original_profile = profile_->GetOriginalProfile();
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (original_profile != profile_)
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path,
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                                result);
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadManager::SearchDownloads(const string16& query,
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                      std::vector<DownloadItem*>* result) {
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(result);
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  string16 query_lower(l10n_util::ToLower(query));
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (DownloadMap::iterator it = history_downloads_.begin();
19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       it != history_downloads_.end(); ++it) {
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DownloadItem* download_item = it->second;
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (download_item->is_temporary() || download_item->is_extension_install())
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      continue;
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Display Incognito downloads only in Incognito window, and vice versa.
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // The Incognito Downloads page will get the list of non-Incognito downloads
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // from its parent profile.
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (profile_->IsOffTheRecord() != download_item->is_otr())
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      continue;
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (download_item->MatchesQuery(query_lower))
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      result->push_back(download_item);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If we have a parent profile, let it add its downloads to the results.
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Profile* original_profile = profile_->GetOriginalProfile();
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (original_profile != profile_)
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    original_profile->GetDownloadManager()->SearchDownloads(query, result);
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Query the history service for information about all persisted downloads.
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DownloadManager::Init(Profile* profile) {
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(profile);
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!shutdown_needed_)  << "DownloadManager already initialized.";
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  shutdown_needed_ = true;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  profile_ = profile;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_context_getter_ = profile_->GetRequestContext();
2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  download_history_.reset(new DownloadHistory(profile));
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  download_history_->Load(
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewCallback(this, &DownloadManager::OnQueryDownloadEntriesComplete));
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  download_prefs_.reset(new DownloadPrefs(profile_->GetPrefs()));
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // In test mode, there may be no ResourceDispatcherHost.  In this case it's
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // safe to avoid setting |file_manager_| because we only call a small set of
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // functions, none of which need it.
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceDispatcherHost* rdh = g_browser_process->resource_dispatcher_host();
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rdh) {
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_manager_ = rdh->download_file_manager();
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(file_manager_);
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  other_download_manager_observer_.reset(
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OtherDownloadManagerObserver(this));
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We have received a message from DownloadFileManager about a new download. We
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// create a download item and store it in our download map, and inform the
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// history system of a new download. Since this method can be called while the
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// history service thread is still reading the persistent state, we do not
25221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// insert the new DownloadItem into 'history_downloads_' or inform our
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// observers at this point. OnCreateDownloadEntryComplete() handles that
25421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// finalization of the the download creation as a callback from the
25521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// history thread.
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::StartDownload(DownloadCreateInfo* info) {
257731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Create a client to verify download URL with safebrowsing.
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // It deletes itself after the callback.
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<DownloadSBClient> sb_client = new DownloadSBClient(
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      info->download_id, info->url_chain, info->referrer_url);
263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  sb_client->CheckDownloadUrl(
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      info, NewCallback(this, &DownloadManager::CheckDownloadUrlDone));
265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid DownloadManager::CheckDownloadUrlDone(DownloadCreateInfo* info,
268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                           bool is_dangerous_url) {
269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(info);
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  info->is_dangerous_url = is_dangerous_url;
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check whether this download is for an extension install or not.
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow extensions to be explicitly saved.
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!info->prompt_user_for_save_location) {
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (UserScript::IsURLUserScript(info->url(), info->mime_type) ||
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        info->mime_type == Extension::kMimeType) {
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info->is_extension_install = true;
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (info->save_info.file_path.empty()) {
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FilePath generated_name;
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    download_util::GenerateFileNameFromInfo(info, &generated_name);
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Freeze the user's preference for showing a Save As dialog.  We're going
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // to bounce around a bunch of threads and we don't want to worry about race
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // conditions where the user changes this pref out from under us.
290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (download_prefs_->PromptForDownload()) {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // But ignore the user's preference for the following scenarios:
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // 1) Extension installation. Note that we only care here about the case
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      //    where an extension is installed, not when one is downloaded with
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      //    "save as...".
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // 2) Filetypes marked "always open." If the user just wants this file
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      //    opened, don't bother asking where to keep it.
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!info->is_extension_install &&
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          !ShouldOpenFileBasedOnExtension(generated_name))
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        info->prompt_user_for_save_location = true;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (download_prefs_->IsDownloadPathManaged()) {
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      info->prompt_user_for_save_location = false;
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Determine the proper path for a download, by either one of the following:
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // 1) using the default download directory.
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // 2) prompting the user.
30821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (info->prompt_user_for_save_location && !last_download_path_.empty()) {
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info->suggested_path = last_download_path_;
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      info->suggested_path = download_prefs_->download_path();
3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->suggested_path = info->suggested_path.Append(generated_name);
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->suggested_path = info->save_info.file_path;
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!info->prompt_user_for_save_location &&
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info->save_info.file_path.empty()) {
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    info->is_dangerous_file = download_util::IsDangerous(
32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        info, profile(), ShouldOpenFileBasedOnExtension(info->suggested_path));
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We need to move over to the download thread because we don't want to stat
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the suggested path on the UI thread.
326731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // We can only access preferences on the UI thread, so check the download path
327731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // now and pass the value to the FILE thread.
328731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
329731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::FILE, FROM_HERE,
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(
331731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          this,
332731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          &DownloadManager::CheckIfSuggestedPathExists,
333731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          info,
334731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          download_prefs()->download_path()));
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
337731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info,
338731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                 const FilePath& default_path) {
339731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(info);
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
342731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Make sure the default download directory exists.
343731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(phajdan.jr): only create the directory when we're sure the user
344731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // is going to save there and not to another directory of his choice.
345731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  file_util::CreateDirectory(default_path);
346731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check writability of the suggested path. If we can't write to it, default
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to the user's "My Documents" directory. We'll prompt them in this case.
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath dir = info->suggested_path.DirName();
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath filename = info->suggested_path.BaseName();
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!file_util::PathIsWritable(dir)) {
352201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    VLOG(1) << "Unable to write to directory \"" << dir.value() << "\"";
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->prompt_user_for_save_location = true;
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->suggested_path = info->suggested_path.Append(filename);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the download is deemed dangerous, we'll use a temporary name for it.
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (info->IsDangerous()) {
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->original_name = FilePath(info->suggested_path).BaseName();
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Create a temporary file to hold the file until the user approves its
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // download.
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FilePath::StringType file_name;
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FilePath path;
36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN)
36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    string16 unconfirmed_prefix =
36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#else
36972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string unconfirmed_prefix =
37072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
37172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
37272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (path.empty()) {
374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      base::SStringPrintf(
375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          &file_name,
37672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          unconfirmed_prefix.append(
37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              FILE_PATH_LITERAL(" %d.crdownload")).c_str(),
378513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          base::RandInt(0, 100000));
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      path = dir.Append(file_name);
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (file_util::PathExists(path))
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        path = FilePath();
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    info->suggested_path = path;
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Do not add the path uniquifier if we are saving to a specific path as in
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the drag-out case.
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (info->save_info.file_path.empty()) {
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info->path_uniquifier = download_util::GetUniquePathNumberWithCrDownload(
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          info->suggested_path);
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We know the final path, build it if necessary.
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (info->path_uniquifier > 0) {
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      download_util::AppendNumberToPath(&(info->suggested_path),
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        info->path_uniquifier);
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Setting path_uniquifier to 0 to make sure we don't try to unique it
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // later on.
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info->path_uniquifier = 0;
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (info->path_uniquifier == -1) {
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We failed to find a unique path.  We have to prompt the user.
400201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      VLOG(1) << "Unable to find a unique path for suggested path \""
401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << info->suggested_path.value() << "\"";
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info->prompt_user_for_save_location = true;
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create an empty file at the suggested path so that we don't allocate the
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // same "non-existant" path to multiple downloads.
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // See: http://code.google.com/p/chromium/issues/detail?id=3662
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!info->prompt_user_for_save_location &&
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      info->save_info.file_path.empty()) {
411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (info->IsDangerous())
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      file_util::WriteFile(info->suggested_path, "", 0);
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      file_util::WriteFile(download_util::GetCrDownloadPath(
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          info->suggested_path), "", 0);
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
418731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
419731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::UI, FROM_HERE,
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(this,
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        &DownloadManager::OnPathExistenceAvailable,
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        info));
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) {
426201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString();
427731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(info);
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (info->prompt_user_for_save_location) {
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We must ask the user for the place to put the download.
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!select_file_dialog_.get())
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      select_file_dialog_ = SelectFileDialog::Create(this);
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabContents* contents = tab_util::GetTabContentsByID(info->child_id,
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                         info->render_view_id);
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SelectFileDialog::FileTypeInfo file_type_info;
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_type_info.extensions.resize(1);
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_type_info.extensions[0].push_back(info->suggested_path.Extension());
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!file_type_info.extensions[0][0].empty())
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      file_type_info.extensions[0][0].erase(0, 1);  // drop the .
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_type_info.include_all_files = true;
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::NativeWindow owning_window =
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        contents ? platform_util::GetTopLevel(contents->GetNativeView()) : NULL;
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE,
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    string16(),
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    info->suggested_path,
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &file_type_info, 0, FILE_PATH_LITERAL(""),
449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    contents, owning_window, info);
450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FOR_EACH_OBSERVER(Observer, observers_,
451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                      SelectFileDialogDisplayed(info->download_id));
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // No prompting for download, just continue with the suggested name.
454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    info->path = info->suggested_path;
455dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AttachDownloadItem(info);
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) {
46021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
46121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
46221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DownloadItem* download = new DownloadItem(this, *info,
46321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                            profile_->IsOffTheRecord());
46421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!ContainsKey(in_progress_, info->download_id));
46572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!ContainsKey(active_downloads_, info->download_id));
46621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  downloads_.insert(download);
46772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  active_downloads_[info->download_id] = download;
46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
46921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
470dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid DownloadManager::AttachDownloadItem(DownloadCreateInfo* info) {
47172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString();
47272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
475dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Life of |info| ends here. No more references to it after this method.
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<DownloadCreateInfo> infop(info);
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // NOTE(ahendrickson) Eventually |active_downloads_| will replace
47972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // |in_progress_|, but we don't want to change the semantics yet.
4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(!ContainsKey(in_progress_, info->download_id));
48172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(ContainsKey(active_downloads_, info->download_id));
48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DownloadItem* download = active_downloads_[info->download_id];
48321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(download != NULL);
48472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(ContainsKey(downloads_, download));
48572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
48621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  download->SetFileCheckResults(info->path,
487dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                info->is_dangerous_file,
488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                info->is_dangerous_url,
48921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                info->path_uniquifier,
49021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                info->prompt_user_for_save_location,
49121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                info->is_extension_install,
49221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                info->original_name);
4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  in_progress_[info->download_id] = download;
49472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UpdateAppIcon();  // Reflect entry into in_progress_.
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Rename to intermediate name.
497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  FilePath download_path;
498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (info->IsDangerous()) {
49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // The download is not safe.  We can now rename the file to its
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // tentative name using RenameInProgressDownloadFile.
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // NOTE: The |Rename| below will be a no-op for dangerous files, as we're
502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // renaming it to the same name.
503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    download_path = info->path;
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // The download is a safe download.  We need to
50672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // rename it to its intermediate '.crdownload' path.  The final
50772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // name after user confirmation will be set from
508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // DownloadItem::OnDownloadCompleting.
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    download_path = download_util::GetCrDownloadPath(info->path);
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(
515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          file_manager_, &DownloadFileManager::RenameInProgressDownloadFile,
516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          download->id(), download_path));
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  download->Rename(download_path);
519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  download_history_->AddEntry(*info, download,
5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete));
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::UpdateDownload(int32 download_id, int64 size) {
52572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
52672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DownloadMap::iterator it = active_downloads_.find(download_id);
52772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (it != active_downloads_.end()) {
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DownloadItem* download = it->second;
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (download->IsInProgress()) {
53072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      download->Update(size);
53172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      UpdateAppIcon();  // Reflect size updates.
53272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      download_history_->UpdateEntry(download);
53372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadManager::OnResponseCompleted(int32 download_id,
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                          int64 size,
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                          int os_error,
540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                          const std::string& hash) {
541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5423dff810fe0cc4962a5fa554318e9bf8bc45f5274Kristian Monsen  // ERR_CONNECTION_CLOSED is allowed since a number of servers in the wild
5433dff810fe0cc4962a5fa554318e9bf8bc45f5274Kristian Monsen  // advertise a larger Content-Length than the amount of bytes in the message
5443dff810fe0cc4962a5fa554318e9bf8bc45f5274Kristian Monsen  // body, and then close the connection. Other browsers - IE8, Firefox 4.0.1,
5453dff810fe0cc4962a5fa554318e9bf8bc45f5274Kristian Monsen  // and Safari 5.0.4 - treat the download as complete in this case, so we
5463dff810fe0cc4962a5fa554318e9bf8bc45f5274Kristian Monsen  // follow their lead.
5473dff810fe0cc4962a5fa554318e9bf8bc45f5274Kristian Monsen  if (os_error == 0 || os_error == net::ERR_CONNECTION_CLOSED) {
548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnAllDataSaved(download_id, size, hash);
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    OnDownloadError(download_id, size, os_error);
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadManager::OnAllDataSaved(int32 download_id,
555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     int64 size,
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const std::string& hash) {
557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           << " size = " << size;
559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
56072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
56172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If it's not in active_downloads_, that means it was cancelled; just
56272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ignore the notification.
56372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (active_downloads_.count(download_id) == 0)
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DownloadItem* download = active_downloads_[download_id];
56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  download->OnAllDataSaved(size);
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // When hash is not available, it means either it is not calculated
570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // or there is error while it is calculated. We will skip the download hash
571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // check in that case.
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!hash.empty()) {
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    scoped_refptr<DownloadSBClient> sb_client =
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        new DownloadSBClient(download_id,
575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             download->url_chain(),
576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             download->referrer_url());
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sb_client->CheckDownloadHash(
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        hash, NewCallback(this, &DownloadManager::CheckDownloadHashDone));
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
58072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MaybeCompleteDownload(download);
58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
582201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(lzheng): This function currently works as a callback place holder.
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Once we decide the hash check is reliable, we could move the
585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// MaybeCompleteDownload in OnAllDataSaved to this function.
586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadManager::CheckDownloadHashDone(int32 download_id,
587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                            bool is_dangerous_hash) {
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DVLOG(1) << "CheckDownloadHashDone, download_id: " << download_id
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           << " is dangerous_hash: " << is_dangerous_hash;
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If it's not in active_downloads_, that means it was cancelled or
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // the download already finished.
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (active_downloads_.count(download_id) == 0)
595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DVLOG(1) << "CheckDownloadHashDone, url: "
598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           << active_downloads_[download_id]->url().spec();
599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
60172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) {
60272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If we don't have all the data, the download is not ready for
60372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // completion.
60472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!download->all_data_saved())
60572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
606201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If the download is dangerous, but not yet validated, it's not ready for
608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // completion.
609dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (download->safety_state() == DownloadItem::DANGEROUS)
610dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
611dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
61272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If the download isn't active (e.g. has been cancelled) it's not
61372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ready for completion.
61472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (active_downloads_.count(download->id()) == 0)
61572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If the download hasn't been inserted into the history system
61872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // (which occurs strictly after file name determination, intermediate
61972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // file rename, and UI display) then it's not ready for completion.
62072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return (download->db_handle() != DownloadHistory::kUninitializedHandle);
62172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DownloadManager::MaybeCompleteDownload(DownloadItem* download) {
62472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  VLOG(20) << __FUNCTION__ << "()" << " download = "
62672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           << download->DebugString(false);
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!IsDownloadReadyForCompletion(download))
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
63172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(rdsmith): DCHECK that we only pass through this point
63272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // once per download.  The natural way to do this is by a state
63372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // transition on the DownloadItem.
63472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
63572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Confirm we're in the proper set of states to be here;
636dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // in in_progress_, have all data, have a history handle, (validated or safe).
637dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_NE(DownloadItem::DANGEROUS, download->safety_state());
63872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK_EQ(1u, in_progress_.count(download->id()));
63972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(download->all_data_saved());
64072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(download->db_handle() != DownloadHistory::kUninitializedHandle);
64172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK_EQ(1u, history_downloads_.count(download->db_handle()));
64272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
64372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
64472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           << download->DebugString(false);
64572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
64672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Remove the id from in_progress
64772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  in_progress_.erase(download->id());
64872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UpdateAppIcon();  // Reflect removal from in_progress_.
64972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
65072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  download_history_->UpdateEntry(download);
65172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Finish the download.
653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  download->OnDownloadCompleting(file_manager_);
65472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadManager::DownloadCompleted(int32 download_id) {
65772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DownloadItem* download = GetDownloadItem(download_id);
659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(download);
660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  download_history_->UpdateEntry(download);
66172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  active_downloads_.erase(download_id);
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadManager::OnDownloadRenamedToFinalName(int download_id,
665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                   const FilePath& full_path,
666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                   int uniquifier) {
667201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           << " full_path = \"" << full_path.value() << "\""
669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           << " uniquifier = " << uniquifier;
670731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
6723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DownloadItem* item = GetDownloadItem(download_id);
6733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!item)
6743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (item->safety_state() == DownloadItem::SAFE) {
677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK_EQ(0, uniquifier) << "We should not uniquify SAFE downloads twice";
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
680731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(
683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          file_manager_, &DownloadFileManager::CompleteDownload, download_id));
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (uniquifier)
686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    item->set_path_uniquifier(uniquifier);
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  item->OnDownloadRenamedToFinalName(full_path);
689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  download_history_->UpdateDownloadPath(item, full_path);
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::DownloadCancelled(int32 download_id) {
69372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadMap::iterator it = in_progress_.find(download_id);
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == in_progress_.end())
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadItem* download = it->second;
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
699201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
700201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           << " download = " << download->DebugString(true);
701201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Clean up will happen when the history system create callback runs if we
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // don't have a valid db_handle yet.
7043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    in_progress_.erase(it);
70672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    active_downloads_.erase(download_id);
70772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UpdateAppIcon();  // Reflect removal from in_progress_.
7083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    download_history_->UpdateEntry(download);
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadCancelledInternal(download_id,
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            download->render_process_id(),
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            download->request_id());
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::DownloadCancelledInternal(int download_id,
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                int render_process_id,
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                int request_id) {
719ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancel the network request.  RDH is guaranteed to outlive the IO thread.
721731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
722731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::IO, FROM_HERE,
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableFunction(&download_util::CancelDownloadRequest,
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          g_browser_process->resource_dispatcher_host(),
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          render_process_id,
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          request_id));
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
728731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
729731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::FILE, FROM_HERE,
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          file_manager_, &DownloadFileManager::CancelDownload, download_id));
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid DownloadManager::OnDownloadError(int32 download_id,
735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      int64 size,
736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      int os_error) {
737ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DownloadMap::iterator it = active_downloads_.find(download_id);
739ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // A cancel at the right time could remove the download from the
740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // |active_downloads_| map before we get here.
741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (it == active_downloads_.end())
742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DownloadItem* download = it->second;
745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  VLOG(20) << "Error " << os_error << " at offset "
747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           << download->received_bytes() << " for download = "
748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen           << download->DebugString(true);
749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(ahendrickson) - Remove this when we add resuming of interrupted
751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // downloads, as we will keep the download item around in that case.
752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //
753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Clean up will happen when the history system create callback runs if we
754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // don't have a valid db_handle yet.
755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    in_progress_.erase(download_id);
757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_downloads_.erase(download_id);
758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UpdateAppIcon();  // Reflect removal from in_progress_.
759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    download_history_->UpdateEntry(download);
760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
761ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
762ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  download->Interrupted(size, os_error);
763ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
764ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  BrowserThread::PostTask(
765ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      BrowserThread::FILE, FROM_HERE,
766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NewRunnableMethod(
767ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          file_manager_, &DownloadFileManager::CancelDownload, download_id));
768ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::PauseDownload(int32 download_id, bool pause) {
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadMap::iterator it = in_progress_.find(download_id);
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == in_progress_.end())
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadItem* download = it->second;
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (pause == download->is_paused())
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
779731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
780731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::IO, FROM_HERE,
7813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewRunnableMethod(this,
7823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        &DownloadManager::PauseDownloadRequest,
7833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        g_browser_process->resource_dispatcher_host(),
7843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        download->render_process_id(),
7853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        download->request_id(),
7863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        pause));
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::UpdateAppIcon() {
7903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (status_updater_)
7913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    status_updater_->Update();
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadManager::PauseDownloadRequest(ResourceDispatcherHost* rdh,
7953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int render_process_id,
7963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int request_id,
7973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           bool pause) {
798731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
7993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rdh->PauseRequest(render_process_id, request_id, pause);
800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::RemoveDownload(int64 download_handle) {
80321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DownloadMap::iterator it = history_downloads_.find(download_handle);
80421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (it == history_downloads_.end())
805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make history update.
808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadItem* download = it->second;
8093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  download_history_->RemoveEntry(download);
810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Remove from our tables and delete.
81221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  history_downloads_.erase(it);
81321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int downloads_count = downloads_.erase(download);
81421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK_EQ(1, downloads_count);
815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Tell observers to refresh their views.
817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotifyModelChanged();
818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete download;
820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            const base::Time remove_end) {
8243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  download_history_->RemoveEntriesBetween(remove_begin, remove_end);
825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // All downloads visible to the user will be in the history,
82721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // so scan that map.
82821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DownloadMap::iterator it = history_downloads_.begin();
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<DownloadItem*> pending_deletes;
83021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  while (it != history_downloads_.end()) {
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DownloadItem* download = it->second;
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (download->start_time() >= remove_begin &&
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (remove_end.is_null() || download->start_time() < remove_end) &&
834ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        (download->IsComplete() ||
835ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         download->IsCancelled() ||
836ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         download->IsInterrupted())) {
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Remove from the map and move to the next in the list.
83821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      history_downloads_.erase(it++);
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Also remove it from any completed dangerous downloads.
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      pending_deletes.push_back(download);
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ++it;
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // If we aren't deleting anything, we're done.
85021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (pending_deletes.empty())
85121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return 0;
85221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
85321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Remove the chosen downloads from the main owning container.
85421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (std::vector<DownloadItem*>::iterator it = pending_deletes.begin();
85521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       it != pending_deletes.end(); it++) {
85621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    downloads_.erase(*it);
85721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
85821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Tell observers to refresh their views.
86021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  NotifyModelChanged();
86121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
86221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Delete the download items themselves.
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int num_deleted = static_cast<int>(pending_deletes.size());
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_deletes.clear();
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return num_deleted;
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint DownloadManager::RemoveDownloads(const base::Time remove_begin) {
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return RemoveDownloadsBetween(remove_begin, base::Time());
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint DownloadManager::RemoveAllDownloads() {
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (this != profile_->GetOriginalProfile()->GetDownloadManager()) {
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This is an incognito downloader. Clear All should clear main download
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // manager as well.
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads();
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The null times make the date range unbounded.
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return RemoveDownloadsBetween(base::Time(), base::Time());
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid DownloadManager::SavePageAsDownloadStarted(DownloadItem* download_item) {
88621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if !defined(NDEBUG)
88721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  save_page_as_downloads_.insert(download_item);
88821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
88921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  downloads_.insert(download_item);
8903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
8913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Initiate a download of a specific URL. We send the request to the
893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ResourceDispatcherHost, and let it send us responses like a regular
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// download.
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::DownloadUrl(const GURL& url,
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  const GURL& referrer,
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  const std::string& referrer_charset,
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  TabContents* tab_contents) {
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(),
900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    tab_contents);
901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::DownloadUrlToFile(const GURL& url,
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        const GURL& referrer,
905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        const std::string& referrer_charset,
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        const DownloadSaveInfo& save_info,
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        TabContents* tab_contents) {
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(tab_contents);
909731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableFunction(&download_util::DownloadUrl,
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          url,
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          referrer,
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          referrer_charset,
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          save_info,
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          g_browser_process->resource_dispatcher_host(),
916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          tab_contents->GetRenderProcessHost()->id(),
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          tab_contents->render_view_host()->routing_id(),
918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          request_context_getter_));
919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::AddObserver(Observer* observer) {
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  observers_.AddObserver(observer);
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  observer->ModelChanged();
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::RemoveObserver(Observer* observer) {
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  observers_.RemoveObserver(observer);
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DownloadManager::ShouldOpenFileBasedOnExtension(
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath& path) const {
932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath::StringType extension = path.Extension();
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (extension.empty())
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (Extension::IsExtension(path))
936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(extension[0] == FilePath::kExtensionSeparator);
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  extension.erase(0, 1);
9393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return download_prefs_->IsAutoOpenEnabledForExtension(extension);
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool DownloadManager::IsDownloadProgressKnown() {
9433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (DownloadMap::iterator i = in_progress_.begin();
9443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i != in_progress_.end(); ++i) {
9453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (i->second->total_bytes() <= 0)
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint64 DownloadManager::GetInProgressDownloadCount() {
9533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return in_progress_.size();
954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint64 DownloadManager::GetReceivedDownloadBytes() {
9573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(IsDownloadProgressKnown());
9583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int64 received_bytes = 0;
9593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (DownloadMap::iterator i = in_progress_.begin();
9603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i != in_progress_.end(); ++i) {
9613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    received_bytes += i->second->received_bytes();
9623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
9633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return received_bytes;
964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint64 DownloadManager::GetTotalDownloadBytes() {
9673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(IsDownloadProgressKnown());
9683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int64 total_bytes = 0;
9693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (DownloadMap::iterator i = in_progress_.begin();
9703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i != in_progress_.end(); ++i) {
9713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    total_bytes += i->second->total_bytes();
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
9733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return total_bytes;
974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::FileSelected(const FilePath& path,
977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   int index, void* params) {
978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params);
979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (info->prompt_user_for_save_location)
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    last_download_path_ = path.DirName();
981dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
982dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  info->path = path;
983dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AttachDownloadItem(info);
984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::FileSelectionCanceled(void* params) {
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The user didn't pick a place to save the file, so need to cancel the
988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // download that's already in progress to the temporary location.
989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params);
990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadCancelledInternal(info->download_id,
991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            info->child_id,
992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            info->request_id);
993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::DangerousDownloadValidated(DownloadItem* download) {
996dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state());
998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED);
999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  download->UpdateObservers();
1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1001dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MaybeCompleteDownload(download);
1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Operations posted to us from the history service ----------------------------
1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The history service has retrieved all download entries. 'entries' contains
1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 'DownloadCreateInfo's in sorted order (by ascending start_time).
1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::OnQueryDownloadEntriesComplete(
1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<DownloadCreateInfo>* entries) {
1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < entries->size(); ++i) {
10113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DownloadItem* download = new DownloadItem(this, entries->at(i));
101221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
101321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    downloads_.insert(download);
101421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    history_downloads_[download->db_handle()] = download;
1015201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    VLOG(20) << __FUNCTION__ << "()" << i << ">"
1016201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             << " download = " << download->DebugString(true);
1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotifyModelChanged();
1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Once the new DownloadItem's creation info has been committed to the history
1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// service, we associate the DownloadItem with the db handle, update our
102321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// 'history_downloads_' map and inform observers.
1024513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid DownloadManager::OnCreateDownloadEntryComplete(
10254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    DownloadCreateInfo info,
1026513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int64 db_handle) {
102772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadMap::iterator it = in_progress_.find(info.download_id);
1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(it != in_progress_.end());
1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DownloadItem* download = it->second;
1032201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
1033201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           << " download_id = " << info.download_id
1034201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           << " download = " << download->DebugString(true);
1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1036ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // It's not immediately obvious, but HistoryBackend::CreateDownload() can
1037ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // call this function with an invalid |db_handle|. For instance, this can
1038ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // happen when the history database is offline. We cannot have multiple
1039ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // DownloadItems with the same invalid db_handle, so we need to assign a
1040ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // unique |db_handle| here.
1041ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (db_handle == DownloadHistory::kUninitializedHandle)
1042ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    db_handle = download_history_->GetNextFakeDbHandle();
1043ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1044ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle);
1045ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  download->set_db_handle(db_handle);
1046ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1047ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
1048ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  history_downloads_[download->db_handle()] = download;
1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
105072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Show in the appropriate browser UI.
1051dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // This includes buttons to save or cancel, for a dangerous download.
1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShowDownloadInBrowser(info, download);
1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Inform interested objects about the new download.
1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotifyModelChanged();
1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1057ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If the download is still in progress, try to complete it.
105872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //
1059ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Otherwise, download has been cancelled or interrupted before we've
1060ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // received the DB handle.  We post one final message to the history
1061ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // service so that it can be properly in sync with the DownloadItem's
1062ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // completion status, and also inform any observers so that they get
1063ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // more than just the start notification.
1064ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (download->IsInProgress()) {
1065ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    MaybeCompleteDownload(download);
1066ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
1067ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(download->IsCancelled())
1068ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        << " download = " << download->DebugString(true);
1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    in_progress_.erase(it);
107072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    active_downloads_.erase(info.download_id);
10713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    download_history_->UpdateEntry(download);
1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    download->UpdateObservers();
1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info,
1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            DownloadItem* download) {
1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The 'contents' may no longer exist if the user closed the tab before we
1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // get this start completion event. If it does, tell the origin TabContents
1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to display its download shelf.
1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* contents = tab_util::GetTabContentsByID(info.child_id,
1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                       info.render_view_id);
1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the contents no longer exists, we start the download in the last active
1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // browser. This is not ideal but better than fully hiding the download from
1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the user.
1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!contents) {
1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Browser* last_active = BrowserList::GetLastActive();
1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (last_active)
1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      contents = last_active->GetSelectedTabContents();
1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (contents)
1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    contents->OnStartDownload(download);
1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Clears the last download path, used to initialize "save as" dialogs.
1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::ClearLastDownloadPath() {
1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  last_download_path_ = FilePath();
1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::NotifyModelChanged() {
1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FOR_EACH_OBSERVER(Observer, observers_, ModelChanged());
1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11063345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickDownloadItem* DownloadManager::GetDownloadItem(int id) {
110721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (DownloadMap::iterator it = history_downloads_.begin();
110821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       it != history_downloads_.end(); ++it) {
11093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DownloadItem* item = it->second;
11103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (item->id() == id)
11113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return item;
11123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
11133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return NULL;
11143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
111621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Confirm that everything in all maps is also in |downloads_|, and that
111721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// everything in |downloads_| is also in some other map.
111821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DownloadManager::AssertContainersConsistent() const {
111921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if !defined(NDEBUG)
112021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Turn everything into sets.
112172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DownloadSet active_set, history_set;
112272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_};
112372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DownloadSet* local_sets[] = {&active_set, &history_set};
112421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets));
112521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) {
112621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    for (DownloadMap::const_iterator it = input_maps[i]->begin();
112721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         it != input_maps[i]->end(); it++) {
112821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      local_sets[i]->insert(&*it->second);
112921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
113021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
113121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
113221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Check if each set is fully present in downloads, and create a union.
113372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const DownloadSet* all_sets[] = {&active_set, &history_set,
113421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                   &save_page_as_downloads_};
113521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DownloadSet downloads_union;
113621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) {
113721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DownloadSet remainder;
113821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
113921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
114021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                        downloads_.begin(), downloads_.end(),
114121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                        insert_it);
114221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK(remainder.empty());
114321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    std::insert_iterator<DownloadSet>
114421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        insert_union(downloads_union, downloads_union.end());
114521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    std::set_union(downloads_union.begin(), downloads_union.end(),
114621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   all_sets[i]->begin(), all_sets[i]->end(),
114721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                   insert_union);
114821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
114921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
115021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Is everything in downloads_ present in one of the other sets?
115121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DownloadSet remainder;
115221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::insert_iterator<DownloadSet>
115321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      insert_remainder(remainder, remainder.begin());
115421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::set_difference(downloads_.begin(), downloads_.end(),
115521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                      downloads_union.begin(), downloads_union.end(),
115621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                      insert_remainder);
115721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(remainder.empty());
115821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
115921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
116021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// DownloadManager::OtherDownloadManagerObserver implementation ----------------
1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadManager::OtherDownloadManagerObserver::OtherDownloadManagerObserver(
1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DownloadManager* observing_download_manager)
1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : observing_download_manager_(observing_download_manager),
1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      observed_download_manager_(NULL) {
1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (observing_download_manager->profile_->GetOriginalProfile() ==
1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      observing_download_manager->profile_) {
1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  observed_download_manager_ = observing_download_manager_->
1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_->GetOriginalProfile()->GetDownloadManager();
1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  observed_download_manager_->AddObserver(this);
1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDownloadManager::OtherDownloadManagerObserver::~OtherDownloadManagerObserver() {
1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (observed_download_manager_)
1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    observed_download_manager_->RemoveObserver(this);
1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::OtherDownloadManagerObserver::ModelChanged() {
1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  observing_download_manager_->NotifyModelChanged();
1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() {
1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  observed_download_manager_ = NULL;
1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1189