blob: 18653e1787488e4c5aeadfb8495c563b68d98ce2 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/sync/driver/glue/sync_transport_data_prefs.h"
#include <memory>
#include <utility>
#include "base/base64.h"
#include "base/feature_list.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/sync/base/model_type.h"
namespace syncer {
namespace {
constexpr base::Feature kSyncResetVeryShortPollInterval{
"SyncResetVeryShortPollInterval", base::FEATURE_ENABLED_BY_DEFAULT};
// 64-bit integer serialization of the base::Time when the last sync occurred.
const char kSyncLastSyncedTime[] = "sync.last_synced_time";
// 64-bit integer serialization of the base::Time of the last sync poll.
const char kSyncLastPollTime[] = "sync.last_poll_time";
// 64-bit integer serialization of base::TimeDelta storing poll intervals
// received by the server (in seconds). For historic reasons, this is called
// "short_poll_interval", but it's not worth the hassle to rename it.
const char kSyncPollIntervalSeconds[] = "sync.short_poll_interval";
const char kSyncGaiaId[] = "sync.gaia_id";
const char kSyncCacheGuid[] = "sync.cache_guid";
const char kSyncBirthday[] = "sync.birthday";
const char kSyncBagOfChips[] = "sync.bag_of_chips";
// Dictionary of last seen invalidation versions for each model type.
const char kDeprecatedSyncInvalidationVersions[] = "sync.invalidation_versions";
const char kSyncInvalidationVersions2[] = "sync.invalidation_versions2";
// Obsolete pref.
const char kSyncObsoleteKeystoreEncryptionBootstrapToken[] =
"sync.keystore_encryption_bootstrap_token";
void UpdateInvalidationVersions(
const std::map<ModelType, int64_t>& invalidation_versions,
PrefService* pref_service) {
auto invalidation_dictionary = std::make_unique<base::DictionaryValue>();
for (const auto& map_iter : invalidation_versions) {
std::string version_str = base::NumberToString(map_iter.second);
invalidation_dictionary->SetString(
base::NumberToString(
GetSpecificsFieldNumberFromModelType(map_iter.first)),
version_str);
}
pref_service->Set(kSyncInvalidationVersions2, *invalidation_dictionary);
}
} // namespace
SyncTransportDataPrefs::SyncTransportDataPrefs(PrefService* pref_service)
: pref_service_(pref_service) {}
SyncTransportDataPrefs::~SyncTransportDataPrefs() = default;
// static
void SyncTransportDataPrefs::RegisterProfilePrefs(
PrefRegistrySimple* registry) {
registry->RegisterStringPref(kSyncGaiaId, std::string());
registry->RegisterStringPref(kSyncCacheGuid, std::string());
registry->RegisterStringPref(kSyncBirthday, std::string());
registry->RegisterStringPref(kSyncBagOfChips, std::string());
registry->RegisterTimePref(kSyncLastSyncedTime, base::Time());
registry->RegisterTimePref(kSyncLastPollTime, base::Time());
registry->RegisterTimeDeltaPref(kSyncPollIntervalSeconds, base::TimeDelta());
registry->RegisterDictionaryPref(kDeprecatedSyncInvalidationVersions);
registry->RegisterDictionaryPref(kSyncInvalidationVersions2);
// Obsolete pref.
registry->RegisterStringPref(kSyncObsoleteKeystoreEncryptionBootstrapToken,
std::string());
}
void SyncTransportDataPrefs::ClearAll() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
pref_service_->ClearPref(kSyncLastSyncedTime);
pref_service_->ClearPref(kSyncLastPollTime);
pref_service_->ClearPref(kSyncPollIntervalSeconds);
pref_service_->ClearPref(kSyncInvalidationVersions2);
pref_service_->ClearPref(kDeprecatedSyncInvalidationVersions);
pref_service_->ClearPref(kSyncGaiaId);
pref_service_->ClearPref(kSyncCacheGuid);
pref_service_->ClearPref(kSyncBirthday);
pref_service_->ClearPref(kSyncBagOfChips);
}
base::Time SyncTransportDataPrefs::GetLastSyncedTime() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return pref_service_->GetTime(kSyncLastSyncedTime);
}
void SyncTransportDataPrefs::SetLastSyncedTime(base::Time time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
pref_service_->SetTime(kSyncLastSyncedTime, time);
}
base::Time SyncTransportDataPrefs::GetLastPollTime() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return pref_service_->GetTime(kSyncLastPollTime);
}
void SyncTransportDataPrefs::SetLastPollTime(base::Time time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
pref_service_->SetTime(kSyncLastPollTime, time);
}
base::TimeDelta SyncTransportDataPrefs::GetPollInterval() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::TimeDelta poll_interval =
pref_service_->GetTimeDelta(kSyncPollIntervalSeconds);
// If the poll interval is unreasonably short, reset it. This will cause
// callers to use a reasonable default value instead.
// This fixes a past bug where stored pref values were accidentally
// re-interpreted from "seconds" to "microseconds"; see crbug.com/1246850.
if (poll_interval < base::Minutes(1) &&
base::FeatureList::IsEnabled(kSyncResetVeryShortPollInterval)) {
pref_service_->ClearPref(kSyncPollIntervalSeconds);
return base::TimeDelta();
}
return poll_interval;
}
void SyncTransportDataPrefs::SetPollInterval(base::TimeDelta interval) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
pref_service_->SetTimeDelta(kSyncPollIntervalSeconds, interval);
}
void SyncTransportDataPrefs::SetGaiaId(const std::string& gaia_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
pref_service_->SetString(kSyncGaiaId, gaia_id);
}
std::string SyncTransportDataPrefs::GetGaiaId() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return pref_service_->GetString(kSyncGaiaId);
}
void SyncTransportDataPrefs::SetCacheGuid(const std::string& cache_guid) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
pref_service_->SetString(kSyncCacheGuid, cache_guid);
}
std::string SyncTransportDataPrefs::GetCacheGuid() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return pref_service_->GetString(kSyncCacheGuid);
}
void SyncTransportDataPrefs::SetBirthday(const std::string& birthday) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
pref_service_->SetString(kSyncBirthday, birthday);
}
std::string SyncTransportDataPrefs::GetBirthday() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return pref_service_->GetString(kSyncBirthday);
}
void SyncTransportDataPrefs::SetBagOfChips(const std::string& bag_of_chips) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// |bag_of_chips| contains a serialized proto which is not utf-8, hence we use
// base64 encoding in prefs.
std::string encoded;
base::Base64Encode(bag_of_chips, &encoded);
pref_service_->SetString(kSyncBagOfChips, encoded);
}
std::string SyncTransportDataPrefs::GetBagOfChips() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// |kSyncBagOfChips| gets stored in base64 because it represents a serialized
// proto which is not utf-8 encoding.
const std::string encoded = pref_service_->GetString(kSyncBagOfChips);
std::string decoded;
base::Base64Decode(encoded, &decoded);
return decoded;
}
// static
void SyncTransportDataPrefs::MigrateInvalidationVersions(
PrefService* pref_service) {
const base::Value* invalidation_dictionary =
pref_service->GetDictionary(kDeprecatedSyncInvalidationVersions);
if (invalidation_dictionary->DictEmpty()) {
// No data, or was already migrated. Nothing to do here.
return;
}
// Read data from the deprecated pref.
std::map<ModelType, int64_t> invalidation_versions;
for (ModelType type : ProtocolTypes()) {
// TODO(crbug.com/1173546): Fork a minimal version of ModelTypeToString in
// this file, so that ModelTypeToString itself (meant only for debugging
// purposes) can be changed without breaking this code.
std::string key = ModelTypeToString(type);
const std::string* version_str =
invalidation_dictionary->FindStringKey(key);
if (!version_str)
continue;
int64_t version = 0;
if (!base::StringToInt64(*version_str, &version))
continue;
invalidation_versions[type] = version;
}
// Write to the new pref and clear the deprecated one.
syncer::UpdateInvalidationVersions(invalidation_versions, pref_service);
pref_service->ClearPref(kDeprecatedSyncInvalidationVersions);
}
std::map<ModelType, int64_t> SyncTransportDataPrefs::GetInvalidationVersions()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::map<ModelType, int64_t> invalidation_versions;
const base::Value* invalidation_dictionary =
pref_service_->GetDictionary(kSyncInvalidationVersions2);
for (ModelType type : ProtocolTypes()) {
std::string key =
base::NumberToString(GetSpecificsFieldNumberFromModelType(type));
const std::string* version_str =
invalidation_dictionary->FindStringKey(key);
if (!version_str)
continue;
int64_t version = 0;
if (!base::StringToInt64(*version_str, &version))
continue;
invalidation_versions[type] = version;
}
return invalidation_versions;
}
void SyncTransportDataPrefs::UpdateInvalidationVersions(
const std::map<ModelType, int64_t>& invalidation_versions) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
syncer::UpdateInvalidationVersions(invalidation_versions, pref_service_);
}
void ClearObsoleteKeystoreBootstrapTokenPref(PrefService* pref_service) {
pref_service->ClearPref(kSyncObsoleteKeystoreEncryptionBootstrapToken);
}
} // namespace syncer