// Copyright 2012 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/database/database_tracker.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/containers/contains.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/user_metrics.h"
#include "base/not_fatal_until.h"
#include "base/observer_list.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/types/pass_key.h"
#include "components/services/storage/public/cpp/quota_client_callback_wrapper.h"
#include "components/services/storage/public/mojom/quota_client.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/net_errors.h"
#include "sql/database.h"
#include "sql/meta_table.h"
#include "sql/transaction.h"
#include "storage/browser/database/database_quota_client.h"
#include "storage/browser/database/database_util.h"
#include "storage/browser/database/databases_table.h"
#include "storage/browser/quota/quota_client_type.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "third_party/sqlite/sqlite3.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace storage {

const base::FilePath::CharType kDatabaseDirectoryName[] =
    FILE_PATH_LITERAL("databases");
const base::FilePath::CharType kIncognitoDatabaseDirectoryName[] =
    FILE_PATH_LITERAL("databases-off-the-record");
const base::FilePath::CharType kTrackerDatabaseFileName[] =
    FILE_PATH_LITERAL("Databases.db");
static const int kDatabaseTrackerCurrentSchemaVersion = 2;
static const int kDatabaseTrackerCompatibleVersion = 1;

const base::FilePath::CharType kTemporaryDirectoryPrefix[] =
    FILE_PATH_LITERAL("DeleteMe");
const base::FilePath::CharType kTemporaryDirectoryPattern[] =
    FILE_PATH_LITERAL("DeleteMe*");

OriginInfo::OriginInfo()
    : total_size_(0) {}

OriginInfo::OriginInfo(const OriginInfo& origin_info) = default;

OriginInfo::~OriginInfo() = default;

int64_t OriginInfo::GetDatabaseSize(const std::u16string& database_name) const {
  auto it = database_sizes_.find(database_name);
  if (it != database_sizes_.end())
    return it->second;
  return 0;
}

OriginInfo::OriginInfo(const std::string& origin_identifier, int64_t total_size)
    : origin_identifier_(origin_identifier), total_size_(total_size) {}

scoped_refptr<DatabaseTracker> DatabaseTracker::Create(
    const base::FilePath& profile_path,
    bool is_incognito,
    scoped_refptr<QuotaManagerProxy> quota_manager_proxy) {
  auto database_tracker = base::MakeRefCounted<DatabaseTracker>(
      profile_path, is_incognito, std::move(quota_manager_proxy),
      base::PassKey<DatabaseTracker>());
  database_tracker->RegisterQuotaClient();
  return database_tracker;
}

DatabaseTracker::DatabaseTracker(
    const base::FilePath& profile_path,
    bool is_incognito,
    scoped_refptr<QuotaManagerProxy> quota_manager_proxy,
    base::PassKey<DatabaseTracker>)
    : is_incognito_(is_incognito),
      profile_path_(profile_path),
      db_dir_(is_incognito_
                  ? profile_path_.Append(kIncognitoDatabaseDirectoryName)
                  : profile_path_.Append(kDatabaseDirectoryName)),
      db_(std::make_unique<sql::Database>(
          sql::Database::Tag("DatabaseTracker"))),
      quota_manager_proxy_(std::move(quota_manager_proxy)),
      task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
           // SKIP_ON_SHUTDOWN cannot be used because Shutdown() needs to run
           // before the destructor, and Shutdown() is ran by PostTask()ing to
           // this sequence. See https://crbug.com/1220191.
           //
           // We may be able to switch to SKIP_ON_SHUTDOWN if we get
           // DatabaseTracker to be used entirely on the database sequence, so
           // the destructor can absorb the logic that is currently in
           // Shutdown().
           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
      quota_client_(std::make_unique<DatabaseQuotaClient>(*this)),
      quota_client_wrapper_(
          std::make_unique<QuotaClientCallbackWrapper>(quota_client_.get())),
      quota_client_receiver_(quota_client_wrapper_.get()) {}

DatabaseTracker::~DatabaseTracker() {
  // base::RefCountedThreadSafe inserts the appropriate barriers to ensure
  // member access in the destructor does not introduce data races.
  DCHECK(dbs_to_be_deleted_.empty());
  DCHECK(deletion_callbacks_.empty());

  DCHECK(!quota_client_);
  DCHECK(!quota_client_wrapper_);
  DCHECK(!quota_client_receiver_.is_bound());
}

void DatabaseTracker::RegisterQuotaClient() {
  if (!quota_manager_proxy_)
    return;

  // QuotaManagerProxy::RegisterClient() must be called synchronously during
  // DatabaseTracker creation until crbug.com/1182630 is fixed.
  mojo::PendingRemote<storage::mojom::QuotaClient> quota_client_remote;
  mojo::PendingReceiver<storage::mojom::QuotaClient> quota_client_receiver =
      quota_client_remote.InitWithNewPipeAndPassReceiver();
  quota_manager_proxy_->RegisterClient(std::move(quota_client_remote),
                                       storage::QuotaClientType::kDatabase,
                                       {blink::mojom::StorageType::kTemporary});

  task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](scoped_refptr<DatabaseTracker> self,
             mojo::PendingReceiver<storage::mojom::QuotaClient> receiver) {
            self->quota_client_receiver_.Bind(std::move(receiver));
          },
          base::RetainedRef(this), std::move(quota_client_receiver)));
}

void DatabaseTracker::DatabaseOpened(const std::string& origin_identifier,
                                     const std::u16string& database_name,
                                     const std::u16string& database_description,
                                     int64_t* database_size) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (shutting_down_ || !LazyInit()) {
    *database_size = 0;
    return;
  }

  if (quota_manager_proxy_.get())
    quota_manager_proxy_->NotifyBucketAccessed(
        BucketLocator::ForDefaultBucket(blink::StorageKey::CreateFirstParty(
            GetOriginFromIdentifier(origin_identifier))),
        base::Time::Now());

  InsertOrUpdateDatabaseDetails(origin_identifier, database_name,
                                database_description);
  if (database_connections_.AddConnection(origin_identifier, database_name)) {
    *database_size = SeedOpenDatabaseInfo(origin_identifier,
                                          database_name,
                                          database_description);
    return;
  }
  *database_size  = UpdateOpenDatabaseInfoAndNotify(origin_identifier,
                                                    database_name,
                                                    &database_description);
}

void DatabaseTracker::DatabaseModified(const std::string& origin_identifier,
                                       const std::u16string& database_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (!LazyInit())
    return;
  UpdateOpenDatabaseSizeAndNotify(origin_identifier, database_name);
}

void DatabaseTracker::DatabaseClosed(const std::string& origin_identifier,
                                     const std::u16string& database_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (database_connections_.IsEmpty()) {
    DCHECK(!is_initialized_);
    return;
  }

  // We call NotifiyStorageAccessed when a db is opened and also when
  // closed because we don't call it for read while open.
  if (quota_manager_proxy_.get())
    quota_manager_proxy_->NotifyBucketAccessed(
        BucketLocator::ForDefaultBucket(blink::StorageKey::CreateFirstParty(
            GetOriginFromIdentifier(origin_identifier))),
        base::Time::Now());

  UpdateOpenDatabaseSizeAndNotify(origin_identifier, database_name);
  if (database_connections_.RemoveConnection(origin_identifier, database_name))
    DeleteDatabaseIfNeeded(origin_identifier, database_name);
}

void DatabaseTracker::HandleSqliteError(const std::string& origin_identifier,
                                        const std::u16string& database_name,
                                        int error) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  // We only handle errors that indicate corruption and we
  // do so with a heavy hand, we delete it. Any renderers/workers
  // with this database open will receive a message to close it
  // immediately, once all have closed, the files will be deleted.
  // In the interim, all attempts to open a new connection to that
  // database will fail.
  // Note: the client-side filters out all but these two errors as
  // a small optimization, see WebDatabaseObserverImpl::HandleSqliteError.
  if (error == SQLITE_CORRUPT || error == SQLITE_NOTADB) {
    DeleteDatabase(origin_identifier, database_name, base::DoNothing());
  }
}

void DatabaseTracker::CloseDatabases(const DatabaseConnections& connections) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (database_connections_.IsEmpty()) {
    DCHECK(!is_initialized_ || connections.IsEmpty());
    return;
  }

  // When being closed by this route, there's a chance that
  // the tracker missed some DatabaseModified calls. This method is used
  // when a renderer crashes to cleanup its open resources.
  // We need to examine what we have in connections for the
  // size of each open databases and notify any differences between the
  // actual file sizes now.
  for (auto& pair : connections.ListConnections())
    UpdateOpenDatabaseSizeAndNotify(pair.first, pair.second);

  for (auto& pair : database_connections_.RemoveConnections(connections))
    DeleteDatabaseIfNeeded(pair.first, pair.second);
}

void DatabaseTracker::DeleteDatabaseIfNeeded(
    const std::string& origin_identifier,
    const std::u16string& database_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(!database_connections_.IsDatabaseOpened(origin_identifier,
                                                 database_name));
  if (IsDatabaseScheduledForDeletion(origin_identifier, database_name)) {
    DeleteClosedDatabase(origin_identifier, database_name);
    dbs_to_be_deleted_[origin_identifier].erase(database_name);
    if (dbs_to_be_deleted_[origin_identifier].empty())
      dbs_to_be_deleted_.erase(origin_identifier);

    auto callback = deletion_callbacks_.begin();
    while (callback != deletion_callbacks_.end()) {
      auto found_origin = callback->second.find(origin_identifier);
      if (found_origin != callback->second.end()) {
        std::set<std::u16string>& databases = found_origin->second;
        databases.erase(database_name);
        if (databases.empty()) {
          callback->second.erase(found_origin);
          if (callback->second.empty()) {
            std::move(callback->first).Run(net::OK);
            callback = deletion_callbacks_.erase(callback);
            continue;
          }
        }
      }

      ++callback;
    }
  }
}

void DatabaseTracker::AddObserver(Observer* observer) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  observers_.AddObserver(observer);
}

void DatabaseTracker::RemoveObserver(Observer* observer) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  // When we remove a listener, we do not know which cached information
  // is still needed and which information can be discarded. So we just
  // clear all caches and re-populate them as needed.
  observers_.RemoveObserver(observer);
  ClearAllCachedOriginInfo();
}

void DatabaseTracker::CloseTrackerDatabaseAndClearCaches() {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  ClearAllCachedOriginInfo();

  if (!is_incognito_) {
    meta_table_.reset(nullptr);
    databases_table_.reset(nullptr);
    db_->Close();
    is_initialized_ = false;
  }
}

base::FilePath DatabaseTracker::GetOriginDirectory(
    const std::string& origin_identifier) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());

  std::u16string origin_directory;

  if (!is_incognito_) {
    origin_directory = base::UTF8ToUTF16(origin_identifier);
  } else {
    auto it = incognito_origin_directories_.find(origin_identifier);
    if (it != incognito_origin_directories_.end()) {
      origin_directory = it->second;
    } else {
      origin_directory =
          base::NumberToString16(incognito_origin_directories_generator_++);
      incognito_origin_directories_[origin_identifier] = origin_directory;
    }
  }

  return db_dir_.Append(base::FilePath::FromUTF16Unsafe(origin_directory));
}

base::FilePath DatabaseTracker::GetFullDBFilePath(
    const std::string& origin_identifier,
    const std::u16string& database_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(!origin_identifier.empty());
  if (!LazyInit())
    return base::FilePath();

  int64_t id =
      databases_table_->GetDatabaseID(origin_identifier, database_name);
  if (id < 0)
    return base::FilePath();

  return GetOriginDirectory(origin_identifier)
      .AppendASCII(base::NumberToString(id));
}

bool DatabaseTracker::GetOriginInfo(const std::string& origin_identifier,
                                    OriginInfo* info) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(info);
  CachedOriginInfo* cached_info = GetCachedOriginInfo(origin_identifier);
  if (!cached_info)
    return false;
  *info = OriginInfo(*cached_info);
  return true;
}

bool DatabaseTracker::GetAllOriginIdentifiers(
    std::vector<std::string>* origin_identifiers) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(origin_identifiers);
  DCHECK(origin_identifiers->empty());
  if (!LazyInit())
    return false;
  return databases_table_->GetAllOriginIdentifiers(origin_identifiers);
}

bool DatabaseTracker::GetAllOriginsInfo(
    std::vector<OriginInfo>* origins_info) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(origins_info);
  DCHECK(origins_info->empty());

  std::vector<std::string> origins;
  if (!GetAllOriginIdentifiers(&origins))
    return false;

  for (const auto& origin : origins) {
    CachedOriginInfo* origin_info = GetCachedOriginInfo(origin);
    if (!origin_info) {
      // Restore 'origins_info' to its initial state.
      origins_info->clear();
      return false;
    }
    origins_info->push_back(OriginInfo(*origin_info));
  }

  return true;
}

bool DatabaseTracker::DeleteClosedDatabase(
    const std::string& origin_identifier,
    const std::u16string& database_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (!LazyInit())
    return false;

  // Check if the database is opened by any renderer.
  if (database_connections_.IsDatabaseOpened(origin_identifier, database_name))
    return false;

  int64_t db_file_size = quota_manager_proxy_.get()
                             ? GetDBFileSize(origin_identifier, database_name)
                             : 0;

  // Try to delete the file on the hard drive.
  base::FilePath db_file = GetFullDBFilePath(origin_identifier, database_name);
  if (!sql::Database::Delete(db_file))
    return false;

  if (quota_manager_proxy_.get() && db_file_size) {
    quota_manager_proxy_->NotifyBucketModified(
        QuotaClientType::kDatabase,
        BucketLocator::ForDefaultBucket(blink::StorageKey::CreateFirstParty(
            GetOriginFromIdentifier(origin_identifier))),
        -db_file_size, base::Time::Now(),
        base::SequencedTaskRunner::GetCurrentDefault(), base::DoNothing());
  }

  // Clean up the main database and invalidate the cached record.
  databases_table_->DeleteDatabaseDetails(origin_identifier, database_name);
  origins_info_map_.erase(origin_identifier);

  std::vector<DatabaseDetails> details;
  if (databases_table_->GetAllDatabaseDetailsForOriginIdentifier(
          origin_identifier, &details) && details.empty()) {
    // Try to delete the origin in case this was the last database.
    DeleteOrigin(origin_identifier, false);
  }
  return true;
}

bool DatabaseTracker::DeleteOrigin(const std::string& origin_identifier,
                                   bool force) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (!LazyInit())
    return false;

  // Check if any database in this origin is opened by any renderer.
  if (database_connections_.IsOriginUsed(origin_identifier) && !force)
    return false;

  int64_t deleted_size = 0;
  if (quota_manager_proxy_.get()) {
    CachedOriginInfo* origin_info = GetCachedOriginInfo(origin_identifier);
    if (origin_info)
      deleted_size = origin_info->TotalSize();
  }

  origins_info_map_.erase(origin_identifier);
  base::FilePath origin_dir = GetOriginDirectory(origin_identifier);

  // Create a temporary directory to move possibly still existing databases to,
  // as we can't delete the origin directory on windows if it contains opened
  // files.
  base::FilePath new_origin_dir;
  base::CreateTemporaryDirInDir(db_dir_,
                                kTemporaryDirectoryPrefix,
                                &new_origin_dir);
  base::FileEnumerator databases(
      origin_dir,
      false,
      base::FileEnumerator::FILES);
  for (base::FilePath database = databases.Next(); !database.empty();
       database = databases.Next()) {
    base::FilePath new_file = new_origin_dir.Append(database.BaseName());
    base::Move(database, new_file);
  }
  base::DeletePathRecursively(origin_dir);
  base::DeletePathRecursively(new_origin_dir);  // Might fail on windows.

  if (is_incognito_) {
    incognito_origin_directories_.erase(origin_identifier);

    // TODO(jsbell): Consider alternate data structures to avoid this
    // linear scan.
    for (auto it = incognito_file_handles_.begin();
         it != incognito_file_handles_.end();) {
      std::string id;
      if (DatabaseUtil::CrackVfsFileName(it->first, &id, nullptr, nullptr) &&
          id == origin_identifier) {
        delete it->second;
        it = incognito_file_handles_.erase(it);
      } else {
        ++it;
      }
    }
  }

  databases_table_->DeleteOriginIdentifier(origin_identifier);

  if (quota_manager_proxy_.get() && deleted_size) {
    quota_manager_proxy_->NotifyBucketModified(
        QuotaClientType::kDatabase,
        BucketLocator::ForDefaultBucket(blink::StorageKey::CreateFirstParty(
            GetOriginFromIdentifier(origin_identifier))),
        -deleted_size, base::Time::Now(),
        base::SequencedTaskRunner::GetCurrentDefault(), base::DoNothing());
  }

  return true;
}

bool DatabaseTracker::IsDatabaseScheduledForDeletion(
    const std::string& origin_identifier,
    const std::u16string& database_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  auto it = dbs_to_be_deleted_.find(origin_identifier);
  if (it == dbs_to_be_deleted_.end())
    return false;

  const std::set<std::u16string>& databases = it->second;
  return (databases.find(database_name) != databases.end());
}

bool DatabaseTracker::LazyInit() {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (!is_initialized_ && !shutting_down_) {
    DCHECK(!db_->is_open());
    DCHECK(!databases_table_.get());
    DCHECK(!meta_table_.get());

    // If there are left-over directories from failed deletion attempts, clean
    // them up.
    if (base::DirectoryExists(db_dir_)) {
      base::FileEnumerator directories(
          db_dir_,
          false,
          base::FileEnumerator::DIRECTORIES,
          kTemporaryDirectoryPattern);
      for (base::FilePath directory = directories.Next(); !directory.empty();
           directory = directories.Next()) {
        base::DeletePathRecursively(directory);
      }
    }

    // If the tracker database exists, but it's corrupt or doesn't
    // have a meta table, delete the database directory.
    const base::FilePath kTrackerDatabaseFullPath =
        db_dir_.Append(base::FilePath(kTrackerDatabaseFileName));
    if (base::DirectoryExists(db_dir_) &&
        base::PathExists(kTrackerDatabaseFullPath) &&
        (!db_->Open(kTrackerDatabaseFullPath) ||
         !sql::MetaTable::DoesTableExist(db_.get()))) {
      db_->Close();
      if (!base::DeletePathRecursively(db_dir_))
        return false;
    }

    databases_table_ = std::make_unique<DatabasesTable>(db_.get());
    meta_table_ = std::make_unique<sql::MetaTable>();

    is_initialized_ = base::CreateDirectory(db_dir_) &&
                      (db_->is_open() ||
                       (is_incognito_ ? db_->OpenInMemory()
                                      : db_->Open(kTrackerDatabaseFullPath))) &&
                      UpgradeToCurrentVersion();
    if (!is_initialized_) {
      databases_table_.reset(nullptr);
      meta_table_.reset(nullptr);
      db_->Close();
    }
  }
  return is_initialized_;
}

bool DatabaseTracker::UpgradeToCurrentVersion() {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  sql::Transaction transaction(db_.get());
  if (!transaction.Begin() ||
      !meta_table_->Init(db_.get(), kDatabaseTrackerCurrentSchemaVersion,
                         kDatabaseTrackerCompatibleVersion) ||
      (meta_table_->GetCompatibleVersionNumber() >
       kDatabaseTrackerCurrentSchemaVersion) ||
      !databases_table_->Init())
    return false;

  if (meta_table_->GetVersionNumber() < kDatabaseTrackerCurrentSchemaVersion &&
      !meta_table_->SetVersionNumber(kDatabaseTrackerCurrentSchemaVersion)) {
    return false;
  }

  return transaction.Commit();
}

void DatabaseTracker::InsertOrUpdateDatabaseDetails(
    const std::string& origin_identifier,
    const std::u16string& database_name,
    const std::u16string& database_description) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DatabaseDetails details;
  if (!databases_table_->GetDatabaseDetails(
          origin_identifier, database_name, &details)) {
    details.origin_identifier = origin_identifier;
    details.database_name = database_name;
    details.description = database_description;
    databases_table_->InsertDatabaseDetails(details);
  } else if (details.description != database_description) {
    details.description = database_description;
    databases_table_->UpdateDatabaseDetails(details);
  }
}

void DatabaseTracker::ClearAllCachedOriginInfo() {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  origins_info_map_.clear();
}

DatabaseTracker::CachedOriginInfo* DatabaseTracker::MaybeGetCachedOriginInfo(
    const std::string& origin_identifier, bool create_if_needed) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (!LazyInit())
    return nullptr;

  // Populate the cache with data for this origin if needed.
  if (!base::Contains(origins_info_map_, origin_identifier)) {
    if (!create_if_needed)
      return nullptr;

    std::vector<DatabaseDetails> details;
    if (!databases_table_->GetAllDatabaseDetailsForOriginIdentifier(
            origin_identifier, &details)) {
      return nullptr;
    }

    CachedOriginInfo& origin_info = origins_info_map_[origin_identifier];
    origin_info.SetOriginIdentifier(origin_identifier);
    for (const auto& db : details) {
      int64_t db_file_size;
      if (database_connections_.IsDatabaseOpened(origin_identifier,
                                                 db.database_name)) {
        db_file_size = database_connections_.GetOpenDatabaseSize(
            origin_identifier, db.database_name);
      } else {
        db_file_size = GetDBFileSize(origin_identifier, db.database_name);
      }
      origin_info.SetDatabaseSize(db.database_name, db_file_size);

      base::FilePath path =
          GetFullDBFilePath(origin_identifier, db.database_name);
      base::File::Info file_info;
      // TODO(jsbell): Avoid duplicate base::GetFileInfo calls between this and
      // the GetDBFileSize() call above.
      if (base::GetFileInfo(path, &file_info)) {
        origin_info.UpdateLastModified(file_info.last_modified);
      }
    }
  }

  return &origins_info_map_[origin_identifier];
}

int64_t DatabaseTracker::GetDBFileSize(const std::string& origin_identifier,
                                       const std::u16string& database_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  base::FilePath db_file_name = GetFullDBFilePath(origin_identifier,
                                                  database_name);
  return base::GetFileSize(db_file_name).value_or(0);
}

int64_t DatabaseTracker::SeedOpenDatabaseInfo(
    const std::string& origin_id,
    const std::u16string& name,
    const std::u16string& description) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(database_connections_.IsDatabaseOpened(origin_id, name));
  int64_t size = GetDBFileSize(origin_id, name);
  database_connections_.SetOpenDatabaseSize(origin_id, name,  size);
  CachedOriginInfo* info = MaybeGetCachedOriginInfo(origin_id, false);
  if (info) {
    info->SetDatabaseSize(name, size);
  }
  return size;
}

int64_t DatabaseTracker::UpdateOpenDatabaseInfoAndNotify(
    const std::string& origin_id,
    const std::u16string& name,
    const std::u16string* opt_description) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(database_connections_.IsDatabaseOpened(origin_id, name));
  int64_t new_size = GetDBFileSize(origin_id, name);
  int64_t old_size = database_connections_.GetOpenDatabaseSize(origin_id, name);
  CachedOriginInfo* info = MaybeGetCachedOriginInfo(origin_id, false);
  if (old_size != new_size) {
    database_connections_.SetOpenDatabaseSize(origin_id, name, new_size);
    if (info)
      info->SetDatabaseSize(name, new_size);

    if (quota_manager_proxy_.get()) {
      quota_manager_proxy_->NotifyBucketModified(
          QuotaClientType::kDatabase,
          BucketLocator::ForDefaultBucket(blink::StorageKey::CreateFirstParty(
              GetOriginFromIdentifier(origin_id))),
          new_size - old_size, base::Time::Now(),
          base::SequencedTaskRunner::GetCurrentDefault(), base::DoNothing());
    }

    for (auto& observer : observers_)
      observer.OnDatabaseSizeChanged(origin_id, name, new_size);
  }
  return new_size;
}

void DatabaseTracker::ScheduleDatabaseForDeletion(
    const std::string& origin_identifier,
    const std::u16string& database_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(database_connections_.IsDatabaseOpened(origin_identifier,
                                                database_name));
  dbs_to_be_deleted_[origin_identifier].insert(database_name);
  for (auto& observer : observers_)
    observer.OnDatabaseScheduledForDeletion(origin_identifier, database_name);
}

void DatabaseTracker::ScheduleDatabasesForDeletion(
    const DatabaseSet& databases,
    net::CompletionOnceCallback callback) {
  DCHECK(!databases.empty());

  if (!callback.is_null())
    deletion_callbacks_.emplace_back(std::move(callback), databases);
  for (const auto& origin_dbs : databases) {
    for (const std::u16string& db : origin_dbs.second)
      ScheduleDatabaseForDeletion(origin_dbs.first, db);
  }
}

void DatabaseTracker::DeleteDatabase(const std::string& origin_identifier,
                                     const std::u16string& database_name,
                                     net::CompletionOnceCallback callback) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(!callback.is_null());
  if (!LazyInit()) {
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }

  if (database_connections_.IsDatabaseOpened(origin_identifier,
                                             database_name)) {
    DatabaseSet set;
    set[origin_identifier].insert(database_name);
    deletion_callbacks_.emplace_back(std::move(callback), std::move(set));
    ScheduleDatabaseForDeletion(origin_identifier, database_name);
    return;
  }

  DeleteClosedDatabase(origin_identifier, database_name);
  std::move(callback).Run(net::OK);
}

void DatabaseTracker::DeleteDataModifiedSince(
    const base::Time& cutoff,
    net::CompletionOnceCallback callback) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(!callback.is_null());
  if (!LazyInit()) {
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }

  std::vector<std::string> origins_identifiers;
  if (!databases_table_->GetAllOriginIdentifiers(&origins_identifiers)) {
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }

  DatabaseSet to_be_deleted;
  int rv = net::OK;
  for (const auto& origin : origins_identifiers) {
    std::vector<DatabaseDetails> details;
    if (!databases_table_->GetAllDatabaseDetailsForOriginIdentifier(origin,
                                                                    &details)) {
      rv = net::ERR_FAILED;
    }
    for (const DatabaseDetails& db : details) {
      base::FilePath db_file = GetFullDBFilePath(origin, db.database_name);
      base::File::Info file_info;
      base::GetFileInfo(db_file, &file_info);
      if (file_info.last_modified < cutoff)
        continue;

      // Check if the database is opened by any renderer.
      if (database_connections_.IsDatabaseOpened(origin, db.database_name)) {
        to_be_deleted[origin].insert(db.database_name);
      } else {
        DeleteClosedDatabase(origin, db.database_name);
      }
    }
  }

  if (rv != net::OK) {
    DCHECK_EQ(rv, net::ERR_FAILED);
    std::move(callback).Run(rv);
    return;
  }

  if (!to_be_deleted.empty()) {
    ScheduleDatabasesForDeletion(to_be_deleted, std::move(callback));
    return;
  }

  std::move(callback).Run(net::OK);
}

void DatabaseTracker::DeleteDataForOrigin(
    const url::Origin& origin,
    net::CompletionOnceCallback callback) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(!callback.is_null());
  if (!LazyInit()) {
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }

  const std::string identifier = GetIdentifierFromOrigin(origin);

  std::vector<DatabaseDetails> details;
  if (!databases_table_->GetAllDatabaseDetailsForOriginIdentifier(identifier,
                                                                  &details)) {
    std::move(callback).Run(net::ERR_FAILED);
    return;
  }

  DatabaseSet to_be_deleted;
  for (const DatabaseDetails& db : details) {
    // Check if the database is opened by any renderer.
    if (database_connections_.IsDatabaseOpened(identifier, db.database_name)) {
      to_be_deleted[identifier].insert(db.database_name);
    } else {
      DeleteClosedDatabase(identifier, db.database_name);
    }
  }

  if (!to_be_deleted.empty()) {
    ScheduleDatabasesForDeletion(to_be_deleted, std::move(callback));
    return;
  }

  std::move(callback).Run(net::OK);
}

const base::File* DatabaseTracker::GetIncognitoFile(
    const std::u16string& vfs_file_name) const {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(is_incognito_);
  auto it = incognito_file_handles_.find(vfs_file_name);
  if (it != incognito_file_handles_.end())
    return it->second;

  return nullptr;
}

const base::File* DatabaseTracker::SaveIncognitoFile(
    const std::u16string& vfs_file_name,
    base::File file) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(is_incognito_);
  if (!file.IsValid())
    return nullptr;

  base::File* to_insert = new base::File(std::move(file));
  auto rv =
      incognito_file_handles_.insert(std::make_pair(vfs_file_name, to_insert));
  DCHECK(rv.second);
  base::RecordAction(base::UserMetricsAction("IncognitoWebSQL_Created"));
  return rv.first->second;
}

void DatabaseTracker::CloseIncognitoFileHandle(
    const std::u16string& vfs_file_name) {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  DCHECK(is_incognito_);
  CHECK(incognito_file_handles_.find(vfs_file_name) !=
            incognito_file_handles_.end(),
        base::NotFatalUntil::M130);

  auto it = incognito_file_handles_.find(vfs_file_name);
  if (it != incognito_file_handles_.end()) {
    delete it->second;
    incognito_file_handles_.erase(it);
  }
  base::RecordAction(base::UserMetricsAction("IncognitoWebSQL_Released"));
}

bool DatabaseTracker::HasSavedIncognitoFileHandle(
    const std::u16string& vfs_file_name) const {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  return base::Contains(incognito_file_handles_, vfs_file_name);
}

void DatabaseTracker::DeleteIncognitoDBDirectory() {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  is_initialized_ = false;

  for (auto& pair : incognito_file_handles_)
    delete pair.second;

  base::FilePath incognito_db_dir =
      profile_path_.Append(kIncognitoDatabaseDirectoryName);
  if (base::DirectoryExists(incognito_db_dir))
    base::DeletePathRecursively(incognito_db_dir);
}

void DatabaseTracker::Shutdown() {
  DCHECK(task_runner_->RunsTasksInCurrentSequence());
  if (shutting_down_) {
    NOTREACHED();
  }
  shutting_down_ = true;

  // The mojo receiver must be reset before the instance it calls into is
  // destroyed.
  quota_client_receiver_.reset();
  quota_client_wrapper_.reset();
  quota_client_.reset();

  if (is_incognito_)
    DeleteIncognitoDBDirectory();
  CloseTrackerDatabaseAndClearCaches();

  // Explicitly destroy `db_` on the correct sequence rather than waiting for
  // the destructor, which may run on another sequence. Destroy related fields
  // first to prevent dangling pointers. Destruction order is important.
  meta_table_.reset();
  databases_table_.reset();
  db_.reset();
}

}  // namespace storage
