Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2022 The Chromium Authors |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Sreeja Kamishetty | f66553a | 2022-07-14 17:41:27 | [diff] [blame] | 5 | #ifndef CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_SERVICE_H_ |
| 6 | #define CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_SERVICE_H_ |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 7 | |
Max Curran | 646fb64 | 2022-03-16 00:44:09 | [diff] [blame] | 8 | #include <map> |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 9 | #include <optional> |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 10 | |
Adithya Srinivasan | d5e37cb | 2023-07-05 14:45:23 | [diff] [blame] | 11 | #include "base/dcheck_is_on.h" |
Max Curran | 646fb64 | 2022-03-16 00:44:09 | [diff] [blame] | 12 | #include "base/memory/weak_ptr.h" |
Sreeja Kamishetty | f66553a | 2022-07-14 17:41:27 | [diff] [blame] | 13 | #include "content/browser/preloading/prefetch/prefetch_container.h" |
Hiroshige Hayashizaki | 583b496 | 2025-08-19 18:58:26 | [diff] [blame] | 14 | #include "content/browser/preloading/prefetch/prefetch_key.h" |
Hiroshige Hayashizaki | c853c030 | 2023-09-13 08:51:07 | [diff] [blame] | 15 | #include "content/browser/preloading/prefetch/prefetch_streaming_url_loader_common_types.h" |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 16 | #include "content/common/content_export.h" |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 17 | #include "content/public/browser/frame_tree_node_id.h" |
Taiyo Mizuhashi | 94ce74f | 2025-01-28 04:20:14 | [diff] [blame] | 18 | #include "content/public/browser/prefetch_handle.h" |
Steven Wei | e829c85f7 | 2025-03-17 18:57:59 | [diff] [blame] | 19 | #include "content/public/browser/storage_partition.h" |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 20 | #include "services/network/public/mojom/url_response_head.mojom.h" |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 21 | #include "url/gurl.h" |
| 22 | |
Hiroshige Hayashizaki | e51e2f26 | 2025-03-04 23:14:38 | [diff] [blame] | 23 | namespace network { |
| 24 | class SharedURLLoaderFactory; |
| 25 | } // namespace network |
| 26 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 27 | namespace network::mojom { |
Max Curran | cc1ab0c | 2022-09-12 22:03:11 | [diff] [blame] | 28 | class NetworkContext; |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 29 | } // namespace network::mojom |
| 30 | |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 31 | namespace content { |
| 32 | |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 33 | class BrowserContext; |
Liviu Tinta | 4eaa53c2 | 2023-08-02 21:01:06 | [diff] [blame] | 34 | class PrefetchMatchResolver; |
Max Curran | 0146f85 | 2022-08-01 19:49:33 | [diff] [blame] | 35 | class PrefetchOriginProber; |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 36 | class PrefetchProxyConfigurator; |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 37 | class PrefetchScheduler; |
Hiroshige Hayashizaki | b3ff61d | 2025-08-12 06:28:08 | [diff] [blame] | 38 | class PrefetchServiceDelegate; |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 39 | class ServiceWorkerContext; |
Hiroshige Hayashizaki | 583b496 | 2025-08-19 18:58:26 | [diff] [blame] | 40 | enum class ServiceWorkerCapability; |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 41 | |
Max Curran | 7d2578b | 2023-04-12 19:19:28 | [diff] [blame] | 42 | // These values are persisted to logs. Entries should not be renumbered and |
| 43 | // numeric values should never be reused. |
| 44 | enum class PrefetchRedirectResult { |
| 45 | kSuccessRedirectFollowed = 0, |
| 46 | kFailedNullPrefetch = 1, |
Jeremy Roman | 337e495 | 2024-07-04 20:36:49 | [diff] [blame] | 47 | // OBSOLETE: kFailedRedirectsDisabled = 2, |
Max Curran | 7d2578b | 2023-04-12 19:19:28 | [diff] [blame] | 48 | kFailedInvalidMethod = 3, |
| 49 | kFailedInvalidResponseCode = 4, |
| 50 | kFailedInvalidChangeInNetworkContext = 5, |
| 51 | kFailedIneligible = 6, |
Devlin Cronin | 7f318c1 | 2023-06-09 00:57:01 | [diff] [blame] | 52 | kFailedInsufficientReferrerPolicy = 7, |
| 53 | kMaxValue = kFailedInsufficientReferrerPolicy, |
Max Curran | 7d2578b | 2023-04-12 19:19:28 | [diff] [blame] | 54 | }; |
| 55 | |
| 56 | // These values are persisted to logs. Entries should not be renumbered and |
| 57 | // numeric values should never be reused. |
| 58 | enum class PrefetchRedirectNetworkContextTransition { |
| 59 | kDefaultToDefault = 0, |
| 60 | kDefaultToIsolated = 1, |
| 61 | kIsolatedToDefault = 2, |
| 62 | kIsolatedToIsolated = 3, |
| 63 | kMaxValue = kIsolatedToIsolated, |
| 64 | }; |
| 65 | |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 66 | // Manages all prefetches within a single BrowserContext. Responsible for |
| 67 | // checking the eligibility of the prefetch, making the network request for the |
| 68 | // prefetch, and provide prefetched resources to URL loader interceptor when |
| 69 | // needed. |
Hiroshige Hayashizaki | 70db51b | 2025-07-14 23:09:49 | [diff] [blame] | 70 | // |
| 71 | // `PrefetchService` is an `PrefetchContainer::Observer` to `PrefetchContainer`s |
| 72 | // in `owned_prefetches_`. |
| 73 | class CONTENT_EXPORT PrefetchService : public PrefetchContainer::Observer { |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 74 | public: |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 75 | static PrefetchService* GetFromFrameTreeNodeId( |
| 76 | FrameTreeNodeId frame_tree_node_id); |
Hiroshige Hayashizaki | 805be686 | 2023-03-28 08:16:22 | [diff] [blame] | 77 | static void SetFromFrameTreeNodeIdForTesting( |
Avi Drissman | dcc8e68 | 2024-09-04 14:14:48 | [diff] [blame] | 78 | FrameTreeNodeId frame_tree_node_id, |
Hiroshige Hayashizaki | 805be686 | 2023-03-28 08:16:22 | [diff] [blame] | 79 | std::unique_ptr<PrefetchService> prefetch_service); |
| 80 | |
Adithya Srinivasan | 8e0c92e | 2023-06-27 19:15:04 | [diff] [blame] | 81 | // |browser_context| must outlive this instance. In general this should always |
| 82 | // be true, since |PrefetchService| will be indirectly owned by |
| 83 | // |BrowserContext|. |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 84 | explicit PrefetchService(BrowserContext* browser_context); |
Hiroshige Hayashizaki | 70db51b | 2025-07-14 23:09:49 | [diff] [blame] | 85 | ~PrefetchService() override; |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 86 | |
| 87 | PrefetchService(const PrefetchService&) = delete; |
| 88 | const PrefetchService& operator=(const PrefetchService&) = delete; |
| 89 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 90 | BrowserContext* GetBrowserContext() const { return browser_context_; } |
| 91 | |
Max Curran | ead64a6 | 2022-06-22 01:10:52 | [diff] [blame] | 92 | PrefetchServiceDelegate* GetPrefetchServiceDelegate() const { |
| 93 | return delegate_.get(); |
| 94 | } |
Jeremy Roman | e561b41 | 2024-02-15 18:31:34 | [diff] [blame] | 95 | void SetPrefetchServiceDelegateForTesting( |
| 96 | std::unique_ptr<PrefetchServiceDelegate> delegate); |
Max Curran | ead64a6 | 2022-06-22 01:10:52 | [diff] [blame] | 97 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 98 | PrefetchProxyConfigurator* GetPrefetchProxyConfigurator() const { |
| 99 | return prefetch_proxy_configurator_.get(); |
| 100 | } |
| 101 | |
Hiroshige Hayashizaki | 805be686 | 2023-03-28 08:16:22 | [diff] [blame] | 102 | virtual PrefetchOriginProber* GetPrefetchOriginProber() const; |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 103 | virtual void PrefetchUrl(base::WeakPtr<PrefetchContainer> prefetch_container); |
| 104 | |
Max Curran | 7dbdea4d | 2023-03-21 23:47:37 | [diff] [blame] | 105 | // Copies any cookies in the isolated network context associated with |
| 106 | // |prefetch_container| to the default network context. |
Hiroshige Hayashizaki | 16b6e54f | 2025-08-12 06:56:57 | [diff] [blame] | 107 | virtual void CopyIsolatedCookies(const PrefetchServingHandle& serving_handle); |
Max Curran | 7dbdea4d | 2023-03-21 23:47:37 | [diff] [blame] | 108 | |
Hiroshige Hayashizaki | 40a2532f | 2025-03-07 21:42:00 | [diff] [blame] | 109 | // Adds `PrefetchContainer` under control of `PrefetchService` and returns |
| 110 | // PrefetchHandle so that the caller can control prefetch resources associated |
| 111 | // with this. |
kenoss | b68c9e8 | 2024-10-10 10:11:15 | [diff] [blame] | 112 | // |
Hiroshige Hayashizaki | 40a2532f | 2025-03-07 21:42:00 | [diff] [blame] | 113 | // `AddPrefetchContainer*()` synchronously destruct `prefetch_container` if |
| 114 | // the key conflicted to the one already added with migration of some |
| 115 | // attributes. See also `MigrateNewlyaAdded()`. |
| 116 | [[nodiscard]] std::unique_ptr<PrefetchHandle> AddPrefetchContainerWithHandle( |
Taiyo Mizuhashi | 94ce74f | 2025-01-28 04:20:14 | [diff] [blame] | 117 | std::unique_ptr<PrefetchContainer> prefetch_container); |
kenoss | b68c9e8 | 2024-10-10 10:11:15 | [diff] [blame] | 118 | void AddPrefetchContainerWithoutStartingPrefetchForTesting( |
| 119 | std::unique_ptr<PrefetchContainer> prefetch_container); |
Hiroshige Hayashizaki | 7a34d018 | 2023-11-07 20:54:34 | [diff] [blame] | 120 | |
Wayne Jackson Jr. | 0118d2a | 2025-02-21 10:53:46 | [diff] [blame] | 121 | // Returns `true` if a new prefetch request with `url` and |
| 122 | // `no_vary_search_hint` has a duplicate in the prefetch cache and thus the |
| 123 | // caller can choose not to start the prefetch request. |
| 124 | // |
| 125 | // Note: This is currently used for WebView initiated prefetches |
| 126 | // so consideration should be taken if updating the |
| 127 | // underlying implementation (or its dependencies). |
| 128 | bool IsPrefetchDuplicate( |
| 129 | GURL& url, |
| 130 | std::optional<net::HttpNoVarySearchData> no_vary_search_hint); |
| 131 | |
Hiroshige Hayashizaki | a129d91c | 2025-03-05 22:28:12 | [diff] [blame] | 132 | // Whether the prefetch attempt for `key` has failed or discarded. |
| 133 | // Note: the semantics of this method is not super clear and thus is exposed |
| 134 | // only for the existing `PrefetchDocumentManager` use case for now. |
| 135 | bool IsPrefetchAttemptFailedOrDiscardedInternal( |
| 136 | base::PassKey<PrefetchDocumentManager>, |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 137 | PrefetchKey key) const; |
Hiroshige Hayashizaki | a129d91c | 2025-03-05 22:28:12 | [diff] [blame] | 138 | |
Taiyo Mizuhashi | 94ce74f | 2025-01-28 04:20:14 | [diff] [blame] | 139 | // An interface to notify `PrefetchService` that the given `PrefetchContainer` |
| 140 | // is no longer needed from outside of the service. |
| 141 | void MayReleasePrefetch(base::WeakPtr<PrefetchContainer> prefetch_container); |
Hiroshige Hayashizaki | 7a34d018 | 2023-11-07 20:54:34 | [diff] [blame] | 142 | |
Adithya Srinivasan | d5e37cb | 2023-07-05 14:45:23 | [diff] [blame] | 143 | // Called by PrefetchDocumentManager when it finishes processing the latest |
| 144 | // update of speculation candidates. |
| 145 | void OnCandidatesUpdated(); |
| 146 | |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 147 | // Helper functions to control the behavior of the eligibility check when |
| 148 | // testing. |
| 149 | static void SetServiceWorkerContextForTesting(ServiceWorkerContext* context); |
| 150 | static void SetHostNonUniqueFilterForTesting( |
Md Hasibul Hasan | a963a934 | 2024-04-03 10:15:14 | [diff] [blame] | 151 | bool (*filter)(std::string_view)); |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 152 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 153 | // Sets the URLLoaderFactory to be used during testing instead of the |
| 154 | // |PrefetchNetworkContext| associated with each |PrefetchContainer|. Note |
| 155 | // that this does not take ownership of |url_loader_factory|, and caller must |
| 156 | // keep ownership over the course of the test. |
| 157 | static void SetURLLoaderFactoryForTesting( |
Hiroshige Hayashizaki | e51e2f26 | 2025-03-04 23:14:38 | [diff] [blame] | 158 | network::SharedURLLoaderFactory* url_loader_factory); |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 159 | |
Max Curran | cc1ab0c | 2022-09-12 22:03:11 | [diff] [blame] | 160 | // Sets the NetworkContext to use just for the proxy lookup. Note that this |
| 161 | // does not take ownership of |network_context|, and the caller must keep |
| 162 | // ownership over the course of the test. |
| 163 | static void SetNetworkContextForProxyLookupForTesting( |
| 164 | network::mojom::NetworkContext* network_context); |
| 165 | |
kenoss | b68c9e8 | 2024-10-10 10:11:15 | [diff] [blame] | 166 | // Set a callback for injecting delay for eligibility check in tests. |
kenoss | 14462ae | 2025-03-21 02:39:51 | [diff] [blame] | 167 | // |
| 168 | // Make sure to call |
| 169 | // `SetDelayEligibilityCheckForTesting(base::NullCallback())` at the end of an |
| 170 | // unit test that used this method, as this sets a global variable and it is |
| 171 | // shared in unit tests. |
kenoss | b68c9e8 | 2024-10-10 10:11:15 | [diff] [blame] | 172 | using DelayEligibilityCheckForTesting = |
| 173 | base::RepeatingCallback<void(base::OnceClosure)>; |
| 174 | static void SetDelayEligibilityCheckForTesting( |
| 175 | DelayEligibilityCheckForTesting callback); |
kenoss | 4858a80 | 2024-10-11 06:50:56 | [diff] [blame] | 176 | // Set an ineligibility to make eligibility check always fail in tests. |
| 177 | static void SetForceIneligibilityForTesting(PreloadingEligibility); |
Hiroshige Hayashizaki | c0b6aea | 2023-10-17 21:56:43 | [diff] [blame] | 178 | |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 179 | base::WeakPtr<PrefetchContainer> MatchUrl(const PrefetchKey& key) const; |
Hiroshige Hayashizaki | a00e4c8 | 2023-10-31 20:20:17 | [diff] [blame] | 180 | std::vector<std::pair<GURL, base::WeakPtr<PrefetchContainer>>> |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 181 | GetAllForUrlWithoutRefAndQueryForTesting(const PrefetchKey& key) const; |
Hiroshige Hayashizaki | a00e4c8 | 2023-10-31 20:20:17 | [diff] [blame] | 182 | |
Steven Wei | e829c85f7 | 2025-03-17 18:57:59 | [diff] [blame] | 183 | // Evicts completed and in-progress prefetches as part of |
| 184 | // Clear-Site-Data header and Clearing Browser Data if the prefetch's |
| 185 | // referring origin matches the storage_key_filter. |
| 186 | void EvictPrefetchesForBrowsingDataRemoval( |
| 187 | const StoragePartition::StorageKeyMatcherFunction& storage_key_filter, |
| 188 | PrefetchStatus status); |
| 189 | |
kenoss | 4dc06866 | 2024-10-04 05:03:50 | [diff] [blame] | 190 | // Returns candidate `PrefetchContainer`s and servable states for matching |
| 191 | // process. Corresponds to 3.4. of |
kenoss | f6fbd565 | 2024-09-04 00:40:28 | [diff] [blame] | 192 | // https://wicg.github.io/nav-speculation/prefetch.html#wait-for-a-matching-prefetch-record |
kenoss | 4dc06866 | 2024-10-04 05:03:50 | [diff] [blame] | 193 | // |
| 194 | // Note that `PrefetchContainer::GetServableState()` depends on |
| 195 | // `base::TimeTicks::now()` and can expire (can change from `kServable` to |
| 196 | // `kNotServable`) in the minute between two calls. Deciding something with |
Hiroshige Hayashizaki | b3ff61d | 2025-08-12 06:28:08 | [diff] [blame] | 197 | // multiple `PrefetchContainer::GetServableState()` calls can |
| 198 | // lead inconsistent state. To avoid that, we record |
| 199 | // `PrefetchServableState` in the `flat_map` at the beginning of |
| 200 | // matching process and refer to it. |
| 201 | std::pair<std::vector<PrefetchContainer*>, |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 202 | base::flat_map<PrefetchKey, PrefetchServableState>> |
| 203 | CollectMatchCandidates(const PrefetchKey& key, |
kenoss | 804a72dc | 2024-10-11 12:43:49 | [diff] [blame] | 204 | bool is_nav_prerender, |
kenoss | 4dc06866 | 2024-10-04 05:03:50 | [diff] [blame] | 205 | base::WeakPtr<PrefetchServingPageMetricsContainer> |
| 206 | serving_page_metrics_container); |
kenoss | f6fbd565 | 2024-09-04 00:40:28 | [diff] [blame] | 207 | |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 208 | // Exposes methods for `PrefetchScheduler`. See documentation of private |
| 209 | // methods with the same names. |
| 210 | void EvictPrefetch(base::PassKey<PrefetchScheduler>, |
| 211 | base::WeakPtr<PrefetchContainer> prefetch_container); |
| 212 | bool StartSinglePrefetch(base::PassKey<PrefetchScheduler>, |
| 213 | base::WeakPtr<PrefetchContainer> prefetch_container); |
| 214 | |
| 215 | PrefetchScheduler& GetPrefetchSchedulerForTesting() { return *scheduler_; } |
| 216 | |
Hiroshige Hayashizaki | a00e4c8 | 2023-10-31 20:20:17 | [diff] [blame] | 217 | base::WeakPtr<PrefetchService> GetWeakPtr(); |
| 218 | |
Max Curran | 646fb64 | 2022-03-16 00:44:09 | [diff] [blame] | 219 | private: |
Hiroshige Hayashizaki | 3148421 | 2024-01-30 13:35:21 | [diff] [blame] | 220 | friend class PrefetchURLLoaderInterceptorTestBase; |
| 221 | |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 222 | struct CheckEligibilityParams; |
| 223 | |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 224 | // Checks whether the given |prefetch_container| is eligible for prefetch. |
kenoss | 0c7bbc7 | 2024-07-24 08:52:40 | [diff] [blame] | 225 | // Once the eligibility is determined then |OnGotEligibility()| will be |
| 226 | // called. |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 227 | void CheckEligibilityOfPrefetch(CheckEligibilityParams params); |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 228 | |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 229 | void CheckHasServiceWorker(CheckEligibilityParams params); |
Liviu Tinta | f7d62a7 | 2023-08-29 21:48:39 | [diff] [blame] | 230 | |
| 231 | void OnGotServiceWorkerResult( |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 232 | CheckEligibilityParams params, |
Liviu Tinta | 9120230 | 2023-09-26 17:49:11 | [diff] [blame] | 233 | base::Time check_has_service_worker_start_time, |
kenoss | 0c7bbc7 | 2024-07-24 08:52:40 | [diff] [blame] | 234 | ServiceWorkerCapability service_worker_capability); |
Liviu Tinta | f7d62a7 | 2023-08-29 21:48:39 | [diff] [blame] | 235 | |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 236 | // Called after getting the existing cookies associated with |
| 237 | // |prefetch_container|. If there are any cookies, then the prefetch is not |
| 238 | // eligible. |
| 239 | void OnGotCookiesForEligibilityCheck( |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 240 | CheckEligibilityParams params, |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 241 | const net::CookieAccessResultList& cookie_list, |
kenoss | 0c7bbc7 | 2024-07-24 08:52:40 | [diff] [blame] | 242 | const net::CookieAccessResultList& excluded_cookies); |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 243 | |
Max Curran | cc1ab0c | 2022-09-12 22:03:11 | [diff] [blame] | 244 | // Starts the check for whether or not there is a proxy configured for the URL |
| 245 | // of |prefetch_container|. If there is an existing proxy, then the prefetch |
| 246 | // is not eligible. |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 247 | void StartProxyLookupCheck(CheckEligibilityParams params); |
Max Curran | cc1ab0c | 2022-09-12 22:03:11 | [diff] [blame] | 248 | |
| 249 | // Called after looking up the proxy configuration for the URL of |
| 250 | // |prefetch_container|. If there is an existing proxy, then the prefetch is |
| 251 | // not eligible. |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 252 | void OnGotProxyLookupResult(CheckEligibilityParams params, bool has_proxy); |
Max Curran | cc1ab0c | 2022-09-12 22:03:11 | [diff] [blame] | 253 | |
kenoss | 0c7bbc7 | 2024-07-24 08:52:40 | [diff] [blame] | 254 | // Called when the eligibility is determined for each fetch of prefetch, i.e. |
| 255 | // initial fetch and redirects. |
| 256 | // |
| 257 | // If ineligible, these methods may convert the prefetch into decoy. |
| 258 | // |
| 259 | // If the initial fetch (respectively, the redirect) is eligible or the |
| 260 | // prefetch is decoy, the prefetch is added to `prefetch_queue_` |
| 261 | // (respectively, is retained in the queue) and proceeds to the next fetch. |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 262 | void OnGotEligibilityForNonRedirect(CheckEligibilityParams params, |
| 263 | PreloadingEligibility eligibility); |
kenoss | 0c7bbc7 | 2024-07-24 08:52:40 | [diff] [blame] | 264 | void OnGotEligibilityForRedirect( |
kenoss | f8d9f35a | 2024-06-25 07:05:37 | [diff] [blame] | 265 | net::RedirectInfo redirect_info, |
Hiroshige Hayashizaki | 1ae6168b | 2023-06-13 18:15:42 | [diff] [blame] | 266 | network::mojom::URLResponseHeadPtr redirect_head, |
Hiroshige Hayashizaki | 692e3eb | 2025-07-18 21:03:49 | [diff] [blame] | 267 | CheckEligibilityParams params, |
Hiroshige Hayashizaki | 939c5ed4 | 2023-11-01 03:29:21 | [diff] [blame] | 268 | PreloadingEligibility eligibility); |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 269 | |
Hiroshige Hayashizaki | 3148421 | 2024-01-30 13:35:21 | [diff] [blame] | 270 | // Adds `prefetch_container` to the cache but doesn't initiate prefetching. |
Hiroshige Hayashizaki | 40a2532f | 2025-03-07 21:42:00 | [diff] [blame] | 271 | // Use `AddPrefetchContainerWithHandle()` for non-test cases. |
Hiroshige Hayashizaki | 3148421 | 2024-01-30 13:35:21 | [diff] [blame] | 272 | void AddPrefetchContainerWithoutStartingPrefetch( |
| 273 | std::unique_ptr<PrefetchContainer> prefetch_container); |
| 274 | |
Hiroshige Hayashizaki | 70db51b | 2025-07-14 23:09:49 | [diff] [blame] | 275 | // Adds to `owned_prefetches_`. |
| 276 | void AddPrefetchContainerToOwnedPrefetches( |
| 277 | std::unique_ptr<PrefetchContainer> prefetch_container); |
| 278 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 279 | // Starts the network requests for as many prefetches in |prefetch_queue_| as |
| 280 | // possible. |
| 281 | void Prefetch(); |
| 282 | |
Adithya Srinivasan | d5e37cb | 2023-07-05 14:45:23 | [diff] [blame] | 283 | // Pops the first valid prefetch (determined by PrefetchDocumentManager) from |
| 284 | // |prefetch_queue_|. Returns a tuple containing the popped prefetch and |
| 285 | // (optionally) an already completed prefetch that needs to be evicted to make |
| 286 | // space for the new prefetch. If there are no valid prefetches in the queue, |
| 287 | // then (nullptr, nullptr) is returned. |
| 288 | std::tuple<base::WeakPtr<PrefetchContainer>, base::WeakPtr<PrefetchContainer>> |
| 289 | PopNextPrefetchContainer(); |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 290 | |
elabadysayed | f7d6b00f | 2025-02-05 11:27:00 | [diff] [blame] | 291 | // The prefetch is reset after |
| 292 | // `PrefetchContainerDefaultTtlInPrefetchService()` |
| 293 | // or the overridden TTL duration. If |
| 294 | // `PrefetchContainerDefaultTtlInPrefetchService()` returns a value less than |
| 295 | // or equal to zero, the prefetch is kept indefinitely. |
Adithya Srinivasan | d5e37cb | 2023-07-05 14:45:23 | [diff] [blame] | 296 | void OnPrefetchTimeout(base::WeakPtr<PrefetchContainer> prefetch); |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 297 | |
kenoss | 03cdaca3 | 2025-03-28 03:05:14 | [diff] [blame] | 298 | // Evict `prefetch_container` before starting a new prefetch. |
| 299 | // |
| 300 | // Precondition: `prefetch_container` must be valid. |
| 301 | void EvictPrefetch(base::WeakPtr<PrefetchContainer> prefetch_container); |
| 302 | // Starts the given |prefetch_container|. |
| 303 | // |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 304 | // Returns true iff a prefetch is started and the caller should regard this is |
| 305 | // active. |
| 306 | // |
kenoss | 03cdaca3 | 2025-03-28 03:05:14 | [diff] [blame] | 307 | // Precondition: `prefetch_container` must be valid. |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 308 | bool StartSinglePrefetch(base::WeakPtr<PrefetchContainer> prefetch_container); |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 309 | |
Jeremy Roman | 45c89d01 | 2023-08-30 21:22:02 | [diff] [blame] | 310 | // Creates a new URL loader and starts a network request for |
| 311 | // |prefetch_container|. |MakePrefetchRequest| must have been previously |
| 312 | // called. |
| 313 | void SendPrefetchRequest(base::WeakPtr<PrefetchContainer> prefetch_container); |
Max Curran | a84311e | 2023-05-16 20:40:25 | [diff] [blame] | 314 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 315 | // Gets the URL loader for the given |prefetch_container|. If an override was |
| 316 | // set by |SetURLLoaderFactoryForTesting|, then that will be returned instead. |
Hiroshige Hayashizaki | e51e2f26 | 2025-03-04 23:14:38 | [diff] [blame] | 317 | scoped_refptr<network::SharedURLLoaderFactory> |
| 318 | GetURLLoaderFactoryForCurrentPrefetch( |
Hiroshige Hayashizaki | b8c4bf60 | 2023-05-26 01:34:58 | [diff] [blame] | 319 | base::WeakPtr<PrefetchContainer> prefetch_container); |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 320 | |
| 321 | // Called when the request for |prefetch_container| is redirected. |
Max Curran | a84311e | 2023-05-16 20:40:25 | [diff] [blame] | 322 | void OnPrefetchRedirect(base::WeakPtr<PrefetchContainer> prefetch_container, |
| 323 | const net::RedirectInfo& redirect_info, |
Hiroshige Hayashizaki | 1ae6168b | 2023-06-13 18:15:42 | [diff] [blame] | 324 | network::mojom::URLResponseHeadPtr redirect_head); |
Max Curran | 5d4da4b4 | 2023-03-10 23:41:46 | [diff] [blame] | 325 | |
Max Curran | 892ca542 | 2022-12-12 20:55:34 | [diff] [blame] | 326 | // Called when the response for |prefetch_container| has started. Based on |
| 327 | // |head|, returns a status to inform the |PrefetchStreamingURLLoader| whether |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 328 | // the prefetch is servable. If servable, then `std::nullopt` will be |
Hiroshige Hayashizaki | 556ac55 | 2023-10-24 01:36:32 | [diff] [blame] | 329 | // returned, otherwise a failure status is returned. |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 330 | std::optional<PrefetchErrorOnResponseReceived> OnPrefetchResponseStarted( |
Max Curran | 892ca542 | 2022-12-12 20:55:34 | [diff] [blame] | 331 | base::WeakPtr<PrefetchContainer> prefetch_container, |
| 332 | network::mojom::URLResponseHead* head); |
| 333 | |
Hiroshige Hayashizaki | 70db51b | 2025-07-14 23:09:49 | [diff] [blame] | 334 | // PrefetchContainer::Observer overrides: |
| 335 | void OnWillBeDestroyed(PrefetchContainer& prefetch_container) override; |
| 336 | void OnGotInitialEligibility(PrefetchContainer& prefetch_container, |
| 337 | PreloadingEligibility eligibility) override; |
| 338 | void OnDeterminedHead(PrefetchContainer& prefetch_container) override; |
| 339 | void OnPrefetchCompletedOrFailed( |
| 340 | PrefetchContainer& prefetch_container, |
| 341 | const network::URLLoaderCompletionStatus& completion_status, |
| 342 | const std::optional<int>& response_code) override; |
| 343 | |
Max Curran | 7dbdea4d | 2023-03-21 23:47:37 | [diff] [blame] | 344 | // Called when the cookies from |prefetch_conatiner| are read from the |
| 345 | // isolated network context and are ready to be written to the default network |
| 346 | // context. |
Max Curran | c4445fc | 2022-06-02 18:43:43 | [diff] [blame] | 347 | void OnGotIsolatedCookiesForCopy( |
Hiroshige Hayashizaki | 16b6e54f | 2025-08-12 06:56:57 | [diff] [blame] | 348 | PrefetchServingHandle serving_handle, |
Max Curran | c4445fc | 2022-06-02 18:43:43 | [diff] [blame] | 349 | const net::CookieAccessResultList& cookie_list, |
| 350 | const net::CookieAccessResultList& excluded_cookies); |
| 351 | |
Liviu Tinta | 1fe1a6d | 2023-09-20 19:44:04 | [diff] [blame] | 352 | enum class HandlePrefetchContainerResult { |
| 353 | // No prefetch was available to be used. |
| 354 | kNotAvailable, |
| 355 | // There was a prefetch available but it is not usable. |
| 356 | kNotUsable, |
| 357 | // The prefetch will be served. |
| 358 | kToBeServed, |
| 359 | // The prefetch cannot be served because Cookies have changed. |
| 360 | kNotToBeServedCookiesChanged, |
| 361 | // The prefetch's head has not yet been received. |
| 362 | kWaitForHead |
| 363 | }; |
| 364 | |
| 365 | using FallbackToRegularNavigationWhenPrefetchNotUsable = base::StrongAlias< |
| 366 | class FallbackToRegularNavigationWhenPrefetchNotUsableTag, |
| 367 | bool>; |
Max Curran | 2e83b5d | 2022-12-29 18:53:38 | [diff] [blame] | 368 | // Helper function for |GetPrefetchToServe| to return |prefetch_container| via |
Liviu Tinta | 1fe1a6d | 2023-09-20 19:44:04 | [diff] [blame] | 369 | // |on_prefetch_to_serve_ready| callback in |prefetch_match_resolver|. Starts |
| 370 | // the cookie copy process for the given prefetch if needed, and updates its |
| 371 | // state. |
| 372 | HandlePrefetchContainerResult ReturnPrefetchToServe( |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 373 | const PrefetchKey& key, |
Liviu Tinta | 1fe1a6d | 2023-09-20 19:44:04 | [diff] [blame] | 374 | const GURL& prefetch_url, |
Hiroshige Hayashizaki | 16b6e54f | 2025-08-12 06:56:57 | [diff] [blame] | 375 | PrefetchServingHandle serving_handle, |
Liviu Tinta | 1fe1a6d | 2023-09-20 19:44:04 | [diff] [blame] | 376 | PrefetchMatchResolver& prefetch_match_resolver, |
| 377 | FallbackToRegularNavigationWhenPrefetchNotUsable |
| 378 | when_prefetch_not_used_fallback_to_regular_navigation = |
| 379 | FallbackToRegularNavigationWhenPrefetchNotUsable(true)); |
Liviu Tinta | d608e01 | 2023-05-10 19:16:41 | [diff] [blame] | 380 | |
kenoss | f7b4d60d | 2024-07-16 15:15:08 | [diff] [blame] | 381 | // Callback for non-blocking call `PrefetchContainer::StartBlockUntilHead()`. |
| 382 | // Waits non-redirect response header for No-Vary-Search to determine a |
| 383 | // potentially matching prefetch is a matching prefetch. Corresponds 3.6 in |
kenoss | 5a5ad980 | 2024-06-28 10:29:11 | [diff] [blame] | 384 | // https://wicg.github.io/nav-speculation/prefetch.html#wait-for-a-matching-prefetch-record |
| 385 | // |
Liviu Tinta | d608e01 | 2023-05-10 19:16:41 | [diff] [blame] | 386 | // Once we make the decision to use a prefetch, call |PrepareToServe| and |
| 387 | // |GetPrefetchToServe| again in order to enforce that prefetches that are |
| 388 | // served are served from |prefetches_ready_to_serve_|. |
kenoss | f7b4d60d | 2024-07-16 15:15:08 | [diff] [blame] | 389 | void OnMaybeDeterminedHead( |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 390 | const PrefetchKey& key, |
Liviu Tinta | 4eaa53c2 | 2023-08-02 21:01:06 | [diff] [blame] | 391 | base::WeakPtr<PrefetchMatchResolver> prefetch_match_resolver, |
kenoss | 6c5fb09 | 2024-07-05 05:42:14 | [diff] [blame] | 392 | PrefetchContainer& prefetch_container); |
Max Curran | 2e83b5d | 2022-12-29 18:53:38 | [diff] [blame] | 393 | |
Liviu Tinta | 4eaa53c2 | 2023-08-02 21:01:06 | [diff] [blame] | 394 | // Helper function for |GetPrefetchToServe| which handles a |
| 395 | // |prefetch_container| that could potentially be served to the navigation. |
Liviu Tinta | 1fe1a6d | 2023-09-20 19:44:04 | [diff] [blame] | 396 | HandlePrefetchContainerResult HandlePrefetchContainerToServe( |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 397 | const PrefetchKey& key, |
Liviu Tinta | 1fe1a6d | 2023-09-20 19:44:04 | [diff] [blame] | 398 | PrefetchContainer& prefetch_container, |
Liviu Tinta | 4eaa53c2 | 2023-08-02 21:01:06 | [diff] [blame] | 399 | PrefetchMatchResolver& prefetch_match_resolver); |
Liviu Tinta | d608e01 | 2023-05-10 19:16:41 | [diff] [blame] | 400 | |
Hiroshige Hayashizaki | f59d902 | 2023-11-08 00:08:09 | [diff] [blame] | 401 | // Checks if there is a prefetch in |owned_prefetches_| with the same URL as |
Rakina Zata Amni | 39d8e7e | 2022-10-20 18:18:30 | [diff] [blame] | 402 | // |prefetch_container| but from a different referring RenderFrameHost. |
Max Curran | 679a3d5 | 2022-07-11 23:03:31 | [diff] [blame] | 403 | // Records the result to a UMA histogram. |
| 404 | void RecordExistingPrefetchWithMatchingURL( |
Hiroshige Hayashizaki | 70db51b | 2025-07-14 23:09:49 | [diff] [blame] | 405 | const PrefetchContainer& prefetch_container) const; |
Max Curran | 679a3d5 | 2022-07-11 23:03:31 | [diff] [blame] | 406 | |
kenoss | e8d8bbb5 | 2025-05-13 12:35:04 | [diff] [blame] | 407 | // If `should_progress` is true, calls `PrefetchScheduler::ProgressAsync()` |
| 408 | // (implicitly). This argument is meaningful only if `UsePrefetchScheduler()`. |
Taiyo Mizuhashi | 94ce74f | 2025-01-28 04:20:14 | [diff] [blame] | 409 | void ResetPrefetchContainer( |
kenoss | e8d8bbb5 | 2025-05-13 12:35:04 | [diff] [blame] | 410 | base::WeakPtr<PrefetchContainer> prefetch_container, |
| 411 | bool should_progress = true); |
Taiyo Mizuhashi | 94ce74f | 2025-01-28 04:20:14 | [diff] [blame] | 412 | |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 413 | // Methods for scheduling |
| 414 | void ScheduleAndProgress(base::WeakPtr<PrefetchContainer> prefetch_container); |
kenoss | 0a56736 | 2025-05-16 11:18:55 | [diff] [blame] | 415 | void ScheduleAndProgressAsync( |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 416 | base::WeakPtr<PrefetchContainer> prefetch_container); |
kenoss | 0a56736 | 2025-05-16 11:18:55 | [diff] [blame] | 417 | void ResetPrefetchContainerAndProgressAsync( |
| 418 | base::WeakPtr<PrefetchContainer> prefetch_container); |
| 419 | void ResetPrefetchContainersAndProgressAsync( |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 420 | std::vector<base::WeakPtr<PrefetchContainer>> prefetch_containers); |
| 421 | // CAUTION: This doesn't call `ResetPrefetchContainer()` to preserve current |
| 422 | // behavior. |
kenoss | 0a56736 | 2025-05-16 11:18:55 | [diff] [blame] | 423 | void RemoveFromSchedulerAndProgressAsync( |
| 424 | PrefetchContainer& prefetch_container); |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 425 | |
Wayne Jackson Jr. | 0118d2a | 2025-02-21 10:53:46 | [diff] [blame] | 426 | // Returns `true` if the `prefetch_container` is stale. I.e. |
| 427 | // the prefetch either is not or never will be servable to a |
| 428 | // navigation. |
| 429 | // |
| 430 | // Note: This is currently used for WebView initiated prefetches so |
| 431 | // consideration should be taken if updating the underlying implementation (or |
| 432 | // its dependencies). |
| 433 | bool IsPrefetchStale(base::WeakPtr<PrefetchContainer> prefetch_container); |
| 434 | |
kenoss | f7cea393 | 2025-03-28 03:47:37 | [diff] [blame] | 435 | // Returns if the `prefetch_container` is in active set. |
| 436 | bool IsPrefetchContainerInActiveSet( |
| 437 | const PrefetchContainer& prefetch_container); |
| 438 | |
Hiroshige Hayashizaki | 3876eee | 2023-03-27 04:42:04 | [diff] [blame] | 439 | void DumpPrefetchesForDebug() const; |
| 440 | |
Hiroshige Hayashizaki | 72ea9b9 | 2025-07-05 02:47:56 | [diff] [blame] | 441 | // Wrappers for `owned_prefetches_`. Use these wrappers and do not directly |
| 442 | // access `owned_prefetches_`, to avoid accidentally destructing existing |
| 443 | // `PrefetchContainer` e.g. by writing to `owned_prefetches_[key]`. |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 444 | const std::map<PrefetchKey, std::unique_ptr<PrefetchContainer>>& |
Hiroshige Hayashizaki | 72ea9b9 | 2025-07-05 02:47:56 | [diff] [blame] | 445 | owned_prefetches() const { |
| 446 | return owned_prefetches_; |
| 447 | } |
| 448 | |
Ayu Ishii | 29af5af | 2023-11-27 23:13:51 | [diff] [blame] | 449 | raw_ptr<BrowserContext> browser_context_; |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 450 | |
Max Curran | ead64a6 | 2022-06-22 01:10:52 | [diff] [blame] | 451 | // Delegate provided by embedder that controls specific behavior of |this|. |
| 452 | // May be nullptr if embedder doesn't provide a delegate. |
| 453 | std::unique_ptr<PrefetchServiceDelegate> delegate_; |
| 454 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 455 | // The custom proxy configurator for Prefetch Proxy. Only used on prefetches |
| 456 | // that require the proxy. |
| 457 | std::unique_ptr<PrefetchProxyConfigurator> prefetch_proxy_configurator_; |
| 458 | |
Max Curran | 0146f85 | 2022-08-01 19:49:33 | [diff] [blame] | 459 | // The origin prober class which manages all logic for origin probing. |
| 460 | std::unique_ptr<PrefetchOriginProber> origin_prober_; |
| 461 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 462 | // A FIFO queue of prefetches that have been confirmed to be eligible but have |
| 463 | // not started yet. |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 464 | // |
| 465 | // It is used only if `!UsePrefetchScheduler()`. |
| 466 | // |
| 467 | // TODO(crbug.com/406754449): Remove it. |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 468 | std::vector<base::WeakPtr<PrefetchContainer>> prefetch_queue_; |
| 469 | |
Adithya Srinivasan | 9d1b6fa | 2024-08-29 15:04:35 | [diff] [blame] | 470 | // Current prefetch with an in-progress request (if any). |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 471 | // |
| 472 | // It is used only if `!UsePrefetchScheduler()`. |
| 473 | // |
| 474 | // TODO(crbug.com/406754449): Remove it. |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 475 | std::optional<PrefetchKey> active_prefetch_; |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 476 | |
Taiyo Mizuhashi | 1847c40 | 2025-03-04 23:51:09 | [diff] [blame] | 477 | // Prefetches owned by `this`. All `PrefetchContainer`s added by |
| 478 | // `AddPrefetchContainer*` will be stored here. |
Hiroshige Hayashizaki | 72ea9b9 | 2025-07-05 02:47:56 | [diff] [blame] | 479 | // |
Hiroshige Hayashizaki | 70db51b | 2025-07-14 23:09:49 | [diff] [blame] | 480 | // `PrefetchContainer`s in `owned_prefetches_` must be always: |
| 481 | // - Added by `AddPrefetchContainerToOwnedPrefetches()`. |
| 482 | // - Destructed either by: |
| 483 | // - `ResetPrefetchContainer()` or |
| 484 | // - `~PrefetchService()` dtor. |
| 485 | // |
Hiroshige Hayashizaki | 72ea9b9 | 2025-07-05 02:47:56 | [diff] [blame] | 486 | // Use `owned_prefetches()` wherever possible, to avoid unintentional |
| 487 | // destruction of `PrefetchContainer`s in `owned_prefetches_`. |
Hiroshige Hayashizaki | 70db51b | 2025-07-14 23:09:49 | [diff] [blame] | 488 | // |
Hiroshige Hayashizaki | 72ea9b9 | 2025-07-05 02:47:56 | [diff] [blame] | 489 | // Note that `PrefetchContainer` not added to `owned_prefetches_` can be |
| 490 | // destroyed elsewhere even if it has a relevant `PrefetchService` (e.g. in |
| 491 | // `PrefetchContainer::MigrateNewlyAdded()`). |
Hiroshige Hayashizaki | c625e81 | 2025-08-19 18:42:35 | [diff] [blame] | 492 | std::map<PrefetchKey, std::unique_ptr<PrefetchContainer>> owned_prefetches_; |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 493 | |
Adithya Srinivasan | d5e37cb | 2023-07-05 14:45:23 | [diff] [blame] | 494 | // Protects against Prefetch() being called recursively. |
| 495 | #if DCHECK_IS_ON() |
| 496 | bool prefetch_reentrancy_guard_ = false; |
| 497 | #endif |
| 498 | |
kenoss | 1b8ebc2 | 2025-04-04 00:11:35 | [diff] [blame] | 499 | // Manages queue of prefetches, active set, and scheduling. |
| 500 | // |
| 501 | // It is used only if `UsePrefetchScheduler()`. |
| 502 | // |
| 503 | // TODO(crbug.com/406754449): Remove the last sentence. |
| 504 | std::unique_ptr<PrefetchScheduler> scheduler_; |
| 505 | |
Max Curran | 18a6f2b | 2022-05-02 23:13:24 | [diff] [blame] | 506 | SEQUENCE_CHECKER(sequence_checker_); |
| 507 | |
Max Curran | 146bf44 | 2022-03-28 23:22:14 | [diff] [blame] | 508 | base::WeakPtrFactory<PrefetchService> weak_method_factory_{this}; |
Max Curran | 6c2835ea | 2022-03-07 19:52:38 | [diff] [blame] | 509 | }; |
| 510 | |
| 511 | } // namespace content |
| 512 | |
Sreeja Kamishetty | f66553a | 2022-07-14 17:41:27 | [diff] [blame] | 513 | #endif // CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_SERVICE_H_ |