12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/download/download_ui_controller.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/download/download_item_model.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_tabstrip.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/download_item.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents_delegate.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_ANDROID)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/android/download_controller_android.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DefaultUIControllerDelegate{Android,} is used when a DownloadUIController is
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// constructed without specifying an explicit Delegate.
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_ANDROID)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DefaultUIControllerDelegateAndroid
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public DownloadUIController::Delegate {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DefaultUIControllerDelegateAndroid() {}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DefaultUIControllerDelegateAndroid() {}
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // DownloadUIController::Delegate
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnNewDownloadReady(content::DownloadItem* item) OVERRIDE;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DefaultUIControllerDelegateAndroid::OnNewDownloadReady(
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::DownloadItem* item) {
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The Android DownloadController is only interested in IN_PROGRESS downloads.
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Ones which are INTERRUPTED etc. can't be handed over to the Android
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // DownloadManager.
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (item->GetState() != content::DownloadItem::IN_PROGRESS)
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // GET downloads without authentication are delegated to the Android
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // DownloadManager. Chrome is responsible for the rest.  See
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // InterceptDownloadResourceThrottle::ProcessDownloadRequest().
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  content::DownloadControllerAndroid::Get()->OnDownloadStarted(item);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else  // OS_ANDROID
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DefaultUIControllerDelegate : public DownloadUIController::Delegate {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |profile| is required to outlive DefaultUIControllerDelegate.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit DefaultUIControllerDelegate(Profile* profile)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : profile_(profile) {}
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DefaultUIControllerDelegate() {}
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // DownloadUIController::Delegate
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnNewDownloadReady(content::DownloadItem* item) OVERRIDE;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Profile* profile_;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DefaultUIControllerDelegate::OnNewDownloadReady(
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::DownloadItem* item) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContents* web_contents = item->GetWebContents();
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Browser* browser =
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      web_contents ? chrome::FindBrowserWithWebContents(web_contents) : NULL;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // As a last resort, use the last active browser for this profile. Not ideal,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // but better than not showing the download at all.
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (browser == NULL) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser = chrome::FindLastActiveWithProfile(profile_,
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                chrome::GetActiveDesktop());
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (browser)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser->ShowDownload(item);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // !OS_ANDROID
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadUIController::Delegate::~Delegate() {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadUIController::DownloadUIController(content::DownloadManager* manager,
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           scoped_ptr<Delegate> delegate)
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : download_notifier_(manager, this),
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delegate_(delegate.Pass()) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!delegate_) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_ANDROID)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delegate_.reset(new DefaultUIControllerDelegateAndroid());
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The delegate should not be invoked after the profile has gone away. This
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // should be the case since DownloadUIController is owned by
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // DownloadService, which in turn is a profile keyed service.
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delegate_.reset(new DefaultUIControllerDelegate(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Profile::FromBrowserContext(manager->GetBrowserContext())));
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadUIController::~DownloadUIController() {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadUIController::OnDownloadCreated(content::DownloadManager* manager,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             content::DownloadItem* item) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SavePackage downloads are created in a state where they can be shown in the
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // browser. Call OnDownloadUpdated() once to notify the UI immediately.
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnDownloadUpdated(manager, item);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DownloadUIController::OnDownloadUpdated(content::DownloadManager* manager,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             content::DownloadItem* item) {
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DownloadItemModel item_model(item);
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ignore if we've already notified the UI about |item| or if it isn't a new
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // download.
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (item_model.WasUINotified() || !item_model.ShouldNotifyUI())
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wait until the target path is determined.
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (item->GetTargetFilePath().empty())
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DownloadItemModel(item).SetWasUINotified(true);
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  delegate_->OnNewDownloadReady(item);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
136