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