| // Copyright 2020 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/nearby_sharing/nearby_share_delegate_impl.h" |
| |
| #include <memory> |
| |
| #include "ash/public/cpp/nearby_share_controller.h" |
| #include "ash/public/cpp/session/session_controller.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/time/clock.h" |
| #include "build/branding_buildflags.h" |
| #include "chrome/browser/nearby_sharing/common/nearby_share_features.h" |
| #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h" |
| #include "chrome/browser/nearby_sharing/local_device_data/fake_nearby_share_local_device_data_manager.h" |
| #include "chrome/browser/nearby_sharing/mock_nearby_sharing_service.h" |
| #include "chrome/browser/nearby_sharing/nearby_share_settings.h" |
| #include "chrome/browser/ui/ash/session/test_session_controller.h" |
| #include "chromeos/constants/chromeos_features.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/vector_icon_types.h" |
| |
| namespace { |
| |
| const char kDefaultDeviceName[] = "Josh's Chromebook"; |
| |
| } // namespace |
| |
| using ::testing::_; |
| using ::testing::Assign; |
| using ::testing::AtLeast; |
| using ::testing::Return; |
| using ::testing::ReturnPointee; |
| |
| class MockSettingsOpener : public NearbyShareDelegateImpl::SettingsOpener { |
| public: |
| MOCK_METHOD(void, ShowSettingsPage, (const std::string&), (override)); |
| }; |
| |
| class MockNearbyShareController : public ash::NearbyShareController { |
| public: |
| MOCK_METHOD(void, HighVisibilityEnabledChanged, (bool), (override)); |
| MOCK_METHOD(void, NearbyShareEnabledChanged, (bool), (override)); |
| MOCK_METHOD(void, |
| VisibilityChanged, |
| (::nearby_share::mojom::Visibility), |
| (const override)); |
| }; |
| |
| // TODO(crbug.com/1127940): Refactor these tests to avoid use of GMock. |
| class NearbyShareDelegateImplTest : public ::testing::Test { |
| public: |
| NearbyShareDelegateImplTest() |
| : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), |
| test_local_device_data_(kDefaultDeviceName) { |
| RegisterNearbySharingPrefs(test_pref_service_.registry()); |
| settings_ = std::make_unique<NearbyShareSettings>(&test_pref_service_, |
| &test_local_device_data_); |
| } |
| |
| ~NearbyShareDelegateImplTest() override = default; |
| |
| base::Time Now() const { return task_environment_.GetMockClock()->Now(); } |
| |
| // Fast-forwards mock time by |delta| and fires relevant timers. |
| void FastForward(base::TimeDelta delta) { |
| task_environment_.FastForwardBy(delta); |
| } |
| |
| void SetHighVisibilityOn(bool high_visibility_on) { |
| if (high_visibility_on_ != high_visibility_on) { |
| high_visibility_on_ = high_visibility_on; |
| delegate_->OnHighVisibilityChanged(high_visibility_on); |
| } |
| } |
| |
| void SetNearbyShareEnabled(bool enabled) { |
| delegate_->OnEnabledChanged(enabled); |
| } |
| |
| void SetUp() override { |
| settings_->SetIsOnboardingComplete(true); |
| settings_->SetEnabled(false); |
| |
| InitDelegate(); |
| } |
| |
| void InitDelegate() { |
| if (delegate_) { |
| delegate_.reset(); |
| } |
| delegate_ = std::make_unique<NearbyShareDelegateImpl>(&controller_); |
| |
| EXPECT_CALL(nearby_share_service_, GetSettings()) |
| .WillRepeatedly(Return(settings_.get())); |
| EXPECT_CALL(nearby_share_service_, IsInHighVisibility()) |
| .WillRepeatedly(ReturnPointee(&high_visibility_on_)); |
| EXPECT_CALL(nearby_share_service_, AddObserver(_)) |
| .WillRepeatedly(Assign(&service_observer_bound_, true)); |
| EXPECT_CALL(nearby_share_service_, RemoveObserver(_)) |
| .WillRepeatedly(Assign(&service_observer_bound_, false)); |
| EXPECT_CALL(nearby_share_service_, HasObserver(_)) |
| .WillRepeatedly(ReturnPointee(&service_observer_bound_)); |
| |
| delegate_->SetNearbyShareServiceForTest(&nearby_share_service_); |
| delegate_->SetNearbyShareSettingsForTest(settings_.get()); |
| |
| std::unique_ptr<MockSettingsOpener> settings_opener = |
| std::make_unique<MockSettingsOpener>(); |
| settings_opener_ = settings_opener.get(); |
| delegate_->set_settings_opener_for_test(std::move(settings_opener)); |
| } |
| |
| NearbyShareSettings* settings() { return settings_.get(); } |
| |
| protected: |
| content::BrowserTaskEnvironment task_environment_; |
| MockNearbySharingService nearby_share_service_; |
| TestSessionController session_controller_; |
| sync_preferences::TestingPrefServiceSyncable test_pref_service_; |
| FakeNearbyShareLocalDeviceDataManager test_local_device_data_; |
| std::unique_ptr<NearbyShareSettings> settings_; |
| raw_ptr<MockSettingsOpener, DanglingUntriaged> settings_opener_; |
| MockNearbyShareController controller_; |
| std::unique_ptr<NearbyShareDelegateImpl> delegate_; |
| bool high_visibility_on_ = false; |
| bool service_observer_bound_ = false; |
| }; |
| |
| TEST_F(NearbyShareDelegateImplTest, StartHighVisibilityAndTimeout) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeature(chromeos::features::kQuickShareV2); |
| InitDelegate(); |
| settings()->SetEnabled(true); |
| |
| EXPECT_CALL(*settings_opener_, ShowSettingsPage(_)); |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(true)); |
| |
| delegate_->EnableHighVisibility(); |
| SetHighVisibilityOn(true); |
| |
| EXPECT_CALL(nearby_share_service_, ClearForegroundReceiveSurfaces()).Times(0); |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(false)).Times(0); |
| FastForward(base::Minutes(9)); |
| |
| EXPECT_CALL(nearby_share_service_, ClearForegroundReceiveSurfaces()).Times(1); |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(false)).Times(1); |
| FastForward(base::Minutes(1)); |
| |
| // DisableHighVisibility will be called automatically after the timer fires. |
| SetHighVisibilityOn(false); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, StartHighVisibilityAndTimeout_Legacy) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndDisableFeature(chromeos::features::kQuickShareV2); |
| InitDelegate(); |
| settings()->SetEnabled(true); |
| |
| EXPECT_CALL(*settings_opener_, ShowSettingsPage(_)); |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(true)); |
| |
| delegate_->EnableHighVisibility(); |
| SetHighVisibilityOn(true); |
| |
| EXPECT_CALL(nearby_share_service_, ClearForegroundReceiveSurfaces()); |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(false)); |
| |
| // DisableHighVisibility will be called automatically after the timer fires. |
| FastForward(base::Minutes(10)); |
| SetHighVisibilityOn(false); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, StartStopHighVisibility) { |
| settings()->SetEnabled(true); |
| |
| EXPECT_CALL(*settings_opener_, ShowSettingsPage(_)); |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(true)); |
| |
| delegate_->EnableHighVisibility(); |
| SetHighVisibilityOn(true); |
| |
| EXPECT_CALL(nearby_share_service_, ClearForegroundReceiveSurfaces()); |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(false)); |
| |
| delegate_->DisableHighVisibility(); |
| SetHighVisibilityOn(false); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, TestIsEnableHighVisibilityRequestActive) { |
| settings()->SetEnabled(true); |
| |
| EXPECT_CALL(*settings_opener_, ShowSettingsPage(_)); |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(true)); |
| |
| delegate_->EnableHighVisibility(); |
| EXPECT_TRUE(delegate_->IsEnableHighVisibilityRequestActive()); |
| SetHighVisibilityOn(true); |
| EXPECT_FALSE(delegate_->IsEnableHighVisibilityRequestActive()); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, TestIsEnableOnHighVisibilityRequest) { |
| settings()->SetEnabled(true); |
| |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(true)); |
| |
| delegate_->OnHighVisibilityChangeRequested(); |
| EXPECT_TRUE(delegate_->IsEnableHighVisibilityRequestActive()); |
| SetHighVisibilityOn(true); |
| EXPECT_FALSE(delegate_->IsEnableHighVisibilityRequestActive()); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, StopHighVisibilityOnScreenLock) { |
| settings()->SetEnabled(true); |
| |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(true)); |
| EXPECT_CALL(*settings_opener_, ShowSettingsPage(_)); |
| |
| delegate_->EnableHighVisibility(); |
| SetHighVisibilityOn(true); |
| |
| EXPECT_CALL(controller_, HighVisibilityEnabledChanged(false)); |
| EXPECT_CALL(nearby_share_service_, ClearForegroundReceiveSurfaces()); |
| |
| // DisableHighVisibility will be called when the screen locks. |
| delegate_->OnLockStateChanged(/*locked=*/true); |
| SetHighVisibilityOn(false); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, ShowNearbyShareSettings) { |
| EXPECT_CALL(*settings_opener_, ShowSettingsPage(_)); |
| |
| delegate_->ShowNearbyShareSettings(); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, |
| ExpectControllerObservation_OnNearbyShareToggled) { |
| EXPECT_CALL(controller_, NearbyShareEnabledChanged(true)); |
| settings()->SetEnabled(true); |
| SetNearbyShareEnabled(true); |
| |
| EXPECT_CALL(controller_, NearbyShareEnabledChanged(false)); |
| settings()->SetEnabled(false); |
| SetNearbyShareEnabled(false); |
| } |
| |
| #if BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| TEST_F(NearbyShareDelegateImplTest, GetIconFlagEnabledOfficialBuild) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{::features::kIsNameEnabled}, |
| /*disabled_features=*/{}); |
| |
| EXPECT_FALSE(delegate_->GetIcon(/*on_icon=*/false).is_empty()); |
| EXPECT_FALSE(delegate_->GetIcon(/*on_icon=*/true).is_empty()); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, GetIconFlagDisabledOfficialBuild) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{}, |
| /*disabled_features=*/{::features::kIsNameEnabled}); |
| |
| EXPECT_TRUE(delegate_->GetIcon(/*on_icon=*/false).is_empty()); |
| EXPECT_TRUE(delegate_->GetIcon(/*on_icon=*/true).is_empty()); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, |
| GetPlaceholderFeatureNameFlagEnabledOfficialBuild) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{::features::kIsNameEnabled}, |
| /*disabled_features=*/{}); |
| |
| // Just enforce non empty string for official branded builds.. |
| EXPECT_NE(delegate_->GetPlaceholderFeatureName(), u""); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, |
| GetPlaceholderFeatureNameFlagDisabledOfficialBuild) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{}, |
| /*disabled_features=*/{::features::kIsNameEnabled}); |
| |
| // Returns empty string when feature is disabled or on unofficial build. |
| EXPECT_EQ(delegate_->GetPlaceholderFeatureName(), u""); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, SetVisibility) { |
| settings()->SetEnabled(true); |
| EXPECT_EQ(settings()->GetVisibility(), |
| ::nearby_share::mojom::Visibility::kNoOne); |
| delegate_->SetVisibility(::nearby_share::mojom::Visibility::kAllContacts); |
| EXPECT_CALL(controller_, VisibilityChanged( |
| ::nearby_share::mojom::Visibility::kAllContacts)) |
| .Times(0); |
| EXPECT_EQ(settings()->GetVisibility(), |
| ::nearby_share::mojom::Visibility::kAllContacts); |
| } |
| #else // !BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| TEST_F(NearbyShareDelegateImplTest, GetIconFlagEnabledUnofficialBuild) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{::features::kIsNameEnabled}, |
| /*disabled_features=*/{}); |
| |
| EXPECT_TRUE(delegate_->GetIcon(/*on_icon=*/false).is_empty()); |
| EXPECT_TRUE(delegate_->GetIcon(/*on_icon=*/true).is_empty()); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, GetIconFlagDisabledUnofficialBuild) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{}, |
| /*disabled_features=*/{::features::kIsNameEnabled}); |
| |
| EXPECT_TRUE(delegate_->GetIcon(/*on_icon=*/false).is_empty()); |
| EXPECT_TRUE(delegate_->GetIcon(/*on_icon=*/true).is_empty()); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, |
| GetPlaceholderFeatureNameFlagEnabledUnofficialBuild) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{::features::kIsNameEnabled}, |
| /*disabled_features=*/{}); |
| |
| // Returns empty string when feature is disabled or on unofficial build. |
| EXPECT_EQ(delegate_->GetPlaceholderFeatureName(), u""); |
| } |
| |
| TEST_F(NearbyShareDelegateImplTest, |
| GetPlaceholderFeatureNameFlagDisabledUnofficialBuild) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitWithFeatures( |
| /*enabled_features=*/{}, |
| /*disabled_features=*/{::features::kIsNameEnabled}); |
| |
| // Returns empty string when feature is disabled or on unofficial build. |
| EXPECT_EQ(delegate_->GetPlaceholderFeatureName(), u""); |
| } |
| #endif // !BUILDFLAG(GOOGLE_CHROME_BRANDING) |