| Index: chrome/browser/download/download_ui_controller.cc
|
| diff --git a/chrome/browser/download/download_ui_controller.cc b/chrome/browser/download/download_ui_controller.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..20dad7d0e9f5ed7d083f0f5e92a6f04d3e5db090
|
| --- /dev/null
|
| +++ b/chrome/browser/download/download_ui_controller.cc
|
| @@ -0,0 +1,153 @@
|
| +// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/download/download_ui_controller.h"
|
| +
|
| +#include "base/stl_util.h"
|
| +#include "chrome/browser/download/download_item_model.h"
|
| +#include "chrome/browser/ui/browser_finder.h"
|
| +#include "chrome/browser/ui/browser_tabstrip.h"
|
| +#include "content/public/browser/download_item.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/browser/web_contents_delegate.h"
|
| +
|
| +#if defined(OS_ANDROID)
|
| +#include "content/public/browser/android/download_controller_android.h"
|
| +#else
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
|
| +#include "chrome/browser/ui/blocked_content/blocked_content_tab_helper_delegate.h"
|
| +#endif
|
| +
|
| +namespace {
|
| +
|
| +// DefaultUIControllerDelegate{Android,} is used when a DownloadUIController is
|
| +// constructed without specifying an explicit Delegate.
|
| +#if defined(OS_ANDROID)
|
| +
|
| +class DefaultUIControllerDelegateAndroid
|
| + : public DownloadUIController::Delegate {
|
| + public:
|
| + DefaultUIControllerDelegateAndroid() {}
|
| + virtual ~DefaultUIControllerDelegateAndroid() {}
|
| +
|
| + private:
|
| + // DownloadUIController::Delegate
|
| + virtual void NotifyDownloadStarting(content::DownloadItem* item) OVERRIDE;
|
| +};
|
| +
|
| +void DefaultUIControllerDelegateAndroid::NotifyDownloadStarting(
|
| + content::DownloadItem* item) {
|
| + // GET downloads are delegated to the Android DownloadManager. Chrome is only
|
| + // responsible for POST downloads. See
|
| + // ChromeWebContentsDelegateAndroid::CanDownload().
|
| + content::DownloadControllerAndroid::Get()->OnPostDownloadStarted(item);
|
| +}
|
| +
|
| +#else // OS_ANDROID
|
| +
|
| +class DefaultUIControllerDelegate : public DownloadUIController::Delegate {
|
| + public:
|
| + // |profile| is required to outlive DefaultUIControllerDelegate.
|
| + explicit DefaultUIControllerDelegate(Profile* profile)
|
| + : profile_(profile) {}
|
| + virtual ~DefaultUIControllerDelegate() {}
|
| +
|
| + private:
|
| + // DownloadUIController::Delegate
|
| + virtual void NotifyDownloadStarting(content::DownloadItem* item) OVERRIDE;
|
| +
|
| + Profile* profile_;
|
| +};
|
| +
|
| +void DefaultUIControllerDelegate::NotifyDownloadStarting(
|
| + content::DownloadItem* item) {
|
| + content::WebContents* web_contents = item->GetWebContents();
|
| +
|
| + // If the tab requesting the download is a constrained popup that is not
|
| + // shown, treat the request as if it came from the parent.
|
| + if (web_contents != NULL) {
|
| + BlockedContentTabHelper* blocked_content_tab_helper =
|
| + BlockedContentTabHelper::FromWebContents(web_contents);
|
| + if (blocked_content_tab_helper &&
|
| + blocked_content_tab_helper->delegate()) {
|
| + content::WebContents* constraining_web_contents =
|
| + blocked_content_tab_helper->delegate()->
|
| + GetConstrainingWebContents(web_contents);
|
| + if (constraining_web_contents)
|
| + web_contents = constraining_web_contents;
|
| + }
|
| + }
|
| +
|
| + Browser* browser =
|
| + web_contents ? chrome::FindBrowserWithWebContents(web_contents) : NULL;
|
| +
|
| + // As a last resort, use the last active browser for this profile. Not ideal,
|
| + // but better than not showing the download at all.
|
| + if (browser == NULL) {
|
| + browser = chrome::FindLastActiveWithProfile(profile_,
|
| + chrome::GetActiveDesktop());
|
| + }
|
| +
|
| + if (browser)
|
| + browser->ShowDownload(item);
|
| +}
|
| +
|
| +#endif // !OS_ANDROID
|
| +
|
| +} // namespace
|
| +
|
| +DownloadUIController::Delegate::~Delegate() {
|
| +}
|
| +
|
| +DownloadUIController::DownloadUIController(content::DownloadManager* manager,
|
| + scoped_ptr<Delegate> delegate)
|
| + : ALLOW_THIS_IN_INITIALIZER_LIST(download_notifier_(manager, this)),
|
| + delegate_(delegate.Pass()) {
|
| + if (!delegate_) {
|
| +#if defined(OS_ANDROID)
|
| + delegate_.reset(new DefaultUIControllerDelegateAndroid());
|
| +#else
|
| + // The delegate should not be invoked after the profile has gone away. This
|
| + // should be the case since DownloadUIController is owned by
|
| + // DownloadService, which in turn is a profile keyed service.
|
| + delegate_.reset(new DefaultUIControllerDelegate(
|
| + Profile::FromBrowserContext(manager->GetBrowserContext())));
|
| +#endif
|
| + }
|
| +}
|
| +
|
| +DownloadUIController::~DownloadUIController() {
|
| +}
|
| +
|
| +void DownloadUIController::OnDownloadCreated(content::DownloadManager* manager,
|
| + content::DownloadItem* item) {
|
| + // If this isn't a new download, there's nothing to do.
|
| + if (!item->IsInProgress())
|
| + return;
|
| +
|
| + DownloadItemModel(item).SetShouldNotifyUI(true);
|
| + // SavePackage downloads are created in a state where they can be shown in the
|
| + // browser. Call OnDownloadUpdated() once to notify the UI immediately.
|
| + OnDownloadUpdated(manager, item);
|
| +}
|
| +
|
| +void DownloadUIController::OnDownloadUpdated(content::DownloadManager* manager,
|
| + content::DownloadItem* item) {
|
| + // Ignore if we've already notified the UI about |item| or if it isn't a new
|
| + // download.
|
| + if (!DownloadItemModel(item).ShouldNotifyUI())
|
| + return;
|
| +
|
| + // Wait until the target path is determined.
|
| + if (item->GetTargetFilePath().empty())
|
| + return;
|
| +
|
| + // Can't be complete. That would imply that we didn't receive an
|
| + // OnDownloadUpdated() after the target was determined.
|
| + DCHECK(!item->IsComplete());
|
| +
|
| + DownloadItemModel(item).SetShouldNotifyUI(false);
|
| + delegate_->NotifyDownloadStarting(item);
|
| +}
|
|
|