#include "chrome/browser/safe_browsing/incident_reporting/platform_state_store.h"
#include <optional>
#include "base/values.h"
#if defined(USE_PLATFORM_STATE_STORE)
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/safe_browsing/incident_reporting/state_store_data.pb.h"
#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
#endif
namespace safe_browsing {
namespace platform_state_store {
#if defined(USE_PLATFORM_STATE_STORE)
namespace {
using google::protobuf::RepeatedPtrField;
void KeysAndDigestsToProtobuf(
const base::Value::Dict& keys_and_digests,
RepeatedPtrField<StateStoreData::Incidents::KeyDigestMapFieldEntry>*
key_digest_pairs) {
for (const auto item : keys_and_digests) {
uint32_t digest = 0;
if (!item.second.is_string() ||
!base::StringToUint(item.second.GetString(), &digest)) {
NOTREACHED_IN_MIGRATION();
continue;
}
StateStoreData::Incidents::KeyDigestMapFieldEntry* key_digest =
key_digest_pairs->Add();
key_digest->set_key(item.first);
key_digest->set_digest(digest);
}
}
void IncidentsSentToProtobuf(
const base::Value::Dict& incidents_sent,
RepeatedPtrField<StateStoreData::TypeIncidentsMapFieldEntry>*
type_incidents_pairs) {
for (const auto item : incidents_sent) {
const base::Value::Dict* keys_and_digests = item.second.GetIfDict();
if (!keys_and_digests) {
NOTREACHED_IN_MIGRATION();
continue;
}
if (keys_and_digests->empty())
continue;
int incident_type = 0;
if (!base::StringToInt(item.first, &incident_type)) {
NOTREACHED_IN_MIGRATION();
continue;
}
StateStoreData::TypeIncidentsMapFieldEntry* entry =
type_incidents_pairs->Add();
entry->set_type(incident_type);
KeysAndDigestsToProtobuf(
*keys_and_digests, entry->mutable_incidents()->mutable_key_to_digest());
}
}
void RestoreOfTypeFromProtobuf(
const RepeatedPtrField<StateStoreData::Incidents::KeyDigestMapFieldEntry>&
key_digest_pairs,
base::Value::Dict& type_dict) {
for (const auto& key_digest : key_digest_pairs) {
if (!key_digest.has_key() || !key_digest.has_digest())
continue;
type_dict.Set(key_digest.key(), base::NumberToString(key_digest.digest()));
}
}
void RestoreFromProtobuf(
const RepeatedPtrField<StateStoreData::TypeIncidentsMapFieldEntry>&
type_incidents_pairs,
base::Value::Dict& value_dict) {
for (const auto& type_incidents : type_incidents_pairs) {
if (!type_incidents.has_type() || !type_incidents.has_incidents() ||
type_incidents.incidents().key_to_digest_size() == 0) {
continue;
}
std::string type_string(base::NumberToString(type_incidents.type()));
base::Value::Dict* type_dict = value_dict.EnsureDict(type_string);
RestoreOfTypeFromProtobuf(type_incidents.incidents().key_to_digest(),
*type_dict);
}
}
}
#endif
std::optional<base::Value::Dict> Load(Profile* profile) { … }
void Store(Profile* profile, const base::Value::Dict& incidents_sent) { … }
#if defined(USE_PLATFORM_STATE_STORE)
void SerializeIncidentsSent(const base::Value::Dict& incidents_sent,
std::string* data) {
StateStoreData store_data;
IncidentsSentToProtobuf(incidents_sent,
store_data.mutable_type_to_incidents());
store_data.SerializeToString(data);
}
PlatformStateStoreLoadResult DeserializeIncidentsSent(
const std::string& data,
base::Value::Dict& value_dict) {
StateStoreData store_data;
if (data.empty()) {
value_dict.clear();
return PlatformStateStoreLoadResult::SUCCESS;
}
if (!store_data.ParseFromString(data))
return PlatformStateStoreLoadResult::PARSE_ERROR;
value_dict.clear();
RestoreFromProtobuf(store_data.type_to_incidents(), value_dict);
return PlatformStateStoreLoadResult::SUCCESS;
}
#endif
}
}