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/history/history_service.h"
15#include "chrome/browser/history/history_service_factory.h"
16#include "chrome/browser/net/chrome_net_log.h"
17#include "chrome/browser/profiles/profile.h"
18#include "chrome/browser/profiles/profile_manager.h"
19#include "content/public/browser/download_manager.h"
20
21#if defined(ENABLE_EXTENSIONS)
22#include "chrome/browser/extensions/api/downloads/downloads_api.h"
23#endif
24
25using content::BrowserContext;
26using content::DownloadManager;
27using content::DownloadManagerDelegate;
28
29DownloadService::DownloadService(Profile* profile)
30    : download_manager_created_(false),
31      profile_(profile) {
32}
33
34DownloadService::~DownloadService() {}
35
36ChromeDownloadManagerDelegate* DownloadService::GetDownloadManagerDelegate() {
37  DownloadManager* manager = BrowserContext::GetDownloadManager(profile_);
38  // If we've already created the delegate, just return it.
39  if (download_manager_created_) {
40    DCHECK(static_cast<DownloadManagerDelegate*>(manager_delegate_.get()) ==
41           manager->GetDelegate());
42    return manager_delegate_.get();
43  }
44  download_manager_created_ = true;
45
46  // In case the delegate has already been set by
47  // SetDownloadManagerDelegateForTesting.
48  if (!manager_delegate_.get())
49    manager_delegate_.reset(new ChromeDownloadManagerDelegate(profile_));
50
51  manager_delegate_->SetDownloadManager(manager);
52
53#if defined(ENABLE_EXTENSIONS)
54  extension_event_router_.reset(
55      new extensions::ExtensionDownloadsEventRouter(profile_, manager));
56#endif
57
58  if (!profile_->IsOffTheRecord()) {
59    HistoryService* history = HistoryServiceFactory::GetForProfile(
60        profile_, Profile::EXPLICIT_ACCESS);
61    history->GetNextDownloadId(
62        manager_delegate_->GetDownloadIdReceiverCallback());
63    download_history_.reset(new DownloadHistory(
64        manager,
65        scoped_ptr<DownloadHistory::HistoryAdapter>(
66            new DownloadHistory::HistoryAdapter(history))));
67  }
68
69  // Pass an empty delegate when constructing the DownloadUIController. The
70  // default delegate does all the notifications we need.
71  download_ui_.reset(new DownloadUIController(
72      manager, scoped_ptr<DownloadUIController::Delegate>()));
73
74  // Include this download manager in the set monitored by the
75  // global status updater.
76  g_browser_process->download_status_updater()->AddManager(manager);
77
78  return manager_delegate_.get();
79}
80
81DownloadHistory* DownloadService::GetDownloadHistory() {
82  if (!download_manager_created_) {
83    GetDownloadManagerDelegate();
84  }
85  DCHECK(download_manager_created_);
86  return download_history_.get();
87}
88
89bool DownloadService::HasCreatedDownloadManager() {
90  return download_manager_created_;
91}
92
93int DownloadService::NonMaliciousDownloadCount() const {
94  if (!download_manager_created_)
95    return 0;
96  return BrowserContext::GetDownloadManager(profile_)->
97      NonMaliciousInProgressCount();
98}
99
100void DownloadService::CancelDownloads() {
101  if (!download_manager_created_)
102    return;
103
104  DownloadManager* download_manager =
105      BrowserContext::GetDownloadManager(profile_);
106  DownloadManager::DownloadVector downloads;
107  download_manager->GetAllDownloads(&downloads);
108  for (DownloadManager::DownloadVector::iterator it = downloads.begin();
109       it != downloads.end();
110       ++it) {
111    if ((*it)->GetState() == content::DownloadItem::IN_PROGRESS)
112      (*it)->Cancel(false);
113  }
114}
115
116// static
117int DownloadService::NonMaliciousDownloadCountAllProfiles() {
118  std::vector<Profile*> profiles(
119      g_browser_process->profile_manager()->GetLoadedProfiles());
120
121  int count = 0;
122  for (std::vector<Profile*>::iterator it = profiles.begin();
123       it < profiles.end(); ++it) {
124    count += DownloadServiceFactory::GetForBrowserContext(*it)->
125        NonMaliciousDownloadCount();
126    if ((*it)->HasOffTheRecordProfile())
127      count += DownloadServiceFactory::GetForBrowserContext(
128          (*it)->GetOffTheRecordProfile())->NonMaliciousDownloadCount();
129  }
130
131  return count;
132}
133
134// static
135void DownloadService::CancelAllDownloads() {
136  std::vector<Profile*> profiles(
137      g_browser_process->profile_manager()->GetLoadedProfiles());
138  for (std::vector<Profile*>::iterator it = profiles.begin();
139       it < profiles.end();
140       ++it) {
141    DownloadService* service =
142        DownloadServiceFactory::GetForBrowserContext(*it);
143    service->CancelDownloads();
144  }
145}
146
147void DownloadService::SetDownloadManagerDelegateForTesting(
148    scoped_ptr<ChromeDownloadManagerDelegate> new_delegate) {
149  manager_delegate_.swap(new_delegate);
150  DownloadManager* dm = BrowserContext::GetDownloadManager(profile_);
151  dm->SetDelegate(manager_delegate_.get());
152  manager_delegate_->SetDownloadManager(dm);
153  if (new_delegate)
154    new_delegate->Shutdown();
155}
156
157bool DownloadService::IsShelfEnabled() {
158#if defined(OS_ANDROID)
159  return true;
160#else
161  return !extension_event_router_ ||
162         extension_event_router_->IsShelfEnabled();
163#endif
164}
165
166void DownloadService::Shutdown() {
167  if (download_manager_created_) {
168    // Normally the DownloadManager would be shutdown later, after the Profile
169    // goes away and BrowserContext's destructor runs. But that would be too
170    // late for us since we need to use the profile (indirectly through history
171    // code) when the DownloadManager is shutting down. So we shut it down
172    // manually earlier. See http://crbug.com/131692
173    BrowserContext::GetDownloadManager(profile_)->Shutdown();
174  }
175#if defined(ENABLE_EXTENSIONS)
176  extension_event_router_.reset();
177#endif
178  manager_delegate_.reset();
179  download_history_.reset();
180}
181