| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/quick_pair/companion_app/companion_app_broker_impl.h" |
| |
| #include <map> |
| |
| #include "ash/constants/ash_features.h" |
| #include "ash/quick_pair/common/device.h" |
| #include "ash/quick_pair/common/fake_quick_pair_browser_delegate.h" |
| #include "ash/test/ash_test_base.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "components/signin/public/identity_manager/identity_test_environment.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| const std::string kUserEmail = "test@test.test"; |
| constexpr char kTestDeviceAddress[] = "11:12:13:14:15:16"; |
| constexpr char kValidModelId[] = "6EDAF7"; |
| constexpr char kValidCompanionBrowserUri[] = "https://photos.google.com/"; |
| constexpr char kEmptyCompanionBrowserUri[] = ""; |
| constexpr char kCompanionAppId[] = "ncmjhecbjeaamljdfahankockkkdmedg"; |
| constexpr char kValidCompanionPlayStoreUri[] = |
| "https://play.google.com/store/apps/" |
| "details?id=com.google.android.apps.photos"; |
| constexpr char kEmptyCompanionPlayStoreUri[] = ""; |
| |
| } // namespace |
| |
| namespace ash { |
| namespace quick_pair { |
| |
| class CompanionAppBrokerImplUnitTest : public AshTestBase, |
| public CompanionAppBroker::Observer { |
| public: |
| void SetUp() override { |
| AshTestBase::SetUp(); |
| |
| companion_app_broker_ = std::make_unique<CompanionAppBrokerImpl>(); |
| companion_app_broker_->AddObserver(this); |
| |
| test_device_ = base::MakeRefCounted<Device>( |
| kValidModelId, kTestDeviceAddress, Protocol::kFastPairInitial); |
| |
| identity_test_environment_ = |
| std::make_unique<signin::IdentityTestEnvironment>(); |
| identity_manager_ = identity_test_environment_->identity_manager(); |
| } |
| |
| void TearDown() override { |
| ClearLogin(); |
| AshTestBase::TearDown(); |
| } |
| |
| void Login(user_manager::UserType user_type) { |
| SimulateUserLogin(kUserEmail, user_type); |
| } |
| |
| void SetIdentityManager(signin::IdentityManager* identity_manager) { |
| FakeQuickPairBrowserDelegate* delegate = |
| FakeQuickPairBrowserDelegate::Get(); |
| delegate->SetIdentityManager(identity_manager); |
| } |
| |
| void SetCompanionAppInstalled(const std::string& app_id, bool installed) { |
| FakeQuickPairBrowserDelegate* delegate = |
| FakeQuickPairBrowserDelegate::Get(); |
| delegate->SetCompanionAppInstalled(app_id, installed); |
| } |
| |
| // CompanionAppBroker::Observer |
| void ShowInstallCompanionApp(scoped_refptr<Device> device) override { |
| install_companion_app_notification_shown_ = true; |
| } |
| |
| void ShowLaunchCompanionApp(scoped_refptr<Device> device) override { |
| launch_companion_app_notification_shown_ = true; |
| } |
| |
| void OnCompanionAppInstalled(scoped_refptr<Device> device) override {} |
| |
| protected: |
| std::unique_ptr<CompanionAppBrokerImpl> companion_app_broker_; |
| scoped_refptr<Device> test_device_; |
| std::unique_ptr<signin::IdentityTestEnvironment> identity_test_environment_; |
| raw_ptr<signin::IdentityManager> identity_manager_; |
| |
| bool install_companion_app_notification_shown_ = false; |
| bool launch_companion_app_notification_shown_ = false; |
| }; |
| |
| TEST_F(CompanionAppBrokerImplUnitTest, MaybeShowCompanionAppActions_Disabled) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{}, |
| /*disabled_features=*/{ash::features::kFastPairPwaCompanion}); |
| |
| EXPECT_DEATH_IF_SUPPORTED( |
| { companion_app_broker_->MaybeShowCompanionAppActions(test_device_); }, |
| ""); |
| } |
| |
| // The app is not installed and there is a Play store link, so regular |
| // logged-in users would be directed to the Play store via "install" |
| // notification. However, guests are only allowed to access the app through |
| // the browser link. |
| TEST_F(CompanionAppBrokerImplUnitTest, |
| ShowLaunchCompanionApp_Guest_BrowserOnly) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeatureWithParameters( |
| ash::features::kFastPairPwaCompanion, |
| {{ash::features::kFastPairPwaCompanionInstallUri.name, |
| kValidCompanionBrowserUri}, |
| {ash::features::kFastPairPwaCompanionPlayStoreUri.name, |
| kValidCompanionPlayStoreUri}, |
| {ash::features::kFastPairPwaCompanionAppId.name, kCompanionAppId}}); |
| |
| SetIdentityManager(identity_manager_); |
| SetCompanionAppInstalled(kCompanionAppId, false); |
| Login(user_manager::UserType::kGuest); |
| |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| companion_app_broker_->MaybeShowCompanionAppActions(test_device_); |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_TRUE(launch_companion_app_notification_shown_); |
| } |
| |
| // The companion app is installed, but no browser link is supplied and guests |
| // can only access browser link. |
| TEST_F(CompanionAppBrokerImplUnitTest, NoCompanionAppNotification_Guest) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeatureWithParameters( |
| ash::features::kFastPairPwaCompanion, |
| {{ash::features::kFastPairPwaCompanionInstallUri.name, |
| kEmptyCompanionBrowserUri}, |
| {ash::features::kFastPairPwaCompanionPlayStoreUri.name, |
| kValidCompanionPlayStoreUri}, |
| {ash::features::kFastPairPwaCompanionAppId.name, kCompanionAppId}}); |
| |
| SetIdentityManager(identity_manager_); |
| SetCompanionAppInstalled(kCompanionAppId, true); |
| Login(user_manager::UserType::kGuest); |
| |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| companion_app_broker_->MaybeShowCompanionAppActions(test_device_); |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| } |
| |
| // If the app is installed, the user should be pointed directly toward it via |
| // the "Launch" notification |
| TEST_F(CompanionAppBrokerImplUnitTest, ShowLaunchCompanionApp_Installed) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeatureWithParameters( |
| ash::features::kFastPairPwaCompanion, |
| {{ash::features::kFastPairPwaCompanionInstallUri.name, |
| kValidCompanionBrowserUri}, |
| {ash::features::kFastPairPwaCompanionPlayStoreUri.name, |
| kValidCompanionPlayStoreUri}, |
| {ash::features::kFastPairPwaCompanionAppId.name, kCompanionAppId}}); |
| |
| SetIdentityManager(identity_manager_); |
| SetCompanionAppInstalled(kCompanionAppId, true); |
| Login(user_manager::UserType::kRegular); |
| |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| companion_app_broker_->MaybeShowCompanionAppActions(test_device_); |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_TRUE(launch_companion_app_notification_shown_); |
| } |
| |
| // When the app is not yet installed and there is no Play store link, users |
| // should be directed to the browser via "Launch" notification. |
| TEST_F(CompanionAppBrokerImplUnitTest, ShowLaunchCompanionApp_NoPlayStoreLink) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeatureWithParameters( |
| ash::features::kFastPairPwaCompanion, |
| {{ash::features::kFastPairPwaCompanionInstallUri.name, |
| kValidCompanionBrowserUri}, |
| {ash::features::kFastPairPwaCompanionPlayStoreUri.name, |
| kEmptyCompanionPlayStoreUri}, |
| {ash::features::kFastPairPwaCompanionAppId.name, kCompanionAppId}}); |
| |
| SetIdentityManager(identity_manager_); |
| SetCompanionAppInstalled(kCompanionAppId, false); |
| Login(user_manager::UserType::kRegular); |
| |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| companion_app_broker_->MaybeShowCompanionAppActions(test_device_); |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_TRUE(launch_companion_app_notification_shown_); |
| } |
| |
| // If no companion app information is provided for this device, the user cannot |
| // be directed to the app, so no notification will be shown. |
| TEST_F(CompanionAppBrokerImplUnitTest, NoCompanionAppNotification_NoAppInfo) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeatureWithParameters( |
| ash::features::kFastPairPwaCompanion, |
| {{ash::features::kFastPairPwaCompanionInstallUri.name, |
| kEmptyCompanionBrowserUri}, |
| {ash::features::kFastPairPwaCompanionPlayStoreUri.name, |
| kEmptyCompanionPlayStoreUri}, |
| {ash::features::kFastPairPwaCompanionAppId.name, kCompanionAppId}}); |
| |
| SetIdentityManager(identity_manager_); |
| SetCompanionAppInstalled(kCompanionAppId, false); |
| Login(user_manager::UserType::kRegular); |
| |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| companion_app_broker_->MaybeShowCompanionAppActions(test_device_); |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| } |
| |
| // If the app is not yet installed, the Play store link takes precedence over |
| // the browser link. |
| TEST_F(CompanionAppBrokerImplUnitTest, ShowInstallCompanionApp_PlayStoreLink) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeatureWithParameters( |
| ash::features::kFastPairPwaCompanion, |
| {{ash::features::kFastPairPwaCompanionInstallUri.name, |
| kValidCompanionBrowserUri}, |
| {ash::features::kFastPairPwaCompanionPlayStoreUri.name, |
| kValidCompanionPlayStoreUri}, |
| {ash::features::kFastPairPwaCompanionAppId.name, kCompanionAppId}}); |
| |
| SetIdentityManager(identity_manager_); |
| SetCompanionAppInstalled(kCompanionAppId, false); |
| Login(user_manager::UserType::kRegular); |
| |
| EXPECT_FALSE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| companion_app_broker_->MaybeShowCompanionAppActions(test_device_); |
| EXPECT_TRUE(install_companion_app_notification_shown_); |
| EXPECT_FALSE(launch_companion_app_notification_shown_); |
| } |
| |
| TEST_F(CompanionAppBrokerImplUnitTest, InstallCompanionApp_Disabled) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{}, |
| /*disabled_features=*/{ash::features::kFastPairPwaCompanion}); |
| |
| EXPECT_DEATH_IF_SUPPORTED( |
| { companion_app_broker_->InstallCompanionApp(test_device_); }, ""); |
| } |
| |
| // TODO(b/290816916): Update with new logic to check device metadata. |
| // Ensures calling InstallCompanionApp with feature enabled does not crash. |
| TEST_F(CompanionAppBrokerImplUnitTest, InstallCompanionApp_Enabled) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeatureWithParameters( |
| ash::features::kFastPairPwaCompanion, |
| {{ash::features::kFastPairPwaCompanionInstallUri.name, |
| kValidCompanionBrowserUri}, |
| {ash::features::kFastPairPwaCompanionPlayStoreUri.name, |
| kValidCompanionPlayStoreUri}, |
| {ash::features::kFastPairPwaCompanionAppId.name, kCompanionAppId}}); |
| |
| companion_app_broker_->InstallCompanionApp(test_device_); |
| } |
| |
| TEST_F(CompanionAppBrokerImplUnitTest, LaunchCompanionApp_Disabled) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{}, |
| /*disabled_features=*/{ash::features::kFastPairPwaCompanion}); |
| |
| EXPECT_DEATH_IF_SUPPORTED( |
| { companion_app_broker_->LaunchCompanionApp(test_device_); }, ""); |
| } |
| |
| // TODO(b/290816916): Update with new logic to check device metadata. |
| // Ensures calling LaunchCompanionApp with feature enabled does not crash. |
| TEST_F(CompanionAppBrokerImplUnitTest, LaunchCompanionApp_Enabled) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeatureWithParameters( |
| ash::features::kFastPairPwaCompanion, |
| {{ash::features::kFastPairPwaCompanionInstallUri.name, |
| kValidCompanionBrowserUri}, |
| {ash::features::kFastPairPwaCompanionPlayStoreUri.name, |
| kValidCompanionPlayStoreUri}, |
| {ash::features::kFastPairPwaCompanionAppId.name, kCompanionAppId}}); |
| |
| companion_app_broker_->LaunchCompanionApp(test_device_); |
| } |
| |
| } // namespace quick_pair |
| } // namespace ash |