| // 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_settings.h" |
| |
| #include <memory> |
| |
| #include "base/containers/contains.h" |
| #include "base/feature_list.h" |
| #include "base/run_loop.h" |
| #include "base/test/bind.h" |
| #include "base/test/scoped_feature_list.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/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "chromeos/ash/services/nearby/public/mojom/nearby_share_settings.mojom-test-utils.h" |
| #include "chromeos/ash/services/nearby/public/mojom/nearby_share_settings.mojom.h" |
| #include "chromeos/constants/chromeos_features.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "content/public/test/test_utils.h" |
| #include "mojo/public/cpp/bindings/pending_receiver.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| const char kDefaultDeviceName[] = "Josh's Chromebook"; |
| |
| } // namespace |
| |
| using NearbyShareSettingsAsyncWaiter = |
| nearby_share::mojom::NearbyShareSettingsAsyncWaiter; |
| |
| class FakeNearbyShareSettingsObserver |
| : public nearby_share::mojom::NearbyShareSettingsObserver { |
| public: |
| void OnEnabledChanged(bool enabled) override { enabled_ = enabled; } |
| void OnFastInitiationNotificationStateChanged( |
| nearby_share::mojom::FastInitiationNotificationState state) override { |
| fast_initiation_notification_state_ = state; |
| } |
| void OnIsFastInitiationHardwareSupportedChanged(bool is_supported) override { |
| is_fast_initiation_notification_hardware_supported_ = is_supported; |
| } |
| void OnDeviceNameChanged(const std::string& device_name) override { |
| device_name_ = device_name; |
| } |
| void OnDataUsageChanged(nearby_share::mojom::DataUsage data_usage) override { |
| data_usage_ = data_usage; |
| } |
| void OnVisibilityChanged( |
| nearby_share::mojom::Visibility visibility) override { |
| visibility_ = visibility; |
| } |
| void OnAllowedContactsChanged( |
| const std::vector<std::string>& allowed_contacts) override { |
| allowed_contacts_ = allowed_contacts; |
| } |
| void OnIsOnboardingCompleteChanged(bool is_complete) override { |
| is_onboarding_complete_ = is_complete; |
| } |
| |
| bool enabled_ = false; |
| nearby_share::mojom::FastInitiationNotificationState |
| fast_initiation_notification_state_ = |
| nearby_share::mojom::FastInitiationNotificationState::kEnabled; |
| bool is_fast_initiation_notification_hardware_supported_ = false; |
| bool is_onboarding_complete_ = false; |
| std::string device_name_ = "uncalled"; |
| nearby_share::mojom::DataUsage data_usage_ = |
| nearby_share::mojom::DataUsage::kUnknown; |
| nearby_share::mojom::Visibility visibility_ = |
| nearby_share::mojom::Visibility::kUnknown; |
| std::vector<std::string> allowed_contacts_; |
| mojo::Receiver<nearby_share::mojom::NearbyShareSettingsObserver> receiver_{ |
| this}; |
| }; |
| |
| class NearbyShareSettingsTest : public ::testing::Test { |
| public: |
| NearbyShareSettingsTest() : local_device_data_manager_(kDefaultDeviceName) { |
| RegisterNearbySharingPrefs(pref_service_.registry()); |
| nearby_share_settings_ = std::make_unique<NearbyShareSettings>( |
| &pref_service_, &local_device_data_manager_); |
| nearby_share_settings_waiter_ = |
| std::make_unique<NearbyShareSettingsAsyncWaiter>( |
| nearby_share_settings_.get()); |
| |
| nearby_share_settings_->AddSettingsObserver( |
| observer_.receiver_.BindNewPipeAndPassRemote()); |
| } |
| ~NearbyShareSettingsTest() override = default; |
| |
| void FlushMojoMessages() { observer_.receiver_.FlushForTesting(); } |
| |
| NearbyShareSettings* settings() { return nearby_share_settings_.get(); } |
| |
| NearbyShareSettingsAsyncWaiter* settings_waiter() { |
| return nearby_share_settings_waiter_.get(); |
| } |
| |
| void SetIsOnboardingComplete(bool is_complete) { |
| pref_service_.SetBoolean(prefs::kNearbySharingOnboardingCompletePrefName, |
| is_complete); |
| } |
| |
| protected: |
| content::BrowserTaskEnvironment task_environment_; |
| TestingPrefServiceSimple pref_service_; |
| FakeNearbyShareLocalDeviceDataManager local_device_data_manager_; |
| FakeNearbyShareSettingsObserver observer_; |
| std::unique_ptr<NearbyShareSettings> nearby_share_settings_; |
| std::unique_ptr<NearbyShareSettingsAsyncWaiter> nearby_share_settings_waiter_; |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| TEST_F(NearbyShareSettingsTest, GetAndSetEnabled) { |
| EXPECT_FALSE(observer_.enabled_); |
| settings()->SetIsOnboardingComplete(true); |
| settings()->SetEnabled(true); |
| EXPECT_TRUE(settings()->GetEnabled()); |
| FlushMojoMessages(); |
| EXPECT_TRUE(observer_.enabled_); |
| |
| bool enabled = false; |
| settings_waiter()->GetEnabled(&enabled); |
| EXPECT_TRUE(enabled); |
| |
| settings()->SetEnabled(false); |
| EXPECT_FALSE(settings()->GetEnabled()); |
| FlushMojoMessages(); |
| EXPECT_FALSE(observer_.enabled_); |
| |
| settings_waiter()->GetEnabled(&enabled); |
| EXPECT_FALSE(enabled); |
| |
| // Verify that setting the value to false again value doesn't trigger an |
| // observer event. |
| observer_.enabled_ = true; |
| settings()->SetEnabled(false); |
| EXPECT_FALSE(settings()->GetEnabled()); |
| FlushMojoMessages(); |
| // the observers's value should not have been updated. |
| EXPECT_TRUE(observer_.enabled_); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, GetAndSetFastInitiationNotificationState) { |
| // Fast init notifications are enabled by default. |
| EXPECT_EQ(nearby_share::mojom::FastInitiationNotificationState::kEnabled, |
| observer_.fast_initiation_notification_state_); |
| settings()->SetFastInitiationNotificationState( |
| nearby_share::mojom::FastInitiationNotificationState::kDisabledByUser); |
| EXPECT_EQ( |
| nearby_share::mojom::FastInitiationNotificationState::kDisabledByUser, |
| settings()->GetFastInitiationNotificationState()); |
| FlushMojoMessages(); |
| EXPECT_EQ( |
| nearby_share::mojom::FastInitiationNotificationState::kDisabledByUser, |
| observer_.fast_initiation_notification_state_); |
| |
| nearby_share::mojom::FastInitiationNotificationState state = |
| nearby_share::mojom::FastInitiationNotificationState::kEnabled; |
| settings_waiter()->GetFastInitiationNotificationState(&state); |
| EXPECT_EQ( |
| nearby_share::mojom::FastInitiationNotificationState::kDisabledByUser, |
| state); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, |
| ParentFeatureChangesFastInitiationNotificationState) { |
| // Fast init notifications are enabled by default. |
| EXPECT_EQ(nearby_share::mojom::FastInitiationNotificationState::kEnabled, |
| observer_.fast_initiation_notification_state_); |
| settings()->SetIsOnboardingComplete(true); |
| settings()->SetEnabled(true); |
| FlushMojoMessages(); |
| |
| // Simulate toggling the parent feature off. |
| settings()->SetEnabled(false); |
| FlushMojoMessages(); |
| EXPECT_FALSE(settings()->GetEnabled()); |
| EXPECT_EQ( |
| nearby_share::mojom::FastInitiationNotificationState::kDisabledByFeature, |
| observer_.fast_initiation_notification_state_); |
| |
| // Simulate toggling the parent feature on. |
| settings()->SetEnabled(true); |
| FlushMojoMessages(); |
| EXPECT_TRUE(settings()->GetEnabled()); |
| EXPECT_EQ(nearby_share::mojom::FastInitiationNotificationState::kEnabled, |
| observer_.fast_initiation_notification_state_); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, |
| ParentFeatureChangesFastInitiationNotificationDisabedByUser) { |
| // Fast init notifications are enabled by default. |
| EXPECT_EQ(nearby_share::mojom::FastInitiationNotificationState::kEnabled, |
| observer_.fast_initiation_notification_state_); |
| |
| // Set explicitly disabled by user. |
| settings()->SetFastInitiationNotificationState( |
| nearby_share::mojom::FastInitiationNotificationState::kDisabledByUser); |
| FlushMojoMessages(); |
| EXPECT_EQ( |
| nearby_share::mojom::FastInitiationNotificationState::kDisabledByUser, |
| observer_.fast_initiation_notification_state_); |
| |
| // Simulate toggling parent feature on. |
| settings()->SetIsOnboardingComplete(true); |
| settings()->SetEnabled(true); |
| FlushMojoMessages(); |
| |
| // Disabled by user should persist if parent feature was turned on. |
| EXPECT_EQ( |
| nearby_share::mojom::FastInitiationNotificationState::kDisabledByUser, |
| observer_.fast_initiation_notification_state_); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, GetAndSetIsOnboardingComplete) { |
| EXPECT_FALSE(observer_.is_onboarding_complete_); |
| SetIsOnboardingComplete(true); |
| EXPECT_TRUE(settings()->IsOnboardingComplete()); |
| FlushMojoMessages(); |
| EXPECT_TRUE(observer_.is_onboarding_complete_); |
| |
| bool is_complete = false; |
| settings_waiter()->IsOnboardingComplete(&is_complete); |
| EXPECT_TRUE(is_complete); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, GetAndSetIsFastInitiationHardwareSupported) { |
| EXPECT_FALSE(observer_.is_fast_initiation_notification_hardware_supported_); |
| settings()->SetIsFastInitiationHardwareSupported(true); |
| |
| FlushMojoMessages(); |
| EXPECT_TRUE(observer_.is_fast_initiation_notification_hardware_supported_); |
| |
| bool is_supported = false; |
| settings_waiter()->GetIsFastInitiationHardwareSupported(&is_supported); |
| EXPECT_TRUE(is_supported); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, ValidateDeviceName) { |
| auto result = nearby_share::mojom::DeviceNameValidationResult::kValid; |
| local_device_data_manager_.set_next_validation_result( |
| nearby_share::mojom::DeviceNameValidationResult::kErrorEmpty); |
| settings_waiter()->ValidateDeviceName("", &result); |
| EXPECT_EQ(result, |
| nearby_share::mojom::DeviceNameValidationResult::kErrorEmpty); |
| |
| local_device_data_manager_.set_next_validation_result( |
| nearby_share::mojom::DeviceNameValidationResult::kValid); |
| settings_waiter()->ValidateDeviceName("this string is 32 bytes in UTF-8", |
| &result); |
| EXPECT_EQ(result, nearby_share::mojom::DeviceNameValidationResult::kValid); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, GetAndSetDeviceName) { |
| std::string name = "not_the_default"; |
| settings_waiter()->GetDeviceName(&name); |
| EXPECT_EQ(kDefaultDeviceName, name); |
| |
| // When we get a validation error, setting the name should not succeed. |
| EXPECT_EQ("uncalled", observer_.device_name_); |
| auto result = nearby_share::mojom::DeviceNameValidationResult::kValid; |
| local_device_data_manager_.set_next_validation_result( |
| nearby_share::mojom::DeviceNameValidationResult::kErrorEmpty); |
| settings_waiter()->SetDeviceName("", &result); |
| EXPECT_EQ(result, |
| nearby_share::mojom::DeviceNameValidationResult::kErrorEmpty); |
| EXPECT_EQ(kDefaultDeviceName, settings()->GetDeviceName()); |
| |
| // When the name is valid, setting should succeed. |
| EXPECT_EQ("uncalled", observer_.device_name_); |
| result = nearby_share::mojom::DeviceNameValidationResult::kValid; |
| local_device_data_manager_.set_next_validation_result( |
| nearby_share::mojom::DeviceNameValidationResult::kValid); |
| settings_waiter()->SetDeviceName("d", &result); |
| EXPECT_EQ(result, nearby_share::mojom::DeviceNameValidationResult::kValid); |
| EXPECT_EQ("d", settings()->GetDeviceName()); |
| |
| EXPECT_EQ("uncalled", observer_.device_name_); |
| FlushMojoMessages(); |
| EXPECT_EQ("d", observer_.device_name_); |
| |
| settings_waiter()->GetDeviceName(&name); |
| EXPECT_EQ("d", name); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, GetAndSetDataUsage) { |
| EXPECT_EQ(nearby_share::mojom::DataUsage::kUnknown, observer_.data_usage_); |
| settings()->SetDataUsage(nearby_share::mojom::DataUsage::kOffline); |
| EXPECT_EQ(nearby_share::mojom::DataUsage::kOffline, |
| settings()->GetDataUsage()); |
| FlushMojoMessages(); |
| EXPECT_EQ(nearby_share::mojom::DataUsage::kOffline, observer_.data_usage_); |
| |
| nearby_share::mojom::DataUsage data_usage = |
| nearby_share::mojom::DataUsage::kUnknown; |
| settings_waiter()->GetDataUsage(&data_usage); |
| EXPECT_EQ(nearby_share::mojom::DataUsage::kOffline, data_usage); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, GetAndSetVisibility) { |
| EXPECT_EQ(nearby_share::mojom::Visibility::kUnknown, observer_.visibility_); |
| settings()->SetVisibility(nearby_share::mojom::Visibility::kNoOne); |
| EXPECT_EQ(nearby_share::mojom::Visibility::kNoOne, |
| settings()->GetVisibility()); |
| FlushMojoMessages(); |
| EXPECT_EQ(nearby_share::mojom::Visibility::kNoOne, observer_.visibility_); |
| |
| nearby_share::mojom::Visibility visibility = |
| nearby_share::mojom::Visibility::kUnknown; |
| settings_waiter()->GetVisibility(&visibility); |
| EXPECT_EQ(nearby_share::mojom::Visibility::kNoOne, visibility); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, GetAndSetAllowedContacts) { |
| const std::string id1("1"); |
| |
| std::vector<std::string> allowed_contacts; |
| |
| settings_waiter()->GetAllowedContacts(&allowed_contacts); |
| EXPECT_EQ(0u, allowed_contacts.size()); |
| |
| settings()->SetAllowedContacts({id1}); |
| FlushMojoMessages(); |
| EXPECT_EQ(1u, observer_.allowed_contacts_.size()); |
| EXPECT_TRUE(base::Contains(observer_.allowed_contacts_, id1)); |
| |
| settings_waiter()->GetAllowedContacts(&allowed_contacts); |
| EXPECT_EQ(1u, allowed_contacts.size()); |
| EXPECT_TRUE(base::Contains(allowed_contacts, id1)); |
| |
| settings()->SetAllowedContacts({}); |
| FlushMojoMessages(); |
| EXPECT_EQ(0u, observer_.allowed_contacts_.size()); |
| |
| settings_waiter()->GetAllowedContacts(&allowed_contacts); |
| EXPECT_EQ(0u, allowed_contacts.size()); |
| } |
| |
| TEST_F(NearbyShareSettingsTest, QuickShareV2_SomeContacts_ToYourDevices) { |
| feature_list_.InitAndEnableFeature(chromeos::features::kQuickShareV2); |
| pref_service_.SetInteger( |
| prefs::kNearbySharingBackgroundVisibilityName, |
| static_cast<int>(nearby_share::mojom::Visibility::kSelectedContacts)); |
| |
| // Since some contacts -> your devices occurs in constructor, new |
| // NearbyShareSettings object must be created after QuickShareV2 is enabled. |
| NearbyShareSettings nearby_share_settings(&pref_service_, |
| &local_device_data_manager_); |
| |
| EXPECT_EQ(nearby_share_settings.GetVisibility(), |
| nearby_share::mojom::Visibility::kYourDevices); |
| } |