blob: e282b2fccbd77156712a1c7ec402473f160b61b6 [file] [log] [blame]
// Copyright 2020 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/federated_learning/floc_id.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "components/federated_learning/features/features.h"
#include "components/federated_learning/floc_constants.h"
#include "components/federated_learning/sim_hash.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "third_party/blink/public/mojom/federated_learning/floc.mojom.h"
namespace federated_learning {
// static
uint64_t FlocId::SimHashHistory(
const std::unordered_set<std::string>& domains) {
return SimHashStrings(domains, kMaxNumberOfBitsInFloc);
}
// static
FlocId FlocId::CreateInvalid(Status status) {
DCHECK_NE(Status::kValid, status);
DCHECK_NE(Status::kInvalidNoStatusPrefs, status);
return FlocId(/*id=*/0, status,
/*history_begin_time=*/base::Time(),
/*history_end_time=*/base::Time(),
kFlocIdFinchConfigVersion.Get(),
/*sorting_lsh_version=*/0,
/*compute_time=*/base::Time::Now());
}
// static
FlocId FlocId::CreateValid(uint64_t id,
base::Time history_begin_time,
base::Time history_end_time,
uint32_t sorting_lsh_version) {
return FlocId(id, Status::kValid, history_begin_time, history_end_time,
kFlocIdFinchConfigVersion.Get(), sorting_lsh_version,
/*compute_time=*/base::Time::Now());
}
FlocId::FlocId(const FlocId& id) = default;
FlocId::~FlocId() = default;
FlocId& FlocId::operator=(const FlocId& id) = default;
FlocId& FlocId::operator=(FlocId&& id) = default;
bool FlocId::IsValid() const {
return status_ == Status::kValid;
}
bool FlocId::operator==(const FlocId& other) const {
return id_ == other.id_ && status_ == other.status_ &&
history_begin_time_ == other.history_begin_time_ &&
history_end_time_ == other.history_end_time_ &&
finch_config_version_ == other.finch_config_version_ &&
sorting_lsh_version_ == other.sorting_lsh_version_ &&
compute_time_ == other.compute_time_;
}
bool FlocId::operator!=(const FlocId& other) const {
return !(*this == other);
}
blink::mojom::InterestCohortPtr FlocId::ToInterestCohortForJsApi() const {
// TODO(yaoxia): consider returning the version part even when floc is
// invalid.
DCHECK_EQ(Status::kValid, status_);
blink::mojom::InterestCohortPtr result = blink::mojom::InterestCohort::New();
result->id = base::NumberToString(id_);
result->version =
base::StrCat({"chrome.", base::NumberToString(finch_config_version_), ".",
base::NumberToString(sorting_lsh_version_)});
return result;
}
uint64_t FlocId::ToUint64() const {
DCHECK_EQ(Status::kValid, status_);
return id_;
}
// static
void FlocId::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterUint64Pref(kFlocIdValuePrefKey, 0);
registry->RegisterIntegerPref(
kFlocIdStatusPrefKey, static_cast<int>(Status::kInvalidNoStatusPrefs));
registry->RegisterTimePref(kFlocIdHistoryBeginTimePrefKey, base::Time());
registry->RegisterTimePref(kFlocIdHistoryEndTimePrefKey, base::Time());
registry->RegisterUint64Pref(kFlocIdFinchConfigVersionPrefKey, 0);
registry->RegisterUint64Pref(kFlocIdSortingLshVersionPrefKey, 0);
registry->RegisterTimePref(kFlocIdComputeTimePrefKey, base::Time());
}
void FlocId::SaveToPrefs(PrefService* prefs) {
DCHECK_NE(status_, Status::kInvalidNoStatusPrefs);
prefs->SetUint64(kFlocIdValuePrefKey, id_);
prefs->SetInteger(kFlocIdStatusPrefKey, static_cast<int>(status_));
prefs->SetTime(kFlocIdHistoryBeginTimePrefKey, history_begin_time_);
prefs->SetTime(kFlocIdHistoryEndTimePrefKey, history_end_time_);
prefs->SetUint64(kFlocIdFinchConfigVersionPrefKey, finch_config_version_);
prefs->SetUint64(kFlocIdSortingLshVersionPrefKey, sorting_lsh_version_);
prefs->SetTime(kFlocIdComputeTimePrefKey, compute_time_);
}
void FlocId::UpdateStatusAndSaveToPrefs(PrefService* prefs, Status status) {
DCHECK_NE(status, Status::kValid);
DCHECK_NE(status, Status::kInvalidNoStatusPrefs);
status_ = status;
prefs->SetInteger(kFlocIdStatusPrefKey, static_cast<int>(status_));
}
void FlocId::ResetComputeTimeAndSaveToPrefs(base::Time compute_time,
PrefService* prefs) {
compute_time_ = compute_time;
prefs->SetTime(kFlocIdComputeTimePrefKey, compute_time_);
}
// static
FlocId FlocId::ReadFromPrefs(PrefService* prefs) {
Status status = Status::kInvalidNoStatusPrefs;
// We rely on the time to tell whether it's a fresh profile.
if (!prefs->GetTime(kFlocIdComputeTimePrefKey).is_null()) {
// In some previous pref version before the status field is introduced, we
// used to use null path to represent invalid floc. After the status field
// is introduced, that state is represented in status.
if (prefs->HasPrefPath(kFlocIdValuePrefKey)) {
if (prefs->HasPrefPath(kFlocIdStatusPrefKey)) {
status = static_cast<Status>(prefs->GetInteger(kFlocIdStatusPrefKey));
DCHECK_NE(status, Status::kInvalidNoStatusPrefs);
} else {
status = Status::kValid;
}
}
}
return FlocId(prefs->GetUint64(kFlocIdValuePrefKey), status,
prefs->GetTime(kFlocIdHistoryBeginTimePrefKey),
prefs->GetTime(kFlocIdHistoryEndTimePrefKey),
prefs->GetUint64(kFlocIdFinchConfigVersionPrefKey),
prefs->GetUint64(kFlocIdSortingLshVersionPrefKey),
prefs->GetTime(kFlocIdComputeTimePrefKey));
}
FlocId::FlocId(uint64_t id,
Status status,
base::Time history_begin_time,
base::Time history_end_time,
uint32_t finch_config_version,
uint32_t sorting_lsh_version,
base::Time compute_time)
: id_(id),
status_(status),
history_begin_time_(history_begin_time),
history_end_time_(history_end_time),
finch_config_version_(finch_config_version),
sorting_lsh_version_(sorting_lsh_version),
compute_time_(compute_time) {}
} // namespace federated_learning