// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/disk_cache/sql/sql_shared_cache.h"

#include <algorithm>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/hash/hash.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/state_transitions.h"
#include "base/task/sequenced_task_runner.h"
#include "net/base/features.h"
#include "net/disk_cache/backend_cleanup_tracker.h"
#include "net/disk_cache/sql/shared_cache_client_remote.h"
#include "net/disk_cache/sql/sql_persistent_store.h"
#include "net/disk_cache/sql/sql_shared_cache_handle.h"
#include "net/disk_cache/sql/sql_shared_cache_isolated_database.h"
#include "net/http/http_cache.h"
#include "net/http/http_response_info.h"

namespace disk_cache {

SqlSharedCache::SqlSharedCache(
    std::string nik_string,
    SqlPersistentStore& store,
    const base::FilePath& directory,
    base::RepeatingCallback<void(SqlSharedCache&)> on_unreferenced_callback,
    scoped_refptr<base::SequencedTaskRunner> db_task_runner,
    scoped_refptr<SqlReadCacheMemoryMonitor> read_cache_memory_monitor,
    scoped_refptr<BackendCleanupTracker> cleanup_tracker)
    : nik_string_(std::move(nik_string)),
      store_(store),
      directory_(directory),
      on_unreferenced_callback_(std::move(on_unreferenced_callback)),
      db_task_runner_(std::move(db_task_runner)),
      read_cache_memory_monitor_(std::move(read_cache_memory_monitor)),
      cleanup_tracker_(std::move(cleanup_tracker)) {}

SqlSharedCache::~SqlSharedCache() {
  isolated_database_.Reset();
  if (cleanup_tracker_) {
    CHECK(db_task_runner_);
    db_task_runner_->PostTaskAndReply(
        FROM_HERE, base::DoNothing(),
        base::DoNothingWithBoundArgs(std::move(cleanup_tracker_)));
  }
}

void SqlSharedCache::Cleanup(base::OnceClosure callback) {
  if (!isolated_database_) {
    std::move(callback).Run();
    return;
  }
  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::Cleanup)
      .Then(std::move(callback));
  isolated_database_.Reset();
}

void SqlSharedCache::InitIsolatedDatabase(
    SqlSharedCacheDbId shared_cache_db_id,
    base::OnceCallback<void(bool)> callback) {
  CHECK(!shared_cache_db_id_);
  shared_cache_db_id_ = shared_cache_db_id;
  isolated_database_ = SqlTrackedSequenceBound<SqlSharedCacheIsolatedDatabase>(
      db_task_runner_, store_->GetAsyncTaskManager(), nik_string_, directory_,
      shared_cache_db_id, db_task_runner_, read_cache_memory_monitor_);
  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::Init)
      .Then(base::BindOnce(
          [](base::OnceCallback<void(bool)> callback,
             base::expected<void, SqlSharedCacheIsolatedDatabase::Error>
                 result) { std::move(callback).Run(result.has_value()); },
          std::move(callback)));

  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::GetAllUrlHashes)
      .Then(base::BindOnce(&SqlSharedCache::OnHashesLoaded,
                           weak_factory_.GetWeakPtr()));

  for (ClientsMap::iterator it(&clients_); !it.IsAtEnd(); it.Advance()) {
    isolated_database_
        .AsyncCall(&SqlSharedCacheIsolatedDatabase::GetSharedReadOnlyConnection)
        .Then(base::BindOnce(&SqlSharedCache::OnPendingFileSetForClient,
                             weak_factory_.GetWeakPtr(), it.GetCurrentKey()));
  }
}

void SqlSharedCache::RegisterClient(
    std::unique_ptr<SharedCacheClientRemote> client) {
  CHECK(client);
  auto* client_ptr = client.get();
  auto client_id = clients_.Add(std::move(client));
  client_ptr->SetDisconnectHandler(
      base::BindOnce(&SqlSharedCache::OnClientDisconnected,
                     weak_factory_.GetWeakPtr(), client_id, CreateHandle()));

  if (cached_hashes_.has_value()) {
    std::vector<uint32_t> hashes(cached_hashes_->begin(),
                                 cached_hashes_->end());
    client_ptr->OnResourcesAdded(hashes);
  }

  if (isolated_database_) {
    isolated_database_
        .AsyncCall(&SqlSharedCacheIsolatedDatabase::GetSharedReadOnlyConnection)
        .Then(base::BindOnce(&SqlSharedCache::OnPendingFileSetForClient,
                             weak_factory_.GetWeakPtr(), client_id));
  }
}

void SqlSharedCache::OnPendingFileSetForClient(
    ClientId client_id,
    base::expected<sqlite_vfs::PendingFileSet,
                   SqlSharedCacheIsolatedDatabase::Error> pending_file_set) {
  if (!pending_file_set.has_value()) {
    return;
  }
  auto* client = clients_.Lookup(client_id);
  if (!client) {
    return;
  }
  client->Initialize(std::move(*pending_file_set));
}

void SqlSharedCache::OnHashesLoaded(
    base::expected<std::vector<uint32_t>, SqlSharedCacheIsolatedDatabase::Error>
        hashes) {
  if (!cached_hashes_.has_value()) {
    cached_hashes_ = absl::flat_hash_set<uint32_t>();
  }
  if (!hashes.has_value()) {
    return;
  }
  for (auto hash : *hashes) {
    cached_hashes_->insert(hash);
  }

  if (!hashes->empty()) {
    for (ClientsMap::iterator it(&clients_); !it.IsAtEnd(); it.Advance()) {
      it.GetCurrentValue()->OnResourcesAdded(*hashes);
    }
  }
}
void SqlSharedCache::OnClientDisconnected(
    ClientId client_id,
    scoped_refptr<SqlSharedCacheHandle> handle) {
  clients_.Remove(client_id);
}

scoped_refptr<SqlSharedCacheHandle> SqlSharedCache::CreateHandle() {
  return base::MakeRefCounted<SqlSharedCacheHandle>(
      weak_factory_.GetWeakPtr(), base::PassKey<SqlSharedCache>());
}

void SqlSharedCache::IncrementHandleCount(base::PassKey<SqlSharedCacheHandle>) {
  handle_count_++;
}

void SqlSharedCache::DecrementHandleCount(base::PassKey<SqlSharedCacheHandle>) {
  handle_count_--;
  if (!IsReferenced()) {
    on_unreferenced_callback_.Run(*this);
  }
}

void SqlSharedCache::CopyEntries(
    base::queue<SqlPersistentStore::SharedCacheEligibleEntry> entries,
    scoped_refptr<base::RefCountedData<std::atomic_bool>> abort_flag,
    base::OnceCallback<void(
        base::queue<SqlPersistentStore::SharedCacheEligibleEntry>)> callback,
    base::RepeatingCallback<void(const CacheEntryKey&)>
        on_entry_copied_callback) {
  CHECK(pending_copy_entries_.empty());
  CHECK(!copy_callback_);
  CHECK(!current_copy_row_id_);
  CHECK(!on_entry_copied_callback_);
  CHECK(!entries.empty());
  CHECK(shared_cache_db_id_);
  CHECK(isolated_database_);
  pending_copy_entries_ = std::move(entries);
  copy_abort_flag_ = std::move(abort_flag);
  copy_callback_ = std::move(callback);
  on_entry_copied_callback_ = std::move(on_entry_copied_callback);
  CopyNextEntry();
}

void SqlSharedCache::CopyNextEntry() {
  if (pending_copy_entries_.empty() ||
      (copy_abort_flag_ &&
       copy_abort_flag_->data.load(std::memory_order_relaxed))) {
    FinishCopy();
    return;
  }
  auto entry = std::move(pending_copy_entries_.front());
  pending_copy_entries_.pop();
  current_entry_hash_ = base::PersistentHash(entry.url.spec());
  const auto key = entry.key;
  store_->OpenEntry(
      key, base::BindOnce(&SqlSharedCache::OnEntryOpenedForSharedCache,
                          weak_factory_.GetWeakPtr(), std::move(entry)));
}

void SqlSharedCache::OnEntryOpenedForSharedCache(
    SqlPersistentStore::SharedCacheEligibleEntry entry,
    SqlPersistentStore::EntryInfoOrError result) {
  if (!result.has_value() || !result->head) {
    OnCopyEntryFailed();
    return;
  }

  // If the entry already has a `shared_cache_resource_id`, its blob data in the
  // persistent store has already been moved to the shared cache. Attempting to
  // copy it again would read zero-filled body data and create an all-zero
  // duplicate entry in the isolated database.
  if (result->shared_cache_resource_id) {
    OnCopyEntryFailed();
    return;
  }
  auto info = std::move(*result);
  if (info.body_end >
      net::features::kSqlDiskCacheMaxSharedCacheCopyEntrySize.Get()) {
    OnCopyEntryFailed();
    return;
  }
  net::HttpResponseInfo disk_response_info;
  bool response_truncated = false;
  if (!net::HttpCache::ParseResponseInfo(base::as_bytes(info.head->span()),
                                         &disk_response_info,
                                         &response_truncated) ||
      response_truncated ||
      disk_response_info.response_time != entry.response_info->response_time) {
    OnCopyEntryFailed();
    return;
  }
  auto pickled_buffer = base::MakeRefCounted<net::PickledIOBuffer>(
      entry.response_info->MakePickle(/*skip_transient_headers=*/true,
                                      /*response_truncated=*/false));
  if (info.body_end > 0) {
    int64_t chunk_size = std::min(
        static_cast<int64_t>(
            net::features::kSqlDiskCacheSharedCacheReadBufferSize.Get()),
        info.body_end);
    auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(chunk_size);
    const auto key = entry.key;
    const auto res_id = info.res_id;
    const auto body_end = info.body_end;
    store_->ReadEntryData(
        key, res_id, 0, buffer, chunk_size, body_end,
        /*sparse_reading=*/false,
        base::BindOnce(&SqlSharedCache::OnEntryDataReadForInsert,
                       weak_factory_.GetWeakPtr(), std::move(entry), res_id,
                       std::move(pickled_buffer), body_end, buffer));
    return;
  }
  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::Insert)
      .WithArgs(entry.key, std::move(pickled_buffer), info.body_end, nullptr)
      .Then(base::BindOnce(&SqlSharedCache::OnIsolatedDatabaseInserted,
                           weak_factory_.GetWeakPtr(), entry.key, info.res_id,
                           info.body_end, 0));
}

void SqlSharedCache::OnEntryDataReadForInsert(
    SqlPersistentStore::SharedCacheEligibleEntry entry,
    SqlPersistentStore::ResId res_id,
    scoped_refptr<net::PickledIOBuffer> headers,
    int64_t body_end,
    scoped_refptr<net::IOBuffer> buffer,
    base::expected<SqlPersistentStore::ReadResult, SqlPersistentStore::Error>
        result) {
  // For `sparse_reading = false`, `SqlPersistentStoreBackend::ReadEntryData`
  // zero-fills gaps and returns `read_bytes` equal to the requested size
  // as long as the read is within bounds.
  if (!result.has_value() ||
      result.value().read_bytes != static_cast<int>(buffer->size())) {
    OnCopyEntryFailed();
    return;
  }
  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::Insert)
      .WithArgs(entry.key, std::move(headers), body_end, buffer)
      .Then(base::BindOnce(&SqlSharedCache::OnIsolatedDatabaseInserted,
                           weak_factory_.GetWeakPtr(), entry.key, res_id,
                           body_end, buffer->size()));
}

void SqlSharedCache::OnIsolatedDatabaseInserted(
    CacheEntryKey key,
    SqlPersistentStore::ResId res_id,
    int64_t body_end,
    int64_t offset,
    base::expected<SqlSharedCacheRowId, SqlSharedCacheIsolatedDatabase::Error>
        result) {
  if (!result.has_value()) {
    OnCopyEntryFailed();
    return;
  }
  CHECK(!current_copy_row_id_);
  current_copy_row_id_ = result.value();
  ReadNextChunk(std::move(key), res_id, body_end, offset, result.value());
}

void SqlSharedCache::ReadNextChunk(CacheEntryKey key,
                                   SqlPersistentStore::ResId res_id,
                                   int64_t body_end,
                                   int64_t offset,
                                   SqlSharedCacheRowId shared_cache_row_id) {
  CHECK_LE(offset, body_end);
  if (offset == body_end) {
    MoveBlobsToSharedCache(key, res_id, shared_cache_row_id);
    return;
  }
  int64_t chunk_size =
      std::min(static_cast<int64_t>(
                   net::features::kSqlDiskCacheSharedCacheReadBufferSize.Get()),
               body_end - offset);
  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(chunk_size);
  store_->ReadEntryData(
      key, res_id, offset, buffer, chunk_size, body_end,
      /*sparse_reading=*/false,
      base::BindOnce(&SqlSharedCache::OnEntryDataRead,
                     weak_factory_.GetWeakPtr(), key, res_id, body_end, offset,
                     shared_cache_row_id, buffer));
}

void SqlSharedCache::OnEntryDataRead(
    CacheEntryKey key,
    SqlPersistentStore::ResId res_id,
    int64_t body_end,
    int64_t offset,
    SqlSharedCacheRowId shared_cache_row_id,
    scoped_refptr<net::IOBuffer> buffer,
    base::expected<SqlPersistentStore::ReadResult, SqlPersistentStore::Error>
        result) {
  // For `sparse_reading = false`, `SqlPersistentStoreBackend::ReadEntryData`
  // zero-fills gaps and returns `read_bytes` equal to the requested size
  // as long as the read is within bounds.
  if (!result.has_value() || result.value().read_bytes != buffer->size()) {
    OnCopyEntryFailed();
    return;
  }
  bool set_ready = (offset + buffer->size() == body_end);
  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::WriteBody)
      .WithArgs(key, shared_cache_row_id, offset, buffer, set_ready)
      .Then(base::BindOnce(&SqlSharedCache::OnIsolatedDatabaseWritten,
                           weak_factory_.GetWeakPtr(), key, res_id, body_end,
                           offset + buffer->size(), shared_cache_row_id));
}

void SqlSharedCache::OnIsolatedDatabaseWritten(
    CacheEntryKey key,
    SqlPersistentStore::ResId res_id,
    int64_t body_end,
    int64_t next_offset,
    SqlSharedCacheRowId shared_cache_row_id,
    base::expected<void, SqlSharedCacheIsolatedDatabase::Error> result) {
  if (!result.has_value()) {
    OnCopyEntryFailed();
    return;
  }
  ReadNextChunk(std::move(key), res_id, body_end, next_offset,
                shared_cache_row_id);
}

void SqlSharedCache::MoveBlobsToSharedCache(
    CacheEntryKey key,
    SqlPersistentStore::ResId res_id,
    SqlSharedCacheRowId shared_cache_row_id) {
  store_->MoveBlobsToSharedCache(
      key, res_id, {*shared_cache_db_id_, shared_cache_row_id},
      base::BindOnce(
          [](base::WeakPtr<SqlSharedCache> self, CacheEntryKey key,
             SqlPersistentStore::Error error) {
            if (self) {
              if (error == SqlPersistentStore::Error::kOk) {
                self->OnCopyEntryComplete(key);
              } else {
                self->OnCopyEntryFailed();
              }
            }
          },
          weak_factory_.GetWeakPtr(), key));
}

void SqlSharedCache::OnCopyEntryComplete(const CacheEntryKey& key) {
  CHECK(current_entry_hash_);
  // `cached_hashes_` is guaranteed to be populated by `OnHashesLoaded` which
  // was scheduled on the database task runner during `InitIsolatedDatabase`
  // prior to any entry copy operations on the same sequence.
  CHECK(cached_hashes_.has_value());
  if (cached_hashes_->insert(*current_entry_hash_).second) {
    copy_new_hashes_.push_back(*current_entry_hash_);
  }
  current_entry_hash_.reset();
  current_copy_row_id_ = std::nullopt;
  if (on_entry_copied_callback_) {
    on_entry_copied_callback_.Run(key);
  }
  CopyNextEntry();
}

void SqlSharedCache::OnCopyEntryFailed() {
  if (current_copy_row_id_.has_value()) {
    isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::DeleteEntry)
        .WithArgs(*current_copy_row_id_);
    current_copy_row_id_ = std::nullopt;
  }
  current_entry_hash_.reset();
  CopyNextEntry();
}

void SqlSharedCache::FinishCopy() {
  if (!copy_new_hashes_.empty()) {
    for (ClientsMap::iterator it(&clients_); !it.IsAtEnd(); it.Advance()) {
      it.GetCurrentValue()->OnResourcesAdded(copy_new_hashes_);
    }
    copy_new_hashes_.clear();
  }

  CHECK(copy_callback_);
  CHECK(!current_copy_row_id_);
  on_entry_copied_callback_.Reset();
  auto unprocessed_entries = std::move(pending_copy_entries_);
  CHECK(pending_copy_entries_.empty());
  copy_abort_flag_ = nullptr;
  auto callback = std::move(copy_callback_);
  CHECK(!copy_callback_);
  std::move(callback).Run(std::move(unprocessed_entries));
}

void SqlSharedCache::DeleteEntries(
    const std::vector<SqlSharedCacheRowId>& shared_cache_row_ids,
    base::OnceCallback<
        void(base::expected<void, SqlSharedCacheIsolatedDatabase::Error>)>
        callback) {
  if (!isolated_database_) {
    std::move(callback).Run(base::unexpected(
        SqlSharedCacheIsolatedDatabase::Error::kIsolatedDatabaseNotAvailable));
    return;
  }
  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::DeleteEntries)
      .WithArgs(shared_cache_row_ids)
      .Then(std::move(callback));
}

void SqlSharedCache::Read(
    const CacheEntryKey& entry_key,
    SqlSharedCacheRowId shared_cache_row_id,
    int body_size,
    int64_t offset,
    scoped_refptr<net::IOBuffer> buffer,
    SqlPersistentStore::ReadResultOrErrorCallback callback) {
  if (!isolated_database_) {
    std::move(callback).Run(
        base::unexpected(SqlPersistentStore::Error::kNotFound));
    return;
  }
  if (offset > std::numeric_limits<int>::max()) {
    std::move(callback).Run(
        base::unexpected(SqlPersistentStore::Error::kFailedToExecute));
    return;
  }
  int offset_int = static_cast<int>(offset);
  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::Read)
      .WithArgs(entry_key, shared_cache_row_id, body_size, offset_int, buffer)
      .Then(base::BindOnce(&SqlSharedCache::OnIsolatedDatabaseRead,
                           weak_factory_.GetWeakPtr(), std::move(callback)));
}

void SqlSharedCache::OnIsolatedDatabaseRead(
    SqlPersistentStore::ReadResultOrErrorCallback callback,
    SqlSharedCacheIsolatedDatabase::ReadResultOrError result) {
  if (result.has_value()) {
    std::move(callback).Run(result.value());
  } else {
    SqlPersistentStore::Error store_error;
    switch (result.error()) {
      case SqlSharedCacheIsolatedDatabase::Error::kEntryNotFound:
        store_error = SqlPersistentStore::Error::kNotFound;
        break;
      default:
        store_error = SqlPersistentStore::Error::kFailedToExecute;
        break;
    }
    std::move(callback).Run(base::unexpected(store_error));
  }
}

void SqlSharedCache::GetBlobHandle(
    const CacheEntryKey& entry_key,
    SqlSharedCacheRowId shared_cache_row_id,
    int body_size,
    base::OnceCallback<
        void(base::expected<scoped_refptr<SqlSharedCacheBlobHandle>,
                            SqlSharedCacheIsolatedDatabase::Error>)> callback) {
  if (!isolated_database_) {
    std::move(callback).Run(base::unexpected(
        SqlSharedCacheIsolatedDatabase::Error::kIsolatedDatabaseNotAvailable));
    return;
  }
  isolated_database_.AsyncCall(&SqlSharedCacheIsolatedDatabase::GetBlobHandle)
      .WithArgs(entry_key, shared_cache_row_id, body_size)
      .Then(std::move(callback));
}

}  // namespace disk_cache
