blob: bdaa5510734b417574c3a7a1c9f70118dd6de454 [file] [log] [blame]
// 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 <stddef.h>
#include <utility>
#include "base/command_line.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_core_service.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_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/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/download/public/common/download_item.h"
#include "components/prefs/pref_service.h"
#include "components/session_manager/core/session_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/download_manager.h"
#include "content/public/test/download_test_observer.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/url_request/url_request_slow_download_job.h"
#include "services/identity/public/cpp/identity_manager.h"
#include "services/identity/public/cpp/identity_test_utils.h"
#include "ui/base/l10n/l10n_util.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"},
};
class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate {
public:
explicit TestChromeDownloadManagerDelegate(Profile* profile)
: ChromeDownloadManagerDelegate(profile), opened_(false) {}
~TestChromeDownloadManagerDelegate() override = default;
// ChromeDownloadManagerDelegate override:
void OpenDownload(download::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 notification object by id. Warning: this will
// check the last display service that was created. If there's a normal and an
// incognito one, you may want to be explicit.
base::Optional<message_center::Notification> GetNotification(
const std::string& id) {
return NotificationDisplayServiceTester::Get()->GetNotification(id);
}
// Waits for a notification to be updated/added on |display_service|.
void WaitForDownloadNotificationForDisplayService(
NotificationDisplayServiceTester* display_service) {
base::RunLoop run_loop;
display_service->SetNotificationAddedClosure(base::BindRepeating(
[](base::RunLoop* run_loop) { run_loop->Quit(); }, &run_loop));
run_loop.Run();
display_service->SetNotificationAddedClosure(base::RepeatingClosure());
}
} // namespace
// Base class for tests
class DownloadNotificationTestBase : public InProcessBrowserTest {
public:
DownloadNotificationTestBase() = default;
~DownloadNotificationTestBase() override = default;
void SetUpOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->Start());
display_service_ = std::make_unique<NotificationDisplayServiceTester>(
browser()->profile());
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
}
protected:
content::DownloadManager* GetDownloadManager(Browser* browser) {
return content::BrowserContext::GetDownloadManager(browser->profile());
}
// Requests to complete the download and wait for it.
void CompleteTheDownload(size_t wait_count = 1u) {
content::DownloadTestObserverTerminal download_terminal_observer(
GetDownloadManager(browser()), wait_count,
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
ui_test_utils::NavigateToURL(
browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl));
download_terminal_observer.WaitForFinished();
}
std::unique_ptr<NotificationDisplayServiceTester> display_service_;
std::unique_ptr<NotificationDisplayServiceTester> incognito_display_service_;
private:
DISALLOW_COPY_AND_ASSIGN(DownloadNotificationTestBase);
};
//////////////////////////////////////////////////
// Test with a single profile
//////////////////////////////////////////////////
class DownloadNotificationTest : public DownloadNotificationTestBase {
public:
DownloadNotificationTest() = default;
~DownloadNotificationTest() override = default;
void SetUpOnMainThread() override {
Profile* profile = browser()->profile();
std::unique_ptr<TestChromeDownloadManagerDelegate> test_delegate;
test_delegate.reset(new TestChromeDownloadManagerDelegate(profile));
test_delegate->GetDownloadIdReceiverCallback().Run(
download::DownloadItem::kInvalidId + 1);
DownloadCoreServiceFactory::GetForBrowserContext(profile)
->SetDownloadManagerDelegateForTesting(std::move(test_delegate));
DownloadNotificationTestBase::SetUpOnMainThread();
}
TestChromeDownloadManagerDelegate* GetDownloadManagerDelegate() const {
return static_cast<TestChromeDownloadManagerDelegate*>(
DownloadCoreServiceFactory::GetForBrowserContext(browser()->profile())
->GetDownloadManagerDelegate());
}
void PrepareIncognitoBrowser() {
incognito_browser_ = CreateIncognitoBrowser();
Profile* incognito_profile = incognito_browser_->profile();
std::unique_ptr<TestChromeDownloadManagerDelegate> incognito_test_delegate;
incognito_test_delegate.reset(
new TestChromeDownloadManagerDelegate(incognito_profile));
DownloadCoreServiceFactory::GetForBrowserContext(incognito_profile)
->SetDownloadManagerDelegateForTesting(
std::move(incognito_test_delegate));
incognito_display_service_ =
std::make_unique<NotificationDisplayServiceTester>(
incognito_browser()->profile());
}
TestChromeDownloadManagerDelegate* GetIncognitoDownloadManagerDelegate()
const {
Profile* incognito_profile = incognito_browser()->profile();
return static_cast<TestChromeDownloadManagerDelegate*>(
DownloadCoreServiceFactory::GetForBrowserContext(incognito_profile)
->GetDownloadManagerDelegate());
}
void CreateDownload() {
return CreateDownloadForBrowserAndURL(
browser(), GURL(net::URLRequestSlowDownloadJob::kKnownSizeUrl));
}
// Returns the correct display service for the given Browser. If |browser| is
// null, returns the service for browser().
NotificationDisplayServiceTester* GetDisplayServiceForBrowser(
Browser* browser) {
return (browser && browser == DownloadNotificationTest::incognito_browser())
? incognito_display_service_.get()
: display_service_.get();
}
void WaitForDownloadNotification(Browser* browser = nullptr) {
WaitForDownloadNotificationForDisplayService(
GetDisplayServiceForBrowser(browser));
}
void CreateDownloadForBrowserAndURL(Browser* browser, GURL url) {
// Starts a download.
ui_test_utils::NavigateToURL(browser, url);
// Confirms that a notification is created.
WaitForDownloadNotification(browser);
auto download_notifications =
GetDisplayServiceForBrowser(browser)->GetDisplayedNotificationsForType(
NotificationHandler::Type::TRANSIENT);
ASSERT_EQ(1u, download_notifications.size());
notification_id_ = download_notifications[0].id();
EXPECT_FALSE(notification_id_.empty());
ASSERT_TRUE(notification());
// Confirms that a download is also started.
std::vector<download::DownloadItem*> downloads;
GetDownloadManager(browser)->GetAllDownloads(&downloads);
EXPECT_EQ(1u, downloads.size());
download_item_ = downloads[0];
ASSERT_TRUE(download_item_);
}
void CloseNotification() {
EXPECT_TRUE(notification());
display_service_->RemoveNotification(NotificationHandler::Type::TRANSIENT,
notification_id(), true /* by_user */);
EXPECT_FALSE(notification());
EXPECT_EQ(0u, GetDownloadNotifications().size());
}
void VerifyDownloadState(download::DownloadItem::DownloadState state) {
std::vector<download::DownloadItem*> downloads;
GetDownloadManager(browser())->GetAllDownloads(&downloads);
ASSERT_EQ(1u, downloads.size());
EXPECT_EQ(state, downloads[0]->GetState());
}
void VerifyUpdatePropagatesToNotification(download::DownloadItem* item) {
bool notification_updated = false;
display_service_->SetNotificationAddedClosure(base::BindRepeating(
[](bool* updated) { *updated = true; }, &notification_updated));
item->UpdateObservers();
EXPECT_TRUE(notification_updated);
display_service_->SetNotificationAddedClosure(base::RepeatingClosure());
}
void InterruptTheDownload() {
content::DownloadTestObserverInterrupted download_interrupted_observer(
GetDownloadManager(browser()), 1u, /* wait_count */
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
ui_test_utils::NavigateToURL(
browser(), GURL(net::URLRequestSlowDownloadJob::kErrorDownloadUrl));
download_interrupted_observer.WaitForFinished();
}
download::DownloadItem* download_item() const { return download_item_; }
std::string notification_id() const { return notification_id_; }
base::Optional<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();
}
std::vector<message_center::Notification> GetDownloadNotifications() {
return display_service_->GetDisplayedNotificationsForType(
NotificationHandler::Type::TRANSIENT);
}
private:
download::DownloadItem* download_item_ = nullptr;
Browser* incognito_browser_ = nullptr;
std::string notification_id_;
DISALLOW_COPY_AND_ASSIGN(DownloadNotificationTest);
};
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadFile) {
CreateDownload();
EXPECT_EQ(l10n_util::GetStringFUTF16(
IDS_DOWNLOAD_STATUS_IN_PROGRESS_TITLE,
download_item()->GetFileNameToReportUser().LossyDisplayName()),
notification()->title());
EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, notification()->type());
// Confirms that the download update is delivered to the notification.
EXPECT_TRUE(notification());
VerifyUpdatePropagatesToNotification(download_item());
CompleteTheDownload();
// Checks strings.
ASSERT_TRUE(notification());
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_COMPLETE_TITLE),
notification()->title());
EXPECT_EQ(download_item()->GetFileNameToReportUser().LossyDisplayName(),
notification()->message());
EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
notification()->type());
// Confirms that there is only one notification.
ASSERT_EQ(1u, GetDownloadNotifications().size());
// Try to open the downloaded item by clicking the notification.
EXPECT_FALSE(GetDownloadManagerDelegate()->opened());
display_service_->SimulateClick(NotificationHandler::Type::TRANSIENT,
notification_id(), base::nullopt,
base::nullopt);
EXPECT_TRUE(GetDownloadManagerDelegate()->opened());
EXPECT_FALSE(GetNotification(notification_id()));
}
// Flaky test: crbug/822470.
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest,
DISABLED_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(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
download_item()->GetDangerType());
EXPECT_TRUE(download_item()->IsDangerous());
// Clicks the "keep" button.
display_service_->SimulateClick(NotificationHandler::Type::TRANSIENT,
notification_id(), 1, // 2nd button: "Keep"
base::nullopt);
// The notification is closed and re-shown.
EXPECT_TRUE(notification());
// Checks the download status.
EXPECT_EQ(download::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(download::DownloadItem::COMPLETE, download_item()->GetState());
// Checks the downloaded file.
EXPECT_TRUE(base::PathExists(GetDownloadPath().Append(filename.BaseName())));
}
// Disabled due to timeouts; see https://crbug.com/810302.
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest,
DISABLED_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(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
download_item()->GetDangerType());
EXPECT_TRUE(download_item()->IsDangerous());
// Ensures the notification exists.
EXPECT_TRUE(notification());
// Clicks the "Discard" button.
display_service_->SimulateClick(NotificationHandler::Type::TRANSIENT,
notification_id(),
0, // 1st button: "Discard"
base::nullopt);
EXPECT_FALSE(notification());
// Wait for the download completion.
download_terminal_observer.WaitForFinished();
// Checks there is neither any download nor any notification.
EXPECT_FALSE(notification());
EXPECT_EQ(0u, GetDownloadNotifications().size());
std::vector<download::DownloadItem*> 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())));
}
// Disabled due to timeouts; see https://crbug.com/810302.
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DISABLED_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();
WaitForDownloadNotification();
EXPECT_FALSE(notification()->image().IsEmpty());
}
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest,
CloseNotificationAfterDownload) {
CreateDownload();
CompleteTheDownload();
CloseNotification();
VerifyDownloadState(download::DownloadItem::COMPLETE);
}
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest,
CloseNotificationWhileDownloading) {
CreateDownload();
CloseNotification();
VerifyDownloadState(download::DownloadItem::IN_PROGRESS);
CompleteTheDownload();
EXPECT_TRUE(notification());
}
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, InterruptDownload) {
CreateDownload();
InterruptTheDownload();
EXPECT_EQ(1u, GetDownloadNotifications().size());
ASSERT_TRUE(notification());
// Checks strings.
EXPECT_EQ(l10n_util::GetStringFUTF16(
IDS_DOWNLOAD_STATUS_DOWNLOAD_FAILED_TITLE,
download_item()->GetFileNameToReportUser().LossyDisplayName()),
notification()->title());
EXPECT_NE(notification()->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,
notification()->type());
}
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest,
InterruptDownloadAfterClosingNotification) {
CreateDownload();
CloseNotification();
// Confirms that a download is still in progress.
std::vector<download::DownloadItem*> downloads;
content::DownloadManager* download_manager = GetDownloadManager(browser());
download_manager->GetAllDownloads(&downloads);
EXPECT_EQ(1u, downloads.size());
EXPECT_EQ(download::DownloadItem::IN_PROGRESS, downloads[0]->GetState());
// Installs observers before requesting the completion.
content::DownloadTestObserverInterrupted download_terminal_observer(
download_manager, 1u, /* wait_count */
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
InterruptTheDownload();
// Confirms that there is only one notification.
EXPECT_EQ(1u, GetDownloadNotifications().size());
ASSERT_TRUE(notification());
}
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadRemoved) {
CreateDownload();
EXPECT_TRUE(notification());
download_item()->Remove();
EXPECT_FALSE(notification());
// Confirms that the download item is removed.
std::vector<download::DownloadItem*> 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.
ui_test_utils::NavigateToURL(browser(), url1);
WaitForDownloadNotification();
auto notifications = GetDownloadNotifications();
ASSERT_EQ(1u, notifications.size());
std::string notification_id1 = notifications[0].id();
EXPECT_FALSE(notification_id1.empty());
// Confirms that there is a download.
std::vector<download::DownloadItem*> downloads;
GetDownloadManager(browser())->GetAllDownloads(&downloads);
ASSERT_EQ(1u, downloads.size());
download::DownloadItem* download1 = downloads[0];
// Starts the 2nd download.
ui_test_utils::NavigateToURL(browser(), url2);
WaitForDownloadNotification();
// Confirms that there are 2 downloads.
downloads.clear();
GetDownloadManager(browser())->GetAllDownloads(&downloads);
ASSERT_EQ(2u, downloads.size());
download::DownloadItem* download2;
if (download1 == downloads[0])
download2 = downloads[1];
else if (download1 == downloads[1])
download2 = downloads[0];
else
NOTREACHED();
EXPECT_NE(download1, download2);
notifications = GetDownloadNotifications();
// Confirms that there are 2 notifications.
EXPECT_EQ(2u, notifications.size());
std::string notification_id2;
for (const auto& notification : notifications) {
if (notification.id() == notification_id1)
continue;
notification_id2 = notification.id();
}
EXPECT_FALSE(notification_id2.empty());
// 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.
VerifyUpdatePropagatesToNotification(download1);
VerifyUpdatePropagatesToNotification(download2);
// Confirms the correct type of notification while download is in progress.
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.
CompleteTheDownload(2);
// Confirms that the both notifications are visible.
notifications = GetDownloadNotifications();
EXPECT_EQ(2u, notifications.size());
ASSERT_TRUE(GetNotification(notification_id1));
ASSERT_TRUE(GetNotification(notification_id2));
// Confirms that both ask to be re-shown when finished.
EXPECT_TRUE(GetNotification(notification_id1)->renotify());
EXPECT_TRUE(GetNotification(notification_id2)->renotify());
// Confirms that both are default priority after finishing.
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();
download::DownloadItem* first_download_item = download_item();
std::string first_notification_id = notification_id();
CompleteTheDownload();
EXPECT_EQ(download::DownloadItem::COMPLETE, first_download_item->GetState());
// Checks the message center.
EXPECT_TRUE(notification());
// Starts the second download.
GURL url(net::URLRequestSlowDownloadJob::kKnownSizeUrl);
ui_test_utils::NavigateToURL(browser(), url);
WaitForDownloadNotification();
// Confirms that the second notification is created.
auto notifications = GetDownloadNotifications();
ASSERT_EQ(2u, notifications.size());
std::string second_notification_id =
notifications[(notifications[0].id() == notification_id() ? 1 : 0)].id();
EXPECT_FALSE(second_notification_id.empty());
ASSERT_TRUE(GetNotification(second_notification_id));
// Confirms that the second download is also started.
std::vector<download::DownloadItem*> downloads;
GetDownloadManager(browser())->GetAllDownloads(&downloads);
EXPECT_EQ(2u, downloads.size());
EXPECT_TRUE(first_download_item == downloads[0] ||
first_download_item == downloads[1]);
download::DownloadItem* second_download_item =
downloads[first_download_item == downloads[0] ? 1 : 0];
EXPECT_EQ(download::DownloadItem::IN_PROGRESS,
second_download_item->GetState());
// Requests to complete the second download.
CompleteTheDownload();
EXPECT_EQ(2u, GetDownloadNotifications().size());
}
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, CancelDownload) {
CreateDownload();
// Cancels the notification by clicking the "cancel" button.
display_service_->SimulateClick(NotificationHandler::Type::TRANSIENT,
notification_id(), 1, base::nullopt);
EXPECT_FALSE(notification());
EXPECT_EQ(0u, GetDownloadNotifications().size());
// Confirms that the download is cancelled.
std::vector<download::DownloadItem*> downloads;
GetDownloadManager(browser())->GetAllDownloads(&downloads);
ASSERT_EQ(1u, downloads.size());
EXPECT_EQ(download::DownloadItem::CANCELLED, downloads[0]->GetState());
}
IN_PROC_BROWSER_TEST_F(DownloadNotificationTest,
DownloadCancelledByUserExternally) {
CreateDownload();
// Cancels the notification through the DownloadItem.
download_item()->Cancel(true /* by_user */);
EXPECT_FALSE(notification());
EXPECT_EQ(0u, GetDownloadNotifications().size());
// Confirms that the download is cancelled.
std::vector<download::DownloadItem*> downloads;
GetDownloadManager(browser())->GetAllDownloads(&downloads);
EXPECT_EQ(1u, downloads.size());
EXPECT_EQ(download::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()),
notification()->title());
EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, notification()->type());
EXPECT_TRUE(content::DownloadItemUtils::GetBrowserContext(download_item())
->IsOffTheRecord());
// Requests to complete the download.
content::DownloadTestObserverTerminal download_terminal_observer(
GetDownloadManager(incognito_browser()), 1,
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
ui_test_utils::NavigateToURL(
incognito_browser(),
GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl));
download_terminal_observer.WaitForFinished();
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_COMPLETE_TITLE),
notification()->title());
EXPECT_EQ(download_item()->GetFileNameToReportUser().LossyDisplayName(),
notification()->message());
EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
notification()->type());
// Try to open the downloaded item by clicking the notification.
EXPECT_TRUE(incognito_display_service_->GetNotification(notification_id()));
EXPECT_FALSE(GetIncognitoDownloadManagerDelegate()->opened());
incognito_display_service_->SimulateClick(
NotificationHandler::Type::TRANSIENT, notification_id(), base::nullopt,
base::nullopt);
EXPECT_TRUE(GetIncognitoDownloadManagerDelegate()->opened());
EXPECT_FALSE(GetDownloadManagerDelegate()->opened());
EXPECT_FALSE(incognito_display_service_->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.
ui_test_utils::NavigateToURL(incognito_browser(), url_incognito);
WaitForDownloadNotification(incognito_browser());
auto incognito_notifications =
incognito_display_service_->GetDisplayedNotificationsForType(
NotificationHandler::Type::TRANSIENT);
ASSERT_EQ(1u, incognito_notifications.size());
std::string notification_id1 = incognito_notifications[0].id();
EXPECT_FALSE(notification_id1.empty());
// Confirms that there is a download.
std::vector<download::DownloadItem*> downloads;
GetDownloadManager(browser())->GetAllDownloads(&downloads);
EXPECT_EQ(0u, downloads.size());
downloads.clear();
GetDownloadManager(incognito_browser())->GetAllDownloads(&downloads);
EXPECT_EQ(1u, downloads.size());
download::DownloadItem* download_incognito = downloads[0];
// Starts the normal download.
ui_test_utils::NavigateToURL(browser(), url_normal);
WaitForDownloadNotification();
auto normal_notifications = GetDownloadNotifications();
ASSERT_EQ(1u, normal_notifications.size());
std::string notification_id2 = normal_notifications[0].id();
EXPECT_FALSE(notification_id2.empty());
// Confirms that there are 2 downloads.
downloads.clear();
GetDownloadManager(browser())->GetAllDownloads(&downloads);
download::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.
auto incognito_notification =
incognito_display_service_->GetNotification(notification_id1);
ASSERT_TRUE(incognito_notification);
EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS,
incognito_notification->type());
EXPECT_EQ(-1, incognito_notification->progress());
auto normal_notification =
display_service_->GetNotification(notification_id2);
ASSERT_TRUE(normal_notification);
EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS,
normal_notification->type());
EXPECT_LE(0, normal_notification->progress());
EXPECT_TRUE(content::DownloadItemUtils::GetBrowserContext(download_incognito)
->IsOffTheRecord());
EXPECT_FALSE(content::DownloadItemUtils::GetBrowserContext(download_normal)
->IsOffTheRecord());
// Request to complete the normal download.
CompleteTheDownload();
// Confirms the types of download notifications are correct.
incognito_notification =
incognito_display_service_->GetNotification(notification_id1);
EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
incognito_notification->type());
normal_notification = display_service_->GetNotification(notification_id2);
EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
normal_notification->type());
chrome::CloseWindow(incognito_browser());
}
//////////////////////////////////////////////////
// Test with multi profiles
//////////////////////////////////////////////////
class MultiProfileDownloadNotificationTest
: public DownloadNotificationTestBase {
public:
MultiProfileDownloadNotificationTest() = default;
~MultiProfileDownloadNotificationTest() override = default;
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);
// Don't require policy for our sessions - this is required because
// this test creates a secondary profile synchronously, so we need to
// let the policy code know not to expect cached policy.
command_line->AppendSwitchASCII(chromeos::switches::kProfileRequiresPolicy,
"false");
}
// 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) {
// The primary account was already set up in SetUpOnMainThread, so skip it
// here.
if (i == PRIMARY_ACCOUNT_INDEX)
continue;
AddUser(kTestAccounts[i], i >= SECONDARY_ACCOUNT_INDEX_START);
}
}
Profile* GetProfileByIndex(int index) {
return chromeos::ProfileHelper::GetProfileByUserIdHashForTest(
kTestAccounts[index].hash);
}
// Adds a new user for testing to the current session.
void AddUser(const TestAccountInfo& info, bool log_in) {
if (log_in) {
session_manager::SessionManager::Get()->CreateSession(
AccountId::FromUserEmailGaiaId(info.email, info.gaia_id), info.hash,
false);
}
user_manager::UserManager::Get()->SaveUserDisplayName(
AccountId::FromUserEmailGaiaId(info.email, info.gaia_id),
base::UTF8ToUTF16(info.display_name));
Profile* profile =
chromeos::ProfileHelper::GetProfileByUserIdHashForTest(info.hash);
identity::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile);
if (!identity_manager->HasPrimaryAccount())
identity::MakePrimaryAccountAvailable(identity_manager, info.email);
}
std::unique_ptr<NotificationDisplayServiceTester> display_service1_;
std::unique_ptr<NotificationDisplayServiceTester> display_service2_;
private:
DISALLOW_COPY_AND_ASSIGN(MultiProfileDownloadNotificationTest);
};
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);
display_service1_ =
std::make_unique<NotificationDisplayServiceTester>(profile1);
display_service2_ =
std::make_unique<NotificationDisplayServiceTester>(profile2);
// First user starts a download.
ui_test_utils::NavigateToURL(browser1, url);
WaitForDownloadNotificationForDisplayService(display_service1_.get());
// Confirms that the download is started.
std::vector<download::DownloadItem*> downloads;
GetDownloadManager(browser1)->GetAllDownloads(&downloads);
EXPECT_EQ(1u, downloads.size());
download::DownloadItem* download1 = downloads[0];
// Confirms that a download notification is generated.
auto notifications1 = display_service1_->GetDisplayedNotificationsForType(
NotificationHandler::Type::TRANSIENT);
ASSERT_EQ(1u, notifications1.size());
std::string notification_id_user1 = notifications1[0].id();
EXPECT_FALSE(notification_id_user1.empty());
// Second user starts a download.
ui_test_utils::NavigateToURL(browser2, url);
WaitForDownloadNotificationForDisplayService(display_service2_.get());
auto notifications2 = display_service2_->GetDisplayedNotificationsForType(
NotificationHandler::Type::TRANSIENT);
ASSERT_EQ(1u, notifications2.size());
std::string notification_id_user2 = notifications2[0].id();
EXPECT_FALSE(notification_id_user2.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.
ui_test_utils::NavigateToURL(browser2, url);
WaitForDownloadNotificationForDisplayService(display_service2_.get());
notifications2 = display_service2_->GetDisplayedNotificationsForType(
NotificationHandler::Type::TRANSIENT);
ASSERT_EQ(2u, notifications2.size());
// Confirms that the second user has 2 downloads.
downloads.clear();
GetDownloadManager(browser2)->GetAllDownloads(&downloads);
ASSERT_EQ(2u, downloads.size());
download::DownloadItem* download2 = downloads[0];
download::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,
display_service1_->GetNotification(notification_id_user1)->type());
EXPECT_EQ(
-1,
display_service1_->GetNotification(notification_id_user1)->progress());
// Normal notifications for user2.
notifications2 = display_service2_->GetDisplayedNotificationsForType(
NotificationHandler::Type::TRANSIENT);
EXPECT_EQ(2u, notifications2.size());
for (const auto& notification : notifications2) {
EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, notification.type());
EXPECT_EQ(-1, notification.progress());
}
// Requests to complete the downloads.
content::DownloadTestObserverTerminal download_terminal_observer(
GetDownloadManager(browser1), 1u /* wait_count */,
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
content::DownloadTestObserverTerminal download_terminal_observer2(
GetDownloadManager(browser2), 2u /* wait_count */,
content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
ui_test_utils::NavigateToURL(
browser1, GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl));
ui_test_utils::NavigateToURL(
browser2, GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl));
download_terminal_observer.WaitForFinished();
download_terminal_observer2.WaitForFinished();
// Confirms the types of download notifications are correct.
EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
display_service1_->GetNotification(notification_id_user1)->type());
notifications2 = display_service2_->GetDisplayedNotificationsForType(
NotificationHandler::Type::TRANSIENT);
EXPECT_EQ(2u, notifications2.size());
for (const auto& notification : notifications2) {
EXPECT_EQ(message_center::NOTIFICATION_TYPE_BASE_FORMAT,
notification.type());
}
}