[go: nahoru, domu]

blob: 7ed66654eb5ab2b9faad262040fae1746d31e858 [file] [log] [blame]
// 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 "services/network/trust_tokens/sqlite_trust_token_persister.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_split.h"
#include "base/task/sequenced_task_runner.h"
#include "components/sqlite_proto/key_value_data.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/trust_tokens/proto/storage.pb.h"
#include "services/network/trust_tokens/trust_token_database_owner.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/url_constants.h"
namespace network {
namespace {
const char kIssuerToplevelKeySeparator[] = " ";
// Converts an (issuer, top-level origin) pair keying Trust Tokens state into a
// unique string suitable for indexing persistent storage. Changes should be
// kept in sync with |FromKey|.
std::string ToKey(const SuitableTrustTokenOrigin& issuer,
const SuitableTrustTokenOrigin& toplevel) {
// U+0020 space is a character forbidden in schemes/hosts/ports, so it
// shouldn't appear in the serialization of either origin, preventing
// collisions.
return issuer.Serialize() + kIssuerToplevelKeySeparator +
toplevel.Serialize();
}
// Attempts to deserialize |key_from_database| fresh off the disk. This might
// not be the output of |ToKey| because of corruption during storage on disk:
// returns false on failure.
//
// The parameters |issuer| and |toplevel| are pointers-to-optionals because
// SuitableTrustTokenOrigin does not have a default constructor.
bool FromKey(base::StringPiece key_from_database,
absl::optional<SuitableTrustTokenOrigin>* issuer,
absl::optional<SuitableTrustTokenOrigin>* toplevel) {
DCHECK(issuer);
DCHECK(toplevel);
auto pieces =
base::SplitStringPiece(key_from_database, kIssuerToplevelKeySeparator,
base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
if (pieces.size() != 2)
return false;
*issuer = SuitableTrustTokenOrigin::Create(GURL(pieces[0]));
*toplevel = SuitableTrustTokenOrigin::Create(GURL(pieces[1]));
return issuer->has_value() && toplevel->has_value();
}
void OnDatabaseOwnerCreated(
base::OnceCallback<void(std::unique_ptr<SQLiteTrustTokenPersister>)>
on_done_initializing,
std::unique_ptr<TrustTokenDatabaseOwner> database_owner) {
auto ret =
std::make_unique<SQLiteTrustTokenPersister>(std::move(database_owner));
std::move(on_done_initializing).Run(std::move(ret));
}
template <typename T>
bool DeleteOriginKeyedKeyValueData(
base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher,
sqlite_proto::KeyValueData<T>* key_value_data) {
DCHECK(key_value_data);
std::vector<std::string> keys_to_delete;
bool data_from_filter_was_deleted = false;
for (const auto& kv : key_value_data->GetAllCached()) {
// Creation can fail if the record was corrupted on disk.
absl::optional<SuitableTrustTokenOrigin> maybe_key =
SuitableTrustTokenOrigin::Create(GURL(kv.first));
// If the record's key is corrupt, delete the record no matter what, but
// don't record the deletion request as having led to data being deleted.
if (!maybe_key) {
keys_to_delete.push_back(kv.first);
continue;
}
if (matcher.Run(*maybe_key)) {
keys_to_delete.push_back(kv.first);
data_from_filter_was_deleted = true;
}
}
key_value_data->DeleteData(keys_to_delete);
return data_from_filter_was_deleted;
}
bool DeleteMatchingIssuerToplevelPairData(
base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher,
sqlite_proto::KeyValueData<TrustTokenIssuerToplevelPairConfig>*
key_value_data) {
std::vector<std::string> keys_to_delete;
bool data_from_filter_was_deleted = false;
for (const auto& kv : key_value_data->GetAllCached()) {
absl::optional<SuitableTrustTokenOrigin> maybe_issuer;
absl::optional<SuitableTrustTokenOrigin> maybe_toplevel;
// If the record's key is corrupt, delete the record no matter what, but
// don't record the deletion request as having led to data being deleted.
if (!FromKey(kv.first, &maybe_issuer, &maybe_toplevel)) {
keys_to_delete.push_back(kv.first);
continue;
}
if (matcher.Run(*maybe_issuer) || matcher.Run(*maybe_toplevel)) {
keys_to_delete.push_back(kv.first);
data_from_filter_was_deleted = true;
}
}
key_value_data->DeleteData(keys_to_delete);
return data_from_filter_was_deleted;
}
} // namespace
SQLiteTrustTokenPersister::SQLiteTrustTokenPersister(
std::unique_ptr<TrustTokenDatabaseOwner> database_owner)
: database_owner_(std::move(database_owner)) {}
SQLiteTrustTokenPersister::~SQLiteTrustTokenPersister() = default;
void SQLiteTrustTokenPersister::CreateForFilePath(
scoped_refptr<base::SequencedTaskRunner> db_task_runner,
const base::FilePath& path,
base::TimeDelta flush_delay_for_writes,
base::OnceCallback<void(std::unique_ptr<SQLiteTrustTokenPersister>)>
on_done_initializing) {
TrustTokenDatabaseOwner::Create(
/*db_opener=*/base::BindOnce(
[](const base::FilePath& path, sql::Database* db) {
const base::FilePath directory = path.DirName();
if (!base::PathExists(directory) &&
!base::CreateDirectory(directory)) {
return false;
}
return db->Open(path);
},
path),
db_task_runner, flush_delay_for_writes,
base::BindOnce(&OnDatabaseOwnerCreated, std::move(on_done_initializing)));
}
std::unique_ptr<TrustTokenIssuerConfig>
SQLiteTrustTokenPersister::GetIssuerConfig(
const SuitableTrustTokenOrigin& issuer) {
auto* data = database_owner_->IssuerData();
CHECK(data);
auto ret = std::make_unique<TrustTokenIssuerConfig>();
return data->TryGetData(issuer.Serialize(), ret.get()) ? std::move(ret)
: nullptr;
}
std::unique_ptr<TrustTokenToplevelConfig>
SQLiteTrustTokenPersister::GetToplevelConfig(
const SuitableTrustTokenOrigin& toplevel) {
auto* data = database_owner_->ToplevelData();
CHECK(data);
auto ret = std::make_unique<TrustTokenToplevelConfig>();
return data->TryGetData(toplevel.Serialize(), ret.get()) ? std::move(ret)
: nullptr;
}
std::unique_ptr<TrustTokenIssuerToplevelPairConfig>
SQLiteTrustTokenPersister::GetIssuerToplevelPairConfig(
const SuitableTrustTokenOrigin& issuer,
const SuitableTrustTokenOrigin& toplevel) {
auto* data = database_owner_->IssuerToplevelPairData();
CHECK(data);
auto ret = std::make_unique<TrustTokenIssuerToplevelPairConfig>();
return data->TryGetData(ToKey(issuer, toplevel), ret.get()) ? std::move(ret)
: nullptr;
}
void SQLiteTrustTokenPersister::SetIssuerConfig(
const SuitableTrustTokenOrigin& issuer,
std::unique_ptr<TrustTokenIssuerConfig> config) {
sqlite_proto::KeyValueData<TrustTokenIssuerConfig>* data =
database_owner_->IssuerData();
CHECK(data);
data->UpdateData(issuer.Serialize(), *config);
}
void SQLiteTrustTokenPersister::SetToplevelConfig(
const SuitableTrustTokenOrigin& toplevel,
std::unique_ptr<TrustTokenToplevelConfig> config) {
sqlite_proto::KeyValueData<TrustTokenToplevelConfig>* data =
database_owner_->ToplevelData();
CHECK(data);
data->UpdateData(toplevel.Serialize(), *config);
}
void SQLiteTrustTokenPersister::SetIssuerToplevelPairConfig(
const SuitableTrustTokenOrigin& issuer,
const SuitableTrustTokenOrigin& toplevel,
std::unique_ptr<TrustTokenIssuerToplevelPairConfig> config) {
sqlite_proto::KeyValueData<TrustTokenIssuerToplevelPairConfig>* data =
database_owner_->IssuerToplevelPairData();
CHECK(data);
data->UpdateData(ToKey(issuer, toplevel), *config);
}
bool SQLiteTrustTokenPersister::DeleteForOrigins(
base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher) {
bool any_data_was_deleted = false;
any_data_was_deleted |=
DeleteOriginKeyedKeyValueData(matcher, database_owner_->IssuerData());
any_data_was_deleted |=
DeleteOriginKeyedKeyValueData(matcher, database_owner_->ToplevelData());
any_data_was_deleted |= DeleteMatchingIssuerToplevelPairData(
matcher, database_owner_->IssuerToplevelPairData());
return any_data_was_deleted;
}
base::flat_map<SuitableTrustTokenOrigin, int>
SQLiteTrustTokenPersister::GetStoredTrustTokenCounts() {
base::flat_map<SuitableTrustTokenOrigin, int> result;
sqlite_proto::KeyValueData<TrustTokenIssuerConfig>* data =
database_owner_->IssuerData();
for (const auto& kv : data->GetAllCached()) {
absl::optional<SuitableTrustTokenOrigin> origin =
SuitableTrustTokenOrigin::Create(GURL(kv.first));
// The Create call can fail when the SQLite data was corrupted on the disk.
if (origin) {
result.emplace(std::move(*origin), kv.second.tokens_size());
}
}
return result;
}
} // namespace network