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