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/history/history_service.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/chrome_net_log.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_manager.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS)
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/extensions/api/downloads/downloads_api.h"
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserContext;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadManager;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadManagerDelegate;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadService::DownloadService(Profile* profile)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : download_manager_created_(false),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadService::~DownloadService() {}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeDownloadManagerDelegate* DownloadService::GetDownloadManagerDelegate() {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManager* manager = BrowserContext::GetDownloadManager(profile_);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we've already created the delegate, just return it.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (download_manager_created_) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(static_cast<DownloadManagerDelegate*>(manager_delegate_.get()) ==
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           manager->GetDelegate());
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return manager_delegate_.get();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download_manager_created_ = true;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In case the delegate has already been set by
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetDownloadManagerDelegateForTesting.
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!manager_delegate_.get())
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    manager_delegate_.reset(new ChromeDownloadManagerDelegate(profile_));
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager_delegate_->SetDownloadManager(manager);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS)
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  extension_event_router_.reset(
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new extensions::ExtensionDownloadsEventRouter(profile_, manager));
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!profile_->IsOffTheRecord()) {
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    HistoryService* history = HistoryServiceFactory::GetForProfile(
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        profile_, Profile::EXPLICIT_ACCESS);
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    history->GetNextDownloadId(
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        manager_delegate_->GetDownloadIdReceiverCallback());
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    download_history_.reset(new DownloadHistory(
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        manager,
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        scoped_ptr<DownloadHistory::HistoryAdapter>(
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            new DownloadHistory::HistoryAdapter(history))));
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Pass an empty delegate when constructing the DownloadUIController. The
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // default delegate does all the notifications we need.
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  download_ui_.reset(new DownloadUIController(
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      manager, scoped_ptr<DownloadUIController::Delegate>()));
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Include this download manager in the set monitored by the
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // global status updater.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_browser_process->download_status_updater()->AddManager(manager);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return manager_delegate_.get();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadHistory* DownloadService::GetDownloadHistory() {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!download_manager_created_) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GetDownloadManagerDelegate();
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(download_manager_created_);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return download_history_.get();
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadService::HasCreatedDownloadManager() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return download_manager_created_;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int DownloadService::NonMaliciousDownloadCount() const {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!download_manager_created_)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return BrowserContext::GetDownloadManager(profile_)->
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      NonMaliciousInProgressCount();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid DownloadService::CancelDownloads() {
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!download_manager_created_)
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DownloadManager* download_manager =
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      BrowserContext::GetDownloadManager(profile_);
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DownloadManager::DownloadVector downloads;
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  download_manager->GetAllDownloads(&downloads);
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (DownloadManager::DownloadVector::iterator it = downloads.begin();
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       it != downloads.end();
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch       ++it) {
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if ((*it)->GetState() == content::DownloadItem::IN_PROGRESS)
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      (*it)->Cancel(false);
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int DownloadService::NonMaliciousDownloadCountAllProfiles() {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Profile*> profiles(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_browser_process->profile_manager()->GetLoadedProfiles());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = 0;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<Profile*>::iterator it = profiles.begin();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it < profiles.end(); ++it) {
1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    count += DownloadServiceFactory::GetForBrowserContext(*it)->
1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        NonMaliciousDownloadCount();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->HasOffTheRecordProfile())
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      count += DownloadServiceFactory::GetForBrowserContext(
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          (*it)->GetOffTheRecordProfile())->NonMaliciousDownloadCount();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return count;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DownloadService::CancelAllDownloads() {
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<Profile*> profiles(
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      g_browser_process->profile_manager()->GetLoadedProfiles());
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (std::vector<Profile*>::iterator it = profiles.begin();
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it < profiles.end();
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       ++it) {
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    DownloadService* service =
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        DownloadServiceFactory::GetForBrowserContext(*it);
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    service->CancelDownloads();
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadService::SetDownloadManagerDelegateForTesting(
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<ChromeDownloadManagerDelegate> new_delegate) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  manager_delegate_.swap(new_delegate);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManager* dm = BrowserContext::GetDownloadManager(profile_);
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dm->SetDelegate(manager_delegate_.get());
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  manager_delegate_->SetDownloadManager(dm);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (new_delegate)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    new_delegate->Shutdown();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool DownloadService::IsShelfEnabled() {
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_ANDROID)
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#else
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return !extension_event_router_ ||
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)         extension_event_router_->IsShelfEnabled();
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadService::Shutdown() {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (download_manager_created_) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Normally the DownloadManager would be shutdown later, after the Profile
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // goes away and BrowserContext's destructor runs. But that would be too
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // late for us since we need to use the profile (indirectly through history
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // code) when the DownloadManager is shutting down. So we shut it down
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // manually earlier. See http://crbug.com/131692
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserContext::GetDownloadManager(profile_)->Shutdown();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension_event_router_.reset();
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  manager_delegate_.reset();
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  download_history_.reset();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
181