xref: /aosp_15_r20/external/cronet/net/http/http_cache.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This file declares a HttpTransactionFactory implementation that can be
6 // layered on top of another HttpTransactionFactory to add HTTP caching.  The
7 // caching logic follows RFC 7234 (any exceptions are called out in the code).
8 //
9 // The HttpCache takes a disk_cache::Backend as a parameter, and uses that for
10 // the cache storage.
11 //
12 // See HttpTransactionFactory and HttpTransaction for more details.
13 
14 #ifndef NET_HTTP_HTTP_CACHE_H_
15 #define NET_HTTP_HTTP_CACHE_H_
16 
17 #include <list>
18 #include <map>
19 #include <memory>
20 #include <optional>
21 #include <set>
22 #include <string>
23 #include <unordered_map>
24 #include <unordered_set>
25 
26 #include "base/files/file_path.h"
27 #include "base/functional/callback.h"
28 #include "base/gtest_prod_util.h"
29 #include "base/memory/raw_ptr.h"
30 #include "base/memory/scoped_refptr.h"
31 #include "base/memory/weak_ptr.h"
32 #include "base/threading/thread_checker.h"
33 #include "base/time/clock.h"
34 #include "build/build_config.h"
35 #include "net/base/cache_type.h"
36 #include "net/base/completion_once_callback.h"
37 #include "net/base/load_states.h"
38 #include "net/base/net_errors.h"
39 #include "net/base/net_export.h"
40 #include "net/base/request_priority.h"
41 #include "net/disk_cache/disk_cache.h"
42 #include "net/http/http_transaction_factory.h"
43 
44 class GURL;
45 
46 namespace net {
47 
48 class HttpNetworkSession;
49 class HttpResponseInfo;
50 class NetLog;
51 class NetworkIsolationKey;
52 struct HttpRequestInfo;
53 
54 class NET_EXPORT HttpCache : public HttpTransactionFactory {
55  public:
56   // The cache mode of operation.
57   enum Mode {
58     // Normal mode just behaves like a standard web cache.
59     NORMAL = 0,
60     // Disables reads and writes from the cache.
61     // Equivalent to setting LOAD_DISABLE_CACHE on every request.
62     DISABLE
63   };
64 
65   // A BackendFactory creates a backend object to be used by the HttpCache.
66   class NET_EXPORT BackendFactory {
67    public:
68     virtual ~BackendFactory() = default;
69 
70     // The actual method to build the backend. The return value and `callback`
71     // conventions match disk_cache::CreateCacheBackend
72     //
73     // The implementation must not access the factory object after invoking the
74     // `callback` because the object can be deleted from within the callback.
75     virtual disk_cache::BackendResult CreateBackend(
76         NetLog* net_log,
77         base::OnceCallback<void(disk_cache::BackendResult)> callback) = 0;
78 
79 #if BUILDFLAG(IS_ANDROID)
SetAppStatusListenerGetter(disk_cache::ApplicationStatusListenerGetter app_status_listener_getter)80     virtual void SetAppStatusListenerGetter(
81         disk_cache::ApplicationStatusListenerGetter
82             app_status_listener_getter) {}
83 #endif
84   };
85 
86   // A default backend factory for the common use cases.
87   class NET_EXPORT DefaultBackend : public BackendFactory {
88    public:
89     // `file_operations_factory` can be null, in that case
90     // TrivialFileOperationsFactory is used. `path` is the destination for any
91     // files used by the backend. If `max_bytes` is  zero, a default value
92     // will be calculated automatically.
93     DefaultBackend(CacheType type,
94                    BackendType backend_type,
95                    scoped_refptr<disk_cache::BackendFileOperationsFactory>
96                        file_operations_factory,
97                    const base::FilePath& path,
98                    int max_bytes,
99                    bool hard_reset);
100     ~DefaultBackend() override;
101 
102     // Returns a factory for an in-memory cache.
103     static std::unique_ptr<BackendFactory> InMemory(int max_bytes);
104 
105     // BackendFactory implementation.
106     disk_cache::BackendResult CreateBackend(
107         NetLog* net_log,
108         base::OnceCallback<void(disk_cache::BackendResult)> callback) override;
109 
110 #if BUILDFLAG(IS_ANDROID)
111     void SetAppStatusListenerGetter(disk_cache::ApplicationStatusListenerGetter
112                                         app_status_listener_getter) override;
113 #endif
114 
115    private:
116     CacheType type_;
117     BackendType backend_type_;
118     const scoped_refptr<disk_cache::BackendFileOperationsFactory>
119         file_operations_factory_;
120     const base::FilePath path_;
121     int max_bytes_;
122     bool hard_reset_;
123 #if BUILDFLAG(IS_ANDROID)
124     disk_cache::ApplicationStatusListenerGetter app_status_listener_getter_;
125 #endif
126   };
127 
128   // Whether a transaction can join parallel writing or not is a function of the
129   // transaction as well as the current writers (if present). This enum
130   // captures that decision as well as when a Writers object is first created.
131   // This is also used to log metrics so should be consistent with the values in
132   // enums.xml and should only be appended to.
133   enum ParallelWritingPattern {
134     // Used as the default value till the transaction is in initial headers
135     // phase.
136     PARALLEL_WRITING_NONE,
137     // The transaction creates a writers object. This is only logged for
138     // transactions that did not fail to join existing writers earlier.
139     PARALLEL_WRITING_CREATE,
140     // The transaction joins existing writers.
141     PARALLEL_WRITING_JOIN,
142     // The transaction cannot join existing writers since either itself or
143     // existing writers instance is serving a range request.
144     PARALLEL_WRITING_NOT_JOIN_RANGE,
145     // The transaction cannot join existing writers since either itself or
146     // existing writers instance is serving a non GET request.
147     PARALLEL_WRITING_NOT_JOIN_METHOD_NOT_GET,
148     // The transaction cannot join existing writers since it does not have cache
149     // write privileges.
150     PARALLEL_WRITING_NOT_JOIN_READ_ONLY,
151     // Writers does not exist and the transaction does not need to create one
152     // since it is going to read from the cache.
153     PARALLEL_WRITING_NONE_CACHE_READ,
154     // Unable to join since the entry is too big for cache backend to handle.
155     PARALLEL_WRITING_NOT_JOIN_TOO_BIG_FOR_CACHE,
156     // On adding a value here, make sure to add in enums.xml as well.
157     PARALLEL_WRITING_MAX
158   };
159 
160   // The number of minutes after a resource is prefetched that it can be used
161   // again without validation.
162   static const int kPrefetchReuseMins = 5;
163 
164   // Initialize the cache from its component parts. |network_layer| and
165   // |backend_factory| will be destroyed when the HttpCache is.
166   HttpCache(std::unique_ptr<HttpTransactionFactory> network_layer,
167             std::unique_ptr<BackendFactory> backend_factory);
168 
169   HttpCache(const HttpCache&) = delete;
170   HttpCache& operator=(const HttpCache&) = delete;
171 
172   ~HttpCache() override;
173 
network_layer()174   HttpTransactionFactory* network_layer() { return network_layer_.get(); }
175 
176   // Retrieves the cache backend for this HttpCache instance. If the backend
177   // is not initialized yet, this method will initialize it. The return value is
178   // a network error code, and it could be ERR_IO_PENDING, in which case the
179   // `callback` will be notified when the operation completes. The pointer that
180   // receives the `backend` must remain valid until the operation completes.
181   // `callback` will get cancelled if the HttpCache is destroyed.
182   int GetBackend(disk_cache::Backend** backend,
183                  CompletionOnceCallback callback);
184 
185   // Returns the current backend (can be NULL).
186   disk_cache::Backend* GetCurrentBackend() const;
187 
188   // Given a header data blob, convert it to a response info object.
189   static bool ParseResponseInfo(const char* data,
190                                 int len,
191                                 HttpResponseInfo* response_info,
192                                 bool* response_truncated);
193 
194   // Get/Set the cache's mode.
set_mode(Mode value)195   void set_mode(Mode value) { mode_ = value; }
mode()196   Mode mode() { return mode_; }
197 
198   // Get/Set the cache's clock. These are public only for testing.
SetClockForTesting(base::Clock * clock)199   void SetClockForTesting(base::Clock* clock) { clock_ = clock; }
clock()200   base::Clock* clock() const { return clock_; }
201 
202   // Close currently active sockets so that fresh page loads will not use any
203   // recycled connections.  For sockets currently in use, they may not close
204   // immediately, but they will not be reusable. This is for debugging.
205   void CloseAllConnections(int net_error, const char* net_log_reason_utf8);
206 
207   // Close all idle connections. Will close all sockets not in active use.
208   void CloseIdleConnections(const char* net_log_reason_utf8);
209 
210   // Called whenever an external cache in the system reuses the resource
211   // referred to by |url| and |http_method| and |network_isolation_key|.
212   void OnExternalCacheHit(const GURL& url,
213                           const std::string& http_method,
214                           const NetworkIsolationKey& network_isolation_key,
215                           bool is_subframe_document_resource,
216                           bool include_credentials);
217 
218   // Causes all transactions created after this point to simulate lock timeout
219   // and effectively bypass the cache lock whenever there is lock contention.
SimulateCacheLockTimeoutForTesting()220   void SimulateCacheLockTimeoutForTesting() { bypass_lock_for_test_ = true; }
221 
222   // Causes all transactions created after this point to simulate lock timeout
223   // and effectively bypass the cache lock whenever there is lock contention
224   // after the transaction has completed its headers phase.
SimulateCacheLockTimeoutAfterHeadersForTesting()225   void SimulateCacheLockTimeoutAfterHeadersForTesting() {
226     bypass_lock_after_headers_for_test_ = true;
227   }
228 
DelayAddTransactionToEntryForTesting()229   void DelayAddTransactionToEntryForTesting() {
230     delay_add_transaction_to_entry_for_test_ = true;
231   }
232 
233   // Causes all transactions created after this point to generate a failure
234   // when attempting to conditionalize a network request.
FailConditionalizationForTest()235   void FailConditionalizationForTest() {
236     fail_conditionalization_for_test_ = true;
237   }
238 
239   // HttpTransactionFactory implementation:
240   int CreateTransaction(RequestPriority priority,
241                         std::unique_ptr<HttpTransaction>* transaction) override;
242   HttpCache* GetCache() override;
243   HttpNetworkSession* GetSession() override;
244 
GetWeakPtr()245   base::WeakPtr<HttpCache> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
246 
247   // Resets the network layer to allow for tests that probe
248   // network changes (e.g. host unreachable).  The old network layer is
249   // returned to allow for filter patterns that only intercept
250   // some creation requests.  Note ownership exchange.
251   std::unique_ptr<HttpTransactionFactory>
252   SetHttpNetworkTransactionFactoryForTesting(
253       std::unique_ptr<HttpTransactionFactory> new_network_layer);
254 
255   // Get the URL from the entry's cache key.
256   static std::string GetResourceURLFromHttpCacheKey(const std::string& key);
257 
258   // Generates the cache key for a request. Returns nullopt if the cache is
259   // configured to be split by the NetworkIsolationKey, and the
260   // NetworkIsolationKey is transient, in which case nothing should generally be
261   // stored to disk.
262   static std::optional<std::string> GenerateCacheKey(
263       const GURL& url,
264       int load_flags,
265       const NetworkIsolationKey& network_isolation_key,
266       int64_t upload_data_identifier,
267       bool is_subframe_document_resource);
268   static std::optional<std::string> GenerateCacheKeyForRequest(
269       const HttpRequestInfo* request);
270 
271   // Enable split cache feature if not already overridden in the feature list.
272   // Should only be invoked during process initialization before the HTTP
273   // cache is initialized.
274   static void SplitCacheFeatureEnableByDefault();
275 
276   // Returns true if split cache is enabled either by default or by other means
277   // like command line or field trials.
278   static bool IsSplitCacheEnabled();
279 
280   // Resets g_init_cache and g_enable_split_cache for tests.
281   static void ClearGlobalsForTesting();
282 
283  private:
284   // Types --------------------------------------------------------------------
285 
286   // The type of operation represented by a work item.
287   enum WorkItemOperation {
288     WI_CREATE_BACKEND,
289     WI_OPEN_OR_CREATE_ENTRY,
290     WI_OPEN_ENTRY,
291     WI_CREATE_ENTRY,
292     WI_DOOM_ENTRY
293   };
294 
295   // Disk cache entry data indices.
296   enum {
297     kResponseInfoIndex = 0,
298     kResponseContentIndex,
299     kDeprecatedMetadataIndex,
300     // Must remain at the end of the enum.
301     kNumCacheEntryDataIndices
302   };
303 
304   class QuicServerInfoFactoryAdaptor;
305   class Transaction;
306   class WorkItem;
307   class Writers;
308 
309   friend class WritersTest;
310   friend class TestHttpCacheTransaction;
311   friend class TestHttpCache;
312   friend class Transaction;
313   struct PendingOp;  // Info for an entry under construction.
314 
315   // To help with testing.
316   friend class MockHttpCache;
317   friend class HttpCacheIOCallbackTest;
318 
319   FRIEND_TEST_ALL_PREFIXES(HttpCacheTest_SplitCacheFeatureEnabled,
320                            SplitCacheWithNetworkIsolationKey);
321   FRIEND_TEST_ALL_PREFIXES(HttpCacheTest, NonSplitCache);
322   FRIEND_TEST_ALL_PREFIXES(HttpCacheTest_SplitCacheFeatureEnabled, SplitCache);
323   FRIEND_TEST_ALL_PREFIXES(HttpCacheTest_SplitCacheFeatureEnabled,
324                            SplitCacheUsesRegistrableDomain);
325 
326   using TransactionList = std::list<raw_ptr<Transaction, CtnExperimental>>;
327   using TransactionSet =
328       std::unordered_set<raw_ptr<Transaction, CtnExperimental>>;
329   typedef std::list<std::unique_ptr<WorkItem>> WorkItemList;
330 
331   // We implement a basic reader/writer lock for the disk cache entry. If there
332   // is a writer, then all transactions must wait to read the body. But the
333   // waiting transactions can start their headers phase in parallel. Headers
334   // phase is allowed for one transaction at a time so that if it doesn't match
335   // the existing headers, remaining transactions do not also try to match the
336   // existing entry in parallel leading to wasted network requests. If the
337   // headers do not match, this entry will be doomed.
338   //
339   // A transaction goes through these state transitions.
340   //
341   // Write mode transactions eligible for shared writing:
342   // add_to_entry_queue-> headers_transaction -> writers (first writer)
343   // add_to_entry_queue-> headers_transaction -> done_headers_queue -> writers
344   // (subsequent writers)
345   // add_to_entry_queue-> headers_transaction -> done_headers_queue -> readers
346   // (transactions not eligible for shared writing - once the data is written to
347   // the cache by writers)
348   //
349   // Read only transactions:
350   // add_to_entry_queue-> headers_transaction -> done_headers_queue -> readers
351   // (once the data is written to the cache by writers)
352 
353   class NET_EXPORT_PRIVATE ActiveEntry : public base::RefCounted<ActiveEntry> {
354    public:
355     ActiveEntry(base::WeakPtr<HttpCache> cache,
356                 disk_cache::Entry* entry,
357                 bool opened_in);
358 
359     ActiveEntry(ActiveEntry const&) = delete;
360     ActiveEntry& operator=(ActiveEntry const&) = delete;
361 
GetEntry()362     disk_cache::Entry* GetEntry() { return disk_entry_.get(); }
363 
opened()364     bool opened() const { return opened_; }
365 
set_opened(bool opened)366     void set_opened(bool opened) { opened_ = opened; }
367 
will_process_queued_transactions()368     bool will_process_queued_transactions() {
369       return will_process_queued_transactions_;
370     }
371 
set_will_process_queued_transactions(bool will_process_queued_transactions)372     void set_will_process_queued_transactions(
373         bool will_process_queued_transactions) {
374       will_process_queued_transactions_ = will_process_queued_transactions;
375     }
376 
add_to_entry_queue()377     TransactionList& add_to_entry_queue() { return add_to_entry_queue_; }
378 
done_headers_queue()379     TransactionList& done_headers_queue() { return done_headers_queue_; }
380 
readers()381     TransactionSet& readers() { return readers_; }
382 
headers_transaction()383     const Transaction* headers_transaction() const {
384       return headers_transaction_;
385     }
386 
ClearHeadersTransaction()387     void ClearHeadersTransaction() { headers_transaction_ = nullptr; }
388 
HasWriters()389     bool HasWriters() const { return writers_.get(); }
390 
391     // Returns true if a transaction is currently writing the response body.
IsWritingInProgress()392     bool IsWritingInProgress() const { return writers_.get(); }
393 
writers()394     Writers* writers() const { return writers_.get(); }
395 
396     void Doom();
397 
IsDoomed()398     bool IsDoomed() { return doomed_; }
399 
400     bool TransactionInReaders(Transaction* transaction) const;
401 
402     // Restarts headers_transaction and done_headers_queue transactions.
403     void RestartHeadersPhaseTransactions();
404 
405     // Restarts the headers_transaction by setting its state. Since the
406     // headers_transaction is awaiting an asynchronous operation completion,
407     // it will be restarted when it's Cache IO callback is invoked.
408     void RestartHeadersTransaction();
409 
410     // Checks if a transaction can be added to `add_to_entry_queue_`. If yes, it
411     // will invoke the Cache IO callback of the transaction. It will take a
412     // transaction from add_to_entry_queue and make it a headers_transaction, if
413     // one doesn't exist already.
414     void ProcessAddToEntryQueue();
415 
416     // Removes `transaction` from the `add_to_entry_queue_`.
417     bool RemovePendingTransaction(Transaction* transaction);
418 
419     // Removes and returns all queued transactions in `this` in FIFO order.
420     // This includes transactions that have completed the headers phase and
421     // those that have not been added to the entry yet in that order.
422     TransactionList TakeAllQueuedTransactions();
423 
424     void ReleaseWriters();
425 
426     void AddTransactionToWriters(
427         Transaction* transaction,
428         ParallelWritingPattern parallel_writing_pattern);
429 
430     // Returns true if this transaction can write headers to the entry.
431     bool CanTransactionWriteResponseHeaders(Transaction* transaction,
432                                             bool is_partial,
433                                             bool is_match) const;
434 
435    private:
436     friend class base::RefCounted<ActiveEntry>;
437 
438     ~ActiveEntry();
439 
440     // Destroys `this`.
441     void Deactivate();
442 
443     // Destroys `this` using an exhaustive search.
444     void SlowDeactivate();
445 
446     // Closes a previously doomed entry.
447     void FinalizeDoomed();
448 
449     // The HttpCache that created this.
450     base::WeakPtr<HttpCache> cache_;
451 
452     const disk_cache::ScopedEntryPtr disk_entry_;
453 
454     // Indicates if the disk_entry was opened or not (i.e.: created).
455     // It is set to true when a transaction is added to an entry so that other,
456     // queued, transactions do not mistake it for a newly created entry.
457     bool opened_ = false;
458 
459     // Transactions waiting to be added to entry.
460     TransactionList add_to_entry_queue_;
461 
462     // Transaction currently in the headers phase, either validating the
463     // response or getting new headers. This can exist simultaneously with
464     // writers or readers while validating existing headers.
465     raw_ptr<Transaction> headers_transaction_ = nullptr;
466 
467     // Transactions that have completed their headers phase and are waiting
468     // to read the response body or write the response body.
469     TransactionList done_headers_queue_;
470 
471     // Transactions currently reading from the network and writing to the cache.
472     std::unique_ptr<Writers> writers_;
473 
474     // Transactions that can only read from the cache. Only one of writers or
475     // readers can be non-empty at a time.
476     TransactionSet readers_;
477 
478     // The following variables are true if OnProcessQueuedTransactions is posted
479     bool will_process_queued_transactions_ = false;
480 
481     // True if entry is doomed.
482     bool doomed_ = false;
483   };
484 
485   // `ActiveEntriesMap` and `ActiveEntriesSet` holding `raw_ref`s to
486   // `ActiveEntry` is safe because `ActiveEntry` removes itself from the map or
487   // set it is in on destruction.
488   using ActiveEntriesMap =
489       std::unordered_map<std::string, base::raw_ref<ActiveEntry>>;
490   using PendingOpsMap = std::unordered_map<std::string, PendingOp*>;
491   using ActiveEntriesSet = std::set<base::raw_ref<ActiveEntry>>;
492 
493   // Methods ------------------------------------------------------------------
494 
495   // Creates a WorkItem and sets it as the |pending_op|'s writer, or adds it to
496   // the queue if a writer already exists.
497   net::Error CreateAndSetWorkItem(scoped_refptr<ActiveEntry>* entry,
498                                   Transaction* transaction,
499                                   WorkItemOperation operation,
500                                   PendingOp* pending_op);
501 
502   // Creates the `disk_cache_` object and notifies the `callback` when the
503   // operation completes. Returns an error code.
504   int CreateBackend(CompletionOnceCallback callback);
505 
506   void ReportGetBackendResult(disk_cache::Backend** backend,
507                               CompletionOnceCallback callback,
508                               int net_error);
509 
510   // Makes sure that the backend creation is complete before allowing the
511   // provided transaction to use the object. Returns an error code.
512   // |transaction| will be notified via its Cache IO callback if this method
513   // returns ERR_IO_PENDING. The transaction is free to use the backend
514   // directly at any time after receiving the notification.
515   int GetBackendForTransaction(Transaction* transaction);
516 
517   // Dooms the entry selected by |key|, if it is currently in the list of active
518   // entries.
519   void DoomActiveEntry(const std::string& key);
520 
521   // Dooms the entry selected by |key|. |transaction| will be notified via its
522   // Cache IO callback if this method returns ERR_IO_PENDING. The entry can be
523   // currently in use or not. If entry is in use and the invoking transaction
524   // is associated with this entry and this entry is already doomed, this API
525   // should not be invoked.
526   int DoomEntry(const std::string& key, Transaction* transaction);
527 
528   // Dooms the entry selected by |key|. |transaction| will be notified via its
529   // Cache IO callback if this method returns ERR_IO_PENDING. The entry should
530   // not be currently in use.
531   int AsyncDoomEntry(const std::string& key, Transaction* transaction);
532 
533   // Dooms the entry associated with a GET for a given url and network
534   // isolation key.
535   void DoomMainEntryForUrl(const GURL& url,
536                            const NetworkIsolationKey& isolation_key,
537                            bool is_subframe_document_resource);
538 
539   // Returns if there is an entry that is currently in use and not doomed, or
540   // NULL.
541   bool HasActiveEntry(const std::string& key);
542 
543   // Returns an entry that is currently in use and not doomed, or NULL.
544   scoped_refptr<ActiveEntry> GetActiveEntry(const std::string& key);
545 
546   // Creates a new ActiveEntry and starts tracking it. |disk_entry| is the disk
547   // cache entry.
548   scoped_refptr<ActiveEntry> ActivateEntry(disk_cache::Entry* disk_entry,
549                                            bool opened);
550 
551   // Returns the PendingOp for the desired |key|. If an entry is not under
552   // construction already, a new PendingOp structure is created.
553   PendingOp* GetPendingOp(const std::string& key);
554 
555   // Deletes a PendingOp.
556   void DeletePendingOp(PendingOp* pending_op);
557 
558   // Opens the disk cache entry associated with |key|, creating the entry if it
559   // does not already exist, returning an ActiveEntry in |*entry|. |transaction|
560   // will be notified via its Cache IO callback if this method returns
561   // ERR_IO_PENDING. This should not be called if there already is an active
562   // entry associated with |key|, e.g. you should call GetActiveEntry first.
563   int OpenOrCreateEntry(const std::string& key,
564                         scoped_refptr<ActiveEntry>* entry,
565                         Transaction* transaction);
566 
567   // Opens the disk cache entry associated with |key|, returning an ActiveEntry
568   // in |*entry|. |transaction| will be notified via its Cache IO callback if
569   // this method returns ERR_IO_PENDING. This should not be called if there
570   // already is an active entry associated with |key|, e.g. you should call
571   // GetActiveEntry first.
572   int OpenEntry(const std::string& key,
573                 scoped_refptr<ActiveEntry>* entry,
574                 Transaction* transaction);
575 
576   // Creates the disk cache entry associated with |key|, returning an
577   // ActiveEntry in |*entry|. |transaction| will be notified via its Cache IO
578   // callback if this method returns ERR_IO_PENDING.
579   int CreateEntry(const std::string& key,
580                   scoped_refptr<ActiveEntry>* entry,
581                   Transaction* transaction);
582 
583   // Adds a transaction to an ActiveEntry. This method returns ERR_IO_PENDING
584   // and the transaction will be notified about completion via a callback to
585   // cache_io_callback().
586   // In a failure case, the callback will be invoked with ERR_CACHE_RACE.
587   int AddTransactionToEntry(scoped_refptr<ActiveEntry>& entry,
588                             Transaction* transaction);
589 
590   // Transaction invokes this when its response headers phase is complete
591   // If the transaction is responsible for writing the response body,
592   // it becomes the writer and returns OK. In other cases ERR_IO_PENDING is
593   // returned and the transaction will be notified about completion via its
594   // Cache IO callback. In a failure case, the callback will be invoked with
595   // ERR_CACHE_RACE.
596   int DoneWithResponseHeaders(scoped_refptr<ActiveEntry>& entry,
597                               Transaction* transaction,
598                               bool is_partial);
599 
600   // Called when the transaction has finished working with this entry.
601   // |entry_is_complete| is true if the transaction finished reading/writing
602   // from the entry successfully, else it's false.
603   void DoneWithEntry(scoped_refptr<ActiveEntry>& entry,
604                      Transaction* transaction,
605                      bool entry_is_complete,
606                      bool is_partial);
607 
608   // Invoked when writers wants to doom the entry and restart any queued and
609   // headers transactions.
610   // Virtual so that it can be extended in tests.
611   virtual void WritersDoomEntryRestartTransactions(ActiveEntry* entry);
612 
613   // Invoked when current transactions in writers have completed writing to the
614   // cache. It may be successful completion of the response or failure as given
615   // by |success|. Must delete the writers object.
616   // |entry| is the owner of writers.
617   // |should_keep_entry| indicates if the entry should be doomed/destroyed.
618   // Virtual so that it can be extended in tests.
619   virtual void WritersDoneWritingToEntry(scoped_refptr<ActiveEntry> entry,
620                                          bool success,
621                                          bool should_keep_entry,
622                                          TransactionSet make_readers);
623 
624   // Called when the transaction has received a non-matching response to
625   // validation and it's not the transaction responsible for writing the
626   // response body.
627   void DoomEntryValidationNoMatch(scoped_refptr<ActiveEntry> entry);
628 
629   // Processes either writer's failure to write response body or
630   // headers_transactions's failure to write headers.
631   void ProcessEntryFailure(ActiveEntry* entry);
632 
633   // Resumes processing the queued transactions of |entry|.
634   void ProcessQueuedTransactions(scoped_refptr<ActiveEntry> entry);
635 
636   // Checks if a transaction can be added to the entry. If yes, it will
637   // invoke the Cache IO callback of the transaction. This is a helper function
638   // for OnProcessQueuedTransactions. It will take a transaction from
639   // add_to_entry_queue and make it a headers_transaction, if one doesn't exist
640   // already.
641   void ProcessAddToEntryQueue(scoped_refptr<ActiveEntry> entry);
642 
643   // The implementation is split into a separate function so that it can be
644   // called with a delay for testing.
645   void ProcessAddToEntryQueueImpl(scoped_refptr<ActiveEntry> entry);
646 
647   // Returns if the transaction can join other transactions for writing to
648   // the cache simultaneously. It is only supported for non-Read only,
649   // GET requests which are not range requests.
650   ParallelWritingPattern CanTransactionJoinExistingWriters(
651       Transaction* transaction);
652 
653   // Invoked when a transaction that has already completed the response headers
654   // phase can resume reading/writing the response body. It will invoke the IO
655   // callback of the transaction. This is a helper function for
656   // OnProcessQueuedTransactions.
657   void ProcessDoneHeadersQueue(scoped_refptr<ActiveEntry> entry);
658 
659   // Returns the LoadState of the provided pending transaction.
660   LoadState GetLoadStateForPendingTransaction(const Transaction* transaction);
661 
662   // Removes the transaction |transaction|, from the pending list of an entry
663   // (PendingOp, active or doomed entry).
664   void RemovePendingTransaction(Transaction* transaction);
665 
666   // Removes the transaction |transaction|, from the pending list of
667   // |pending_op|.
668   bool RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
669                                              Transaction* transaction);
670 
671   // Events (called via PostTask) ---------------------------------------------
672 
673   void OnProcessQueuedTransactions(scoped_refptr<ActiveEntry> entry);
674 
675   // Callbacks ----------------------------------------------------------------
676 
677   // Processes BackendCallback notifications.
678   void OnIOComplete(int result, PendingOp* entry);
679 
680   // Helper to conditionally delete |pending_op| if HttpCache has been deleted.
681   // This is necessary because |pending_op| owns a disk_cache::Backend that has
682   // been passed in to CreateCacheBackend(), therefore must live until callback
683   // is called.
684   static void OnPendingOpComplete(base::WeakPtr<HttpCache> cache,
685                                   PendingOp* pending_op,
686                                   int result);
687 
688   // Variant for Open/Create method family, which has a different signature.
689   static void OnPendingCreationOpComplete(base::WeakPtr<HttpCache> cache,
690                                           PendingOp* pending_op,
691                                           disk_cache::EntryResult result);
692 
693   // Variant for CreateCacheBackend, which has a different signature.
694   static void OnPendingBackendCreationOpComplete(
695       base::WeakPtr<HttpCache> cache,
696       PendingOp* pending_op,
697       disk_cache::BackendResult result);
698 
699   // Processes the backend creation notification.
700   void OnBackendCreated(int result, PendingOp* pending_op);
701 
702   // Constants ----------------------------------------------------------------
703 
704   // Used when generating and accessing keys if cache is split.
705   static const char kDoubleKeyPrefix[];
706   static const char kDoubleKeySeparator[];
707   static const char kSubframeDocumentResourcePrefix[];
708 
709   // Used for single-keyed entries if the cache is split.
710   static const char kSingleKeyPrefix[];
711   static const char kSingleKeySeparator[];
712 
713   // Variables ----------------------------------------------------------------
714 
715   raw_ptr<NetLog> net_log_;
716 
717   // Used when lazily constructing the disk_cache_.
718   std::unique_ptr<BackendFactory> backend_factory_;
719   bool building_backend_ = false;
720   bool bypass_lock_for_test_ = false;
721   bool bypass_lock_after_headers_for_test_ = false;
722   bool delay_add_transaction_to_entry_for_test_ = false;
723   bool fail_conditionalization_for_test_ = false;
724 
725   Mode mode_ = NORMAL;
726 
727   std::unique_ptr<HttpTransactionFactory> network_layer_;
728 
729   std::unique_ptr<disk_cache::Backend> disk_cache_;
730 
731   // The set of active entries indexed by cache key.
732   ActiveEntriesMap active_entries_;
733 
734   // The set of doomed entries.
735   ActiveEntriesSet doomed_entries_;
736 
737   // The set of entries "under construction".
738   PendingOpsMap pending_ops_;
739 
740   // A clock that can be swapped out for testing.
741   raw_ptr<base::Clock> clock_;
742 
743   THREAD_CHECKER(thread_checker_);
744 
745   base::WeakPtrFactory<HttpCache> weak_factory_{this};
746 };
747 
748 }  // namespace net
749 
750 #endif  // NET_HTTP_HTTP_CACHE_H_
751