1 // Copyright 2013 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.
5 #include "chrome/browser/download/download_ui_controller.h"
7 #include "base/callback.h"
8 #include "base/stl_util.h"
9 #include "chrome/browser/download/download_item_model.h"
10 #include "chrome/browser/ui/browser_finder.h"
11 #include "chrome/browser/ui/browser_tabstrip.h"
12 #include "content/public/browser/download_item.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/public/browser/web_contents_delegate.h"
16 #if defined(OS_ANDROID)
17 #include "content/public/browser/android/download_controller_android.h"
19 #include "chrome/browser/profiles/profile.h"
24 // DefaultUIControllerDelegate{Android,} is used when a DownloadUIController is
25 // constructed without specifying an explicit Delegate.
26 #if defined(OS_ANDROID)
28 class DefaultUIControllerDelegateAndroid
29 : public DownloadUIController::Delegate
{
31 DefaultUIControllerDelegateAndroid() {}
32 virtual ~DefaultUIControllerDelegateAndroid() {}
35 // DownloadUIController::Delegate
36 virtual void OnNewDownloadReady(content::DownloadItem
* item
) OVERRIDE
;
39 void DefaultUIControllerDelegateAndroid::OnNewDownloadReady(
40 content::DownloadItem
* item
) {
41 // The Android DownloadController is only interested in IN_PROGRESS downloads.
42 // Ones which are INTERRUPTED etc. can't be handed over to the Android
44 if (item
->GetState() != content::DownloadItem::IN_PROGRESS
)
47 // GET downloads without authentication are delegated to the Android
48 // DownloadManager. Chrome is responsible for the rest. See
49 // InterceptDownloadResourceThrottle::ProcessDownloadRequest().
50 content::DownloadControllerAndroid::Get()->OnDownloadStarted(item
);
55 class DefaultUIControllerDelegate
: public DownloadUIController::Delegate
{
57 // |profile| is required to outlive DefaultUIControllerDelegate.
58 explicit DefaultUIControllerDelegate(Profile
* profile
)
59 : profile_(profile
) {}
60 virtual ~DefaultUIControllerDelegate() {}
63 // DownloadUIController::Delegate
64 virtual void OnNewDownloadReady(content::DownloadItem
* item
) OVERRIDE
;
69 void DefaultUIControllerDelegate::OnNewDownloadReady(
70 content::DownloadItem
* item
) {
71 content::WebContents
* web_contents
= item
->GetWebContents();
73 web_contents
? chrome::FindBrowserWithWebContents(web_contents
) : NULL
;
75 // As a last resort, use the last active browser for this profile. Not ideal,
76 // but better than not showing the download at all.
77 if (browser
== NULL
) {
78 browser
= chrome::FindLastActiveWithProfile(profile_
,
79 chrome::GetActiveDesktop());
83 browser
->ShowDownload(item
);
90 DownloadUIController::Delegate::~Delegate() {
93 DownloadUIController::DownloadUIController(content::DownloadManager
* manager
,
94 scoped_ptr
<Delegate
> delegate
)
95 : download_notifier_(manager
, this),
96 delegate_(delegate
.Pass()) {
98 #if defined(OS_ANDROID)
99 delegate_
.reset(new DefaultUIControllerDelegateAndroid());
101 // The delegate should not be invoked after the profile has gone away. This
102 // should be the case since DownloadUIController is owned by
103 // DownloadService, which in turn is a profile keyed service.
104 delegate_
.reset(new DefaultUIControllerDelegate(
105 Profile::FromBrowserContext(manager
->GetBrowserContext())));
110 DownloadUIController::~DownloadUIController() {
113 void DownloadUIController::OnDownloadCreated(content::DownloadManager
* manager
,
114 content::DownloadItem
* item
) {
115 // SavePackage downloads are created in a state where they can be shown in the
116 // browser. Call OnDownloadUpdated() once to notify the UI immediately.
117 OnDownloadUpdated(manager
, item
);
120 void DownloadUIController::OnDownloadUpdated(content::DownloadManager
* manager
,
121 content::DownloadItem
* item
) {
122 DownloadItemModel
item_model(item
);
124 // Ignore if we've already notified the UI about |item| or if it isn't a new
126 if (item_model
.WasUINotified() || !item_model
.ShouldNotifyUI())
129 // Wait until the target path is determined.
130 if (item
->GetTargetFilePath().empty())
133 DownloadItemModel(item
).SetWasUINotified(true);
134 delegate_
->OnNewDownloadReady(item
);