chromium/components/sync_preferences/pref_service_syncable_unittest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/sync_preferences/pref_service_syncable.h"

#include <stdint.h>

#include <memory>

#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_string_value_serializer.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/chromeos_buildflags.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_notifier_impl.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_store.h"
#include "components/sync/base/client_tag_hash.h"
#include "components/sync/base/data_type.h"
#include "components/sync/base/features.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/model/sync_change_processor.h"
#include "components/sync/model/sync_data.h"
#include "components/sync/model/syncable_service.h"
#include "components/sync/protocol/entity_specifics.pb.h"
#include "components/sync/protocol/preference_specifics.pb.h"
#include "components/sync_preferences/pref_model_associator.h"
#include "components/sync_preferences/pref_model_associator_client.h"
#include "components/sync_preferences/pref_service_syncable_factory.h"
#include "components/sync_preferences/pref_service_syncable_observer.h"
#include "components/sync_preferences/syncable_prefs_database.h"
#include "components/sync_preferences/synced_pref_observer.h"
#include "components/sync_preferences/test_syncable_prefs_database.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "testing/gmock/include/gmock/gmock-matchers.h"
#endif

DataType;
DataTypeSet;
SyncChange;
SyncData;
Eq;
IsEmpty;
Matches;
NotNull;
UnorderedElementsAre;
PrefRegistrySyncable;

namespace sync_preferences {

namespace {

const char kExampleUrl0[] =;
const char kExampleUrl1[] =;
const char kExampleUrl2[] =;
const char kStringPrefName[] =;
const char kListPrefName[] =;
const char kMergeableListPrefName[] =;
const char kMergeableDictPrefName[] =;
const char kUnsyncedPreferenceName[] =;
const char kUnsyncedPreferenceDefaultValue[] =;
const char kDefaultCharsetPrefName[] =;
const char kNonDefaultCharsetValue[] =;
const char kDefaultCharsetValue[] =;
const char kBrowserPrefName[] =;
const char kBrowserPriorityPrefName[] =;
#if BUILDFLAG(IS_CHROMEOS_ASH)
const char kOsPrefName[] = "os_pref";
const char kOsPriorityPrefName[] = "os_priority_pref";
#endif

// Assigning an id of 0 to all the test prefs.
const TestSyncablePrefsDatabase::PrefsMap kSyncablePrefsDatabase =;

// Searches for a preference matching `name` and, if specified,`change_type`,
// within `list`. Returns the value of the first matching pref, or nullopt if
// none is found.
std::optional<base::Value> FindValue(
    const std::string& name,
    const syncer::SyncChangeList& list,
    std::optional<syncer::SyncChange::SyncChangeType> change_type =
        std::nullopt) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
constexpr DataTypeSet kAllPreferenceDataTypes = {
    syncer::PREFERENCES, syncer::PRIORITY_PREFERENCES, syncer::OS_PREFERENCES,
    syncer::OS_PRIORITY_PREFERENCES};

MATCHER_P(MatchesDataType, data_type, "") {
  const syncer::SyncChange& sync_change = arg;
  return Matches(data_type)(sync_change.sync_data().GetDataType());
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

class TestSyncProcessorStub : public syncer::SyncChangeProcessor {};

class TestSyncedPrefObserver : public SyncedPrefObserver {};

class TestPrefServiceSyncableObserver : public PrefServiceSyncableObserver {};

syncer::SyncChange MakeRemoteChange(const std::string& name,
                                    base::ValueView value,
                                    SyncChange::SyncChangeType change_type,
                                    syncer::DataType data_type) {}

// Creates a SyncChange for data type |PREFERENCES|.
syncer::SyncChange MakeRemoteChange(const std::string& name,
                                    base::ValueView value,
                                    SyncChange::SyncChangeType type) {}

// Creates SyncData for a remote pref change.
SyncData CreateRemoteSyncData(const std::string& name, base::ValueView value) {}

class PrefServiceSyncableTest : public testing::Test {};

TEST_F(PrefServiceSyncableTest, CreatePrefSyncData) {}

TEST_F(PrefServiceSyncableTest, ModelAssociationDoNotSyncDefaults) {}

TEST_F(PrefServiceSyncableTest, ModelAssociationEmptyCloud) {}

TEST_F(PrefServiceSyncableTest, ModelAssociationCloudHasData) {}

// Verifies that the implementation gracefully handles an initial remote sync
// data of wrong type. The local version should not get modified in these cases.
TEST_F(PrefServiceSyncableTest, ModelAssociationWithDataTypeMismatch) {}

class TestPrefModelAssociatorClient : public PrefModelAssociatorClient {};

class PrefServiceSyncableMergeTest : public testing::Test {};

TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedListValues) {}

// List preferences have special handling at association time due to our ability
// to merge the local and sync value. Make sure the merge logic doesn't merge
// managed preferences.
TEST_F(PrefServiceSyncableMergeTest, ManagedListPreferences) {}

TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedDictionaryValues) {}

// TODO(jamescook): In production all prefs are registered before the
// PrefServiceSyncable is created. This test should do the same.
TEST_F(PrefServiceSyncableMergeTest, KeepPriorityPreferencesSeparately) {}

TEST_F(PrefServiceSyncableMergeTest, ShouldIgnoreUpdatesToNotSyncablePrefs) {}

TEST_F(PrefServiceSyncableTest, FailModelAssociation) {}

TEST_F(PrefServiceSyncableTest, UpdatedPreferenceWithDefaultValue) {}

TEST_F(PrefServiceSyncableTest, UpdatedPreferenceWithValue) {}

TEST_F(PrefServiceSyncableTest, AddAndUpdatePreference) {}

TEST_F(PrefServiceSyncableTest, StopAndRestartSync) {}

TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionUpdate) {}

// Verifies that the implementation gracefully handles a remote update with the
// wrong type. The local version should not get modified in these cases.
TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionUpdateTypeMismatch) {}

TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeActionAdd) {}

TEST_F(PrefServiceSyncableTest, UpdatedSyncNodeUnknownPreference) {}

TEST_F(PrefServiceSyncableTest, ManagedPreferences) {}

TEST_F(PrefServiceSyncableTest, DynamicManagedPreferences) {}

TEST_F(PrefServiceSyncableTest, DynamicManagedPreferencesWithSyncChange) {}

TEST_F(PrefServiceSyncableTest, DynamicManagedDefaultPreferences) {}

TEST_F(PrefServiceSyncableTest, DeletePreference) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
// The Chrome OS tests exercise pref model association that happens in the
// constructor of PrefServiceSyncable. The tests must register prefs first,
// then create the PrefServiceSyncable object. The tests live in this file
// because they share utility code with the cross-platform tests.
class PrefServiceSyncableChromeOsTest : public testing::Test {
 public:
  PrefServiceSyncableChromeOsTest()
      : pref_registry_(base::MakeRefCounted<PrefRegistrySyncable>()),
        pref_notifier_(new PrefNotifierImpl),
        user_prefs_(base::MakeRefCounted<TestingPrefStore>()),
        standalone_browser_prefs_(base::MakeRefCounted<TestingPrefStore>()),
        managed_prefs_(base::MakeRefCounted<TestingPrefStore>()),
        supervised_user_prefs_(base::MakeRefCounted<TestingPrefStore>()),
        extension_prefs_(base::MakeRefCounted<TestingPrefStore>()),
        command_line_prefs_(base::MakeRefCounted<TestingPrefStore>()),
        recommended_prefs_(base::MakeRefCounted<TestingPrefStore>()),
        client_(base::MakeRefCounted<TestPrefModelAssociatorClient>()) {}

  void CreatePrefService() {
    // Register prefs of various types.
    pref_registry_->RegisterStringPref(kUnsyncedPreferenceName, std::string());
    pref_registry_->RegisterStringPref(kBrowserPrefName, std::string(),
                                       PrefRegistrySyncable::SYNCABLE_PREF);
    pref_registry_->RegisterStringPref(
        kBrowserPriorityPrefName, std::string(),
        PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
    pref_registry_->RegisterStringPref(kOsPrefName, std::string(),
                                       PrefRegistrySyncable::SYNCABLE_OS_PREF);
    pref_registry_->RegisterStringPref(
        kOsPriorityPrefName, std::string(),
        PrefRegistrySyncable::SYNCABLE_OS_PRIORITY_PREF);

    // Create the PrefServiceSyncable after prefs are registered, which is the
    // order used in production.
    prefs_ = std::make_unique<PrefServiceSyncable>(
        std::unique_ptr<PrefNotifierImpl>(pref_notifier_),
        std::make_unique<PrefValueStore>(
            managed_prefs_.get(), supervised_user_prefs_.get(),
            extension_prefs_.get(), standalone_browser_prefs_.get(),
            command_line_prefs_.get(), user_prefs_.get(),
            recommended_prefs_.get(), pref_registry_->defaults().get(),
            pref_notifier_),
        user_prefs_, standalone_browser_prefs_, pref_registry_, client_,
        /*read_error_callback=*/base::DoNothing(),
        /*async=*/false);
  }

  void InitSyncForType(DataType type) {
    syncer::SyncDataList empty_data;
    std::optional<syncer::ModelError> error =
        prefs_->GetSyncableService(type)->MergeDataAndStartSyncing(
            type, empty_data, std::make_unique<TestSyncProcessorStub>(nullptr));
    EXPECT_FALSE(error.has_value());
  }

  void InitSyncForAllTypes() {
    for (DataType type : kAllPreferenceDataTypes) {
      InitSyncForType(type);
    }
  }

  DataTypeSet GetRegisteredDataTypes(const std::string& pref_name) {
    DataTypeSet registered_types;
    for (DataType type : kAllPreferenceDataTypes) {
      if (static_cast<PrefModelAssociator*>(prefs_->GetSyncableService(type))
              ->IsPrefRegistered(pref_name)) {
        registered_types.Put(type);
      }
    }
    return registered_types;
  }

  SyncData MakeRemoteSyncData(const std::string& name,
                              base::ValueView value,
                              syncer::DataType data_type) {
    std::string serialized;
    JSONStringValueSerializer json(&serialized);
    EXPECT_TRUE(json.Serialize(value));
    sync_pb::EntitySpecifics entity;
    sync_pb::PreferenceSpecifics* pref =
        PrefModelAssociator::GetMutableSpecifics(data_type, &entity);
    pref->set_name(name);
    pref->set_value(serialized);
    return SyncData::CreateRemoteData(
        entity, syncer::ClientTagHash::FromUnhashed(data_type, name));
  }

 protected:
  scoped_refptr<PrefRegistrySyncable> pref_registry_;
  raw_ptr<PrefNotifierImpl, DanglingUntriaged>
      pref_notifier_;  // Owned by |prefs_|.
  scoped_refptr<TestingPrefStore> user_prefs_;
  scoped_refptr<TestingPrefStore> standalone_browser_prefs_;
  scoped_refptr<TestingPrefStore> managed_prefs_;
  scoped_refptr<TestingPrefStore> supervised_user_prefs_;
  scoped_refptr<TestingPrefStore> extension_prefs_;
  scoped_refptr<TestingPrefStore> command_line_prefs_;
  scoped_refptr<TestingPrefStore> recommended_prefs_;
  scoped_refptr<TestPrefModelAssociatorClient> client_;
  std::unique_ptr<PrefServiceSyncable> prefs_;
};

TEST_F(PrefServiceSyncableChromeOsTest, IsPrefRegistered) {
  CreatePrefService();
  EXPECT_TRUE(GetRegisteredDataTypes(kUnsyncedPreferenceName).empty());
  EXPECT_EQ(DataTypeSet({syncer::PREFERENCES}),
            GetRegisteredDataTypes(kBrowserPrefName));
  EXPECT_EQ(DataTypeSet({syncer::PRIORITY_PREFERENCES}),
            GetRegisteredDataTypes(kBrowserPriorityPrefName));
  EXPECT_EQ(DataTypeSet({syncer::OS_PREFERENCES}),
            GetRegisteredDataTypes(kOsPrefName));
  EXPECT_EQ(DataTypeSet({syncer::OS_PRIORITY_PREFERENCES}),
            GetRegisteredDataTypes(kOsPriorityPrefName));
}

TEST_F(PrefServiceSyncableChromeOsTest, IsSyncing) {
  CreatePrefService();
  InitSyncForType(syncer::PREFERENCES);
  EXPECT_TRUE(prefs_->IsSyncing());
  EXPECT_FALSE(prefs_->IsPrioritySyncing());
  EXPECT_FALSE(prefs_->AreOsPrefsSyncing());
  EXPECT_FALSE(prefs_->AreOsPriorityPrefsSyncing());
}

TEST_F(PrefServiceSyncableChromeOsTest, IsPrioritySyncing) {
  CreatePrefService();
  InitSyncForType(syncer::PRIORITY_PREFERENCES);
  EXPECT_FALSE(prefs_->IsSyncing());
  EXPECT_TRUE(prefs_->IsPrioritySyncing());
  EXPECT_FALSE(prefs_->AreOsPrefsSyncing());
  EXPECT_FALSE(prefs_->AreOsPriorityPrefsSyncing());
}

TEST_F(PrefServiceSyncableChromeOsTest, AreOsPrefsSyncing) {
  CreatePrefService();
  InitSyncForType(syncer::OS_PREFERENCES);
  EXPECT_FALSE(prefs_->IsSyncing());
  EXPECT_FALSE(prefs_->IsPrioritySyncing());
  EXPECT_TRUE(prefs_->AreOsPrefsSyncing());
  EXPECT_FALSE(prefs_->AreOsPriorityPrefsSyncing());
}

TEST_F(PrefServiceSyncableChromeOsTest, AreOsPriorityPrefsSyncing) {
  CreatePrefService();
  InitSyncForType(syncer::OS_PRIORITY_PREFERENCES);
  EXPECT_FALSE(prefs_->IsSyncing());
  EXPECT_FALSE(prefs_->IsPrioritySyncing());
  EXPECT_FALSE(prefs_->AreOsPrefsSyncing());
  EXPECT_TRUE(prefs_->AreOsPriorityPrefsSyncing());
}

TEST_F(PrefServiceSyncableChromeOsTest, IsPrefSynced_OsPref) {
  CreatePrefService();
  InitSyncForAllTypes();
  auto* associator = static_cast<PrefModelAssociator*>(
      prefs_->GetSyncableService(syncer::OS_PREFERENCES));
  EXPECT_FALSE(associator->IsPrefSyncedForTesting(kOsPrefName));

  syncer::SyncChangeList list;
  list.push_back(MakeRemoteChange(kOsPrefName, base::Value("value"),
                                  SyncChange::ACTION_ADD,
                                  syncer::OS_PREFERENCES));
  associator->ProcessSyncChanges(FROM_HERE, list);
  EXPECT_TRUE(associator->IsPrefSyncedForTesting(kOsPrefName));
}

TEST_F(PrefServiceSyncableChromeOsTest, IsPrefSynced_OsPriorityPref) {
  CreatePrefService();
  InitSyncForAllTypes();
  auto* associator = static_cast<PrefModelAssociator*>(
      prefs_->GetSyncableService(syncer::OS_PRIORITY_PREFERENCES));
  EXPECT_FALSE(associator->IsPrefSyncedForTesting(kOsPriorityPrefName));

  syncer::SyncChangeList list;
  list.push_back(MakeRemoteChange(kOsPriorityPrefName, base::Value("value"),
                                  SyncChange::ACTION_ADD,
                                  syncer::OS_PRIORITY_PREFERENCES));
  associator->ProcessSyncChanges(FROM_HERE, list);
  EXPECT_TRUE(associator->IsPrefSyncedForTesting(kOsPriorityPrefName));
}

TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_OsPref) {
  CreatePrefService();
  InitSyncForAllTypes();

  TestSyncedPrefObserver observer;
  prefs_->AddSyncedPrefObserver(kOsPrefName, &observer);

  prefs_->SetString(kOsPrefName, "value");
  EXPECT_EQ(kOsPrefName, observer.last_pref_);
  EXPECT_EQ(1, observer.changed_count_);

  prefs_->RemoveSyncedPrefObserver(kOsPrefName, &observer);
}

TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_OsPriorityPref) {
  CreatePrefService();
  InitSyncForAllTypes();

  TestSyncedPrefObserver observer;
  prefs_->AddSyncedPrefObserver(kOsPriorityPrefName, &observer);

  prefs_->SetString(kOsPriorityPrefName, "value");
  EXPECT_EQ(kOsPriorityPrefName, observer.last_pref_);
  EXPECT_EQ(1, observer.changed_count_);

  prefs_->RemoveSyncedPrefObserver(kOsPriorityPrefName, &observer);
}

TEST_F(PrefServiceSyncableChromeOsTest,
       UpdatesFromOldClientsAreIgnored_Startup) {
  CreatePrefService();
  TestSyncedPrefObserver observer;
  prefs_->AddSyncedPrefObserver(kOsPrefName, &observer);

  // Simulate an old client that has `kOsPrefName` registered as SYNCABLE_PREF
  // instead of SYNCABLE_OS_PREF.
  syncer::SyncDataList list;
  list.push_back(CreateRemoteSyncData(kOsPrefName, base::Value("new_value")));

  // Simulate the first sync at startup of the legacy browser prefs DataType.
  auto* browser_associator = static_cast<PrefModelAssociator*>(
      prefs_->GetSyncableService(syncer::PREFERENCES));
  syncer::SyncChangeList outgoing_changes;
  browser_associator->MergeDataAndStartSyncing(
      syncer::PREFERENCES, list,
      std::make_unique<TestSyncProcessorStub>(&outgoing_changes));

  // No outgoing changes were triggered.
  EXPECT_TRUE(outgoing_changes.empty());

  // The value from the old client was not applied.
  EXPECT_NE("new_value", prefs_->GetString(kOsPrefName));

  // The pref is not considered to be syncing, because it still has its default
  // value.
  EXPECT_FALSE(browser_associator->IsPrefSyncedForTesting(kOsPrefName));

  // Observers were not notified of changes.
  EXPECT_EQ(0, observer.changed_count_);

  prefs_->RemoveSyncedPrefObserver(kOsPrefName, &observer);
}

TEST_F(PrefServiceSyncableChromeOsTest,
       UpdatesFromOldClientsAreIgnored_Update) {
  CreatePrefService();
  InitSyncForAllTypes();
  TestSyncedPrefObserver observer;
  prefs_->AddSyncedPrefObserver(kOsPrefName, &observer);

  syncer::SyncChangeList list;
  // Simulate an old client that has `kOsPrefName` registered as SYNCABLE_PREF
  // instead of SYNCABLE_OS_PREF.
  list.push_back(MakeRemoteChange(kOsPrefName, base::Value("new_value"),
                                  SyncChange::ACTION_ADD, syncer::PREFERENCES));

  // Simulate a sync update after startup.
  prefs_->GetSyncableService(syncer::PREFERENCES)
      ->ProcessSyncChanges(FROM_HERE, list);

  // Update was not applied.
  EXPECT_NE("new_value", prefs_->GetString(kOsPrefName));

  // Observers were not notified of changes.
  EXPECT_EQ(0, observer.changed_count_);

  prefs_->RemoveSyncedPrefObserver(kOsPrefName, &observer);
}

TEST_F(PrefServiceSyncableChromeOsTest,
       SyncedPrefObserver_OsPrefIsChangedFromSync) {
  CreatePrefService();
  prefs_->SetString(kOsPrefName, "default_value");

  TestSyncedPrefObserver observer;
  prefs_->AddSyncedPrefObserver(kOsPrefName, &observer);

  TestPrefServiceSyncableObserver pref_service_sync_observer;
  pref_service_sync_observer.SetSyncedPrefObserver(&observer);
  prefs_->AddObserver(&pref_service_sync_observer);

  // Simulate that `kOsPrefName` is registered as SYNCABLE_PREF
  syncer::SyncDataList list;
  list.push_back(MakeRemoteSyncData(kOsPrefName, base::Value("new_value"),
                                    syncer::OS_PREFERENCES));

  // Simulate the first sync at startup.
  syncer::SyncChangeList outgoing_changes;
  prefs_->GetSyncableService(syncer::OS_PREFERENCES)
      ->MergeDataAndStartSyncing(
          syncer::OS_PREFERENCES, list,
          std::make_unique<TestSyncProcessorStub>(&outgoing_changes));

  EXPECT_EQ(kOsPrefName, observer.synced_pref_);
  EXPECT_EQ(1, observer.sync_started_count_);
  EXPECT_TRUE(pref_service_sync_observer.is_syncing_changed());

  prefs_->RemoveObserver(&pref_service_sync_observer);
  prefs_->RemoveSyncedPrefObserver(kOsPrefName, &observer);
}

TEST_F(PrefServiceSyncableChromeOsTest,
       SyncedPrefObserver_OsPrefIsNotChangedFromSync) {
  CreatePrefService();
  prefs_->SetString(kOsPrefName, "default_value");

  TestSyncedPrefObserver observer;
  prefs_->AddSyncedPrefObserver(kOsPrefName, &observer);

  TestPrefServiceSyncableObserver pref_service_sync_observer;
  pref_service_sync_observer.SetSyncedPrefObserver(&observer);
  prefs_->AddObserver(&pref_service_sync_observer);

  // Simulate that `kOsPrefName` is registered as SYNCABLE_PREF
  syncer::SyncDataList list;
  list.push_back(MakeRemoteSyncData(kOsPrefName, base::Value("new_value"),
                                    syncer::OS_PREFERENCES));

  // Simulate the first sync at startup.
  syncer::SyncChangeList outgoing_changes;
  prefs_->GetSyncableService(syncer::OS_PREFERENCES)
      ->MergeDataAndStartSyncing(
          syncer::OS_PREFERENCES, list,
          std::make_unique<TestSyncProcessorStub>(&outgoing_changes));

  EXPECT_EQ(kOsPrefName, observer.synced_pref_);
  EXPECT_EQ(1, observer.sync_started_count_);
  EXPECT_TRUE(pref_service_sync_observer.is_syncing_changed());

  prefs_->RemoveObserver(&pref_service_sync_observer);
  prefs_->RemoveSyncedPrefObserver(kOsPrefName, &observer);
}

TEST_F(PrefServiceSyncableChromeOsTest, SyncedPrefObserver_EmptyCloud) {
  CreatePrefService();
  prefs_->SetString(kOsPrefName, "new_value");

  TestSyncedPrefObserver observer;
  prefs_->AddSyncedPrefObserver(kOsPrefName, &observer);

  // Simulate the first sync at startup.
  syncer::SyncChangeList outgoing_changes;
  prefs_->GetSyncableService(syncer::OS_PREFERENCES)
      ->MergeDataAndStartSyncing(
          syncer::OS_PREFERENCES, syncer::SyncDataList(),
          std::make_unique<TestSyncProcessorStub>(&outgoing_changes));

  EXPECT_EQ("", observer.synced_pref_);
  EXPECT_EQ(0, observer.sync_started_count_);

  prefs_->RemoveSyncedPrefObserver(kOsPrefName, &observer);
}

TEST_F(PrefServiceSyncableChromeOsTest,
       StandaloneBrowserPrefsNotLeakedInIncognito) {
  CreatePrefService();

  prefs_->SetStandaloneBrowserPref(kOsPrefName, base::Value("test_value"));

  scoped_refptr<TestingPrefStore> incognito_extension_pref_store =
      base::MakeRefCounted<TestingPrefStore>();

  std::unique_ptr<PrefServiceSyncable> incognito_prefs =
      prefs_->CreateIncognitoPrefService(incognito_extension_pref_store.get(),
                                         /*persistent_pref_names=*/{});

  // Verify that the primary profile has the `kOsPrefName` pref set.
  {
    const PrefService::Preference* main_profile_pref =
        prefs_->FindPreference(kOsPrefName);
    ASSERT_TRUE(main_profile_pref);
    EXPECT_TRUE(main_profile_pref->IsStandaloneBrowserControlled());
    EXPECT_EQ(*main_profile_pref->GetValue(), base::Value("test_value"));
  }

  // Verify that the incognito profile does not have the `kOsPrefName` pref set.
  {
    const PrefService::Preference* incognito_pref =
        incognito_prefs->FindPreference(kOsPrefName);
    ASSERT_TRUE(incognito_pref);
    EXPECT_FALSE(incognito_pref->IsStandaloneBrowserControlled());
    EXPECT_EQ(*incognito_pref->GetValue(), base::Value(""));
  }

  // Ensure this does not crash if it's accidentally called.
  incognito_prefs->SetStandaloneBrowserPref(kOsPrefName,
                                            base::Value("test_value"));
  // Verify that standalone browser settings cannot be configured by the
  // Incognito profile.
  {
    const PrefService::Preference* incognito_pref =
        incognito_prefs->FindPreference(kOsPrefName);
    ASSERT_TRUE(incognito_pref);
    EXPECT_FALSE(incognito_pref->IsStandaloneBrowserControlled());
    EXPECT_EQ(*incognito_pref->GetValue(), base::Value(""));
  }
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

class PrefServiceSyncableFactoryTest : public PrefServiceSyncableTest {};

TEST_F(PrefServiceSyncableFactoryTest,
       ShouldCreateSyncServiceWithoutDualLayerStoreIfFeatureDisabled) {}

TEST_F(PrefServiceSyncableFactoryTest,
       ShouldCreateSyncServiceWithDualLayerStoreIfFeatureEnabled) {}

}  // namespace

}  // namespace sync_preferences