1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
content / browser / preloading / prefetch / prefetch_document_manager.h [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_DOCUMENT_MANAGER_H_
#define CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_DOCUMENT_MANAGER_H_
#include <map>
#include <memory>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/preloading/prefetch/prefetch_type.h"
#include "content/browser/preloading/preload_pipeline_info.h"
#include "content/browser/preloading/speculation_host_devtools_observer.h"
#include "content/common/content_export.h"
#include "content/common/features.h"
#include "content/public/browser/document_user_data.h"
#include "content/public/browser/prefetch_metrics.h"
#include "content/public/browser/preloading.h"
#include "content/public/browser/web_contents_observer.h"
#include "net/http/http_no_vary_search_data.h"
#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom.h"
#include "url/gurl.h"
namespace content {
class PrefetchContainer;
class PrefetchService;
class PreloadingPredictor;
// Manages the state of and tracks metrics about prefetches for a single page
// load.
class CONTENT_EXPORT PrefetchDocumentManager
: public DocumentUserData<PrefetchDocumentManager> {
public:
using PrefetchDestructionCallback =
base::RepeatingCallback<void(const GURL&)>;
~PrefetchDocumentManager() override;
PrefetchDocumentManager(const PrefetchDocumentManager&) = delete;
const PrefetchDocumentManager operator=(const PrefetchDocumentManager&) =
delete;
// Returns the `PrefetchDocumentManager` associated with a Document if already
// exists, or `nullptr` otherwise.
static PrefetchDocumentManager* FromDocumentToken(
int process_id,
const blink::DocumentToken& document_token);
// Processes the given speculation candidates to see if they can be
// prefetched. Any candidates that can be prefetched are removed from
// |candidates|, and a prefetch for the URL of the candidate is started.
void ProcessCandidates(
std::vector<blink::mojom::SpeculationCandidatePtr>& candidates,
base::WeakPtr<SpeculationHostDevToolsObserver> devtools_observer);
// Attempts to prefetch the given candidate. Returns true if a new prefetch
// for the candidate's URL is started.
bool MaybePrefetch(
blink::mojom::SpeculationCandidatePtr candidate,
const PreloadingPredictor& enacting_predictor,
base::WeakPtr<SpeculationHostDevToolsObserver> devtools_observer);
void PrefetchAheadOfPrerender(
scoped_refptr<PreloadPipelineInfo> preload_pipeline_info,
blink::mojom::SpeculationCandidatePtr candidate,
const PreloadingPredictor& enacting_predictor);
// Starts the process to prefetch |url| with the given |prefetch_type|.
void PrefetchUrl(
const GURL& url,
const PrefetchType& prefetch_type,
const PreloadingPredictor& enacting_predictor,
PreloadingType planned_max_preloading_type,
const blink::mojom::Referrer& referrer,
const network::mojom::NoVarySearchPtr& no_vary_search_expected,
scoped_refptr<PreloadPipelineInfo> preload_pipeline_info,
base::WeakPtr<SpeculationHostDevToolsObserver> devtools_observer);
// Checking the canary cache can be a slow and blocking operation (see
// crbug.com/1266018), so we only do this for the first non-decoy prefetch we
// make on the page.
bool HaveCanaryChecksStarted() const { return have_canary_checks_started_; }
void OnCanaryChecksStarted() { have_canary_checks_started_ = true; }
// Returns metrics for prefetches requested by the associated page load.
PrefetchReferringPageMetrics& GetReferringPageMetrics() {
return referring_page_metrics_;
}
// Updates metrics when the eligibility check for a prefetch requested by this
// page load is completed.
void OnEligibilityCheckComplete(bool is_eligible);
// Updates metrics when the response for a prefetch requested by this page
// load is received.
void OnPrefetchSuccessful(PrefetchContainer* prefetch);
// Whether the prefetch attempt for target |url| failed or discarded
bool IsPrefetchAttemptFailedOrDiscarded(const GURL& url);
// Returns a tuple: (can_prefetch_now, prefetch_to_evict). 'can_prefetch_now'
// is true if we can prefetch |next_prefetch| based on the state of the
// document, and the number of existing completed prefetches (only if
// |kPrefetchNewLimits| is enabled). The eagerness of |next_prefetch| is taken
// into account when making the decision. 'prefetch_to_evict' is set to an
// existing prefetch if one needs to be evicted to make space for the prefetch
// of |next_prefetch|, or nullptr otherwise. 'prefetch_to_evict' will only be
// non-null if 'can_prefetch_now' is true.
std::tuple<bool, base::WeakPtr<PrefetchContainer>> CanPrefetchNow(
PrefetchContainer* next_prefetch);
// See documentation for |prefetch_destruction_callback_|.
void SetPrefetchDestructionCallback(PrefetchDestructionCallback callback);
// Called when a PrefetchContainer started by |this| is being destroyed.
void PrefetchWillBeDestroyed(PrefetchContainer* prefetch);
base::WeakPtr<PrefetchDocumentManager> GetWeakPtr() {
return weak_method_factory_.GetWeakPtr();
}
static void SetPrefetchServiceForTesting(PrefetchService* prefetch_service);
private:
explicit PrefetchDocumentManager(RenderFrameHost* rfh);
friend DocumentUserData;
// Helper function to get the |PrefetchService| associated with |this|.
PrefetchService* GetPrefetchService() const;
bool IsPrefetchAttemptFailedOrDiscardedInternal(
const GURL& url,
PreloadingType planned_max_preloading_type);
blink::DocumentToken document_token_;
// This map holds references to all |PrefetchContainer| associated with
// |this|.
//
// Keyed with `(url, planned_max_preloading_type)`.
// `planned_max_preloading_type == kPrerender` indicates it's ahead of
// prerender.
//
// We allow normal prefetch and prefetch ahead of prerender with the same key
// here, to handle and merge them in `PrefetchService`.
std::map<std::pair<GURL, PreloadingType>, base::WeakPtr<PrefetchContainer>>
all_prefetches_;
// Stores whether or not canary checks have been started for this page.
bool have_canary_checks_started_{false};
// A list of eager prefetch requests (from this page) that have completed
// (oldest to newest).
std::vector<base::WeakPtr<PrefetchContainer>> completed_eager_prefetches_;
// A list of non-eager prefetch requests (from this page) that have completed
// (oldest to newest).
std::vector<base::WeakPtr<PrefetchContainer>> completed_non_eager_prefetches_;
// Metrics related to the prefetches requested by this page load.
PrefetchReferringPageMetrics referring_page_metrics_;
// Callback that is run when a prefetch started by |this| is being destroyed.
PrefetchDestructionCallback prefetch_destruction_callback_;
base::WeakPtrFactory<PrefetchDocumentManager> weak_method_factory_{this};
DOCUMENT_USER_DATA_KEY_DECL();
};
} // namespace content
#endif // CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_DOCUMENT_MANAGER_H_