download_service.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/chrome_download_manager_delegate.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/download/download_history.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_service_factory.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_status_updater.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/download/download_ui_controller.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/downloads/downloads_api.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/chrome_net_log.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_manager.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserContext;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadManager;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadManagerDelegate;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadService::DownloadService(Profile* profile)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : download_manager_created_(false),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadService::~DownloadService() {}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeDownloadManagerDelegate* DownloadService::GetDownloadManagerDelegate() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManager* manager = BrowserContext::GetDownloadManager(profile_);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we've already created the delegate, just return it.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (download_manager_created_) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(static_cast<DownloadManagerDelegate*>(manager_delegate_.get()) ==
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           manager->GetDelegate());
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return manager_delegate_.get();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download_manager_created_ = true;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In case the delegate has already been set by
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetDownloadManagerDelegateForTesting.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!manager_delegate_.get())
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_delegate_ = new ChromeDownloadManagerDelegate(profile_);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager_delegate_->SetDownloadManager(manager);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension_event_router_.reset(new ExtensionDownloadsEventRouter(
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_, manager));
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!profile_->IsOffTheRecord()) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    HistoryService* hs = HistoryServiceFactory::GetForProfile(
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        profile_, Profile::EXPLICIT_ACCESS);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (hs)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download_history_.reset(new DownloadHistory(
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          manager,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          scoped_ptr<DownloadHistory::HistoryAdapter>(
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new DownloadHistory::HistoryAdapter(hs))));
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Pass an empty delegate when constructing the DownloadUIController. The
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // default delegate does all the notifications we need.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<DownloadUIController::Delegate> empty_ui_delegate;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  download_ui_.reset(new DownloadUIController(manager,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              empty_ui_delegate.Pass()));
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Include this download manager in the set monitored by the
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // global status updater.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_browser_process->download_status_updater()->AddManager(manager);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return manager_delegate_.get();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadHistory* DownloadService::GetDownloadHistory() {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!download_manager_created_) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GetDownloadManagerDelegate();
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(download_manager_created_);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return download_history_.get();
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadService::HasCreatedDownloadManager() {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return download_manager_created_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DownloadService::DownloadCount() const {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!download_manager_created_)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return BrowserContext::GetDownloadManager(profile_)->InProgressCount();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DownloadService::DownloadCountAllProfiles() {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Profile*> profiles(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_browser_process->profile_manager()->GetLoadedProfiles());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = 0;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<Profile*>::iterator it = profiles.begin();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it < profiles.end(); ++it) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count += DownloadServiceFactory::GetForProfile(*it)->DownloadCount();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->HasOffTheRecordProfile())
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      count += DownloadServiceFactory::GetForProfile(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*it)->GetOffTheRecordProfile())->DownloadCount();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return count;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadService::SetDownloadManagerDelegateForTesting(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChromeDownloadManagerDelegate* new_delegate) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the new delegate first so that if BrowserContext::GetDownloadManager()
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // causes a new download manager to be created, we won't create a redundant
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChromeDownloadManagerDelegate().
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager_delegate_ = new_delegate;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Guarantee everything is properly initialized.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManager* dm = BrowserContext::GetDownloadManager(profile_);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dm->GetDelegate() != new_delegate) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dm->SetDelegate(new_delegate);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_delegate->SetDownloadManager(dm);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadService::Shutdown() {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (download_manager_created_) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Normally the DownloadManager would be shutdown later, after the Profile
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // goes away and BrowserContext's destructor runs. But that would be too
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // late for us since we need to use the profile (indirectly through history
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // code) when the DownloadManager is shutting down. So we shut it down
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // manually earlier. See http://crbug.com/131692
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserContext::GetDownloadManager(profile_)->Shutdown();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension_event_router_.reset();
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager_delegate_ = NULL;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  download_history_.reset();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
142