#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "net/http/http_cache.h"
#include <optional>
#include <string_view>
#include <utility>
#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/hash/sha1.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/histogram_macros_local.h"
#include "base/not_fatal_until.h"
#include "base/numerics/safe_conversions.h"
#include "base/pickle.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/default_clock.h"
#include "build/build_config.h"
#include "http_request_info.h"
#include "net/base/cache_type.h"
#include "net/base/features.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/network_isolation_key.h"
#include "net/base/upload_data_stream.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_cache_transaction.h"
#include "net/http/http_cache_writers.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
#include "net/log/net_log_with_source.h"
#include "net/quic/quic_server_info.h"
#include "url/origin.h"
#if BUILDFLAG(IS_POSIX)
#include <unistd.h>
#endif
namespace net {
namespace {
bool g_init_cache = …;
bool g_enable_split_cache = …;
}
const char HttpCache::kDoubleKeyPrefix[] = …;
const char HttpCache::kDoubleKeySeparator[] = …;
const char HttpCache::kSubframeDocumentResourcePrefix[] = …;
HttpCache::DefaultBackend::DefaultBackend(
CacheType type,
BackendType backend_type,
scoped_refptr<disk_cache::BackendFileOperationsFactory>
file_operations_factory,
const base::FilePath& path,
int max_bytes,
bool hard_reset)
: … { … }
HttpCache::DefaultBackend::~DefaultBackend() = default;
std::unique_ptr<HttpCache::BackendFactory> HttpCache::DefaultBackend::InMemory(
int max_bytes) { … }
disk_cache::BackendResult HttpCache::DefaultBackend::CreateBackend(
NetLog* net_log,
base::OnceCallback<void(disk_cache::BackendResult)> callback) { … }
#if BUILDFLAG(IS_ANDROID)
void HttpCache::DefaultBackend::SetAppStatusListenerGetter(
disk_cache::ApplicationStatusListenerGetter app_status_listener_getter) {
app_status_listener_getter_ = std::move(app_status_listener_getter);
}
#endif
HttpCache::ActiveEntry::ActiveEntry(base::WeakPtr<HttpCache> cache,
disk_cache::Entry* entry,
bool opened_in)
: … { … }
HttpCache::ActiveEntry::~ActiveEntry() { … }
void HttpCache::ActiveEntry::FinalizeDoomed() { … }
void HttpCache::ActiveEntry::Deactivate() { … }
void HttpCache::ActiveEntry::SlowDeactivate() { … }
bool HttpCache::ActiveEntry::TransactionInReaders(
Transaction* transaction) const { … }
void HttpCache::ActiveEntry::ReleaseWriters() { … }
void HttpCache::ActiveEntry::AddTransactionToWriters(
Transaction* transaction,
ParallelWritingPattern parallel_writing_pattern) { … }
void HttpCache::ActiveEntry::Doom() { … }
void HttpCache::ActiveEntry::RestartHeadersPhaseTransactions() { … }
void HttpCache::ActiveEntry::RestartHeadersTransaction() { … }
void HttpCache::ActiveEntry::ProcessAddToEntryQueue() { … }
bool HttpCache::ActiveEntry::RemovePendingTransaction(
Transaction* transaction) { … }
HttpCache::TransactionList HttpCache::ActiveEntry::TakeAllQueuedTransactions() { … }
bool HttpCache::ActiveEntry::CanTransactionWriteResponseHeaders(
Transaction* transaction,
bool is_partial,
bool is_match) const { … }
struct HttpCache::PendingOp { … };
class HttpCache::WorkItem { … };
HttpCache::HttpCache(std::unique_ptr<HttpTransactionFactory> network_layer,
std::unique_ptr<BackendFactory> backend_factory)
: … { … }
HttpCache::~HttpCache() { … }
HttpCache::GetBackendResult HttpCache::GetBackend(GetBackendCallback callback) { … }
void HttpCache::ReportGetBackendResult(GetBackendCallback callback,
int net_error) { … }
disk_cache::Backend* HttpCache::GetCurrentBackend() const { … }
bool HttpCache::ParseResponseInfo(base::span<const uint8_t> data,
HttpResponseInfo* response_info,
bool* response_truncated) { … }
void HttpCache::CloseAllConnections(int net_error,
const char* net_log_reason_utf8) { … }
void HttpCache::CloseIdleConnections(const char* net_log_reason_utf8) { … }
void HttpCache::OnExternalCacheHit(
const GURL& url,
const std::string& http_method,
const NetworkIsolationKey& network_isolation_key,
bool used_credentials) { … }
int HttpCache::CreateTransaction(
RequestPriority priority,
std::unique_ptr<HttpTransaction>* transaction) { … }
HttpCache* HttpCache::GetCache() { … }
HttpNetworkSession* HttpCache::GetSession() { … }
std::unique_ptr<HttpTransactionFactory>
HttpCache::SetHttpNetworkTransactionFactoryForTesting(
std::unique_ptr<HttpTransactionFactory> new_network_layer) { … }
std::string HttpCache::GetResourceURLFromHttpCacheKey(const std::string& key) { … }
bool HttpCache::CanGenerateCacheKeyForRequest(const HttpRequestInfo* request) { … }
std::string HttpCache::GenerateCacheKey(
const GURL& url,
int load_flags,
const NetworkIsolationKey& network_isolation_key,
int64_t upload_data_identifier,
bool is_subframe_document_resource,
bool is_mainframe_navigation,
std::optional<url::Origin> initiator) { … }
HttpCache::ExperimentMode HttpCache::GetExperimentMode() { … }
std::optional<std::string> HttpCache::GenerateCacheKeyForRequest(
const HttpRequestInfo* request) { … }
void HttpCache::SplitCacheFeatureEnableByDefault() { … }
bool HttpCache::IsSplitCacheEnabled() { … }
void HttpCache::ClearGlobalsForTesting() { … }
Error HttpCache::CreateAndSetWorkItem(scoped_refptr<ActiveEntry>* entry,
Transaction* transaction,
WorkItemOperation operation,
PendingOp* pending_op) { … }
int HttpCache::CreateBackend(CompletionOnceCallback callback) { … }
int HttpCache::GetBackendForTransaction(Transaction* transaction) { … }
void HttpCache::DoomActiveEntry(const std::string& key) { … }
int HttpCache::DoomEntry(const std::string& key, Transaction* transaction) { … }
int HttpCache::AsyncDoomEntry(const std::string& key,
Transaction* transaction) { … }
void HttpCache::DoomMainEntryForUrl(
const GURL& url,
const NetworkIsolationKey& isolation_key,
bool is_subframe_document_resource,
bool is_main_frame_navigation,
const std::optional<url::Origin>& initiator) { … }
bool HttpCache::HasActiveEntry(const std::string& key) { … }
scoped_refptr<HttpCache::ActiveEntry> HttpCache::GetActiveEntry(
const std::string& key) { … }
scoped_refptr<HttpCache::ActiveEntry> HttpCache::ActivateEntry(
disk_cache::Entry* disk_entry,
bool opened) { … }
HttpCache::PendingOp* HttpCache::GetPendingOp(const std::string& key) { … }
void HttpCache::DeletePendingOp(PendingOp* pending_op) { … }
int HttpCache::OpenOrCreateEntry(const std::string& key,
scoped_refptr<ActiveEntry>* entry,
Transaction* transaction) { … }
int HttpCache::OpenEntry(const std::string& key,
scoped_refptr<ActiveEntry>* entry,
Transaction* transaction) { … }
int HttpCache::CreateEntry(const std::string& key,
scoped_refptr<ActiveEntry>* entry,
Transaction* transaction) { … }
int HttpCache::AddTransactionToEntry(scoped_refptr<ActiveEntry>& entry,
Transaction* transaction) { … }
int HttpCache::DoneWithResponseHeaders(scoped_refptr<ActiveEntry>& entry,
Transaction* transaction,
bool is_partial) { … }
void HttpCache::DoneWithEntry(scoped_refptr<ActiveEntry>& entry,
Transaction* transaction,
bool entry_is_complete,
bool is_partial) { … }
void HttpCache::WritersDoomEntryRestartTransactions(ActiveEntry* entry) { … }
void HttpCache::WritersDoneWritingToEntry(scoped_refptr<ActiveEntry> entry,
bool success,
bool should_keep_entry,
TransactionSet make_readers) { … }
void HttpCache::DoomEntryValidationNoMatch(scoped_refptr<ActiveEntry> entry) { … }
void HttpCache::ProcessEntryFailure(ActiveEntry* entry) { … }
void HttpCache::ProcessQueuedTransactions(scoped_refptr<ActiveEntry> entry) { … }
void HttpCache::ProcessAddToEntryQueue(scoped_refptr<ActiveEntry> entry) { … }
void HttpCache::ProcessAddToEntryQueueImpl(scoped_refptr<ActiveEntry> entry) { … }
HttpCache::ParallelWritingPattern HttpCache::CanTransactionJoinExistingWriters(
Transaction* transaction) { … }
void HttpCache::ProcessDoneHeadersQueue(scoped_refptr<ActiveEntry> entry) { … }
LoadState HttpCache::GetLoadStateForPendingTransaction(
const Transaction* transaction) { … }
void HttpCache::RemovePendingTransaction(Transaction* transaction) { … }
bool HttpCache::RemovePendingTransactionFromPendingOp(
PendingOp* pending_op,
Transaction* transaction) { … }
void HttpCache::MarkKeyNoStore(const std::string& key) { … }
bool HttpCache::DidKeyLeadToNoStoreResponse(const std::string& key) { … }
void HttpCache::OnProcessQueuedTransactions(scoped_refptr<ActiveEntry> entry) { … }
void HttpCache::OnIOComplete(int result, PendingOp* pending_op) { … }
void HttpCache::OnPendingOpComplete(base::WeakPtr<HttpCache> cache,
PendingOp* pending_op,
int rv) { … }
void HttpCache::OnPendingCreationOpComplete(base::WeakPtr<HttpCache> cache,
PendingOp* pending_op,
disk_cache::EntryResult result) { … }
void HttpCache::OnPendingBackendCreationOpComplete(
base::WeakPtr<HttpCache> cache,
PendingOp* pending_op,
disk_cache::BackendResult result) { … }
void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) { … }
}