From 2889a37a758bb1d50d41799ebe5e40726b5a7727 Mon Sep 17 00:00:00 2001 From: paulzhchen Date: Fri, 30 Jul 2021 02:04:17 +0000 Subject: [PATCH] [CrOS PhoneHub] Hook up recent apps UI to real data. Connect the recent app view to recent apps interaction handler to hook up data. and ash_unittests. Test: Pass test cases: chromeos_components_unittests, Bug: b/190466630, b/190466008 Change-Id: I82a42bf5d69bc7df79083d6c2e1ef824c9d359b7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3030882 Commit-Queue: Paulz Chen Auto-Submit: Paulz Chen Reviewed-by: Ryan Hansberry Reviewed-by: Daniel Nishi Cr-Commit-Position: refs/heads/master@{#906970} --- ash/system/phonehub/phone_connected_view.cc | 9 +- .../phonehub/phone_hub_recent_app_button.cc | 16 +-- .../phonehub/phone_hub_recent_app_button.h | 11 +- .../phonehub/phone_hub_recent_apps_view.cc | 29 +++-- .../phonehub/phone_hub_recent_apps_view.h | 12 +- .../phone_hub_recent_apps_view_unittest.cc | 71 +++++++++-- .../fake_recent_apps_interaction_handler.cc | 24 +++- .../fake_recent_apps_interaction_handler.h | 15 ++- .../phonehub/recent_app_click_observer.h | 3 +- .../recent_apps_interaction_handler.cc | 43 ++++++- .../recent_apps_interaction_handler.h | 15 ++- ...ecent_apps_interaction_handler_unittest.cc | 118 +++++++++++++++--- 12 files changed, 301 insertions(+), 65 deletions(-) diff --git a/ash/system/phonehub/phone_connected_view.cc b/ash/system/phonehub/phone_connected_view.cc index 1a4c95240307b..3128be7973f2e 100644 --- a/ash/system/phonehub/phone_connected_view.cc +++ b/ash/system/phonehub/phone_connected_view.cc @@ -55,9 +55,12 @@ PhoneConnectedView::PhoneConnectedView( phone_model, phone_hub_manager->GetUserActionRecorder()))); } - if (features::IsEcheSWAEnabled() && features::IsPhoneHubRecentAppsEnabled()) { - setup_layered_view( - AddChildView(std::make_unique())); + auto* recent_apps_handler = + phone_hub_manager->GetRecentAppsInteractionHandler(); + if (features::IsEcheSWAEnabled() && features::IsPhoneHubRecentAppsEnabled() && + recent_apps_handler) { + setup_layered_view(AddChildView( + std::make_unique(recent_apps_handler))); } } diff --git a/ash/system/phonehub/phone_hub_recent_app_button.cc b/ash/system/phonehub/phone_hub_recent_app_button.cc index 487215263496f..2a880a8254d50 100644 --- a/ash/system/phonehub/phone_hub_recent_app_button.cc +++ b/ash/system/phonehub/phone_hub_recent_app_button.cc @@ -6,6 +6,7 @@ #include "ash/style/ash_color_provider.h" #include "ash/system/tray/tray_popup_utils.h" +#include "ui/gfx/image/image_skia_operations.h" #include "ui/views/controls/focus_ring.h" #include "ui/views/controls/highlight_path_generator.h" #include "ui/views/controls/image_view.h" @@ -19,10 +20,13 @@ constexpr int kRecentAppButtonSize = 32; } // namespace -PhoneHubRecentAppButton::PhoneHubRecentAppButton() - : views::ImageButton( - base::BindRepeating(&PhoneHubRecentAppButton::ButtonPressed, - base::Unretained(this))) { +PhoneHubRecentAppButton::PhoneHubRecentAppButton(const gfx::Image& icon, + PressedCallback callback) + : views::ImageButton(callback) { + SetImage(views::Button::STATE_NORMAL, + gfx::ImageSkiaOperations::CreateResizedImage( + icon.AsImageSkia(), skia::ImageOperations::RESIZE_BEST, + gfx::Size(kRecentAppButtonSize, kRecentAppButtonSize))); SetImageHorizontalAlignment(ALIGN_CENTER); SetImageVerticalAlignment(ALIGN_MIDDLE); TrayPopupUtils::ConfigureTrayPopupButton(this); @@ -57,8 +61,4 @@ const char* PhoneHubRecentAppButton::GetClassName() const { return "PhoneHubRecentAppButton"; } -void PhoneHubRecentAppButton::ButtonPressed() { - // TODO(paulzchen): Launch the recent apps with package name. -} - } // namespace ash diff --git a/ash/system/phonehub/phone_hub_recent_app_button.h b/ash/system/phonehub/phone_hub_recent_app_button.h index 9d767ebfa0d19..24d9564a96f97 100644 --- a/ash/system/phonehub/phone_hub_recent_app_button.h +++ b/ash/system/phonehub/phone_hub_recent_app_button.h @@ -6,15 +6,19 @@ #define ASH_SYSTEM_PHONEHUB_PHONE_HUB_RECENT_APP_BUTTON_H_ #include "ash/ash_export.h" +#include "chromeos/components/phonehub/recent_apps_interaction_handler.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/image/image.h" #include "ui/views/controls/button/image_button.h" namespace ash { -// A recent app button containing an |AppMetadata|. +// A recent app button containing a application |icon|. The |callback| provided +// to build PhoneHubRecentAppButton implicitly contains the package name of the +// same application. class ASH_EXPORT PhoneHubRecentAppButton : public views::ImageButton { public: - PhoneHubRecentAppButton(); + PhoneHubRecentAppButton(const gfx::Image& icon, PressedCallback callback); ~PhoneHubRecentAppButton() override; PhoneHubRecentAppButton(PhoneHubRecentAppButton&) = delete; PhoneHubRecentAppButton operator=(PhoneHubRecentAppButton&) = delete; @@ -26,9 +30,6 @@ class ASH_EXPORT PhoneHubRecentAppButton : public views::ImageButton { void PaintButtonContents(gfx::Canvas* canvas) override; const char* GetClassName() const override; void OnThemeChanged() override; - - private: - void ButtonPressed(); }; } // namespace ash diff --git a/ash/system/phonehub/phone_hub_recent_apps_view.cc b/ash/system/phonehub/phone_hub_recent_apps_view.cc index 0f1e8095f8d26..ef4ad68959cc0 100644 --- a/ash/system/phonehub/phone_hub_recent_apps_view.cc +++ b/ash/system/phonehub/phone_hub_recent_apps_view.cc @@ -14,6 +14,7 @@ #include "ash/system/phonehub/ui_constants.h" #include "ash/system/tray/tray_constants.h" #include "base/cxx17_backports.h" +#include "chromeos/components/phonehub/notification.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/geometry/insets.h" #include "ui/views/controls/label.h" @@ -60,7 +61,10 @@ class HeaderView : public views::Label { } // namespace -PhoneHubRecentAppsView::PhoneHubRecentAppsView() { +PhoneHubRecentAppsView::PhoneHubRecentAppsView( + chromeos::phonehub::RecentAppsInteractionHandler* + recent_apps_interaction_handler) + : recent_apps_interaction_handler_(recent_apps_interaction_handler) { SetID(PhoneHubViewID::kPhoneHubRecentAppsView); auto* layout = SetLayoutManager(std::make_unique( views::BoxLayout::Orientation::kVertical)); @@ -70,10 +74,6 @@ PhoneHubRecentAppsView::PhoneHubRecentAppsView() { recent_app_buttons_view_ = AddChildView(std::make_unique()); - // TODO(paulzchen): Add recent apps button using real data from phone. - recent_app_button_list_.push_back( - std::make_unique()); - Update(); } @@ -146,15 +146,26 @@ void PhoneHubRecentAppsView::RecentAppButtonsView::Reset() { void PhoneHubRecentAppsView::Update() { recent_app_buttons_view_->Reset(); + recent_app_button_list_.clear(); - if (recent_app_button_list_.empty()) { + std::vector recent_apps_list = + recent_apps_interaction_handler_->FetchRecentAppMetadataList(); + if (recent_apps_list.empty()) { SetVisible(false); return; } - // TODO(paulzchen): Add recent apps button using real data from phone. - for (auto& recent_app_button : recent_app_button_list_) - recent_app_buttons_view_->AddRecentAppButton(recent_app_button.get()); + for (const auto& recent_app : recent_apps_list) { + auto pressed_callback = + base::BindRepeating(&chromeos::phonehub::RecentAppsInteractionHandler:: + NotifyRecentAppClicked, + base::Unretained(recent_apps_interaction_handler_), + recent_app.package_name); + recent_app_button_list_.push_back(std::make_unique( + recent_app.icon, pressed_callback)); + recent_app_buttons_view_->AddRecentAppButton( + recent_app_button_list_.back().get()); + } PreferredSizeChanged(); SetVisible(true); diff --git a/ash/system/phonehub/phone_hub_recent_apps_view.h b/ash/system/phonehub/phone_hub_recent_apps_view.h index ab1e65490b32e..34642b66b7e15 100644 --- a/ash/system/phonehub/phone_hub_recent_apps_view.h +++ b/ash/system/phonehub/phone_hub_recent_apps_view.h @@ -6,6 +6,7 @@ #define ASH_SYSTEM_PHONEHUB_PHONE_HUB_RECENT_APPS_VIEW_H_ #include "ash/ash_export.h" +#include "chromeos/components/phonehub/recent_apps_interaction_handler.h" #include "ui/views/view.h" #include "ui/views/view_model.h" @@ -15,7 +16,9 @@ namespace ash { // the recent apps list. class ASH_EXPORT PhoneHubRecentAppsView : public views::View { public: - PhoneHubRecentAppsView(); + explicit PhoneHubRecentAppsView( + chromeos::phonehub::RecentAppsInteractionHandler* + recent_apps_interaction_handler); ~PhoneHubRecentAppsView() override; PhoneHubRecentAppsView(PhoneHubRecentAppsView&) = delete; PhoneHubRecentAppsView operator=(PhoneHubRecentAppsView&) = delete; @@ -25,7 +28,10 @@ class ASH_EXPORT PhoneHubRecentAppsView : public views::View { private: FRIEND_TEST_ALL_PREFIXES(RecentAppButtonsViewTest, TaskViewVisibility); - FRIEND_TEST_ALL_PREFIXES(RecentAppButtonsViewTest, RecentAppButtonsView); + FRIEND_TEST_ALL_PREFIXES(RecentAppButtonsViewTest, + SingleRecentAppButtonsView); + FRIEND_TEST_ALL_PREFIXES(RecentAppButtonsViewTest, + MultipleRecentAppButtonsView); class RecentAppButtonsView : public views::View { public: @@ -48,6 +54,8 @@ class ASH_EXPORT PhoneHubRecentAppsView : public views::View { RecentAppButtonsView* recent_app_buttons_view_ = nullptr; std::vector> recent_app_button_list_; + chromeos::phonehub::RecentAppsInteractionHandler* + recent_apps_interaction_handler_ = nullptr; }; } // namespace ash diff --git a/ash/system/phonehub/phone_hub_recent_apps_view_unittest.cc b/ash/system/phonehub/phone_hub_recent_apps_view_unittest.cc index 09d327b97ecb3..3fdb6d846baf3 100644 --- a/ash/system/phonehub/phone_hub_recent_apps_view_unittest.cc +++ b/ash/system/phonehub/phone_hub_recent_apps_view_unittest.cc @@ -6,9 +6,25 @@ #include "ash/system/phonehub/phone_hub_recent_app_button.h" #include "ash/test/ash_test_base.h" +#include "chromeos/components/phonehub/fake_recent_apps_interaction_handler.h" +#include "chromeos/components/phonehub/notification.h" +#include "ui/gfx/image/image.h" +#include "ui/views/test/button_test_api.h" namespace ash { +const char16_t kAppName[] = u"Test App"; +const char kPackageName[] = "com.google.testapp"; + +namespace { + +class FakeEvent : public ui::Event { + public: + FakeEvent() : Event(ui::ET_UNKNOWN, base::TimeTicks(), 0) {} +}; + +} // namespace + class RecentAppButtonsViewTest : public AshTestBase { public: RecentAppButtonsViewTest() = default; @@ -18,7 +34,8 @@ class RecentAppButtonsViewTest : public AshTestBase { void SetUp() override { AshTestBase::SetUp(); - phone_hub_recent_apps_view_ = std::make_unique(); + phone_hub_recent_apps_view_ = std::make_unique( + &fake_recent_apps_interaction_handler_); } void TearDown() override { @@ -31,28 +48,64 @@ class RecentAppButtonsViewTest : public AshTestBase { return phone_hub_recent_apps_view_.get(); } + void NotifyRecentAppAddedOrUpdated() { + fake_recent_apps_interaction_handler_.NotifyRecentAppAddedOrUpdated( + chromeos::phonehub::Notification::AppMetadata(kAppName, kPackageName, + /*icon=*/gfx::Image()), + base::Time::Now()); + } + + size_t PackageNameToClickCount(const std::string& package_name) { + return fake_recent_apps_interaction_handler_.HandledRecentAppsCount( + package_name); + } + private: std::unique_ptr phone_hub_recent_apps_view_; + chromeos::phonehub::FakeRecentAppsInteractionHandler + fake_recent_apps_interaction_handler_; }; TEST_F(RecentAppButtonsViewTest, TaskViewVisibility) { - // The view should not be shown when tab sync is not enabled. - recent_apps_view()->recent_app_button_list_.clear(); - recent_apps_view()->Update(); + // The recent app view is not visible if the NotifyRecentAppAddedOrUpdated + // function never be called, e.g. device boot. EXPECT_FALSE(recent_apps_view()->GetVisible()); - recent_apps_view()->recent_app_button_list_.push_back( - std::make_unique()); + NotifyRecentAppAddedOrUpdated(); recent_apps_view()->Update(); + EXPECT_TRUE(recent_apps_view()->GetVisible()); } -TEST_F(RecentAppButtonsViewTest, RecentAppButtonsView) { - // TODO(paulzchen): Check real expected number when the recent app button - // using real data from phone. +TEST_F(RecentAppButtonsViewTest, SingleRecentAppButtonsView) { + NotifyRecentAppAddedOrUpdated(); + recent_apps_view()->Update(); + size_t expected_recent_app_button = 1; EXPECT_EQ(expected_recent_app_button, recent_apps_view()->recent_app_buttons_view_->children().size()); } +TEST_F(RecentAppButtonsViewTest, MultipleRecentAppButtonsView) { + NotifyRecentAppAddedOrUpdated(); + NotifyRecentAppAddedOrUpdated(); + NotifyRecentAppAddedOrUpdated(); + recent_apps_view()->Update(); + + size_t expected_recent_app_button = 3; + EXPECT_EQ(expected_recent_app_button, + recent_apps_view()->recent_app_buttons_view_->children().size()); + + for (auto* child : recent_apps_view()->recent_app_buttons_view_->children()) { + PhoneHubRecentAppButton* recent_app = + static_cast(child); + // Simulate clicking button using placeholder event. + views::test::ButtonTestApi(recent_app).NotifyClick(FakeEvent()); + } + + size_t expected_number_of_button_be_clicked = 3; + EXPECT_EQ(expected_number_of_button_be_clicked, + PackageNameToClickCount(kPackageName)); +} + } // namespace ash \ No newline at end of file diff --git a/chromeos/components/phonehub/fake_recent_apps_interaction_handler.cc b/chromeos/components/phonehub/fake_recent_apps_interaction_handler.cc index 8d0b701c329af..e950c00cc688a 100644 --- a/chromeos/components/phonehub/fake_recent_apps_interaction_handler.cc +++ b/chromeos/components/phonehub/fake_recent_apps_interaction_handler.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chromeos/components/phonehub/fake_recent_apps_interaction_handler.h" +#include "base/containers/contains.h" #include "chromeos/components/phonehub/notification.h" namespace chromeos { @@ -13,8 +14,12 @@ FakeRecentAppsInteractionHandler::FakeRecentAppsInteractionHandler() = default; FakeRecentAppsInteractionHandler::~FakeRecentAppsInteractionHandler() = default; void FakeRecentAppsInteractionHandler::NotifyRecentAppClicked( - const Notification::AppMetadata& app_metadata) { - handled_recent_apps_count_++; + const std::string& recent_app_package_name) { + if (base::Contains(package_name_to_click_count_, recent_app_package_name)) { + package_name_to_click_count_.at(recent_app_package_name)++; + return; + } + package_name_to_click_count_[recent_app_package_name] = 1; } void FakeRecentAppsInteractionHandler::AddRecentAppClickObserver( @@ -27,5 +32,20 @@ void FakeRecentAppsInteractionHandler::RemoveRecentAppClickObserver( recent_app_click_observer_count_--; } +void FakeRecentAppsInteractionHandler::NotifyRecentAppAddedOrUpdated( + const Notification::AppMetadata& app_metadata, + base::Time last_accessed_timestamp) { + recent_apps_metadata_.emplace_back(app_metadata, last_accessed_timestamp); +} + +std::vector +FakeRecentAppsInteractionHandler::FetchRecentAppMetadataList() { + std::vector app_metadata_list; + for (const auto& recent_app_metadata : recent_apps_metadata_) { + app_metadata_list.emplace_back(recent_app_metadata.first); + } + return app_metadata_list; +} + } // namespace phonehub } // namespace chromeos diff --git a/chromeos/components/phonehub/fake_recent_apps_interaction_handler.h b/chromeos/components/phonehub/fake_recent_apps_interaction_handler.h index 95f64d235bb46..80e5afb12eb57 100644 --- a/chromeos/components/phonehub/fake_recent_apps_interaction_handler.h +++ b/chromeos/components/phonehub/fake_recent_apps_interaction_handler.h @@ -22,8 +22,8 @@ class FakeRecentAppsInteractionHandler : public RecentAppsInteractionHandler { const FakeRecentAppsInteractionHandler&) = delete; ~FakeRecentAppsInteractionHandler() override; - size_t handled_recent_apps_count() const { - return handled_recent_apps_count_; + size_t HandledRecentAppsCount(const std::string& package_name) const { + return package_name_to_click_count_.at(package_name); } size_t recent_app_click_observer_count() const { @@ -31,13 +31,20 @@ class FakeRecentAppsInteractionHandler : public RecentAppsInteractionHandler { } void NotifyRecentAppClicked( - const Notification::AppMetadata& app_metadata) override; + const std::string& recent_app_package_name) override; void AddRecentAppClickObserver(RecentAppClickObserver* observer) override; void RemoveRecentAppClickObserver(RecentAppClickObserver* observer) override; + void NotifyRecentAppAddedOrUpdated( + const Notification::AppMetadata& app_metadata, + base::Time last_accessed_timestamp) override; + std::vector FetchRecentAppMetadataList() override; private: - size_t handled_recent_apps_count_ = 0; size_t recent_app_click_observer_count_ = 0; + + std::vector> + recent_apps_metadata_; + std::map package_name_to_click_count_; }; } // namespace phonehub diff --git a/chromeos/components/phonehub/recent_app_click_observer.h b/chromeos/components/phonehub/recent_app_click_observer.h index 7e44739509a41..e619313c1a27b 100644 --- a/chromeos/components/phonehub/recent_app_click_observer.h +++ b/chromeos/components/phonehub/recent_app_click_observer.h @@ -6,7 +6,6 @@ #define CHROMEOS_COMPONENTS_PHONEHUB_RECENT_APP_CLICK_OBSERVER_H_ #include "base/observer_list_types.h" -#include "chromeos/components/phonehub/notification.h" namespace chromeos { namespace phonehub { @@ -18,7 +17,7 @@ class RecentAppClickObserver : public base::CheckedObserver { // Called when the user clicks the recent app which has an open // action in the PhoneHub. virtual void OnRecentAppClicked( - const Notification::AppMetadata& app_metadata) = 0; + const std::string& recent_app_package_name) = 0; }; } // namespace phonehub diff --git a/chromeos/components/phonehub/recent_apps_interaction_handler.cc b/chromeos/components/phonehub/recent_apps_interaction_handler.cc index 245b29cd09078..7b003abcb8c6c 100644 --- a/chromeos/components/phonehub/recent_apps_interaction_handler.cc +++ b/chromeos/components/phonehub/recent_apps_interaction_handler.cc @@ -8,6 +8,8 @@ namespace chromeos { namespace phonehub { +const size_t kMaxMostRecentApps = 5; + RecentAppsInteractionHandler::RecentAppsInteractionHandler() = default; RecentAppsInteractionHandler::~RecentAppsInteractionHandler() = default; @@ -23,9 +25,46 @@ void RecentAppsInteractionHandler::RemoveRecentAppClickObserver( } void RecentAppsInteractionHandler::NotifyRecentAppClicked( - const Notification::AppMetadata& app_metadata) { + const std::string& package_name) { for (auto& observer : observer_list_) - observer.OnRecentAppClicked(app_metadata); + observer.OnRecentAppClicked(package_name); +} + +void RecentAppsInteractionHandler::NotifyRecentAppAddedOrUpdated( + const Notification::AppMetadata& app_metadata, + base::Time last_accessed_timestamp) { + // Each element of |recent_app_metadata_list_| has a unique |package_name|. + for (auto it = recent_app_metadata_list_.begin(); + it != recent_app_metadata_list_.end(); ++it) { + if (it->first.package_name == app_metadata.package_name) { + recent_app_metadata_list_.erase(it); + break; + } + } + + recent_app_metadata_list_.emplace_back(app_metadata, last_accessed_timestamp); +} + +std::vector +RecentAppsInteractionHandler::FetchRecentAppMetadataList() { + // Sort |recent_app_metadata_list_| from most recently visited to least + // recently visited. + std::sort(recent_app_metadata_list_.begin(), recent_app_metadata_list_.end(), + [](const std::pair& a, + const std::pair& b) { + // More recently visited apps should come before earlier visited + // apps. + return a.second > b.second; + }); + + // At most |kMaxMostRecentApps| recent apps can be displayed. + size_t num_recent_apps_to_display = + std::min(recent_app_metadata_list_.size(), kMaxMostRecentApps); + std::vector app_metadata_list; + for (size_t i = 0; i < num_recent_apps_to_display; ++i) { + app_metadata_list.push_back(recent_app_metadata_list_[i].first); + } + return app_metadata_list; } } // namespace phonehub diff --git a/chromeos/components/phonehub/recent_apps_interaction_handler.h b/chromeos/components/phonehub/recent_apps_interaction_handler.h index 793a5f7e49a53..818f2592c2be5 100644 --- a/chromeos/components/phonehub/recent_apps_interaction_handler.h +++ b/chromeos/components/phonehub/recent_apps_interaction_handler.h @@ -25,16 +25,21 @@ class RecentAppsInteractionHandler { delete; virtual ~RecentAppsInteractionHandler(); - // Called by RecentAppButton to notify the click event. - // TODO(paulzchen): The |PhoneHubRecentAppButton| notify the button be clicked - // and the other SWA can interaction with this event. - virtual void NotifyRecentAppClicked( - const Notification::AppMetadata& app_metadata); + virtual void NotifyRecentAppClicked(const std::string& package_name); virtual void AddRecentAppClickObserver(RecentAppClickObserver* observer); virtual void RemoveRecentAppClickObserver(RecentAppClickObserver* observer); + virtual void NotifyRecentAppAddedOrUpdated( + const Notification::AppMetadata& app_metadata, + base::Time last_accessed_timestamp); + virtual std::vector FetchRecentAppMetadataList(); + private: + FRIEND_TEST_ALL_PREFIXES(RecentAppsInteractionHandlerTest, RecentAppsUpdated); + base::ObserverList observer_list_; + std::vector> + recent_app_metadata_list_; }; } // namespace phonehub diff --git a/chromeos/components/phonehub/recent_apps_interaction_handler_unittest.cc b/chromeos/components/phonehub/recent_apps_interaction_handler_unittest.cc index 9196ac1d8a5dc..943a64c1ddc49 100644 --- a/chromeos/components/phonehub/recent_apps_interaction_handler_unittest.cc +++ b/chromeos/components/phonehub/recent_apps_interaction_handler_unittest.cc @@ -18,18 +18,13 @@ class FakeClickHandler : public RecentAppClickObserver { FakeClickHandler() = default; ~FakeClickHandler() override = default; - std::u16string get_visible_app_name() { return visible_app_name; } - std::string get_package_name() { return package_name; } - void OnRecentAppClicked( - const Notification::AppMetadata& app_metadata) override { - visible_app_name = app_metadata.visible_app_name; - package_name = app_metadata.package_name; + void OnRecentAppClicked(const std::string& recent_app_package_name) override { + package_name = recent_app_package_name; } private: - std::u16string visible_app_name; std::string package_name; }; @@ -54,10 +49,6 @@ class RecentAppsInteractionHandlerTest : public testing::Test { interaction_handler_->RemoveRecentAppClickObserver(&fake_click_handler_); } - std::u16string GetVisibleAppName() { - return fake_click_handler_.get_visible_app_name(); - } - std::string GetPackageName() { return fake_click_handler_.get_package_name(); } @@ -69,17 +60,116 @@ class RecentAppsInteractionHandlerTest : public testing::Test { std::unique_ptr interaction_handler_; }; -TEST_F(RecentAppsInteractionHandlerTest, NotifyRecentAppsClickHandler) { +TEST_F(RecentAppsInteractionHandlerTest, RecentAppsClicked) { const char16_t expected_app_visible_name[] = u"Fake App"; const char expected_package_name[] = "com.fakeapp"; auto expected_app_metadata = Notification::AppMetadata( expected_app_visible_name, expected_package_name, gfx::Image()); - handler().NotifyRecentAppClicked(expected_app_metadata); + handler().NotifyRecentAppClicked(expected_package_name); - EXPECT_EQ(expected_app_visible_name, GetVisibleAppName()); EXPECT_EQ(expected_package_name, GetPackageName()); } +TEST_F(RecentAppsInteractionHandlerTest, RecentAppsUpdated) { + const char16_t app_visible_name1[] = u"Fake App"; + const char package_name1[] = "com.fakeapp"; + auto app_metadata1 = + Notification::AppMetadata(app_visible_name1, package_name1, gfx::Image()); + + const char16_t app_visible_name2[] = u"Fake App2"; + const char package_name2[] = "com.fakeapp2"; + auto app_metadata2 = + Notification::AppMetadata(app_visible_name2, package_name2, gfx::Image()); + const base::Time now = base::Time::Now(); + + handler().NotifyRecentAppAddedOrUpdated(app_metadata1, now); + EXPECT_EQ(1U, handler().recent_app_metadata_list_.size()); + EXPECT_EQ(now, handler().recent_app_metadata_list_[0].second); + + // The same package name only update last accessed timestamp. + const base::Time next_minute = + base::Time::Now() + base::TimeDelta::FromMinutes(1); + handler().NotifyRecentAppAddedOrUpdated(app_metadata1, next_minute); + EXPECT_EQ(1U, handler().recent_app_metadata_list_.size()); + EXPECT_EQ(next_minute, handler().recent_app_metadata_list_[0].second); + + const base::Time next_hour = + base::Time::Now() + base::TimeDelta::FromHours(1); + handler().NotifyRecentAppAddedOrUpdated(app_metadata2, next_hour); + EXPECT_EQ(2U, handler().recent_app_metadata_list_.size()); +} + +TEST_F(RecentAppsInteractionHandlerTest, FetchRecentAppMetadataList) { + const char16_t app_visible_name1[] = u"Fake App"; + const char package_name1[] = "com.fakeapp"; + auto app_metadata1 = + Notification::AppMetadata(app_visible_name1, package_name1, gfx::Image()); + + const char16_t app_visible_name2[] = u"Fake App2"; + const char package_name2[] = "com.fakeapp2"; + auto app_metadata2 = + Notification::AppMetadata(app_visible_name2, package_name2, gfx::Image()); + + const char16_t app_visible_name3[] = u"Fake App3"; + const char package_name3[] = "com.fakeapp3"; + auto app_metadata3 = + Notification::AppMetadata(app_visible_name3, package_name3, gfx::Image()); + + const base::Time now = base::Time::Now(); + const base::Time next_minute = + base::Time::Now() + base::TimeDelta::FromMinutes(1); + const base::Time next_hour = + base::Time::Now() + base::TimeDelta::FromHours(1); + + handler().NotifyRecentAppAddedOrUpdated(app_metadata1, now); + handler().NotifyRecentAppAddedOrUpdated(app_metadata2, next_minute); + handler().NotifyRecentAppAddedOrUpdated(app_metadata3, next_hour); + + std::vector recent_apps_metadata_result = + handler().FetchRecentAppMetadataList(); + + EXPECT_EQ(3U, recent_apps_metadata_result.size()); + EXPECT_EQ(package_name3, recent_apps_metadata_result[0].package_name); + EXPECT_EQ(package_name2, recent_apps_metadata_result[1].package_name); + EXPECT_EQ(package_name1, recent_apps_metadata_result[2].package_name); + + const char16_t app_visible_name4[] = u"Fake App4"; + const char package_name4[] = "com.fakeapp4"; + auto app_metadata4 = + Notification::AppMetadata(app_visible_name4, package_name4, gfx::Image()); + + const char16_t app_visible_name5[] = u"Fake App5"; + const char package_name5[] = "com.fakeapp5"; + auto app_metadata5 = + Notification::AppMetadata(app_visible_name5, package_name5, gfx::Image()); + + const char16_t app_visible_name6[] = u"Fake App6"; + const char package_name6[] = "com.fakeapp6"; + auto app_metadata6 = + Notification::AppMetadata(app_visible_name6, package_name6, gfx::Image()); + + const base::Time next_two_hour = + base::Time::Now() + base::TimeDelta::FromHours(2); + const base::Time next_three_hour = + base::Time::Now() + base::TimeDelta::FromHours(3); + const base::Time next_four_hour = + base::Time::Now() + base::TimeDelta::FromHours(4); + + handler().NotifyRecentAppAddedOrUpdated(app_metadata4, next_two_hour); + handler().NotifyRecentAppAddedOrUpdated(app_metadata5, next_three_hour); + handler().NotifyRecentAppAddedOrUpdated(app_metadata6, next_four_hour); + + const size_t max_most_recent_apps = 5; + recent_apps_metadata_result = handler().FetchRecentAppMetadataList(); + EXPECT_EQ(max_most_recent_apps, recent_apps_metadata_result.size()); + + EXPECT_EQ(package_name6, recent_apps_metadata_result[0].package_name); + EXPECT_EQ(package_name5, recent_apps_metadata_result[1].package_name); + EXPECT_EQ(package_name4, recent_apps_metadata_result[2].package_name); + EXPECT_EQ(package_name3, recent_apps_metadata_result[3].package_name); + EXPECT_EQ(package_name2, recent_apps_metadata_result[4].package_name); +} + } // namespace phonehub } // namespace chromeos