// 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 #include "base/command_line.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/path_service.h" #include "base/prefs/pref_service.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_prefs.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/browser/ui/browser_commands.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.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 "content/public/test/download_test_observer.h" #include "grit/theme_resources.h" #include "net/test/embedded_test_server/embedded_test_server.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"}, }; template bool IsInNotifications( const T& notifications, const std::string& id) { for (const auto& notification : notifications) { if (notification->id() == id) return true; } return false; } // 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(); } void ResetRunLoop() { run_loop_.reset(new base::RunLoop); } private: scoped_ptr run_loop_; DISALLOW_COPY_AND_ASSIGN(MessageCenterChangeObserver); }; // Class observing of "ADD" notification events. class NotificationAddObserver : public MessageCenterChangeObserver { public: NotificationAddObserver() : count_(1) {} explicit NotificationAddObserver(int count) : count_(count) { MessageCenterChangeObserver(); } ~NotificationAddObserver() override {} bool Wait() { if (count_ <= 0) return count_ == 0; waiting_ = true; ResetRunLoop(); RunLoop(); waiting_ = false; return count_ == 0; } // message_center::MessageCenterObserver: void OnNotificationAdded(const std::string& notification_id) override { count_--; notification_ids_.push_back(notification_id); if (waiting_ && count_ == 0) QuitRunLoop(); } const std::string& notification_id() const { return notification_ids_.at(0); } const std::vector& notification_ids() const { return notification_ids_; } private: std::vector notification_ids_; bool waiting_ = false; int count_; DISALLOW_COPY_AND_ASSIGN(NotificationAddObserver); }; // Class observing of "UPDATE" notification events. class NotificationUpdateObserver : public MessageCenterChangeObserver { public: NotificationUpdateObserver() {} explicit NotificationUpdateObserver(const std::string& id) : target_notification_id_(id) {} ~NotificationUpdateObserver() override {} std::string Wait() { if (!notification_id_.empty()) return notification_id_; waiting_ = true; ResetRunLoop(); RunLoop(); waiting_ = false; std::string notification_id(notification_id_); notification_id_.clear(); return notification_id; } void OnNotificationUpdated(const std::string& notification_id) override { if (notification_id_.empty()) { if (!target_notification_id_.empty() && target_notification_id_ != notification_id) { return; } notification_id_ = notification_id; if (waiting_) QuitRunLoop(); } } void Reset() { notification_id_.clear(); } private: std::string notification_id_; std::string target_notification_id_; bool waiting_ = false; DISALLOW_COPY_AND_ASSIGN(NotificationUpdateObserver); }; // Class observing of "REMOVE" notification events. class NotificationRemoveObserver : public MessageCenterChangeObserver { public: NotificationRemoveObserver() {} ~NotificationRemoveObserver() override {} std::string Wait() { if (!notification_id_.empty()) return notification_id_; waiting_ = true; ResetRunLoop(); RunLoop(); waiting_ = false; return notification_id_; } // message_center::MessageCenterObserver: void OnNotificationRemoved( const std::string& notification_id, bool by_user) override { if (notification_id_.empty()) { notification_id_ = notification_id; if (waiting_) QuitRunLoop(); } } private: std::string notification_id_; bool waiting_ = false; DISALLOW_COPY_AND_ASSIGN(NotificationRemoveObserver); }; 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_; } protected: // Disable DownloadProtectionService in order to disable content checking. safe_browsing::DownloadProtectionService* GetDownloadProtectionService() override { return nullptr; } 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 SetUpOnMainThread() override { ASSERT_TRUE(embedded_test_server()->Start()); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler)); GetMessageCenter()->DisableTimersForTest(); // Set up the temporary download folder. ASSERT_TRUE(CreateAndSetDownloadsDirectory(browser())); } protected: // Must be called after browser creation. Creates a temporary // directory for downloads that is auto-deleted on destruction. // Returning false indicates a failure of the function, and should be asserted // in the caller. bool CreateAndSetDownloadsDirectory(Browser* browser) { if (!browser) return false; if (!downloads_directory_.path().empty()) return true; // already created if (!downloads_directory_.CreateUniqueTempDir()) return false; browser->profile()->GetPrefs()->SetFilePath( prefs::kDownloadDefaultDirectory, downloads_directory_.path()); browser->profile()->GetPrefs()->SetFilePath( prefs::kSaveFileDefaultDirectory, downloads_directory_.path()); return true; } content::DownloadManager* GetDownloadManager(Browser* browser) { return content::BrowserContext::GetDownloadManager(browser->profile()); } private: // Location of the downloads directory for these tests base::ScopedTempDir downloads_directory_; }; ////////////////////////////////////////////////// // Test with a single profile ////////////////////////////////////////////////// class DownloadNotificationTest : public DownloadNotificationTestBase { public: ~DownloadNotificationTest() override {} void SetUpOnMainThread() override { Profile* profile = browser()->profile(); scoped_ptr 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( DownloadServiceFactory::GetForBrowserContext(browser()->profile()) ->GetDownloadManagerDelegate()); } void PrepareIncognitoBrowser() { incognito_browser_ = CreateIncognitoBrowser(); Profile* incognito_profile = incognito_browser_->profile(); ASSERT_TRUE(CreateAndSetDownloadsDirectory(incognito_browser_)); scoped_ptr incognito_test_delegate; incognito_test_delegate.reset( new TestChromeDownloadManagerDelegate(incognito_profile)); DownloadServiceFactory::GetForBrowserContext(incognito_profile) ->SetDownloadManagerDelegateForTesting(incognito_test_delegate.Pass()); } TestChromeDownloadManagerDelegate* GetIncognitoDownloadManagerDelegate() const { Profile* incognito_profile = incognito_browser()->profile(); return static_cast( DownloadServiceFactory::GetForBrowserContext(incognito_profile)-> GetDownloadManagerDelegate()); } void CreateDownload() { return CreateDownloadForBrowserAndURL( browser(), GURL(net::URLRequestSlowDownloadJob::kKnownSizeUrl)); } void CreateDownloadForBrowserAndURL(Browser* browser, GURL url) { // 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. notification_id_ = download_start_notification_observer.notification_id(); EXPECT_FALSE(notification_id_.empty()); ASSERT_TRUE(notification()); // Confirms that there is only one notification. message_center::NotificationList::Notifications visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(1u, visible_notifications.size()); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id_)); // Confirms that a download is also started. std::vector downloads; GetDownloadManager(browser)->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); download_item_ = downloads[0]; ASSERT_TRUE(download_item_); } content::DownloadItem* download_item() const { return download_item_; } std::string notification_id() const { return notification_id_; } message_center::Notification* notification() const { return GetNotification(notification_id_); } Browser* incognito_browser() const { return incognito_browser_; } base::FilePath GetDownloadPath() { return DownloadPrefs::FromDownloadManager(GetDownloadManager(browser()))-> DownloadPath(); } private: content::DownloadItem* download_item_ = nullptr; Browser* incognito_browser_ = nullptr; std::string notification_id_; }; IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadFile) { CreateDownload(); EXPECT_EQ(l10n_util::GetStringFUTF16( IDS_DOWNLOAD_STATUS_IN_PROGRESS_TITLE, download_item()->GetFileNameToReportUser().LossyDisplayName()), GetNotification(notification_id())->title()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, GetNotification(notification_id())->type()); // Confirms that the download update is delivered to the notification. NotificationUpdateObserver download_notification_periodically_update_observer; download_item()->UpdateObservers(); download_notification_periodically_update_observer.Wait(); // Requests to complete the download. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); // Waits for download completion. NotificationUpdateObserver download_change_notification_observer(notification_id()); while (download_item()->GetState() != content::DownloadItem::COMPLETE) { download_change_notification_observer.Wait(); download_change_notification_observer.Reset(); } // Checks strings. EXPECT_EQ(l10n_util::GetStringFUTF16( IDS_DOWNLOAD_STATUS_DOWNLOADED_TITLE, download_item()->GetFileNameToReportUser().LossyDisplayName()), GetNotification(notification_id())->title()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id())->type()); // Confirms that there is only one notification. message_center::NotificationList::Notifications visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(1u, visible_notifications.size()); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id())); // Opens the message center. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); // 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, DownloadDangerousFile) { GURL download_url(embedded_test_server()->GetURL( "/downloads/dangerous/dangerous.swf")); content::DownloadTestObserverTerminal download_terminal_observer( GetDownloadManager(browser()), 1u, /* wait_count */ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_IGNORE); CreateDownloadForBrowserAndURL(browser(), download_url); base::FilePath filename = download_item()->GetFileNameToReportUser(); // Checks the download status. EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, download_item()->GetDangerType()); EXPECT_TRUE(download_item()->IsDangerous()); // Opens the message center. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); NotificationRemoveObserver notification_close_observer; NotificationAddObserver notification_add_observer; // Cicks the "keep" button. notification()->ButtonClick(1); // 2nd button: "Keep" // Clicking makes the message center closed. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_TRANSIENT); // Confirms that the notification is closed and re-shown. EXPECT_EQ(notification_id(), notification_close_observer.Wait()); notification_add_observer.Wait(); EXPECT_EQ(notification_id(), notification_add_observer.notification_id()); EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size()); // Checks the download status. EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED, download_item()->GetDangerType()); EXPECT_FALSE(download_item()->IsDangerous()); // Wait for the download completion. download_terminal_observer.WaitForFinished(); // Checks the download status. EXPECT_FALSE(download_item()->IsDangerous()); EXPECT_EQ(content::DownloadItem::COMPLETE, download_item()->GetState()); // Checks the downloaded file. EXPECT_TRUE(base::PathExists(GetDownloadPath().Append(filename.BaseName()))); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DiscardDangerousFile) { GURL download_url(embedded_test_server()->GetURL( "/downloads/dangerous/dangerous.swf")); content::DownloadTestObserverTerminal download_terminal_observer( GetDownloadManager(browser()), 1u, /* wait_count */ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_IGNORE); CreateDownloadForBrowserAndURL(browser(), download_url); base::FilePath filename = download_item()->GetFileNameToReportUser(); // Checks the download status. EXPECT_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, download_item()->GetDangerType()); EXPECT_TRUE(download_item()->IsDangerous()); // Opens the message center. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); // Ensures the notification exists. EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size()); NotificationRemoveObserver notification_close_observer; // Clicks the "Discard" button. notification()->ButtonClick(0); // 1st button: "Discard" // Clicking makes the message center closed. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_TRANSIENT); // Confirms that the notification is closed. EXPECT_EQ(notification_id(), notification_close_observer.Wait()); // Ensures the notification has closed. EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); // Wait for the download completion. download_terminal_observer.WaitForFinished(); // Checks there is neither any download nor any notification. EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); std::vector downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(0u, downloads.size()); // Checks the downloaded file doesn't exist. EXPECT_FALSE(base::PathExists(GetDownloadPath().Append(filename.BaseName()))); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadImageFile) { GURL download_url(embedded_test_server()->GetURL( "/downloads/image-octet-stream.png")); content::DownloadTestObserverTerminal download_terminal_observer( GetDownloadManager(browser()), 1u, /* wait_count */ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_IGNORE); CreateDownloadForBrowserAndURL(browser(), download_url); // Wait for the download completion. download_terminal_observer.WaitForFinished(); // Waits for download completion. NotificationUpdateObserver download_change_notification_observer(notification_id()); while (GetNotification(notification_id())->image().IsEmpty()) { download_change_notification_observer.Wait(); download_change_notification_observer.Reset(); } } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, CloseNotificationAfterDownload) { CreateDownload(); // Requests to complete the download. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); // Waits for download completion. NotificationUpdateObserver download_change_notification_observer(notification_id()); while (download_item()->GetState() != content::DownloadItem::COMPLETE) { download_change_notification_observer.Wait(); download_change_notification_observer.Reset(); } // Opens the message center. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); // Closes the notification. NotificationRemoveObserver notification_close_observer; GetMessageCenter()->RemoveNotification(notification_id(), true /* by_user */); EXPECT_EQ(notification_id(), notification_close_observer.Wait()); EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); // Confirms that a download is also started. std::vector downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); EXPECT_EQ(content::DownloadItem::COMPLETE, downloads[0]->GetState()); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, CloseNotificationWhileDownloading) { CreateDownload(); // Closes the notification. NotificationRemoveObserver notification_close_observer; GetMessageCenter()->RemoveNotification(notification_id(), true /* by_user */); EXPECT_EQ(notification_id(), notification_close_observer.Wait()); EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); // Confirms that a download is still in progress. std::vector downloads; content::DownloadManager* download_manager = GetDownloadManager(browser()); download_manager->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); EXPECT_EQ(content::DownloadItem::IN_PROGRESS, downloads[0]->GetState()); // Installs observers before requesting the completion. NotificationAddObserver download_notification_add_observer; content::DownloadTestObserverTerminal download_terminal_observer( download_manager, 1u, /* wait_count */ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); // Requests to complete the download and wait for it. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); download_terminal_observer.WaitForFinished(); // Waits that new notification. download_notification_add_observer.Wait(); // Confirms that there is only one notification. message_center::NotificationList::Notifications visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(1u, visible_notifications.size()); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id())); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, InterruptDownload) { CreateDownload(); // Installs observers before requesting. NotificationUpdateObserver download_notification_update_observer(notification_id()); content::DownloadTestObserverInterrupted download_terminal_observer( GetDownloadManager(browser()), 1u, /* wait_count */ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); // Requests to fail the download and wait for it. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kErrorDownloadUrl)); download_terminal_observer.WaitForFinished(); // Waits that new notification. download_notification_update_observer.Wait(); // Confirms that there is only one notification. message_center::NotificationList::Notifications visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(1u, visible_notifications.size()); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id())); // Checks strings. EXPECT_EQ(l10n_util::GetStringFUTF16( IDS_DOWNLOAD_STATUS_DOWNLOAD_FAILED_TITLE, download_item()->GetFileNameToReportUser().LossyDisplayName()), GetNotification(notification_id())->title()); EXPECT_NE(GetNotification(notification_id())->message().find( l10n_util::GetStringFUTF16( IDS_DOWNLOAD_STATUS_INTERRUPTED, l10n_util::GetStringUTF16( IDS_DOWNLOAD_INTERRUPTED_DESCRIPTION_NETWORK_ERROR))), std::string::npos); EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id())->type()); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, InterruptDownloadAfterClosingNotification) { CreateDownload(); // Closes the notification. NotificationRemoveObserver notification_close_observer; GetMessageCenter()->RemoveNotification(notification_id(), true /* by_user */); EXPECT_EQ(notification_id(), notification_close_observer.Wait()); EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); // Confirms that a download is still in progress. std::vector downloads; content::DownloadManager* download_manager = GetDownloadManager(browser()); download_manager->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); EXPECT_EQ(content::DownloadItem::IN_PROGRESS, downloads[0]->GetState()); // Installs observers before requesting the completion. NotificationAddObserver download_notification_add_observer; content::DownloadTestObserverInterrupted download_terminal_observer( download_manager, 1u, /* wait_count */ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); // Requests to fail the download and wait for it. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kErrorDownloadUrl)); download_terminal_observer.WaitForFinished(); // Waits that new notification. download_notification_add_observer.Wait(); // Confirms that there is only one notification. message_center::NotificationList::Notifications visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(1u, visible_notifications.size()); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id())); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadRemoved) { CreateDownload(); NotificationRemoveObserver notification_close_observer; download_item()->Remove(); EXPECT_EQ(notification_id(), notification_close_observer.Wait()); // Confirms that the notification is removed. EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); // Confirms that the download item is removed. std::vector downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(0u, downloads.size()); } 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 downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); content::DownloadItem* download1 = downloads[0]; // Confirms that there is a notifications. message_center::NotificationList::Notifications visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(1u, visible_notifications.size()); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id1)); // Confirms that there is a popup notifications. message_center::NotificationList::PopupNotifications popup_notifications = GetMessageCenter()->GetPopupNotifications(); EXPECT_EQ(1u, popup_notifications.size()); EXPECT_TRUE(IsInNotifications(popup_notifications, notification_id1)); // Starts the 2nd download and waits for a notification. NotificationAddObserver download_start_notification_observer2(2); ui_test_utils::NavigateToURL(browser(), url2); // 2 notifications should be added. One is for new download (url2), and the // other one is for reshowing the existing download (url1) as a low-priority // notification. EXPECT_TRUE(download_start_notification_observer2.Wait()); // Confirms that there are 2 downloads. downloads.clear(); GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(2u, downloads.size()); content::DownloadItem* download2; if (download1 == downloads[0]) download2 = downloads[1]; else if (download1 == downloads[1]) download2 = downloads[0]; else NOTREACHED(); EXPECT_NE(download1, download2); // Confirms that there are 2 notifications. visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(2u, visible_notifications.size()); std::string notification_id2; for (auto notification : visible_notifications) { if (notification->id() == notification_id1) { continue; } else if (notification->type() == message_center::NOTIFICATION_TYPE_PROGRESS) { notification_id2 = (notification->id()); } } EXPECT_TRUE(!notification_id2.empty()); // Confirms that the both notifications are visible either as popup or in the // message center. EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id1)); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id2)); // Confirms that the new one is popup, and the old one is not. popup_notifications = GetMessageCenter()->GetPopupNotifications(); EXPECT_EQ(1u, popup_notifications.size()); EXPECT_FALSE(IsInNotifications(popup_notifications, notification_id1)); EXPECT_TRUE(IsInNotifications(popup_notifications, notification_id2)); // Confirms that the old one is low priority, and the new one is default. EXPECT_EQ(message_center::LOW_PRIORITY, GetNotification(notification_id1)->priority()); EXPECT_EQ(message_center::DEFAULT_PRIORITY, GetNotification(notification_id2)->priority()); // Confirms that the updates of both download are delivered to the // notifications. NotificationUpdateObserver notification_periodically_update_observer1(notification_id1); download1->UpdateObservers(); notification_periodically_update_observer1.Wait(); NotificationUpdateObserver notification_periodically_update_observer2(notification_id2); download2->UpdateObservers(); notification_periodically_update_observer2.Wait(); // Requests to complete the downloads. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); // Waits for the completion of downloads. NotificationUpdateObserver download_change_notification_observer; while (download1->GetState() != content::DownloadItem::COMPLETE || download2->GetState() != content::DownloadItem::COMPLETE) { download_change_notification_observer.Wait(); download_change_notification_observer.Reset(); } // Confirms that the both notifications are visible either as popup or in the // message center. visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(2u, visible_notifications.size()); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id1)); EXPECT_TRUE(IsInNotifications(visible_notifications, notification_id2)); // Confirms that the both are popup'd. popup_notifications = GetMessageCenter()->GetPopupNotifications(); EXPECT_EQ(2u, popup_notifications.size()); EXPECT_TRUE(IsInNotifications(popup_notifications, notification_id1)); EXPECT_TRUE(IsInNotifications(popup_notifications, notification_id2)); // Confirms that the both are default priority after downloads finish. EXPECT_EQ(message_center::DEFAULT_PRIORITY, GetNotification(notification_id1)->priority()); EXPECT_EQ(message_center::DEFAULT_PRIORITY, GetNotification(notification_id2)->priority()); // Confirms the types of download notifications are correct. EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id1)->type()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id2)->type()); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadMultipleFilesOneByOne) { CreateDownload(); content::DownloadItem* first_download_item = download_item(); content::DownloadItem* second_download_item = nullptr; std::string first_notification_id = notification_id(); std::string second_notification_id; // Requests to complete the first download. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); // Waits for completion of the first download. NotificationUpdateObserver download_change_notification_observer1(first_notification_id); while (first_download_item->GetState() != content::DownloadItem::COMPLETE) { download_change_notification_observer1.Wait(); download_change_notification_observer1.Reset(); } EXPECT_EQ(content::DownloadItem::COMPLETE, first_download_item->GetState()); // Checks the message center. EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size()); // Starts the second download. GURL url(net::URLRequestSlowDownloadJob::kKnownSizeUrl); NotificationAddObserver download_start_notification_observer; ui_test_utils::NavigateToURL(browser(), url); EXPECT_TRUE(download_start_notification_observer.Wait()); // Confirms that the second notification is created. second_notification_id = download_start_notification_observer.notification_id(); EXPECT_FALSE(second_notification_id.empty()); ASSERT_TRUE(GetNotification(second_notification_id)); // Confirms that there are two notifications, including the second // notification. message_center::NotificationList::Notifications visible_notifications = GetMessageCenter()->GetVisibleNotifications(); EXPECT_EQ(2u, visible_notifications.size()); EXPECT_TRUE(IsInNotifications(visible_notifications, first_notification_id)); EXPECT_TRUE(IsInNotifications(visible_notifications, second_notification_id)); // Confirms that the second download is also started. std::vector downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(2u, downloads.size()); EXPECT_TRUE(first_download_item == downloads[0] || first_download_item == downloads[1]); // Stores the second download. if (first_download_item == downloads[0]) second_download_item = downloads[1]; else second_download_item = downloads[0]; EXPECT_EQ(content::DownloadItem::IN_PROGRESS, second_download_item->GetState()); // Requests to complete the second download. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); // Waits for completion of the second download. NotificationUpdateObserver download_change_notification_observer2(second_notification_id); while (second_download_item->GetState() != content::DownloadItem::COMPLETE) { download_change_notification_observer2.Wait(); download_change_notification_observer2.Reset(); } // Opens the message center. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); // Checks the message center. EXPECT_EQ(2u, GetMessageCenter()->GetVisibleNotifications().size()); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, CancelDownload) { CreateDownload(); // Opens the message center. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); // Cancels the notification by clicking the "cancel' button. NotificationRemoveObserver notification_close_observer; notification()->ButtonClick(1); EXPECT_EQ(notification_id(), notification_close_observer.Wait()); EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); // Confirms that a download is also cancelled. std::vector downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); EXPECT_EQ(content::DownloadItem::CANCELLED, downloads[0]->GetState()); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadCancelledByUserExternally) { CreateDownload(); // Cancels the notification by clicking the "cancel' button. NotificationRemoveObserver notification_close_observer; download_item()->Cancel(true /* by_user */); EXPECT_EQ(notification_id(), notification_close_observer.Wait()); EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); // Confirms that a download is also cancelled. std::vector downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); EXPECT_EQ(content::DownloadItem::CANCELLED, downloads[0]->GetState()); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadCancelledExternally) { CreateDownload(); // Cancels the notification by clicking the "cancel' button. NotificationRemoveObserver notification_close_observer; download_item()->Cancel(false /* by_user */); EXPECT_EQ(notification_id(), notification_close_observer.Wait()); EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size()); // Confirms that a download is also cancelled. std::vector downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); EXPECT_EQ(content::DownloadItem::CANCELLED, downloads[0]->GetState()); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, IncognitoDownloadFile) { PrepareIncognitoBrowser(); // Starts an incognito download. CreateDownloadForBrowserAndURL( incognito_browser(), GURL(net::URLRequestSlowDownloadJob::kKnownSizeUrl)); EXPECT_EQ(l10n_util::GetStringFUTF16( IDS_DOWNLOAD_STATUS_IN_PROGRESS_TITLE, download_item()->GetFileNameToReportUser().LossyDisplayName()), GetNotification(notification_id())->title()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, GetNotification(notification_id())->type()); EXPECT_TRUE(download_item()->GetBrowserContext()->IsOffTheRecord()); // Requests to complete the download. ui_test_utils::NavigateToURL( incognito_browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); // Waits for download completion. NotificationUpdateObserver download_change_notification_observer(notification_id()); while (download_item()->GetState() != content::DownloadItem::COMPLETE) { download_change_notification_observer.Wait(); download_change_notification_observer.Reset(); } EXPECT_EQ(l10n_util::GetStringFUTF16( IDS_DOWNLOAD_STATUS_DOWNLOADED_TITLE, download_item()->GetFileNameToReportUser().LossyDisplayName()), GetNotification(notification_id())->title()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id())->type()); // Opens the message center. GetMessageCenter()->SetVisibility(message_center::VISIBILITY_MESSAGE_CENTER); // Try to open the downloaded item by clicking the notification. EXPECT_FALSE(GetIncognitoDownloadManagerDelegate()->opened()); GetMessageCenter()->ClickOnNotification(notification_id()); EXPECT_TRUE(GetIncognitoDownloadManagerDelegate()->opened()); EXPECT_FALSE(GetDownloadManagerDelegate()->opened()); EXPECT_FALSE(GetNotification(notification_id())); chrome::CloseWindow(incognito_browser()); } IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, SimultaneousIncognitoAndNormalDownloads) { PrepareIncognitoBrowser(); GURL url_incognito(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); GURL url_normal(net::URLRequestSlowDownloadJob::kKnownSizeUrl); // Starts the incognito download. NotificationAddObserver download_start_notification_observer1; ui_test_utils::NavigateToURL(incognito_browser(), url_incognito); 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 downloads; GetDownloadManager(browser())->GetAllDownloads(&downloads); EXPECT_EQ(0u, downloads.size()); downloads.clear(); GetDownloadManager(incognito_browser())->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); content::DownloadItem* download_incognito = downloads[0]; // Starts the normal download. NotificationAddObserver download_start_notification_observer2; ui_test_utils::NavigateToURL(browser(), url_normal); 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* download_normal = downloads[0]; EXPECT_EQ(1u, downloads.size()); EXPECT_NE(download_normal, download_incognito); downloads.clear(); GetDownloadManager(incognito_browser())->GetAllDownloads(&downloads); EXPECT_EQ(1u, downloads.size()); EXPECT_EQ(download_incognito, downloads[0]); // Confirms the types of download notifications are correct. EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, GetNotification(notification_id1)->type()); EXPECT_EQ(-1, GetNotification(notification_id1)->progress()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, GetNotification(notification_id2)->type()); EXPECT_LE(0, GetNotification(notification_id2)->progress()); EXPECT_TRUE(download_incognito->GetBrowserContext()->IsOffTheRecord()); EXPECT_FALSE(download_normal->GetBrowserContext()->IsOffTheRecord()); // Requests to complete the downloads. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); // Waits for the completion of downloads. NotificationUpdateObserver download_change_notification_observer; while (download_normal->GetState() != content::DownloadItem::COMPLETE || download_incognito->GetState() != content::DownloadItem::COMPLETE) { download_change_notification_observer.Wait(); download_change_notification_observer.Reset(); } // Confirms the types of download notifications are correct. EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id1)->type()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id2)->type()); chrome::CloseWindow(incognito_browser()); } ////////////////////////////////////////////////// // 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(AccountId::FromUserEmail(info.email), info.hash, false); user_manager->SaveUserDisplayName(AccountId::FromUserEmail(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 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_id_user1 = download_start_notification_observer1.notification_id(); EXPECT_FALSE(notification_id_user1.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_id_user2_1 = download_start_notification_observer2.notification_id(); EXPECT_FALSE(notification_id_user2_1.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_id_user2_2 = download_start_notification_observer3.notification_id(); EXPECT_FALSE(notification_id_user2_2.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. // Normal notification for user1. EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, GetNotification(notification_id_user1)->type()); EXPECT_EQ(-1, GetNotification(notification_id_user1)->progress()); // Normal notification for user2. EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, GetNotification(notification_id_user2_1)->type()); EXPECT_EQ(-1, GetNotification(notification_id_user2_1)->progress()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, GetNotification(notification_id_user2_2)->type()); EXPECT_EQ(-1, GetNotification(notification_id_user2_2)->progress()); // Requests to complete the downloads. NotificationUpdateObserver download_change_notification_observer; 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) { // Requests again, since sometimes the request may fail. ui_test_utils::NavigateToURL( browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); download_change_notification_observer.Wait(); } // Confirms the types of download notifications are correct. EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id_user1)->type()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id_user2_1)->type()); // Normal notifications for user2. EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id_user2_1)->type()); EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT, GetNotification(notification_id_user2_2)->type()); }