| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/download/bubble/download_display_controller.h" |
| |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/raw_ref.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/download/bubble/download_bubble_display_info.h" |
| #include "chrome/browser/download/bubble/download_bubble_ui_controller.h" |
| #include "chrome/browser/download/bubble/download_bubble_utils.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_item_model.h" |
| #include "chrome/browser/download/download_prefs.h" |
| #include "chrome/browser/download/offline_item_model_manager_factory.h" |
| #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/download/download_display.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/test/base/test_browser_window.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "components/download/public/common/download_danger_type.h" |
| #include "components/download/public/common/mock_download_item.h" |
| #include "components/offline_items_collection/core/offline_item.h" |
| #include "content/public/browser/download_item_utils.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "content/public/test/mock_download_manager.h" |
| #include "content/public/test/test_utils.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| using ::offline_items_collection::OfflineItem; |
| using ::testing::_; |
| using ::testing::NiceMock; |
| using ::testing::Return; |
| using ::testing::ReturnRef; |
| using ::testing::ReturnRefOfCopy; |
| using ::testing::StrictMock; |
| using StrictMockDownloadItem = StrictMock<download::MockDownloadItem>; |
| using DownloadIconActive = DownloadDisplay::IconActive; |
| using DownloadIconState = DownloadDisplay::IconState; |
| using DownloadState = download::DownloadItem::DownloadState; |
| using DownloadUIModelPtr = DownloadUIModel::DownloadUIModelPtr; |
| using OfflineItemList = |
| offline_items_collection::OfflineContentProvider::OfflineItemList; |
| using OfflineItemState = offline_items_collection::OfflineItemState; |
| |
| class FakeDownloadDisplay : public DownloadDisplay { |
| public: |
| FakeDownloadDisplay() = default; |
| FakeDownloadDisplay(const FakeDownloadDisplay&) = delete; |
| FakeDownloadDisplay& operator=(const FakeDownloadDisplay&) = delete; |
| |
| void ResetState() { |
| shown_ = false; |
| detail_shown_ = false; |
| state_ = DownloadIconState::kComplete; |
| active_ = DownloadIconActive::kInactive; |
| announcement_count_ = 0; |
| } |
| |
| void Show() override { shown_ = true; } |
| |
| void Hide() override { |
| shown_ = false; |
| detail_shown_ = false; |
| } |
| |
| bool IsShowing() const override { return shown_; } |
| |
| void Enable() override { enabled_ = true; } |
| |
| void Disable() override { enabled_ = false; } |
| |
| void UpdateDownloadIcon(const IconUpdateInfo& updates) override { |
| if (updates.new_state) { |
| state_ = *updates.new_state; |
| } |
| if (updates.new_active) { |
| active_ = *updates.new_active; |
| } |
| if (updates.new_progress) { |
| progress_info_ = *updates.new_progress; |
| } |
| } |
| |
| void ShowDetails() override { detail_shown_ = true; } |
| void HideDetails() override { detail_shown_ = false; } |
| bool IsShowingDetails() const override { return detail_shown_; } |
| void AnnounceAccessibleAlertNow(const std::u16string& alert_text) override { |
| ++announcement_count_; |
| } |
| bool IsFullscreenWithParentViewHidden() const override { |
| return is_fullscreen_; |
| } |
| bool ShouldShowExclusiveAccessBubble() const override { |
| return IsFullscreenWithParentViewHidden() && |
| should_show_exclusive_access_bubble_; |
| } |
| |
| DownloadIconState GetIconState() const override { return state_; } |
| DownloadIconActive GetIconActive() const { return active_; } |
| ProgressInfo GetIconProgress() const { return progress_info_; } |
| void SetIsFullscreen(bool is_fullscreen) { is_fullscreen_ = is_fullscreen; } |
| void SetShouldShowExclusiveAccessBubble(bool show) { |
| should_show_exclusive_access_bubble_ = show; |
| } |
| int GetAnnouncementCount() const { return announcement_count_; } |
| void OpenSecuritySubpage( |
| const offline_items_collection::ContentId&) override {} |
| |
| private: |
| bool shown_ = false; |
| bool enabled_ = false; |
| DownloadIconState state_ = DownloadIconState::kComplete; |
| DownloadIconActive active_ = DownloadIconActive::kInactive; |
| ProgressInfo progress_info_; |
| bool detail_shown_ = false; |
| bool is_fullscreen_ = false; |
| bool should_show_exclusive_access_bubble_ = true; |
| int announcement_count_; |
| }; |
| |
| // TODO(chlily): Pull this and the very similar class in |
| // DownloadBubbleUIControllerTest out into a test utils file. |
| class MockDownloadBubbleUpdateService : public DownloadBubbleUpdateService { |
| public: |
| enum class ModelType { |
| kDownloadItem, |
| kOfflineItem, |
| }; |
| |
| MockDownloadBubbleUpdateService( |
| Profile* profile, |
| const std::vector<std::unique_ptr<StrictMockDownloadItem>>& |
| download_items, |
| const OfflineItemList& offline_items) |
| : DownloadBubbleUpdateService(profile), |
| profile_(profile), |
| download_items_(download_items), |
| offline_items_(offline_items) {} |
| MockDownloadBubbleUpdateService(const MockDownloadBubbleUpdateService&) = |
| delete; |
| MockDownloadBubbleUpdateService& operator=( |
| const MockDownloadBubbleUpdateService&) = delete; |
| |
| ~MockDownloadBubbleUpdateService() override = default; |
| |
| void UpdateInfoForModel(const DownloadUIModel& model, |
| DownloadBubbleDisplayInfo& info) { |
| ++info.all_models_size; |
| info.last_completed_time = |
| std::max(info.last_completed_time, model.GetEndTime()); |
| if (model.GetDangerType() == |
| download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING && |
| model.GetState() != download::DownloadItem::CANCELLED) { |
| info.has_deep_scanning = true; |
| } |
| if (!model.WasActionedOn()) { |
| info.has_unactioned = true; |
| } |
| if (IsModelInProgress(&model)) { |
| ++info.in_progress_count; |
| if (model.IsPaused()) { |
| ++info.paused_count; |
| } |
| } |
| } |
| |
| const DownloadBubbleDisplayInfo& GetDisplayInfo( |
| const webapps::AppId* web_app_id) override { |
| info_ = DownloadBubbleDisplayInfo{}; |
| int download_item_index = 0, offline_item_index = 0; |
| // Compose a list of models from the items stored in the test fixture. |
| for (ModelType type : model_types_) { |
| if (type == ModelType::kDownloadItem) { |
| auto model = DownloadItemModel::Wrap( |
| download_items_->at(download_item_index++).get()); |
| if (!model->ShouldShowInBubble()) { |
| continue; |
| } |
| UpdateInfoForModel(*model, info_); |
| } else { |
| auto model = OfflineItemModel::Wrap( |
| OfflineItemModelManagerFactory::GetForBrowserContext(profile_), |
| offline_items_->at(offline_item_index++)); |
| if (!model->ShouldShowInBubble()) { |
| continue; |
| } |
| UpdateInfoForModel(*model, info_); |
| } |
| } |
| return info_; |
| } |
| |
| std::vector<std::u16string> TakeAccessibleAlertsForAnnouncement( |
| const webapps::AppId* web_app_id) override { |
| std::vector<std::u16string> alerts; |
| alerts.swap(accessible_alerts_); |
| return alerts; |
| } |
| |
| void AddModel(ModelType type) { |
| model_types_.push_back(type); |
| AddAlert(); |
| } |
| |
| void AddAlert() { |
| // Add an arbitrary accessible alert. These tests do not care about the |
| // alert content. |
| accessible_alerts_.push_back(u"alert"); |
| } |
| |
| void RemoveLastDownload() { |
| for (auto reverse_it = model_types_.rbegin(); |
| reverse_it != model_types_.rend(); ++reverse_it) { |
| if (*reverse_it == ModelType::kDownloadItem) { |
| model_types_.erase(std::next(reverse_it).base()); |
| break; |
| } |
| } |
| } |
| |
| bool IsInitialized() const override { return true; } |
| |
| MOCK_METHOD(DownloadDisplay::ProgressInfo, |
| GetProgressInfo, |
| (const webapps::AppId*), |
| (const override)); |
| |
| private: |
| raw_ptr<Profile> profile_; |
| DownloadBubbleDisplayInfo info_; |
| std::vector<ModelType> model_types_; |
| const raw_ref<const std::vector<std::unique_ptr<StrictMockDownloadItem>>> |
| download_items_; |
| const raw_ref<const OfflineItemList> offline_items_; |
| std::vector<std::u16string> accessible_alerts_; |
| }; |
| |
| class MockDownloadCoreService : public DownloadCoreService { |
| public: |
| MOCK_METHOD(ChromeDownloadManagerDelegate*, GetDownloadManagerDelegate, ()); |
| MOCK_METHOD(DownloadUIController*, GetDownloadUIController, ()); |
| MOCK_METHOD(DownloadHistory*, GetDownloadHistory, ()); |
| MOCK_METHOD(extensions::ExtensionDownloadsEventRouter*, |
| GetExtensionEventRouter, |
| ()); |
| MOCK_METHOD(bool, HasCreatedDownloadManager, ()); |
| MOCK_METHOD(int, BlockingShutdownCount, (), (const)); |
| MOCK_METHOD(void, |
| CancelDownloads, |
| (DownloadCoreService::CancelDownloadsTrigger)); |
| MOCK_METHOD(void, |
| SetDownloadManagerDelegateForTesting, |
| (std::unique_ptr<ChromeDownloadManagerDelegate> delegate)); |
| MOCK_METHOD(bool, IsDownloadUiEnabled, ()); |
| MOCK_METHOD(bool, IsDownloadObservedByExtension, ()); |
| }; |
| |
| std::unique_ptr<KeyedService> BuildMockDownloadCoreService( |
| content::BrowserContext* browser_context) { |
| return std::make_unique<MockDownloadCoreService>(); |
| } |
| |
| class DownloadDisplayControllerTest : public testing::Test { |
| public: |
| DownloadDisplayControllerTest() |
| : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) { |
| base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kNoFirstRun); |
| } |
| DownloadDisplayControllerTest(const DownloadDisplayControllerTest&) = delete; |
| DownloadDisplayControllerTest& operator=( |
| const DownloadDisplayControllerTest&) = delete; |
| |
| void SetUp() override { |
| ASSERT_TRUE(testing_profile_manager_.SetUp()); |
| |
| profile_ = testing_profile_manager_.CreateTestingProfile("testing_profile"); |
| |
| DownloadCoreServiceFactory::GetInstance()->SetTestingFactory( |
| profile_, base::BindRepeating(&BuildMockDownloadCoreService)); |
| mock_download_core_service_ = static_cast<MockDownloadCoreService*>( |
| DownloadCoreServiceFactory::GetForBrowserContext(profile_)); |
| EXPECT_CALL(*mock_download_core_service(), IsDownloadUiEnabled()) |
| .WillRepeatedly(Return(true)); |
| delegate_ = std::make_unique<ChromeDownloadManagerDelegate>(profile_); |
| EXPECT_CALL(*mock_download_core_service(), GetDownloadManagerDelegate()) |
| .WillRepeatedly(Return(delegate_.get())); |
| |
| mock_update_service_ = |
| std::make_unique<StrictMock<MockDownloadBubbleUpdateService>>( |
| profile_, items_, offline_items_); |
| // Will be called when the DownloadDisplayController is constructed. |
| EXPECT_CALL(*mock_update_service_, GetProgressInfo(_)) |
| .WillRepeatedly(Return(DownloadDisplay::ProgressInfo())); |
| display_ = std::make_unique<FakeDownloadDisplay>(); |
| auto window = std::make_unique<TestBrowserWindow>(); |
| Browser::CreateParams params(profile_, true); |
| params.type = Browser::TYPE_NORMAL; |
| params.window = window.release(); |
| browser_ = Browser::DeprecatedCreateOwnedForTesting(params); |
| bubble_controller_ = std::make_unique<DownloadBubbleUIController>( |
| browser_.get(), mock_update_service_.get()); |
| controller_ = std::make_unique<DownloadDisplayController>( |
| display_.get(), browser_.get(), bubble_controller_.get()); |
| } |
| |
| void TearDown() override { |
| // The controller needs to be reset before download manager, because the |
| // download_notifier_ will unregister itself from the manager. |
| controller_.reset(); |
| mock_update_service_.reset(); |
| } |
| |
| Browser* browser() { return browser_.get(); } |
| |
| protected: |
| download::MockDownloadItem& item(size_t index) { return *items_[index]; } |
| FakeDownloadDisplay& display() { return *display_; } |
| DownloadDisplayController& controller() { return *controller_; } |
| DownloadBubbleUIController& bubble_controller() { |
| return *bubble_controller_; |
| } |
| Profile* profile() { return profile_; } |
| MockDownloadCoreService* mock_download_core_service() { |
| return mock_download_core_service_; |
| } |
| |
| void InitDownloadItem(const base::FilePath::CharType* path, |
| DownloadState state, |
| base::FilePath target_file_path = |
| base::FilePath(FILE_PATH_LITERAL("foo"))) { |
| size_t index = items_.size(); |
| items_.push_back(std::make_unique<StrictMockDownloadItem>()); |
| EXPECT_CALL(item(index), GetId()) |
| .WillRepeatedly(Return(static_cast<uint32_t>(items_.size() + 1))); |
| EXPECT_CALL(item(index), GetState()).WillRepeatedly(Return(state)); |
| EXPECT_CALL(item(index), IsPaused()).WillRepeatedly(Return(false)); |
| EXPECT_CALL(item(index), GetStartTime()) |
| .WillRepeatedly(Return(base::Time::Now())); |
| EXPECT_CALL(item(index), GetEndTime()).WillRepeatedly(Return(base::Time())); |
| EXPECT_CALL(item(index), GetDangerType()) |
| .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)); |
| EXPECT_CALL(item(index), IsDangerous()).WillRepeatedly(Return(false)); |
| EXPECT_CALL(item(index), IsInsecure()).WillRepeatedly(Return(false)); |
| int received_bytes = |
| state == download::DownloadItem::IN_PROGRESS ? 50 : 100; |
| EXPECT_CALL(item(index), GetReceivedBytes()) |
| .WillRepeatedly(Return(received_bytes)); |
| EXPECT_CALL(item(index), GetTotalBytes()).WillRepeatedly(Return(100)); |
| EXPECT_CALL(item(index), AllDataSaved()) |
| .WillRepeatedly(Return(state != download::DownloadItem::IN_PROGRESS)); |
| EXPECT_CALL(item(index), IsDone()).WillRepeatedly(Return(false)); |
| EXPECT_CALL(item(index), IsTransient()).WillRepeatedly(Return(false)); |
| EXPECT_CALL(item(index), GetTargetFilePath()) |
| .WillRepeatedly(ReturnRefOfCopy(target_file_path)); |
| EXPECT_CALL(item(index), GetLastReason()) |
| .WillRepeatedly(Return(download::DOWNLOAD_INTERRUPT_REASON_NONE)); |
| EXPECT_CALL(item(index), GetInsecureDownloadStatus()) |
| .WillRepeatedly( |
| Return(download::DownloadItem::InsecureDownloadStatus::SAFE)); |
| if (state == DownloadState::IN_PROGRESS) { |
| in_progress_count_++; |
| } |
| // Set actioned_on to false (it defaults to true) because the controller |
| // will generally set this to false in OnNewItem(). |
| DownloadItemModel(&item(index)).SetActionedOn(false); |
| |
| std::vector<download::DownloadItem*> items; |
| for (size_t i = 0; i < items_.size(); ++i) { |
| items.push_back(&item(i)); |
| } |
| content::DownloadItemUtils::AttachInfoForTesting(&(item(index)), profile_, |
| nullptr); |
| mock_update_service_->AddModel( |
| MockDownloadBubbleUpdateService::ModelType::kDownloadItem); |
| DownloadDisplay::ProgressInfo progress_info; |
| progress_info.download_count = in_progress_count_; |
| progress_info.progress_percentage = in_progress_count_ > 0 ? 50 : 0; |
| EXPECT_CALL(*mock_update_service_, GetProgressInfo(_)) |
| .WillRepeatedly(Return(progress_info)); |
| controller().OnNewItem(/*show_animation=*/false); |
| } |
| |
| void InitOfflineItem(OfflineItemState state) { |
| OfflineItem item; |
| item.state = state; |
| offline_items_.push_back(item); |
| if (state == OfflineItemState::IN_PROGRESS) { |
| ++in_progress_count_; |
| } |
| DownloadDisplay::ProgressInfo progress_info; |
| progress_info.download_count = in_progress_count_; |
| progress_info.progress_percentage = in_progress_count_ > 0 ? 50 : 0; |
| progress_info.progress_certain = false; |
| EXPECT_CALL(*mock_update_service_, GetProgressInfo(_)) |
| .WillRepeatedly(Return(progress_info)); |
| mock_update_service_->AddModel( |
| MockDownloadBubbleUpdateService::ModelType::kOfflineItem); |
| controller().OnNewItem(/*show_animation=*/false); |
| } |
| |
| void UpdateOfflineItem(int item_index, OfflineItemState state) { |
| offline_items_[item_index].state = state; |
| mock_update_service_->AddAlert(); |
| controller().OnUpdatedItem(state == OfflineItemState::COMPLETE, |
| /*may_show_details=*/true); |
| } |
| |
| void UpdateDownloadItem(int item_index, |
| DownloadState state, |
| download::DownloadDangerType danger_type = |
| download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| bool may_show_details = true, |
| bool is_insecure = false) { |
| DCHECK_GT(items_.size(), static_cast<size_t>(item_index)); |
| |
| // In-progress but dangerous downloads are considered complete. |
| // TODO(crbug.com/40264271): Don't duplicate this logic. |
| bool in_progress_dangerous = |
| (state == DownloadState::IN_PROGRESS && |
| danger_type != download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); |
| EXPECT_CALL(item(item_index), GetState()).WillRepeatedly(Return(state)); |
| EXPECT_CALL(item(item_index), GetDangerType()) |
| .WillRepeatedly(Return(danger_type)); |
| EXPECT_CALL(item(item_index), IsInsecure()) |
| .WillRepeatedly(Return(is_insecure)); |
| if (state == DownloadState::COMPLETE) { |
| EXPECT_CALL(item(item_index), IsDone()).WillRepeatedly(Return(true)); |
| EXPECT_CALL(item(item_index), GetEndTime()) |
| .WillRepeatedly(Return(base::Time::Now())); |
| } else { |
| EXPECT_CALL(item(item_index), IsDone()).WillRepeatedly(Return(false)); |
| } |
| if (state == DownloadState::COMPLETE || in_progress_dangerous) { |
| in_progress_count_--; |
| } |
| mock_update_service_->AddAlert(); |
| controller().OnUpdatedItem( |
| state == DownloadState::COMPLETE || in_progress_dangerous, |
| may_show_details); |
| } |
| |
| void OnRemovedItem(const std::string& id) { |
| controller().OnRemovedItem(ContentId{"LEGACY_DOWNLOAD", id}); |
| } |
| |
| void RemoveLastDownload() { |
| items_.pop_back(); |
| std::vector<download::DownloadItem*> items; |
| for (size_t i = 0; i < items_.size(); ++i) { |
| items.push_back(&item(i)); |
| } |
| mock_update_service_->RemoveLastDownload(); |
| } |
| |
| bool VerifyDisplayState(bool shown, |
| bool detail_shown, |
| DownloadIconState icon_state, |
| bool is_active) { |
| bool success = true; |
| if (shown != display().IsShowing()) { |
| success = false; |
| ADD_FAILURE() << "Display should have shown state " << shown |
| << ", but found " << display().IsShowing(); |
| } |
| if (detail_shown != display().IsShowingDetails()) { |
| success = false; |
| ADD_FAILURE() << "Display should have detailed shown state " |
| << detail_shown << ", but found " |
| << display().IsShowingDetails(); |
| } |
| if (icon_state != display().GetIconState()) { |
| success = false; |
| ADD_FAILURE() << "Display should have detailed icon state " |
| << static_cast<int>(icon_state) << ", but found " |
| << static_cast<int>(display().GetIconState()); |
| } |
| if (is_active != |
| (display().GetIconActive() == DownloadIconActive::kActive)) { |
| success = false; |
| ADD_FAILURE() << "Display should have is_active set to " << is_active |
| << ", but found " |
| << (display().GetIconActive() == |
| DownloadIconActive::kActive); |
| } |
| return success; |
| } |
| |
| // Simulates an update to make the download display update. |
| void TriggerIconUpdate() { |
| controller().OnUpdatedItem(/*is_done=*/true, /*may_show_details=*/true); |
| } |
| |
| content::BrowserTaskEnvironment task_environment_{ |
| base::test::TaskEnvironment::TimeSource::MOCK_TIME}; |
| |
| int in_progress_count_ = 0; |
| |
| std::unique_ptr<DownloadDisplayController> controller_; |
| std::unique_ptr<FakeDownloadDisplay> display_; |
| std::vector<std::unique_ptr<StrictMockDownloadItem>> items_; |
| std::vector<OfflineItem> offline_items_; |
| std::unique_ptr<StrictMock<MockDownloadBubbleUpdateService>> |
| mock_update_service_; |
| std::unique_ptr<DownloadBubbleUIController> bubble_controller_; |
| TestingProfileManager testing_profile_manager_; |
| raw_ptr<Profile> profile_; |
| std::unique_ptr<Browser> browser_; |
| raw_ptr<MockDownloadCoreService> mock_download_core_service_; |
| std::unique_ptr<ChromeDownloadManagerDelegate> delegate_; |
| }; |
| |
| TEST_F(DownloadDisplayControllerTest, GetProgressItemsInProgress) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar2.pdf"), |
| download::DownloadItem::COMPLETE); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar4.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| TriggerIconUpdate(); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 3); |
| EXPECT_EQ(display().GetIconProgress().download_count, 2); |
| EXPECT_EQ(display().GetIconProgress().progress_percentage, 50); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, OfflineItemsUncertainProgress) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar2.pdf"), |
| download::DownloadItem::COMPLETE); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar4.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| // This offline item has uncertain progress |
| InitOfflineItem(OfflineItemState::IN_PROGRESS); |
| TriggerIconUpdate(); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 4); |
| EXPECT_EQ(display().GetIconProgress().download_count, 3); |
| EXPECT_EQ(display().GetIconProgress().progress_percentage, 50); |
| EXPECT_FALSE(display().GetIconProgress().progress_certain); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, GetProgressItemsAllComplete) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::COMPLETE); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar2.pdf"), |
| download::DownloadItem::COMPLETE); |
| TriggerIconUpdate(); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| EXPECT_EQ(display().GetIconProgress().download_count, 0); |
| EXPECT_EQ(display().GetIconProgress().progress_percentage, 0); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, UpdateToolbarButtonState) { |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| // No details are shown on download initiation. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| // No details are shown on download initiation. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| // Pause download 0. |
| EXPECT_CALL(item(0), IsPaused()).WillRepeatedly(Return(true)); |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| // Pause download 1. |
| EXPECT_CALL(item(1), IsPaused()).WillRepeatedly(Return(true)); |
| UpdateDownloadItem(/*item_index=*/1, DownloadState::IN_PROGRESS); |
| // The download display is not active anymore, because all in progress |
| // downloads are paused. Details are not shown because the updated download |
| // is not done. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/false)); |
| // Unpause download 0. |
| EXPECT_CALL(item(0), IsPaused()).WillRepeatedly(Return(false)); |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| // Complete download 0. |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE); |
| // Details are shown because the only in-progress download is still paused. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/false)); |
| |
| // Complete download 1. |
| UpdateDownloadItem(/*item_index=*/1, DownloadState::COMPLETE); |
| // Now details are shown because all downloads are complete. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| task_environment_.FastForwardBy(base::Minutes(1)); |
| // The display is still showing but the state has changed to inactive. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| task_environment_.FastForwardBy(base::Minutes(58)); |
| // The display is still showing because the last download is less than 1 |
| // hour ago. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| task_environment_.FastForwardBy(base::Minutes(2)); |
| // The display should stop showing once the last download is more than 1 |
| // hour ago. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 7); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| UpdateToolbarButtonState_MultipleDownloads) { |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar2.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE); |
| // The download icon state is still kProgress because not all downloads are |
| // completed. details_shown is still false, because the details are only |
| // popped up when all in-progress downloads are complete. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/1, DownloadState::COMPLETE); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| // Reset details_shown while the downloads are in progress. This can happen if |
| // the user clicks somewhere else to dismiss the download bubble. |
| display().HideDetails(); |
| |
| InitOfflineItem(OfflineItemState::IN_PROGRESS); |
| // Do not show details because the offline item is not complete. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateOfflineItem(/*item_index=*/0, OfflineItemState::COMPLETE); |
| // Details are shown because all items are complete. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar3.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| UpdateDownloadItem(/*item_index=*/2, DownloadState::COMPLETE, |
| download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); |
| // Pop up the partial view because all downloads are complete. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 8); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| UpdateToolbarButtonState_OnCompleteItemCreated) { |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::COMPLETE); |
| // Don't show the button if the new download is already completed. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 1); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, UpdateToolbarButtonState_DeepScanning) { |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::IN_PROGRESS, |
| download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING); |
| // Details are shown because the pending deep scan download is considered |
| // complete. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| // Reset details_shown while the downloads are in progress. This can happen if |
| // the user clicks somewhere else to dismiss the download bubble. |
| display().HideDetails(); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::IN_PROGRESS, |
| download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING); |
| // Details are not shown because the scan is ongoing. |
| EXPECT_TRUE( |
| VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kDeepScanning, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE); |
| // Details are shown because all downloads are now complete. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 4); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, UpdateToolbarButtonState_EmptyFilePath) { |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS, |
| /*target_file_path=*/base::FilePath(FILE_PATH_LITERAL(""))); |
| // Empty file path should not be reflected in the UI. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_CALL(item(0), GetTargetFilePath()) |
| .WillRepeatedly( |
| ReturnRefOfCopy(base::FilePath(FILE_PATH_LITERAL("bar.pdf")))); |
| // Add an alert manually because updating the EXPECT_CALL doesn't by itself |
| // add an alert, even though in production such an update would. |
| mock_update_service_->AddAlert(); |
| controller().OnNewItem(/*show_animation=*/false); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| UpdateToolbarButtonState_DangerousDownload) { |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| EXPECT_CALL(item(0), IsDangerous()).WillRepeatedly(Return(true)); |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::IN_PROGRESS, |
| download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST); |
| // Dangerous downloads should be considered completed and |
| // should display details if there are no other in-progress downloads. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::IN_PROGRESS, |
| download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 3); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| UpdateToolbarButtonState_InsecureDownload) { |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::IN_PROGRESS, |
| download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST, |
| /*may_show_details=*/true, /*is_insecure=*/true); |
| // Insecure downloads should be considered completed and |
| // should display details if there are no other in-progress downloads. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, UpdateToolbarButtonState_OnRemovedItem) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar1.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| std::vector<std::string> ids = {"Download 1", "Download 2"}; |
| EXPECT_CALL(item(0), GetGuid()).WillRepeatedly(ReturnRef(ids[0])); |
| EXPECT_CALL(item(1), GetGuid()).WillRepeatedly(ReturnRef(ids[1])); |
| |
| // The download display is still shown, because there are multiple downloads |
| // in the list. Details are not shown because there is still a download in |
| // progress. |
| RemoveLastDownload(); |
| OnRemovedItem(ids[1]); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| // Display is hidden because the last download was deleted. |
| RemoveLastDownload(); |
| OnRemovedItem(ids[0]); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| UpdateToolbarButtonState_DownloadWasActionedOn) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE); |
| // Details are shown because the last in-progress download has completed. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| DownloadItemModel(&item(0)).SetActionedOn(true); |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 3); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, UpdateToolbarButtonState_OnResume) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| EXPECT_CALL(item(0), IsPaused()).WillRepeatedly(Return(true)); |
| // Add an alert manually because updating the EXPECT_CALL doesn't by itself |
| // add an alert, even though in production such an update would. |
| mock_update_service_->AddAlert(); |
| controller().OnResume(); |
| // is_active state should be updated after OnResume is called. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| UpdateToolbarButtonState_DontShowDetailsIfNotAllowed) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE, |
| download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
| /*may_show_details=*/false); |
| // Details are not shown because may_show_details is false. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, InitialState_InProgressDownload) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 1); |
| |
| // Simulate a new window opened. |
| display().ResetState(); |
| DownloadDisplayController controller(&display(), browser(), |
| &bubble_controller()); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 0); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, InitialState_NoLastDownload) { |
| DownloadDisplayController controller(&display(), browser(), |
| &bubble_controller()); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/false, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 0); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, OnButtonPressed_IconStateComplete) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| controller().HandleButtonPressed(); |
| |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, OnButtonPressed_IconStateInProgress) { |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| controller().OnButtonPressed(); |
| |
| // Keep is_active to true because the download is still in progress. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 1); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| Fullscreen_DoesNotShowDetailsForInProgressOnExitFullscreen) { |
| display().SetIsFullscreen(true); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| // Do not show bubble for in-progress download in full screen mode. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| display().SetIsFullscreen(false); |
| controller().OnFullscreenStateChanged(); |
| // Do not show bubble for in-progress download when exiting full screen mode. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| // Nothing is announced for a fullscreen transition. There is only 1 |
| // announcement from InitDownloadItem. |
| EXPECT_EQ(display().GetAnnouncementCount(), 1); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| Fullscreen_ShowsIconAndDetailsForCompletedOnExitFullscreen) { |
| display().SetIsFullscreen(true); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE, |
| download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); |
| // While the bubble does not pop up, and the toolbar not shown, the icon |
| // state is still updated. So |is_active| should be true for one minute |
| // after completed download. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| task_environment_.FastForwardBy(base::Minutes(1)); |
| // The display is still showing but the state has changed to inactive. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| display().SetIsFullscreen(false); |
| controller().OnFullscreenStateChanged(); |
| // On exiting full screen, show download icon as active for 1 minute and show |
| // details, as they were missed while in fullscreen. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| display().HideDetails(); |
| |
| task_environment_.FastForwardBy(base::Minutes(1)); |
| // The display is still showing but the state has changed to inactive. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| // Test the path where the exclusive access bubble should not be shown (e.g. in |
| // kiosk mode or in immersive fullscreen). |
| TEST_F(DownloadDisplayControllerTest, |
| Fullscreen_ShouldNotShowExclusiveAccessBubble) { |
| display().SetIsFullscreen(true); |
| display().SetShouldShowExclusiveAccessBubble(false); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| |
| UpdateDownloadItem(/*item_index=*/0, DownloadState::COMPLETE, |
| download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); |
| // While the bubble does not pop up, and the toolbar not shown, the icon |
| // state is still updated. So |is_active| should be true for one minute |
| // after completed download. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| task_environment_.FastForwardBy(base::Minutes(1)); |
| // The display is still showing but the state has changed to inactive. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| display().SetIsFullscreen(false); |
| controller().OnFullscreenStateChanged(); |
| // On exiting full screen, the details were not shown. |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/false)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| TEST_F(DownloadDisplayControllerTest, |
| ShowsDetailsWhenExtensionObservingDownloads) { |
| EXPECT_CALL(*mock_download_core_service(), IsDownloadObservedByExtension()) |
| .WillRepeatedly(Return(true)); |
| InitDownloadItem(FILE_PATH_LITERAL("/foo/bar.pdf"), |
| download::DownloadItem::IN_PROGRESS); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/false, |
| /*icon_state=*/DownloadIconState::kProgress, |
| /*is_active=*/true)); |
| UpdateDownloadItem(0, download::DownloadItem::COMPLETE); |
| EXPECT_TRUE(VerifyDisplayState(/*shown=*/true, /*detail_shown=*/true, |
| /*icon_state=*/DownloadIconState::kComplete, |
| /*is_active=*/true)); |
| |
| EXPECT_EQ(display().GetAnnouncementCount(), 2); |
| } |
| |
| } // namespace |