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..9b859e8594cfee70c1014b66ecb93087b4763074 |
--- /dev/null |
+++ b/chrome/browser/download/download_ui_controller.cc |
@@ -0,0 +1,140 @@ |
+// Copyright (c) 2012 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/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/ui/blocked_content/blocked_content_tab_helper.h" |
+#include "chrome/browser/ui/blocked_content/blocked_content_tab_helper_delegate.h" |
+#endif |
+ |
+namespace { |
+ |
+// The presence of this UserData in a DownloadItem signals that the UI should be |
+// notified of this download. |
+class ShouldNotifyData : public base::SupportsUserData::Data { |
+ public: |
+ static void Set(content::DownloadItem* item) { |
+ new ShouldNotifyData(item); |
+ } |
+ |
+ static bool IsSet(content::DownloadItem* item) { |
+ return item->GetUserData(kKey) != NULL; |
+ } |
+ |
+ static void Clear(content::DownloadItem* item) { |
+ item->RemoveUserData(kKey); |
+ } |
+ |
+ private: |
+ explicit ShouldNotifyData(content::DownloadItem* item) { |
+ item->SetUserData(kKey, this); |
+ } |
+ |
+ static const char kKey[]; |
+ DISALLOW_COPY_AND_ASSIGN(ShouldNotifyData); |
+}; |
+ |
+const char ShouldNotifyData::kKey[] = "DownloadUIConroller ShouldNotifyData"; |
+ |
+} // namespace |
+ |
+DownloadUIController::DownloadUIController(Profile* profile, |
+ content::DownloadManager* manager) |
+ : ALLOW_THIS_IN_INITIALIZER_LIST(notifier_(manager, this)), |
+ profile_(profile) { |
+} |
+ |
+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; |
+ |
+ ShouldNotifyData::Set(item); |
+ // SavePackage downloads are created in a state where they can be shown |
+ // immediately in the browser. |
+ 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 (!ShouldNotifyData::IsSet(item)) |
+ return; |
+ |
+ // Wait until the target path is determined. |
+ if (item->GetTargetFilePath().empty()) |
+ return; |
+ |
+ // For a download that is in-progress, wait until the intermediate rename is |
+ // complete. |
+ // TODO(asanka): Get rid of remaining users of GetFullPath() in ui/. |
+ if (item->IsInProgress() && item->GetFullPath().empty()) |
+ return; |
+ |
+ // At this point, we expect that the download is either interrupted, or |
+ // in-progress and the path is known. |
+ |
+ // Can't be complete. That would imply that we didn't receive an |
+ // OnDownloadUpdated() after the intermediate rename was completed. |
+ DCHECK(!item->IsComplete()); |
+ |
+ ShouldNotifyData::Clear(item); |
+ NotifyDownloadStarting(item); |
+} |
+ |
+void DownloadUIController::NotifyDownloadStarting(content::DownloadItem* item) { |
+#if defined(OS_ANDROID) |
+ // GET downloads are delegated to and Android DownloadManager. Chrome is only |
benjhayden
2012/12/20 21:09:14
to an
asanka
2012/12/20 22:41:19
Done.
|
+ // responsible for POST downloads. |
+ // See ChromeWebContentsDelegateAndroid::CanDownload(). |
+ content::DownloadControllerAndroid::Get()->OnPostDownloadStarted(item); |
+#else |
+ 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 |
+} |
+ |