Index: chrome/browser/download/notification/download_notification_browsertest.cc |
diff --git a/chrome/browser/download/notification/download_notification_browsertest.cc b/chrome/browser/download/notification/download_notification_browsertest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..287bbbd453645d4a8b3a77f0f4d24ca61e087612 |
--- /dev/null |
+++ b/chrome/browser/download/notification/download_notification_browsertest.cc |
@@ -0,0 +1,501 @@ |
+// Copyright 2015 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 "base/command_line.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "chrome/browser/chromeos/profiles/profile_helper.h" |
+#include "chrome/browser/download/chrome_download_manager_delegate.h" |
+#include "chrome/browser/download/download_service.h" |
+#include "chrome/browser/download/download_service_factory.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/signin/signin_manager_factory.h" |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "chrome/grit/chromium_strings.h" |
+#include "chrome/grit/generated_resources.h" |
+#include "chrome/test/base/in_process_browser_test.h" |
+#include "chrome/test/base/ui_test_utils.h" |
+#include "chromeos/chromeos_switches.h" |
+#include "components/signin/core/browser/signin_manager_base.h" |
+#include "content/public/browser/browser_context.h" |
+#include "content/public/browser/download_item.h" |
+#include "content/public/browser/download_manager.h" |
+#include "grit/theme_resources.h" |
+#include "net/test/url_request/url_request_slow_download_job.h" |
+#include "ui/base/l10n/l10n_util.h" |
+#include "ui/message_center/message_center.h" |
+#include "ui/message_center/message_center_observer.h" |
+#include "url/gurl.h" |
+ |
+namespace { |
+ |
+enum { |
+ DUMMY_ACCOUNT_INDEX = 0, |
+ PRIMARY_ACCOUNT_INDEX = 1, |
+ SECONDARY_ACCOUNT_INDEX_START = 2, |
+}; |
+ |
+// Structure to describe an account info. |
+struct TestAccountInfo { |
+ const char* const email; |
+ const char* const gaia_id; |
+ const char* const hash; |
+ const char* const display_name; |
+}; |
+ |
+// Accounts for multi profile test. |
+static const TestAccountInfo kTestAccounts[] = { |
+ {"__dummy__@invalid.domain", "10000", "hashdummy", "Dummy Account"}, |
+ {"alice@invalid.domain", "10001", "hashalice", "Alice"}, |
+ {"bob@invalid.domain", "10002", "hashbobbo", "Bob"}, |
+ {"charlie@invalid.domain", "10003", "hashcharl", "Charlie"}, |
+}; |
+ |
+// Base class observing notification events. |
+class MessageCenterChangeObserver |
+ : public message_center::MessageCenterObserver { |
+ public: |
+ MessageCenterChangeObserver() { |
+ message_center::MessageCenter::Get()->AddObserver(this); |
+ } |
+ |
+ ~MessageCenterChangeObserver() override { |
+ message_center::MessageCenter::Get()->RemoveObserver(this); |
+ } |
+ |
+ protected: |
+ void RunLoop() { |
+ base::MessageLoop::ScopedNestableTaskAllower allow( |
+ base::MessageLoop::current()); |
+ run_loop_.Run(); |
+ } |
+ |
+ void QuitRunLoop() { |
+ run_loop_.Quit(); |
+ } |
+ |
+ private: |
+ base::RunLoop run_loop_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MessageCenterChangeObserver); |
+}; |
+ |
+// Class observing of "ADD" notification events. |
+class NotificationAddObserver : public MessageCenterChangeObserver { |
+ public: |
+ NotificationAddObserver() : count_(1) { |
+ MessageCenterChangeObserver(); |
+ } |
+ explicit NotificationAddObserver(int count) : count_(count) { |
+ MessageCenterChangeObserver(); |
+ } |
+ ~NotificationAddObserver() override {} |
+ |
+ bool Wait() { |
+ if (count_ <= 0) |
+ return count_ == 0; |
+ |
+ waiting_ = true; |
+ RunLoop(); |
+ waiting_ = false; |
+ return count_ == 0; |
+ } |
+ |
+ // message_center::MessageCenterObserver: |
+ void OnNotificationAdded(const std::string& notification_id) override { |
+ count_--; |
+ |
+ if (notification_id_.empty()) |
+ notification_id_ = notification_id; |
+ |
+ if (waiting_) |
+ QuitRunLoop(); |
+ } |
+ |
+ std::string notification_id() { return notification_id_; } |
+ |
+ private: |
+ std::string notification_id_; |
+ bool waiting_ = false; |
+ int count_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(NotificationAddObserver); |
+}; |
+ |
+// Class observing of "UPDATE" notification events. |
+class NotificationUpdateObserver : public MessageCenterChangeObserver { |
+ public: |
+ NotificationUpdateObserver() : waiting_(false) { |
+ MessageCenterChangeObserver(); |
Nico
2015/05/22 18:41:48
This is not how you call a superclass constructor.
|
+ } |
+ ~NotificationUpdateObserver() override {} |
+ |
+ std::string Wait() { |
+ if (!notification_id_.empty()) |
+ return notification_id_; |
+ |
+ waiting_ = true; |
+ RunLoop(); |
+ waiting_ = false; |
+ return notification_id_; |
+ } |
+ |
+ void OnNotificationUpdated(const std::string& notification_id) override { |
+ if (notification_id_.empty()) { |
+ notification_id_ = notification_id; |
+ |
+ if (waiting_) |
+ QuitRunLoop(); |
+ } |
+ } |
+ |
+ private: |
+ std::string notification_id_; |
+ bool waiting_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(NotificationUpdateObserver); |
+}; |
+ |
+class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate { |
+ public: |
+ explicit TestChromeDownloadManagerDelegate(Profile* profile) |
+ : ChromeDownloadManagerDelegate(profile), opened_(false) {} |
+ ~TestChromeDownloadManagerDelegate() override {} |
+ |
+ // ChromeDownloadManagerDelegate override: |
+ void OpenDownload(content::DownloadItem* item) override { opened_ = true; } |
+ |
+ // Return if the download is opened. |
+ bool opened() const { return opened_; } |
+ |
+ private: |
+ bool opened_; |
+}; |
+ |
+// Utility method to retrieve a message center. |
+message_center::MessageCenter* GetMessageCenter() { |
+ return message_center::MessageCenter::Get(); |
+} |
+ |
+// Utility method to retrieve a notification object by id. |
+message_center::Notification* GetNotification(const std::string& id) { |
+ return GetMessageCenter()->FindVisibleNotificationById(id); |
+} |
+ |
+} // anonnymous namespace |
+ |
+// Base class for tests |
+class DownloadNotificationTestBase : public InProcessBrowserTest { |
+ public: |
+ ~DownloadNotificationTestBase() override {} |
+ |
+ void SetUpCommandLine(base::CommandLine* command_line) override { |
+ // TODO(yoshiki): Remove this after the download notification launches. |
+ command_line->AppendSwitch(switches::kEnableDownloadNotification); |
+ } |
+ |
+ void SetUpOnMainThread() override { |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::IO, FROM_HERE, |
+ base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler)); |
+ } |
+ |
+ content::DownloadManager* GetDownloadManager(Browser* browser) { |
+ return content::BrowserContext::GetDownloadManager(browser->profile()); |
+ } |
+}; |
+ |
+////////////////////////////////////////////////// |
+// Test with a single profile |
+////////////////////////////////////////////////// |
+ |
+class DownloadNotificationTest : public DownloadNotificationTestBase { |
+ public: |
+ ~DownloadNotificationTest() override {} |
+ |
+ void SetUpOnMainThread() override { |
+ Profile* profile = browser()->profile(); |
+ |
+ scoped_ptr<TestChromeDownloadManagerDelegate> test_delegate; |
+ test_delegate.reset(new TestChromeDownloadManagerDelegate(profile)); |
+ test_delegate->GetDownloadIdReceiverCallback().Run( |
+ content::DownloadItem::kInvalidId + 1); |
+ |
+ DownloadServiceFactory::GetForBrowserContext(profile) |
+ ->SetDownloadManagerDelegateForTesting(test_delegate.Pass()); |
+ |
+ DownloadNotificationTestBase::SetUpOnMainThread(); |
+ } |
+ |
+ TestChromeDownloadManagerDelegate* GetDownloadManagerDelegate() const { |
+ return static_cast<TestChromeDownloadManagerDelegate*>( |
+ DownloadServiceFactory::GetForBrowserContext(browser()->profile()) |
+ ->GetDownloadManagerDelegate()); |
+ } |
+}; |
+ |
+IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadFile) { |
+ GURL url(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); |
+ |
+ // Starts a download. |
+ NotificationAddObserver download_start_notification_observer; |
+ ui_test_utils::NavigateToURL(browser(), url); |
+ EXPECT_TRUE(download_start_notification_observer.Wait()); |
+ |
+ // Confirms that a notification is created. |
+ std::string notification_id = |
+ download_start_notification_observer.notification_id(); |
+ EXPECT_FALSE(notification_id.empty()); |
+ |
+ // Confirms that a download is also started. |
+ std::vector<content::DownloadItem*> downloads; |
+ GetDownloadManager(browser())->GetAllDownloads(&downloads); |
+ EXPECT_EQ(1u, downloads.size()); |
+ content::DownloadItem* download = downloads[0]; |
+ |
+ EXPECT_EQ(l10n_util::GetStringFUTF16( |
+ IDS_DOWNLOAD_STATUS_IN_PROGRESS_TITLE, |
+ download->GetFileNameToReportUser().LossyDisplayName()), |
+ GetNotification(notification_id)->title()); |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, |
+ GetNotification(notification_id)->type()); |
+ |
+ // Requests to complete the download. |
+ ui_test_utils::NavigateToURL( |
+ browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); |
+ |
+ // Waits for download completion. |
+ while (download->GetState() != content::DownloadItem::COMPLETE) { |
+ NotificationUpdateObserver download_change_notification_observer; |
+ download_change_notification_observer.Wait(); |
+ } |
+ |
+ EXPECT_EQ(l10n_util::GetStringFUTF16( |
+ IDS_DOWNLOAD_STATUS_DOWNLOADED_TITLE, |
+ download->GetFileNameToReportUser().LossyDisplayName()), |
+ GetNotification(notification_id)->title()); |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, |
+ GetNotification(notification_id)->type()); |
+ |
+ // Try to open the downloaded item by clicking the notification. |
+ EXPECT_FALSE(GetDownloadManagerDelegate()->opened()); |
+ GetMessageCenter()->ClickOnNotification(notification_id); |
+ EXPECT_TRUE(GetDownloadManagerDelegate()->opened()); |
+ |
+ EXPECT_FALSE(GetNotification(notification_id)); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadMultipleFiles) { |
+ GURL url1(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); |
+ GURL url2(net::URLRequestSlowDownloadJob::kKnownSizeUrl); |
+ |
+ // Starts the 1st download. |
+ NotificationAddObserver download_start_notification_observer1; |
+ ui_test_utils::NavigateToURL(browser(), url1); |
+ EXPECT_TRUE(download_start_notification_observer1.Wait()); |
+ std::string notification_id1 = |
+ download_start_notification_observer1.notification_id(); |
+ EXPECT_FALSE(notification_id1.empty()); |
+ |
+ // Confirms that there is a download. |
+ std::vector<content::DownloadItem*> downloads; |
+ GetDownloadManager(browser())->GetAllDownloads(&downloads); |
+ EXPECT_EQ(1u, downloads.size()); |
+ content::DownloadItem* download1or2 = downloads[0]; |
+ |
+ // Starts the 2nd download. |
+ NotificationAddObserver download_start_notification_observer2; |
+ ui_test_utils::NavigateToURL(browser(), url2); |
+ EXPECT_TRUE(download_start_notification_observer2.Wait()); |
+ std::string notification_id2 = |
+ download_start_notification_observer2.notification_id(); |
+ EXPECT_FALSE(notification_id2.empty()); |
+ |
+ // Confirms that there are 2 downloads. |
+ downloads.clear(); |
+ GetDownloadManager(browser())->GetAllDownloads(&downloads); |
+ content::DownloadItem* download1 = downloads[0]; |
+ content::DownloadItem* download2 = downloads[1]; |
+ EXPECT_EQ(2u, downloads.size()); |
+ EXPECT_NE(download1, download2); |
+ EXPECT_TRUE(download1 == download1or2 || download2 == download1or2); |
+ |
+ // Confirms the types of download notifications are correct. |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, |
+ GetNotification(notification_id1)->type()); |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, |
+ GetNotification(notification_id2)->type()); |
+ |
+ // Requests to complete the downloads. |
+ ui_test_utils::NavigateToURL( |
+ browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); |
+ |
+ // Waits for the completion of downloads. |
+ while (download1->GetState() != content::DownloadItem::COMPLETE || |
+ download2->GetState() != content::DownloadItem::COMPLETE) { |
+ NotificationUpdateObserver download_change_notification_observer; |
+ download_change_notification_observer.Wait(); |
+ } |
+ |
+ // Confirms the types of download notifications are correct. |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, |
+ GetNotification(notification_id1)->type()); |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, |
+ GetNotification(notification_id2)->type()); |
+} |
+ |
+////////////////////////////////////////////////// |
+// Test with multi profiles |
+////////////////////////////////////////////////// |
+ |
+class MultiProfileDownloadNotificationTest |
+ : public DownloadNotificationTestBase { |
+ public: |
+ ~MultiProfileDownloadNotificationTest() override {} |
+ |
+ void SetUpCommandLine(base::CommandLine* command_line) override { |
+ DownloadNotificationTestBase::SetUpCommandLine(command_line); |
+ |
+ // Logs in to a dummy profile. |
+ command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, |
+ kTestAccounts[DUMMY_ACCOUNT_INDEX].email); |
+ command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, |
+ kTestAccounts[DUMMY_ACCOUNT_INDEX].hash); |
+ } |
+ |
+ // Logs in to the primary profile. |
+ void SetUpOnMainThread() override { |
+ const TestAccountInfo& info = kTestAccounts[PRIMARY_ACCOUNT_INDEX]; |
+ |
+ AddUser(info, true); |
+ DownloadNotificationTestBase::SetUpOnMainThread(); |
+ } |
+ |
+ // Loads all users to the current session and sets up necessary fields. |
+ // This is used for preparing all accounts in PRE_ test setup, and for testing |
+ // actual login behavior. |
+ void AddAllUsers() { |
+ for (size_t i = 0; i < arraysize(kTestAccounts); ++i) |
+ AddUser(kTestAccounts[i], i >= SECONDARY_ACCOUNT_INDEX_START); |
+ } |
+ |
+ Profile* GetProfileByIndex(int index) { |
+ return chromeos::ProfileHelper::GetProfileByUserIdHash( |
+ kTestAccounts[index].hash); |
+ } |
+ |
+ // Adds a new user for testing to the current session. |
+ void AddUser(const TestAccountInfo& info, bool log_in) { |
+ user_manager::UserManager* const user_manager = |
+ user_manager::UserManager::Get(); |
+ if (log_in) |
+ user_manager->UserLoggedIn(info.email, info.hash, false); |
+ user_manager->SaveUserDisplayName(info.email, |
+ base::UTF8ToUTF16(info.display_name)); |
+ SigninManagerFactory::GetForProfile( |
+ chromeos::ProfileHelper::GetProfileByUserIdHash(info.hash)) |
+ ->SetAuthenticatedAccountInfo(info.gaia_id, info.email); |
+ } |
+}; |
+ |
+IN_PROC_BROWSER_TEST_F(MultiProfileDownloadNotificationTest, |
+ PRE_DownloadMultipleFiles) { |
+ AddAllUsers(); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(MultiProfileDownloadNotificationTest, |
+ DownloadMultipleFiles) { |
+ AddAllUsers(); |
+ |
+ GURL url(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); |
+ |
+ Profile* profile1 = GetProfileByIndex(1); |
+ Profile* profile2 = GetProfileByIndex(2); |
+ Browser* browser1 = CreateBrowser(profile1); |
+ Browser* browser2 = CreateBrowser(profile2); |
+ EXPECT_NE(browser1, browser2); |
+ |
+ // First user starts a download. |
+ NotificationAddObserver download_start_notification_observer1; |
+ ui_test_utils::NavigateToURL(browser1, url); |
+ download_start_notification_observer1.Wait(); |
+ |
+ // Confirms that the download is started. |
+ std::vector<content::DownloadItem*> downloads; |
+ GetDownloadManager(browser1)->GetAllDownloads(&downloads); |
+ EXPECT_EQ(1u, downloads.size()); |
+ content::DownloadItem* download1 = downloads[0]; |
+ |
+ // Confirms that a download notification is generated. |
+ std::string notification_id1 = |
+ download_start_notification_observer1.notification_id(); |
+ EXPECT_FALSE(notification_id1.empty()); |
+ |
+ // Second user starts a download. |
+ NotificationAddObserver download_start_notification_observer2; |
+ ui_test_utils::NavigateToURL(browser2, url); |
+ download_start_notification_observer2.Wait(); |
+ std::string notification_id2 = |
+ download_start_notification_observer2.notification_id(); |
+ EXPECT_FALSE(notification_id2.empty()); |
+ |
+ // Confirms that the second user has only 1 download. |
+ downloads.clear(); |
+ GetDownloadManager(browser2)->GetAllDownloads(&downloads); |
+ ASSERT_EQ(1u, downloads.size()); |
+ |
+ // Second user starts another download. |
+ NotificationAddObserver download_start_notification_observer3; |
+ ui_test_utils::NavigateToURL(browser2, url); |
+ download_start_notification_observer3.Wait(); |
+ std::string notification_id3 = |
+ download_start_notification_observer3.notification_id(); |
+ EXPECT_FALSE(notification_id3.empty()); |
+ |
+ // Confirms that the second user has 2 downloads. |
+ downloads.clear(); |
+ GetDownloadManager(browser2)->GetAllDownloads(&downloads); |
+ ASSERT_EQ(2u, downloads.size()); |
+ content::DownloadItem* download2 = downloads[0]; |
+ content::DownloadItem* download3 = downloads[1]; |
+ EXPECT_NE(download1, download2); |
+ EXPECT_NE(download1, download3); |
+ EXPECT_NE(download2, download3); |
+ |
+ // Confirms that the first user still has only 1 download. |
+ downloads.clear(); |
+ GetDownloadManager(browser1)->GetAllDownloads(&downloads); |
+ ASSERT_EQ(1u, downloads.size()); |
+ EXPECT_EQ(download1, downloads[0]); |
+ |
+ // Confirms the types of download notifications are correct. |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, |
+ GetNotification(notification_id1)->type()); |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, |
+ GetNotification(notification_id2)->type()); |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, |
+ GetNotification(notification_id3)->type()); |
+ |
+ // Requests to complete the downloads. |
+ ui_test_utils::NavigateToURL( |
+ browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); |
+ |
+ // Waits for the completion of downloads. |
+ while (download1->GetState() != content::DownloadItem::COMPLETE || |
+ download2->GetState() != content::DownloadItem::COMPLETE || |
+ download3->GetState() != content::DownloadItem::COMPLETE) { |
+ NotificationUpdateObserver download_change_notification_observer; |
+ download_change_notification_observer.Wait(); |
+ } |
+ |
+ // Confirms the types of download notifications are correct. |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, |
+ GetNotification(notification_id1)->type()); |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, |
+ GetNotification(notification_id2)->type()); |
+ EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, |
+ GetNotification(notification_id3)->type()); |
+} |