blob: 30ac52723c43a2ac7205bc6d3565dd8028f9bb32 [file]
// 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.
#ifndef NET_DISK_CACHE_SQL_SQL_SHARED_CACHE_MANAGER_H_
#define NET_DISK_CACHE_SQL_SQL_SHARED_CACHE_MANAGER_H_
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ref.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequence_bound.h"
#include "net/base/net_export.h"
#include "net/base/network_isolation_key.h"
#include "net/disk_cache/sql/sql_read_cache_memory_monitor.h"
#include "net/disk_cache/sql/sql_shared_cache.h"
#include "net/disk_cache/sql/sql_shared_cache_handle.h"
#include "net/disk_cache/sql/sql_shared_cache_index_database.h"
#include "net/disk_cache/sql/sql_tracked_sequence_bound.h"
#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
namespace disk_cache {
class BackendCleanupTracker;
class SharedCacheClientRemote;
class SqlPersistentStore;
// Manages the creation, lookup, and lifecycle of `SqlSharedCache` instances.
//
// Maintains mapping between NetworkIsolationKey string representation / DbId
// and `SqlSharedCache` objects. Handles serialized database operations for
// initializing index databases and retrieving or creating shared caches.
class NET_EXPORT_PRIVATE SqlSharedCacheManager {
public:
using InitCallback = base::OnceCallback<void(
base::expected<void, SqlSharedCacheIndexDatabase::Error>)>;
SqlSharedCacheManager(
SqlPersistentStore& store,
const base::FilePath& path,
scoped_refptr<SqlReadCacheMemoryMonitor> read_cache_memory_monitor,
scoped_refptr<BackendCleanupTracker> cleanup_tracker);
~SqlSharedCacheManager();
// Asynchronously initializes the index database.
void Init(InitCallback callback);
// Asynchronously retrieves a `SqlSharedCacheHandle` associated with the given
// `shared_cache_db_id`. Calls `callback` with a handle (or nullptr if lookup
// fails/error occurs).
void GetCacheByDbId(
SqlSharedCacheDbId shared_cache_db_id,
base::OnceCallback<void(scoped_refptr<SqlSharedCacheHandle>)> callback);
// Asynchronously retrieves or creates a `SqlSharedCacheHandle` for the given
// `nik`. If `require_shared_cache_db_id` is true, an entry in the index
// database will be created/resolved.
void GetCacheByNik(
const net::NetworkIsolationKey& nik,
bool require_shared_cache_db_id,
base::OnceCallback<void(scoped_refptr<SqlSharedCacheHandle>)> callback);
// Asynchronously deletes the shared cache resources specified by `resources`.
// The resources are grouped by their database ID and deleted from their
// corresponding isolated databases. Invokes `callback` upon completion.
void DeleteResources(std::vector<SqlSharedCacheResourceId> resources,
base::OnceClosure callback);
// Asynchronously copies eligible entries into their corresponding isolated
// shared cache databases grouped by NetworkIsolationKey. Unprocessed entries
// are returned via `callback`.
void ProcessSharedCacheEligibleEntries(
std::map<net::NetworkIsolationKey,
base::queue<SqlPersistentStore::SharedCacheEligibleEntry>>
entries,
scoped_refptr<base::RefCountedData<std::atomic_bool>> abort_flag,
base::OnceCallback<void(
std::vector<SqlPersistentStore::SharedCacheEligibleEntry>)> callback,
base::RepeatingCallback<void(const CacheEntryKey&)>
on_entry_copied_callback = {});
// Registers a remote shared cache client for the given NetworkIsolationKey.
// The client will be notified with a read-only database connection once
// available.
void RegisterClient(const net::NetworkIsolationKey& network_isolation_key,
std::unique_ptr<SharedCacheClientRemote> client);
// Sets a flag to simulate index database operation failures for testing.
void SetSimulateDbFailureForTesting(bool fail);
size_t GetSharedCachesSizeForTest() const { return shared_caches_.size(); }
size_t GetSharedCachesByDbIdSizeForTest() const {
return shared_caches_by_shared_cache_db_id_.size();
}
size_t GetSharedCachesByNikSizeForTest() const {
return shared_caches_by_nik_string_.size();
}
private:
friend class SqlSharedCacheManagerTest;
// Handle used to signal completion of a serialized database operation.
// When destroyed, `FinishDbOperation()` is invoked to run the next queued
// operation.
using DbOperationHandle = base::ScopedClosureRunner;
void PostDbOperation(base::OnceCallback<void(DbOperationHandle)> operation);
void MaybeRunNextDbOperation();
void FinishDbOperation();
void OnSqlSharedCacheUnreferenced(SqlSharedCache& cache);
void DoDeleteUnreferencedSqlSharedCache(
const std::string& nik_string,
DbOperationHandle db_operation_handle);
void DoGetCacheByNik(
net::NetworkIsolationKey nik,
bool require_shared_cache_db_id,
base::OnceCallback<void(scoped_refptr<SqlSharedCacheHandle>)> callback,
DbOperationHandle db_operation_handle);
void OnGetSharedDbIdForNik(
net::NetworkIsolationKey nik,
base::OnceCallback<void(scoped_refptr<SqlSharedCacheHandle>)> callback,
DbOperationHandle db_operation_handle,
base::expected<SqlSharedCacheDbId, SqlSharedCacheIndexDatabase::Error>
result);
scoped_refptr<SqlSharedCacheHandle> RegisterNewSqlSharedCache(
const std::string& nik_str,
std::optional<SqlSharedCacheDbId> shared_cache_db_id,
DbOperationHandle db_operation_handle);
void DoGetCacheByDbId(
SqlSharedCacheDbId shared_cache_db_id,
base::OnceCallback<void(scoped_refptr<SqlSharedCacheHandle>)> callback,
DbOperationHandle db_operation_handle);
void OnGetNikStringForDbId(
SqlSharedCacheDbId shared_cache_db_id,
base::OnceCallback<void(scoped_refptr<SqlSharedCacheHandle>)> callback,
DbOperationHandle db_operation_handle,
base::expected<std::string, SqlSharedCacheIndexDatabase::Error> result);
void DeleteNextResourceGroup(
absl::flat_hash_map<SqlSharedCacheDbId, std::vector<SqlSharedCacheRowId>>
grouped_resources,
base::OnceClosure callback,
DbOperationHandle db_operation_handle);
void DoProcessSharedCacheEligibleEntries(
std::map<net::NetworkIsolationKey,
base::queue<SqlPersistentStore::SharedCacheEligibleEntry>>
entries,
scoped_refptr<base::RefCountedData<std::atomic_bool>> abort_flag,
base::OnceCallback<void(
std::vector<SqlPersistentStore::SharedCacheEligibleEntry>)> callback,
base::RepeatingCallback<void(const CacheEntryKey&)>
on_entry_copied_callback,
DbOperationHandle db_operation_handle);
void ProcessNextNikGroup(
base::queue<base::queue<SqlPersistentStore::SharedCacheEligibleEntry>>
groups,
scoped_refptr<base::RefCountedData<std::atomic_bool>> abort_flag,
std::vector<SqlPersistentStore::SharedCacheEligibleEntry> all_unprocessed,
base::OnceCallback<void(
std::vector<SqlPersistentStore::SharedCacheEligibleEntry>)> callback,
base::RepeatingCallback<void(const CacheEntryKey&)>
on_entry_copied_callback);
void OnGetSharedCacheForProcess(
net::NetworkIsolationKey current_nik,
base::queue<base::queue<SqlPersistentStore::SharedCacheEligibleEntry>>
groups,
scoped_refptr<base::RefCountedData<std::atomic_bool>> abort_flag,
std::vector<SqlPersistentStore::SharedCacheEligibleEntry> all_unprocessed,
base::OnceCallback<void(
std::vector<SqlPersistentStore::SharedCacheEligibleEntry>)> callback,
base::RepeatingCallback<void(const CacheEntryKey&)>
on_entry_copied_callback,
scoped_refptr<SqlSharedCacheHandle> handle);
void OnProcessEntryCompleted(
scoped_refptr<SqlSharedCacheHandle> handle,
base::queue<base::queue<SqlPersistentStore::SharedCacheEligibleEntry>>
groups,
scoped_refptr<base::RefCountedData<std::atomic_bool>> abort_flag,
std::vector<SqlPersistentStore::SharedCacheEligibleEntry> all_unprocessed,
base::OnceCallback<void(
std::vector<SqlPersistentStore::SharedCacheEligibleEntry>)> callback,
base::RepeatingCallback<void(const CacheEntryKey&)>
on_entry_copied_callback,
base::queue<SqlPersistentStore::SharedCacheEligibleEntry> results);
const raw_ref<SqlPersistentStore> store_;
const base::FilePath directory_;
scoped_refptr<base::SequencedTaskRunner> db_task_runner_;
SqlTrackedSequenceBound<SqlSharedCacheIndexDatabase> index_database_;
scoped_refptr<SqlReadCacheMemoryMonitor> read_cache_memory_monitor_;
scoped_refptr<BackendCleanupTracker> cleanup_tracker_;
base::queue<base::OnceCallback<void(DbOperationHandle)>>
pending_db_operations_;
bool db_operation_in_progress_ = true;
base::flat_set<std::unique_ptr<SqlSharedCache>, base::UniquePtrComparator>
shared_caches_;
absl::flat_hash_map<SqlSharedCacheDbId, raw_ptr<SqlSharedCache>>
shared_caches_by_shared_cache_db_id_;
absl::flat_hash_map<std::string, raw_ptr<SqlSharedCache>>
shared_caches_by_nik_string_;
base::WeakPtrFactory<SqlSharedCacheManager> weak_factory_{this};
};
} // namespace disk_cache
#endif // NET_DISK_CACHE_SQL_SQL_SHARED_CACHE_MANAGER_H_