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 22 using content::BrowserContext; 23 using content::DownloadManager; 24 using content::DownloadManagerDelegate; 25 26 DownloadService::DownloadService(Profile* profile) 27 : download_manager_created_(false), 28 profile_(profile) { 29 } 30 31 DownloadService::~DownloadService() {} 32 33 ChromeDownloadManagerDelegate* 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 79 DownloadHistory* DownloadService::GetDownloadHistory() { 80 if (!download_manager_created_) { 81 GetDownloadManagerDelegate(); 82 } 83 DCHECK(download_manager_created_); 84 return download_history_.get(); 85 } 86 87 bool DownloadService::HasCreatedDownloadManager() { 88 return download_manager_created_; 89 } 90 91 int DownloadService::DownloadCount() const { 92 if (!download_manager_created_) 93 return 0; 94 return BrowserContext::GetDownloadManager(profile_)->InProgressCount(); 95 } 96 97 // static 98 int 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 114 void 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 128 bool 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 137 void 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