blob: 7907a1006cc08b522acc5148eef8d6f5fd6a5a49 [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 "services/network/trust_tokens/trust_token_database_owner.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "components/sqlite_proto/key_value_data.h"
#include "components/sqlite_proto/key_value_table.h"
#include "components/sqlite_proto/proto_table_manager.h"
#include "services/network/trust_tokens/proto/storage.pb.h"
namespace network {
namespace {
const char kIssuerTableName[] = "trust_tokens_issuer_config";
const char kToplevelTableName[] = "trust_tokens_toplevel_config";
const char kIssuerToplevelPairTableName[] =
"trust_tokens_issuer_toplevel_pair_config";
} // namespace
void TrustTokenDatabaseOwner::Create(
base::OnceCallback<bool(sql::Database*)> db_opener,
scoped_refptr<base::SequencedTaskRunner> db_task_runner,
base::TimeDelta flush_delay_for_writes,
base::OnceCallback<void(std::unique_ptr<TrustTokenDatabaseOwner>)>
on_done_initializing) {
DCHECK(db_opener);
DCHECK(on_done_initializing);
// No leak: the constructed object wraps itself in a unique_ptr and passes
// that pointer to |on_done_initializing|.
new TrustTokenDatabaseOwner(std::move(db_opener), std::move(db_task_runner),
flush_delay_for_writes,
std::move(on_done_initializing));
}
TrustTokenDatabaseOwner::~TrustTokenDatabaseOwner() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
db_task_runner_->DeleteSoon(FROM_HERE, backing_database_.release());
}
sqlite_proto::KeyValueData<TrustTokenIssuerConfig>*
TrustTokenDatabaseOwner::IssuerData() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return issuer_data_.get();
}
sqlite_proto::KeyValueData<TrustTokenToplevelConfig>*
TrustTokenDatabaseOwner::ToplevelData() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return toplevel_data_.get();
}
sqlite_proto::KeyValueData<TrustTokenIssuerToplevelPairConfig>*
TrustTokenDatabaseOwner::IssuerToplevelPairData() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return issuer_toplevel_pair_data_.get();
}
// Marking NOINLINE saves a few hundred bytes of binary size.
NOINLINE TrustTokenDatabaseOwner::TrustTokenDatabaseOwner(
base::OnceCallback<bool(sql::Database*)> db_opener,
scoped_refptr<base::SequencedTaskRunner> db_task_runner,
base::TimeDelta flush_delay_for_writes,
base::OnceCallback<void(std::unique_ptr<TrustTokenDatabaseOwner>)>
on_done_initializing)
: on_done_initializing_(std::move(on_done_initializing)),
table_manager_(base::MakeRefCounted<sqlite_proto::ProtoTableManager>(
db_task_runner)),
db_task_runner_(db_task_runner),
backing_database_(std::make_unique<sql::Database>()),
issuer_table_(
std::make_unique<sqlite_proto::KeyValueTable<TrustTokenIssuerConfig>>(
kIssuerTableName)),
issuer_data_(
std::make_unique<sqlite_proto::KeyValueData<TrustTokenIssuerConfig>>(
table_manager_,
issuer_table_.get(),
/*max_num_entries=*/base::nullopt,
flush_delay_for_writes)),
toplevel_table_(std::make_unique<
sqlite_proto::KeyValueTable<TrustTokenToplevelConfig>>(
kToplevelTableName)),
toplevel_data_(std::make_unique<
sqlite_proto::KeyValueData<TrustTokenToplevelConfig>>(
table_manager_,
toplevel_table_.get(),
/*max_num_entries=*/base::nullopt,
flush_delay_for_writes)),
issuer_toplevel_pair_table_(
std::make_unique<
sqlite_proto::KeyValueTable<TrustTokenIssuerToplevelPairConfig>>(
kIssuerToplevelPairTableName)),
issuer_toplevel_pair_data_(
std::make_unique<
sqlite_proto::KeyValueData<TrustTokenIssuerToplevelPairConfig>>(
table_manager_,
issuer_toplevel_pair_table_.get(),
/*max_num_entries=*/base::nullopt,
flush_delay_for_writes)) {
// These two lines are boilerplate copied from predictor_database.cc.
backing_database_->set_histogram_tag("TrustTokens");
// We have to call this because the database doesn't have a "meta" table.
backing_database_->set_mmap_alt_status();
// Because TrustTokenDatabaseOwners are only constructed through an
// asynchronous factory method, they are impossible to delete prior to their
// initialization concluding.
db_task_runner->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&TrustTokenDatabaseOwner::InitializeMembersOnDbSequence,
base::Unretained(this), std::move(db_opener)),
base::BindOnce(
&TrustTokenDatabaseOwner::FinishInitializationOnMainSequence,
base::Unretained(this)));
}
void TrustTokenDatabaseOwner::InitializeMembersOnDbSequence(
base::OnceCallback<bool(sql::Database*)> db_opener) {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
if (backing_database_ && !std::move(db_opener).Run(backing_database_.get())) {
// Giving a nullptr database to ProtoTableManager results in the
// operations it executes no-opping, so KeyValueData will fall back to
// reasonable behavior of caching operations' results in memory but not
// writing them to disk.
backing_database_.reset();
}
DCHECK(!backing_database_ || backing_database_->is_open());
if (backing_database_)
backing_database_->Preload();
table_manager_->InitializeOnDbSequence(
backing_database_.get(),
std::vector<std::string>{kIssuerTableName, kToplevelTableName,
kIssuerToplevelPairTableName});
issuer_data_->InitializeOnDBSequence();
toplevel_data_->InitializeOnDBSequence();
issuer_toplevel_pair_data_->InitializeOnDBSequence();
}
void TrustTokenDatabaseOwner::FinishInitializationOnMainSequence() {
// Note: If the backing database fails to initialize,
// InitializeMembersOnDbSequence will provide the table manager a null DB
// pointer, which will make attempts to execute database operations no-op,
// so that the KeyValueData handles fall back to just storing this session's
// Trust Tokens data in memory.
//
// We still consider the TrustTokenDatabaseOwner as having initialized
// "successfully" in this case, since it is safe to execute operations in
// this single-session fallback state.
DCHECK(on_done_initializing_);
std::move(on_done_initializing_).Run(base::WrapUnique(this));
}
} // namespace network