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