// 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/updater/persisted_data.h"

#include <optional>
#include <string>
#include <vector>

#include "base/base64.h"
#include "base/check.h"
#include "base/files/file_path.h"
#include "base/json/values_util.h"
#include "base/logging.h"
#include "base/sequence_checker.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/updater/branded_constants.h"
#include "chrome/updater/registration_data.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/update_client/activity_data_service.h"
#include "components/update_client/persisted_data.h"
#include "components/update_client/update_client_errors.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>

#include "base/containers/span.h"
#include "base/containers/span_reader.h"
#include "base/numerics/byte_conversions.h"
#include "base/win/registry.h"
#include "chrome/updater/util/win_util.h"
#include "chrome/updater/win/win_constants.h"
#endif

namespace {

// PersistedData keys.
constexpr char kVersionPath[] = "pv_path";
constexpr char kVersionKey[] = "pv_key";
constexpr char kECP[] = "ecp";
constexpr char kBC[] = "bc";
constexpr char kBP[] = "bp";
constexpr char kAP[] = "ap";
constexpr char kAPPath[] = "ap_path";
constexpr char kAPKey[] = "ap_key";
constexpr char kLang[] = "lang";

constexpr char kHadApps[] = "had_apps";
constexpr char kUsageStatsEnabledKey[] = "usage_stats_enabled";
constexpr char kRemoteLoggingCookie[] = "remote_logging_cookie";
constexpr char kNextAllowedLoggingAttemptTime[] = "next_logging_attempt_time";
constexpr char kEulaRequired[] = "eula_required";

constexpr char kLastChecked[] = "last_checked";
constexpr char kLastStarted[] = "last_started";
constexpr char kLastOSVersion[] = "last_os_version";

constexpr char kCookieValueKey[] = "value";
constexpr char kCookieExpirationKey[] = "expiration";

}  // namespace

namespace updater {

PersistedData::PersistedData(
    UpdaterScope scope,
    PrefService* pref_service,
    std::unique_ptr<update_client::ActivityDataService> activity_service)
    : scope_(scope),
      pref_service_(pref_service),
      delegate_(update_client::CreatePersistedData(
          base::BindRepeating(
              [](PrefService* pref_service) { return pref_service; },
              pref_service),
          std::move(activity_service))) {
  CHECK(pref_service_);
}

PersistedData::~PersistedData() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

base::Version PersistedData::GetProductVersion(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetProductVersion(id);
}

void PersistedData::SetProductVersion(const std::string& id,
                                      const base::Version& pv) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK(pv.IsValid());
  delegate_->SetProductVersion(id, pv);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, we record the PV in ClientState as well.
  // (Some applications read it from there.) This has the side effect of
  // creating the ClientState key, which is read to sense for application
  // uninstallation.
  SetRegistryKey(UpdaterScopeToHKeyRoot(scope_), GetAppClientStateKey(id),
                 kRegValuePV, base::UTF8ToWide(pv.GetString()));
#endif
}

base::Version PersistedData::GetMaxPreviousProductVersion(
    const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetMaxPreviousProductVersion(id);
}

void PersistedData::SetMaxPreviousProductVersion(
    const std::string& id,
    const base::Version& max_version) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK(max_version.IsValid());
  delegate_->SetMaxPreviousProductVersion(id, max_version);
}

base::FilePath PersistedData::GetProductVersionPath(
    const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::FilePath::FromUTF8Unsafe(GetString(id, kVersionPath));
}

void PersistedData::SetProductVersionPath(const std::string& id,
                                          const base::FilePath& path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  SetString(id, kVersionPath, path.AsUTF8Unsafe());
}

std::string PersistedData::GetProductVersionKey(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return GetString(id, kVersionKey);
}

void PersistedData::SetProductVersionKey(const std::string& id,
                                         const std::string& key) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  SetString(id, kVersionKey, key);
}

std::string PersistedData::GetFingerprint(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetFingerprint(id);
}

void PersistedData::SetFingerprint(const std::string& id,
                                   const std::string& fingerprint) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetFingerprint(id, fingerprint);
}

base::FilePath PersistedData::GetExistenceCheckerPath(
    const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::FilePath::FromUTF8Unsafe(GetString(id, kECP));
}

void PersistedData::SetExistenceCheckerPath(const std::string& id,
                                            const base::FilePath& ecp) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  SetString(id, kECP, ecp.AsUTF8Unsafe());
}

std::string PersistedData::GetBrandCode(const std::string& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  const std::string bc = GetString(id, kBC);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, if there is a brand code in the registry
  // ClientState, that brand code is considered authoritative, and overrides any
  // brand code that is already in `prefs`.
  std::wstring registry_bc;
  if (base::win::RegKey(UpdaterScopeToHKeyRoot(scope_),
                        GetAppClientStateKey(id).c_str(),
                        Wow6432(KEY_QUERY_VALUE))
          .ReadValue(kRegValueBrandCode, &registry_bc) == ERROR_SUCCESS) {
    const std::string registry_brand_code = base::WideToUTF8(registry_bc);
    if (!registry_brand_code.empty() && registry_brand_code != bc) {
      SetString(id, kBC, registry_brand_code);
      return registry_brand_code;
    }
  }
#endif

  if (bc.empty()) {
    return {};
  }

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, record the brand code in ClientState, since
  // some applications read it from there.
  SetRegistryKey(UpdaterScopeToHKeyRoot(scope_), GetAppClientStateKey(id),
                 kRegValueBrandCode, base::UTF8ToWide(bc));
#endif
  return bc;
}

void PersistedData::SetBrandCode(const std::string& id, const std::string& bc) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // If there is already an existing brand code, do not overwrite it.
  if (!GetBrandCode(id).empty()) {
    return;
  }

  SetString(id, kBC, bc);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, record the brand code in ClientState, since
  // some applications read it from there.
  SetRegistryKey(UpdaterScopeToHKeyRoot(scope_), GetAppClientStateKey(id),
                 kRegValueBrandCode, base::UTF8ToWide(bc));
#endif
}

base::FilePath PersistedData::GetBrandPath(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::FilePath::FromUTF8Unsafe(GetString(id, kBP));
}

void PersistedData::SetBrandPath(const std::string& id,
                                 const base::FilePath& bp) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  SetString(id, kBP, bp.AsUTF8Unsafe());
}

std::string PersistedData::GetAP(const std::string& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, we read AP from ClientState first, since some
  // applications write to it there.
  if (const std::string ap(GetAppAPValue(scope_, id)); !ap.empty()) {
    SetAP(id, ap);
    return ap;
  }
#endif

  return GetString(id, kAP);
}

void PersistedData::SetAP(const std::string& id, const std::string& ap) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  SetString(id, kAP, ap);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, we record the AP in ClientState as well.
  // (Some applications read it from there.)

  // Chromium Updater has both local and global pref stores. In practice, if
  // this `PersistedData` is using a local pref store, `id` will be the
  // qualification app and the ClientState value is not important, so it is
  // acceptable for each instance of the updater to overwrite it with various
  // values. Else, this is the global pref store and reflecting the value in
  // registry is correct. Clients should transition to requesting the
  // registration info for their application via RPC.
  SetRegistryKey(UpdaterScopeToHKeyRoot(scope_), GetAppClientStateKey(id),
                 kRegValueAP, base::UTF8ToWide(ap));
#endif
}

base::FilePath PersistedData::GetAPPath(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::FilePath::FromUTF8Unsafe(GetString(id, kAPPath));
}

void PersistedData::SetAPPath(const std::string& id,
                              const base::FilePath& path) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  SetString(id, kAPPath, path.AsUTF8Unsafe());
}

std::string PersistedData::GetAPKey(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return GetString(id, kAPKey);
}

void PersistedData::SetAPKey(const std::string& id, const std::string& key) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  SetString(id, kAPKey, key);
}

std::string PersistedData::GetLang(const std::string& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  const std::string lang = GetString(id, kLang);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, if there is a lang in the registry Clients or
  // ClientState, that lang is considered authoritative, and overrides any lang
  // that is already in `prefs`.
  for (const auto& subkey : {GetAppClientsKey(id), GetAppClientStateKey(id)}) {
    std::wstring registry_lang_w;
    if (base::win::RegKey(UpdaterScopeToHKeyRoot(scope_), subkey.c_str(),
                          Wow6432(KEY_QUERY_VALUE))
            .ReadValue(kRegValueLang, &registry_lang_w) == ERROR_SUCCESS) {
      const std::string registry_lang = base::WideToUTF8(registry_lang_w);
      if (!registry_lang.empty() && registry_lang != lang) {
        SetString(id, kLang, registry_lang);
        return registry_lang;
      }
    }
  }
#endif

  return lang;
}

void PersistedData::SetLang(const std::string& id, const std::string& lang) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  SetString(id, kLang, lang);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, record the lang in ClientState, since some
  // applications read it from there.
  SetRegistryKey(UpdaterScopeToHKeyRoot(scope_), GetAppClientStateKey(id),
                 kRegValueLang, base::UTF8ToWide(lang));
#endif
}

int PersistedData::GetDateLastActive(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetDateLastActive(id);
}

int PersistedData::GetDaysSinceLastActive(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetDaysSinceLastActive(id);
}

void PersistedData::SetDateLastActive(const std::string& id, int dla) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetDateLastActive(id, dla);
}

int PersistedData::GetDateLastRollCall(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetDateLastRollCall(id);
}

int PersistedData::GetDaysSinceLastRollCall(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetDaysSinceLastRollCall(id);
}

void PersistedData::SetDateLastRollCall(const std::string& id, int dlrc) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetDateLastRollCall(id, dlrc);
}

std::string PersistedData::GetCohort(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetCohort(id);
}

void PersistedData::SetCohort(const std::string& id,
                              const std::string& cohort) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetCohort(id, cohort);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, we record the Cohort in ClientState as well.
  // (Some applications read it from there.)
  SetRegistryKey(UpdaterScopeToHKeyRoot(scope_), GetAppCohortKey(id), L"",
                 base::UTF8ToWide(cohort));
#endif
}

std::string PersistedData::GetCohortName(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetCohortName(id);
}

void PersistedData::SetCohortName(const std::string& id,
                                  const std::string& cohort_name) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetCohortName(id, cohort_name);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, we record the Cohort in ClientState as well.
  // (Some applications read it from there.)
  SetRegistryKey(UpdaterScopeToHKeyRoot(scope_), GetAppCohortKey(id),
                 kRegValueCohortName, base::UTF8ToWide(cohort_name));
#endif
}

std::string PersistedData::GetCohortHint(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetCohortHint(id);
}

void PersistedData::SetCohortHint(const std::string& id,
                                  const std::string& cohort_hint) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetCohortHint(id, cohort_hint);
}

std::string PersistedData::GetPingFreshness(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetPingFreshness(id);
}

void PersistedData::SetDateLastData(const std::vector<std::string>& ids,
                                    int datenum,
                                    base::OnceClosure callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetDateLastData(ids, datenum, std::move(callback));
}

int PersistedData::GetInstallDate(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetInstallDate(id);
}

void PersistedData::SetInstallDate(const std::string& id, int install_date) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetInstallDate(id, install_date);
}

std::string PersistedData::GetInstallId(const std::string& app_id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetInstallId(app_id);
}

void PersistedData::SetInstallId(const std::string& app_id,
                                 const std::string& install_id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetInstallId(app_id, install_id);
}

void PersistedData::GetActiveBits(
    const std::vector<std::string>& ids,
    base::OnceCallback<void(const std::set<std::string>&)> callback) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->GetActiveBits(ids, std::move(callback));
}

base::Time PersistedData::GetThrottleUpdatesUntil() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return delegate_->GetThrottleUpdatesUntil();
}

void PersistedData::SetLastUpdateCheckError(
    const update_client::CategorizedError& error) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetLastUpdateCheckError(error);
}

void PersistedData::SetThrottleUpdatesUntil(base::Time time) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  delegate_->SetThrottleUpdatesUntil(time);
}

void PersistedData::RegisterApp(const RegistrationRequest& rq) {
  VLOG(2) << __func__ << ": Registering " << rq.app_id;
  if (rq.version.IsValid()) {
    VLOG(2) << __func__ << ": app version " << rq.version;
    SetProductVersion(rq.app_id, rq.version);
  }
  if (!rq.version_path.empty()) {
    SetProductVersionPath(rq.app_id, rq.version_path);
  }
  if (!rq.version_key.empty()) {
    SetProductVersionKey(rq.app_id, rq.version_key);
  }
  if (!rq.existence_checker_path.empty()) {
    SetExistenceCheckerPath(rq.app_id, rq.existence_checker_path);
  }
  if (!rq.lang.empty()) {
    SetLang(rq.app_id, rq.lang);
  }
  if (!rq.brand_code.empty()) {
    SetBrandCode(rq.app_id, rq.brand_code);
  }
  if (!rq.brand_path.empty()) {
    SetBrandPath(rq.app_id, rq.brand_path);
  }
  if (!rq.ap.empty()) {
    SetAP(rq.app_id, rq.ap);
  }
  if (!rq.ap_path.empty()) {
    SetAPPath(rq.app_id, rq.ap_path);
  }
  if (!rq.ap_key.empty()) {
    SetAPKey(rq.app_id, rq.ap_key);
  }
  if (rq.dla) {
    SetDateLastActive(rq.app_id, rq.dla.value());
  } else if (GetDateLastActive(rq.app_id) == update_client::kDateUnknown) {
    SetDateLastActive(rq.app_id, update_client::kDateFirstTime);
  }
  if (rq.dlrc) {
    SetDateLastRollCall(rq.app_id, rq.dlrc.value());
  } else if (GetDateLastRollCall(rq.app_id) == update_client::kDateUnknown) {
    SetDateLastRollCall(rq.app_id, update_client::kDateFirstTime);
  }
  if (rq.install_date) {
    SetInstallDate(rq.app_id, *rq.install_date);
  }
  if (!rq.cohort.empty()) {
    SetCohort(rq.app_id, rq.cohort);
  }
  if (!rq.cohort_name.empty()) {
    SetCohortName(rq.app_id, rq.cohort_name);
  }
  if (!rq.cohort_hint.empty()) {
    SetCohortHint(rq.app_id, rq.cohort_hint);
  }
  if (!rq.install_id.empty()) {
    SetInstallId(rq.app_id, rq.install_id);
  }
}

bool PersistedData::RemoveApp(const std::string& id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, the `ClientState` and (for system installs)
  // `ClientStateMedium` entries for the app are also removed.
  for (const auto& subkey : [&] {
         std::vector<std::wstring> subkeys = {GetAppClientStateKey(id)};
         if (IsSystemInstall(scope_)) {
           subkeys.push_back(GetAppClientStateMediumKey(id));
         }
         return subkeys;
       }()) {
    base::win::RegKey(UpdaterScopeToHKeyRoot(scope_), L"", Wow6432(DELETE))
        .DeleteKey(subkey.c_str());
  }
#endif

  if (!pref_service_) {
    return false;
  }

  ScopedDictPrefUpdate update(pref_service_,
                              update_client::kPersistedDataPreference);
  base::Value::Dict* apps = update->FindDict("apps");

  return apps ? apps->Remove(base::ToLowerASCII(id)) : false;
}

std::vector<std::string> PersistedData::GetAppIds() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // The prefs is a dictionary of dictionaries, where each inner dictionary
  // corresponds to an app:
  // {"updateclientdata":{"apps":{"{44FC7FE2-65CE-487C-93F4-EDEE46EEAAAB}":{...
  const base::Value::Dict& dict =
      pref_service_->GetDict(update_client::kPersistedDataPreference);
  const base::Value::Dict* apps = dict.FindDict("apps");
  if (!apps) {
    return {};
  }
  std::vector<std::string> app_ids;
  for (auto it = apps->begin(); it != apps->end(); ++it) {
    const auto& app_id = it->first;
    const auto pv = GetProductVersion(app_id);
    if (pv.IsValid()) {
      app_ids.push_back(app_id);
    }
  }
  return app_ids;
}

const base::Value::Dict* PersistedData::GetAppKey(const std::string& id) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!pref_service_) {
    return nullptr;
  }
  const base::Value::Dict& dict =
      pref_service_->GetDict(update_client::kPersistedDataPreference);
  const base::Value::Dict* apps = dict.FindDict("apps");
  if (!apps) {
    return nullptr;
  }
  return apps->FindDict(base::ToLowerASCII(id));
}

std::string PersistedData::GetString(const std::string& id,
                                     const std::string& key) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  const base::Value::Dict* app_key = GetAppKey(id);
  if (!app_key) {
    return {};
  }
  const std::string* value = app_key->FindString(key);
  if (!value) {
    return {};
  }
  return *value;
}

base::Value::Dict* PersistedData::GetOrCreateAppKey(const std::string& id,
                                                    base::Value::Dict& root) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  base::Value::Dict* apps = root.EnsureDict("apps");
  base::Value::Dict* app = apps->EnsureDict(base::ToLowerASCII(id));
  return app;
}

std::optional<int> PersistedData::GetInteger(const std::string& id,
                                             const std::string& key) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!pref_service_) {
    return std::nullopt;
  }
  ScopedDictPrefUpdate update(pref_service_,
                              update_client::kPersistedDataPreference);
  base::Value::Dict* apps = update->FindDict("apps");
  if (!apps) {
    return std::nullopt;
  }
  base::Value::Dict* app = apps->FindDict(base::ToLowerASCII(id));
  if (!app) {
    return std::nullopt;
  }
  return app->FindInt(key);
}

void PersistedData::SetInteger(const std::string& id,
                               const std::string& key,
                               int value) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!pref_service_) {
    return;
  }
  ScopedDictPrefUpdate update(pref_service_,
                              update_client::kPersistedDataPreference);
  GetOrCreateAppKey(id, update.Get())->Set(key, value);
}

void PersistedData::SetString(const std::string& id,
                              const std::string& key,
                              const std::string& value) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!pref_service_) {
    return;
  }
  ScopedDictPrefUpdate update(pref_service_,
                              update_client::kPersistedDataPreference);
  GetOrCreateAppKey(id, update.Get())->Set(key, value);
}

bool PersistedData::GetHadApps() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return pref_service_ && pref_service_->GetBoolean(kHadApps);
}

void PersistedData::SetHadApps() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (pref_service_) {
    pref_service_->SetBoolean(kHadApps, true);
  }
}

std::optional<PersistedData::Cookie> PersistedData::GetRemoteLoggingCookie()
    const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!pref_service_) {
    return std::nullopt;
  }

  const base::Value::Dict& cookie =
      pref_service_->GetDict(kRemoteLoggingCookie);
  const std::string* value = cookie.FindString(kCookieValueKey);
  std::optional<base::Time> expiration =
      base::ValueToTime(cookie.Find(kCookieExpirationKey));
  if (!value || !expiration) {
    return std::nullopt;
  }

  return Cookie{
      .value = *value,
      .expiration = *expiration,
  };
}

void PersistedData::SetRemoteLoggingCookie(const Cookie& logging_cookie) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (pref_service_) {
    pref_service_->SetDict(
        kRemoteLoggingCookie,
        base::Value::Dict()
            .Set(kCookieValueKey, logging_cookie.value)
            .Set(kCookieExpirationKey,
                 base::TimeToValue(logging_cookie.expiration)));
  }
}

void PersistedData::ClearRemoteLoggingCookie() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (pref_service_) {
    pref_service_->ClearPref(kRemoteLoggingCookie);
  }
}

base::Time PersistedData::GetNextAllowedLoggingAttemptTime() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!pref_service_) {
    return base::Time();
  }
  return pref_service_->GetTime(kNextAllowedLoggingAttemptTime);
}

void PersistedData::SetNextAllowedLoggingAttemptTime(base::Time time) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (pref_service_) {
    pref_service_->SetTime(kNextAllowedLoggingAttemptTime, time);
  }
}

bool PersistedData::GetEulaRequired() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return pref_service_ && pref_service_->GetBoolean(kEulaRequired);
}

void PersistedData::SetEulaRequired(bool eula_required) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (pref_service_) {
    pref_service_->SetBoolean(kEulaRequired, eula_required);
  }
#if BUILDFLAG(IS_WIN)
  // For backwards compatibility, `eulaaccepted` is recorded in the registry,
  // since some applications read it from there.
  SetEulaAccepted(scope_, !eula_required);
#endif
}

base::Time PersistedData::GetLastChecked() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return pref_service_->GetTime(kLastChecked);
}

void PersistedData::SetLastChecked(base::Time time) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (pref_service_) {
    pref_service_->SetTime(kLastChecked, time);
  }
}

base::Time PersistedData::GetLastStarted() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return pref_service_->GetTime(kLastStarted);
}

void PersistedData::SetLastStarted(base::Time time) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (pref_service_) {
    pref_service_->SetTime(kLastStarted, time);
  }
}

#if BUILDFLAG(IS_WIN)
std::optional<OSVERSIONINFOEX> PersistedData::GetLastOSVersion() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Unpacks the os version from a base-64-encoded string internally.
  const std::string encoded_os_version =
      pref_service_->GetString(kLastOSVersion);

  if (encoded_os_version.empty()) {
    return std::nullopt;
  }

  const std::optional<std::vector<uint8_t>> decoded_os_version =
      base::Base64Decode(encoded_os_version);
  if (!decoded_os_version ||
      decoded_os_version->size() != sizeof(OSVERSIONINFOEX)) {
    return std::nullopt;
  }

  auto reader = base::SpanReader(base::span(*decoded_os_version));
  OSVERSIONINFOEX info;
  info.dwOSVersionInfoSize =
      base::U32FromNativeEndian(*reader.Read<sizeof(DWORD)>());
  info.dwMajorVersion =
      base::U32FromNativeEndian(*reader.Read<sizeof(DWORD)>());
  info.dwMinorVersion =
      base::U32FromNativeEndian(*reader.Read<sizeof(DWORD)>());
  info.dwBuildNumber = base::U32FromNativeEndian(*reader.Read<sizeof(DWORD)>());
  info.dwPlatformId = base::U32FromNativeEndian(*reader.Read<sizeof(DWORD)>());
  base::as_writable_byte_span(info.szCSDVersion)
      .copy_from(*reader.Read<sizeof((OSVERSIONINFOEX){}.szCSDVersion)>());
  info.wServicePackMajor =
      base::U16FromNativeEndian(*reader.Read<sizeof(WORD)>());
  info.wServicePackMinor =
      base::U16FromNativeEndian(*reader.Read<sizeof(WORD)>());
  info.wSuiteMask = base::U16FromNativeEndian(*reader.Read<sizeof(WORD)>());
  info.wProductType = base::U8FromNativeEndian(*reader.Read<sizeof(BYTE)>());
  info.wReserved = base::U8FromNativeEndian(*reader.Read<sizeof(BYTE)>());

  CHECK_EQ(reader.remaining(), 0u);
  return info;
}

void PersistedData::SetLastOSVersion() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!pref_service_) {
    return;
  }

  // Get and set the current OS version.
  std::optional<OSVERSIONINFOEX> os_version = GetOSVersion();
  if (!os_version) {
    return;
  }

  // The os version is internally stored as a base-64-encoded string.
  std::string encoded_os_version =
      base::Base64Encode(base::byte_span_from_ref(os_version.value()));

  return pref_service_->SetString(kLastOSVersion, encoded_os_version);
}
#endif

// Register persisted data prefs, except for kPersistedDataPreference.
// kPersistedDataPreference is registered by update_client::RegisterPrefs.
void RegisterPersistedDataPrefs(scoped_refptr<PrefRegistrySimple> registry) {
  registry->RegisterBooleanPref(kHadApps, false);
  registry->RegisterBooleanPref(kEulaRequired, false);
  registry->RegisterTimePref(kNextAllowedLoggingAttemptTime, {});
  registry->RegisterTimePref(kLastChecked, {});
  registry->RegisterTimePref(kLastStarted, {});
  registry->RegisterStringPref(kLastOSVersion, {});
  registry->RegisterDictionaryPref(kRemoteLoggingCookie, {});

  // TODO(crbug.com/422187975): Remove obsolete pref no earlier than 6/3/2026.
  registry->RegisterBooleanPref(kUsageStatsEnabledKey, false);
}

void MigrateObsoletePersistedDataPrefs(PrefService* pref_service) {
  // TODO(crbug.com/422187975): Remove obsolete pref no earlier than 6/3/2026.
  pref_service->ClearPref(kUsageStatsEnabledKey);
}

}  // namespace updater
