910e62b5创建于 1月15日历史提交
// 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.

#ifndef COMPONENTS_SYNC_PREFERENCES_SYNCABLE_PREFS_DATABASE_H_
#define COMPONENTS_SYNC_PREFERENCES_SYNCABLE_PREFS_DATABASE_H_

#include <optional>
#include <ostream>
#include <string_view>

#include "base/check.h"
#include "build/build_config.h"
#include "components/sync/base/data_type.h"
#include "components/sync/base/user_selectable_type.h"

namespace sync_preferences {

// TODO(crbug.com/412602018): Rename enum and enum values to better reflect
// their purpose.
enum class PrefSensitivity {
  // The pref is not sensitive and requires only the preference sync toggle to
  // be enabled for syncing.
  kNone,
  // The pref contains sensitive information and requires history opt-in to
  // allow syncing.
  kSensitiveRequiresHistory,
  // The pref is exempt from user control and hence, decoupled from any user
  // toggle. Note that this is only supported for priority prefs.
  kExemptFromUserControlWhileSignedIn,
};

enum class MergeBehavior {
  // The account value wins. This is the default behavior. Any pref update is
  // applied to both - the local value as well as the account value.
  kNone,
  // For dictionary values, all entries in `account_value` and `local_value` are
  // merged recursively. In case of a conflict, the entry from `account_value`
  // wins. With a DualLayerUserPrefStore, pref updates are split between the
  // account value and the local value and only the relevant updates are applied
  // to each.
  kMergeableDict,
  // For list values, all entries of `account_value` come first, followed by all
  // entries in the `local_value`. Any repeating entry in `local_value` is
  // omitted. Any pref update overwrites both - the local value as well as the
  // account value.
  kMergeableListWithRewriteOnUpdate,
  // A custom merge logic has been implemented for this pref.
  kCustom
};

// This class represents the metadata corresponding to a syncable preference.
class SyncablePrefMetadata {
 public:
  constexpr SyncablePrefMetadata(int syncable_pref_id,
                                 syncer::DataType data_type,
                                 PrefSensitivity pref_sensitivity,
                                 MergeBehavior merge_behavior)
      : syncable_pref_id_(syncable_pref_id),
        data_type_(data_type),
        pref_sensitivity_(pref_sensitivity),
        merge_behaviour_(merge_behavior) {
    CHECK(data_type_ == syncer::PREFERENCES ||
          data_type_ == syncer::PRIORITY_PREFERENCES
#if BUILDFLAG(IS_CHROMEOS)
          || data_type_ == syncer::OS_PREFERENCES ||
          data_type_ == syncer::OS_PRIORITY_PREFERENCES
#endif  // BUILDFLAG(IS_CHROMEOS)
          )
        << "Invalid type " << data_type_
        << " for syncable pref with id=" << syncable_pref_id_;
    CHECK(pref_sensitivity_ !=
              PrefSensitivity::kExemptFromUserControlWhileSignedIn ||
          data_type_ == syncer::PRIORITY_PREFERENCES)
        << "Always syncing prefs must be priority prefs.";
  }

  // Returns the unique ID corresponding to the syncable preference.
  int syncable_pref_id() const { return syncable_pref_id_; }
  // Returns the data type of the pref, i.e. PREFERENCES, PRIORITY_PREFERENCES,
  // OS_PREFERENCES or OS_PRIORITY_PREFERENCES.
  syncer::DataType data_type() const { return data_type_; }

  // Returns the sensitivity of the pref. It is used to determine whether the
  // pref requires history opt-in.
  PrefSensitivity pref_sensitivity() const { return pref_sensitivity_; }

  // Returns whether the pref requires history opt-in to be synced.
  bool is_history_opt_in_required() const {
    return pref_sensitivity() == PrefSensitivity::kSensitiveRequiresHistory;
  }

  MergeBehavior merge_behavior() const { return merge_behaviour_; }

 private:
  int syncable_pref_id_;
  syncer::DataType data_type_;
  PrefSensitivity pref_sensitivity_;
  MergeBehavior merge_behaviour_;
};

// This class provides an interface to define the list of syncable
// preferences (and in the future, some additional metadata).
// PrefModelAssociatorClient uses the interface to verify if a preference is
// syncable. Platform-specific preferences should be part of individual
// implementations of this interface.
class SyncablePrefsDatabase {
 public:
  SyncablePrefsDatabase() = default;
  virtual ~SyncablePrefsDatabase() = default;
  SyncablePrefsDatabase(const SyncablePrefsDatabase&) = delete;
  SyncablePrefsDatabase& operator=(const SyncablePrefsDatabase&) = delete;

  // Returns the metadata associated to the pref and null if `pref_name` is not
  // syncable.
  virtual std::optional<SyncablePrefMetadata> GetSyncablePrefMetadata(
      std::string_view pref_name) const = 0;

  // Returns true if `pref_name` is part of the allowlist of syncable
  // preferences.
  bool IsPreferenceSyncable(std::string_view pref_name) const;

  // Return true if `pref_name` is a mergeable syncable preference.
  // Note: `pref_name` must be syncable.
  bool IsPreferenceMergeable(std::string_view pref_name) const;

  // Returns whether `pref_name` is part of the allowlist of preferences that
  // are always synced, irrespective of the preference sync user toggle.
  bool IsPreferenceAlwaysSyncing(std::string_view pref_name) const;
};

}  // namespace sync_preferences

#endif  // COMPONENTS_SYNC_PREFERENCES_SYNCABLE_PREFS_DATABASE_H_