blob: 71a3439394680a07bec5c8a125f78de38c5c47cd [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "storage/browser/quota/quota_database_migrations.h"
#include <string>
#include "base/metrics/histogram_functions.h"
#include "base/sequence_checker.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "components/services/storage/public/cpp/buckets/bucket_id.h"
#include "components/services/storage/public/cpp/buckets/constants.h"
#include "sql/database.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/transaction.h"
#include "storage/browser/quota/quota_database.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/buckets/bucket_manager_host.mojom.h"
namespace storage {
namespace {
// Quota type for deprecated temporary quota.
constexpr int kDeprecatedTemporaryQuotaType = 0;
} // namespace
// static
bool QuotaDatabaseMigrations::UpgradeSchema(QuotaDatabase& quota_database) {
DCHECK_CALLED_ON_VALID_SEQUENCE(quota_database.sequence_checker_);
DCHECK_EQ(0, quota_database.db_->transaction_nesting());
// Reset tables for versions lower than 10 since they are unsupported.
if (quota_database.meta_table_->GetVersionNumber() < 10) {
return false;
}
if (quota_database.meta_table_->GetVersionNumber() == 10) {
bool success = MigrateFromVersion10ToVersion11(quota_database);
RecordMigrationHistogram(/*old_version=*/10, /*new_version=*/11, success);
if (!success) {
return false;
}
}
return quota_database.meta_table_->GetVersionNumber() == 11;
}
void QuotaDatabaseMigrations::RecordMigrationHistogram(int old_version,
int new_version,
bool success) {
base::UmaHistogramBoolean(
base::StrCat({"Quota.DatabaseMigrationFromV",
base::NumberToString(old_version), "ToV",
base::NumberToString(new_version)}),
success);
}
bool QuotaDatabaseMigrations::MigrateFromVersion10ToVersion11(
QuotaDatabase& quota_database) {
DCHECK_CALLED_ON_VALID_SEQUENCE(quota_database.sequence_checker_);
sql::Database* db = quota_database.db_.get();
sql::Transaction transaction(db);
if (!transaction.Begin()) {
return false;
}
// Delete buckets that aren't of the temporary type (see crbug.com/40211051).
static constexpr char kDeleteTemporaryTypeBuckets[] =
"DELETE FROM buckets WHERE type != ? ";
sql::Statement delete_statement(
db->GetCachedStatement(SQL_FROM_HERE, kDeleteTemporaryTypeBuckets));
delete_statement.BindInt(0, kDeprecatedTemporaryQuotaType);
if (!delete_statement.Run()) {
return false;
}
// Drop all indices with type (see crbug.com/40211051).
static constexpr char kDropStorageKeyIndex[] =
"DROP INDEX buckets_by_storage_key";
if (!db->Execute(kDropStorageKeyIndex)) {
return false;
}
static constexpr char kDropHostIndex[] = "DROP INDEX buckets_by_host";
if (!db->Execute(kDropHostIndex)) {
return false;
}
static constexpr char kDropLastAccessedIndex[] =
"DROP INDEX buckets_by_last_accessed";
if (!db->Execute(kDropLastAccessedIndex)) {
return false;
}
static constexpr char kDropLastModifiedIndex[] =
"DROP INDEX buckets_by_last_modified";
if (!db->Execute(kDropLastModifiedIndex)) {
return false;
}
// Drop type column from buckets table (see crbug.com/40211051).
static constexpr char kDropTypeColumn[] =
"ALTER TABLE buckets DROP COLUMN type";
sql::Statement drop_statement(
db->GetCachedStatement(SQL_FROM_HERE, kDropTypeColumn));
if (!drop_statement.Run()) {
return false;
}
// Create all dropped indices without type (see crbug.com/40211051).
static constexpr char kCreateStorageKeyIndex[] =
"CREATE UNIQUE INDEX buckets_by_storage_key ON buckets(storage_key, "
"name)";
if (!db->Execute(kCreateStorageKeyIndex)) {
return false;
}
static constexpr char kCreateHostIndex[] =
"CREATE INDEX buckets_by_host ON buckets(host)";
if (!db->Execute(kCreateHostIndex)) {
return false;
}
static constexpr char kCreateLastAccessedIndex[] =
"CREATE INDEX buckets_by_last_accessed ON buckets(last_accessed)";
if (!db->Execute(kCreateLastAccessedIndex)) {
return false;
}
static constexpr char kCreateLastModifiedIndex[] =
"CREATE INDEX buckets_by_last_modified ON buckets(last_modified);";
if (!db->Execute(kCreateLastModifiedIndex)) {
return false;
}
// Mark database as up to date.
return quota_database.meta_table_->SetVersionNumber(11) &&
quota_database.meta_table_->SetCompatibleVersionNumber(11) &&
transaction.Commit();
}
} // namespace storage