1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/download/download_service.h" 6 7#include "base/callback.h" 8#include "chrome/browser/browser_process.h" 9#include "chrome/browser/download/chrome_download_manager_delegate.h" 10#include "chrome/browser/download/download_history.h" 11#include "chrome/browser/download/download_service_factory.h" 12#include "chrome/browser/download/download_status_updater.h" 13#include "chrome/browser/download/download_ui_controller.h" 14#include "chrome/browser/extensions/api/downloads/downloads_api.h" 15#include "chrome/browser/history/history_service.h" 16#include "chrome/browser/history/history_service_factory.h" 17#include "chrome/browser/net/chrome_net_log.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/profiles/profile_manager.h" 20#include "content/public/browser/download_manager.h" 21 22using content::BrowserContext; 23using content::DownloadManager; 24using content::DownloadManagerDelegate; 25 26DownloadService::DownloadService(Profile* profile) 27 : download_manager_created_(false), 28 profile_(profile) { 29} 30 31DownloadService::~DownloadService() {} 32 33ChromeDownloadManagerDelegate* DownloadService::GetDownloadManagerDelegate() { 34 DownloadManager* manager = BrowserContext::GetDownloadManager(profile_); 35 // If we've already created the delegate, just return it. 36 if (download_manager_created_) { 37 DCHECK(static_cast<DownloadManagerDelegate*>(manager_delegate_.get()) == 38 manager->GetDelegate()); 39 return manager_delegate_.get(); 40 } 41 download_manager_created_ = true; 42 43 // In case the delegate has already been set by 44 // SetDownloadManagerDelegateForTesting. 45 if (!manager_delegate_.get()) 46 manager_delegate_ = new ChromeDownloadManagerDelegate(profile_); 47 48 manager_delegate_->SetDownloadManager(manager); 49 50#if !defined(OS_ANDROID) 51 extension_event_router_.reset(new ExtensionDownloadsEventRouter( 52 profile_, manager)); 53#endif 54 55 if (!profile_->IsOffTheRecord()) { 56 HistoryService* history = HistoryServiceFactory::GetForProfile( 57 profile_, Profile::EXPLICIT_ACCESS); 58 history->GetNextDownloadId(base::Bind( 59 &ChromeDownloadManagerDelegate::SetNextId, manager_delegate_)); 60 download_history_.reset(new DownloadHistory( 61 manager, 62 scoped_ptr<DownloadHistory::HistoryAdapter>( 63 new DownloadHistory::HistoryAdapter(history)))); 64 } 65 66 // Pass an empty delegate when constructing the DownloadUIController. The 67 // default delegate does all the notifications we need. 68 scoped_ptr<DownloadUIController::Delegate> empty_ui_delegate; 69 download_ui_.reset(new DownloadUIController(manager, 70 empty_ui_delegate.Pass())); 71 72 // Include this download manager in the set monitored by the 73 // global status updater. 74 g_browser_process->download_status_updater()->AddManager(manager); 75 76 return manager_delegate_.get(); 77} 78 79DownloadHistory* DownloadService::GetDownloadHistory() { 80 if (!download_manager_created_) { 81 GetDownloadManagerDelegate(); 82 } 83 DCHECK(download_manager_created_); 84 return download_history_.get(); 85} 86 87bool DownloadService::HasCreatedDownloadManager() { 88 return download_manager_created_; 89} 90 91int DownloadService::DownloadCount() const { 92 if (!download_manager_created_) 93 return 0; 94 return BrowserContext::GetDownloadManager(profile_)->InProgressCount(); 95} 96 97// static 98int DownloadService::DownloadCountAllProfiles() { 99 std::vector<Profile*> profiles( 100 g_browser_process->profile_manager()->GetLoadedProfiles()); 101 102 int count = 0; 103 for (std::vector<Profile*>::iterator it = profiles.begin(); 104 it < profiles.end(); ++it) { 105 count += DownloadServiceFactory::GetForBrowserContext(*it)->DownloadCount(); 106 if ((*it)->HasOffTheRecordProfile()) 107 count += DownloadServiceFactory::GetForBrowserContext( 108 (*it)->GetOffTheRecordProfile())->DownloadCount(); 109 } 110 111 return count; 112} 113 114void DownloadService::SetDownloadManagerDelegateForTesting( 115 ChromeDownloadManagerDelegate* new_delegate) { 116 // Set the new delegate first so that if BrowserContext::GetDownloadManager() 117 // causes a new download manager to be created, we won't create a redundant 118 // ChromeDownloadManagerDelegate(). 119 manager_delegate_ = new_delegate; 120 // Guarantee everything is properly initialized. 121 DownloadManager* dm = BrowserContext::GetDownloadManager(profile_); 122 if (dm->GetDelegate() != new_delegate) { 123 dm->SetDelegate(new_delegate); 124 new_delegate->SetDownloadManager(dm); 125 } 126} 127 128bool DownloadService::IsShelfEnabled() { 129#if defined(OS_ANDROID) 130 return true; 131#else 132 return !extension_event_router_ || 133 extension_event_router_->IsShelfEnabled(); 134#endif 135} 136 137void DownloadService::Shutdown() { 138 if (download_manager_created_) { 139 // Normally the DownloadManager would be shutdown later, after the Profile 140 // goes away and BrowserContext's destructor runs. But that would be too 141 // late for us since we need to use the profile (indirectly through history 142 // code) when the DownloadManager is shutting down. So we shut it down 143 // manually earlier. See http://crbug.com/131692 144 BrowserContext::GetDownloadManager(profile_)->Shutdown(); 145 } 146#if !defined(OS_ANDROID) 147 extension_event_router_.reset(); 148#endif 149 manager_delegate_ = NULL; 150 download_history_.reset(); 151} 152