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
177
178
179
180
181
182
183
content / public / browser / preloading_data.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_PUBLIC_BROWSER_PRELOADING_DATA_H_
#define CONTENT_PUBLIC_BROWSER_PRELOADING_DATA_H_
#include <optional>
#include "base/functional/callback.h"
#include "content/common/content_export.h"
#include "content/public/browser/preloading.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "url/gurl.h"
namespace content {
class WebContents;
class NavigationHandle;
using PreloadingURLMatchCallback = base::RepeatingCallback<bool(const GURL&)>;
using PredictorDomainCallback =
base::RepeatingCallback<bool(NavigationHandle*)>;
// PreloadingPrediction and PreloadingAttempt are the preloading logging APIs
// which allows us to set various metrics and log the values.
// All these metrics are logged into the UKM after the page navigates or when
// the WebContents is being destroyed. This API will be used by features both
// inside and outside //content.
// Both PreloadingPrediction and PreloadingAttempt are owned by PreloadingData
// class and that is associated with WebContentsUserData. PreloadingAttempt is
// cleared when either
// - A WebContents is deleted/ destroyed.
// - Primary page of the WebContents changes.
// PreloadingAttempt keeps track of every preloading attempt associated with
// various preloading features defined in preloading.h (please see the comments
// there for more details); whether it is eligible, whether it is triggered or
// not, specifies the failure reason on failing and others.
class CONTENT_EXPORT PreloadingAttempt {
public:
// Sets whether preloading is eligible to be triggered. This should only be
// called once per preloading attempt.
virtual void SetEligibility(PreloadingEligibility eligibility) = 0;
// Whether this preloading attempt should be held back in order to
// counterfactually evaluate how well this type of preloading is performing.
// This is controlled via field trial configuration. Users of preloading
// attempt should always call this before triggering an eligible preloading
// attempt. Note that individual features can also use their own field
// trial-controlled holdbacks, in which case preloading should be disabled if
// either the feature's holdback is enabled or if ShouldHoldback returns true.
// Features implementing their own holdback to should record held back
// preloading attempts by calling SetHoldbackStatus (declared below).
virtual bool ShouldHoldback() = 0;
// Sets the outcome of the holdback check used to implement counterfactual
// experiments. This is not part of eligibility status to clarify that this
// check needs to happen after we are done verifying the eligibility of a
// preloading attempt. In general, eligibility checks can be reordered, but
// the holdback check always needs to come after verifying that the preloading
// attempt was eligible. This must only be called after calling
// SetEligibility(kEligible) and should not be called more than once.
virtual void SetHoldbackStatus(PreloadingHoldbackStatus holdback_status) = 0;
// Updates the preload outcome after it was triggered. This should only be
// called for eligible attempts with a kAllowed holdback status.
// - Initially set to kUnspecified.
// - After triggering this if there is already a preloading attempt available
// for the same URL we set to kDuplicate, or
// - kRunning (for preloading methods with given enough time, we expect to
// update with kReady/ kSuccess/ kFailure).
virtual void SetTriggeringOutcome(
PreloadingTriggeringOutcome triggering_outcome) = 0;
// Sets the specific failure reason specific to the PreloadingType. This also
// sets the PreloadingTriggeringOutcome to kFailure.
virtual void SetFailureReason(PreloadingFailureReason failure_reason) = 0;
virtual base::WeakPtr<PreloadingAttempt> GetWeakPtr() = 0;
protected:
virtual ~PreloadingAttempt() = default;
};
// PreloadingData holds the data associated with all the PreloadingAttempts
// and PreloadingPredictions. This class is responsible for notifying all the
// PreloadingAttempts and PreloadingPredictions about logging the UKMs and
// maintaining its lifetime.
// Lifetime of PreloadingData is associated with WebContentsUserData.
class CONTENT_EXPORT PreloadingData {
public:
// This static function is implemented in PreloadingDataImpl.
// Please see content/browser/preloading/preloading_data_impl.cc for more
// details.
static PreloadingData* GetOrCreateForWebContents(WebContents* web_contents);
static PreloadingData* GetForWebContents(WebContents* web_contents);
// Helper method to return the PreloadingURLMatchCallback for
// `destination_url`. This method will return true only for exact matches to
// `destination_url`.
static PreloadingURLMatchCallback GetSameURLMatcher(
const GURL& destination_url);
// Creates a new PreloadingAttempt and returns a pointer associated with the
// PreloadingAttempt class. Here callers pass the `url_predicate_callback` to
// verify if the navigated and triggered URLs match based on callers logic.
//
// A caller can pass `planned_max_preloading_type` (defaults to
// `preloading_type`) different from `preloading_type` if the caller expects
// this preloading attempt will be consumed by other preloadings. For
// example, a caller can start from triggering prefetch and then proceed
// with triggering prerender. `preloading_type` must be upgradable to
// `planned_max_preloading_type`. See `IsPreloadingTypeUpgradableTo()` in
// //content/browser/preloading/preloading_attempt_impl.cc.
//
// `triggering_primary_page_source_id` is a UKM source ID of the page that
// triggered preloading. This is used for recording the metrics for user
// visible primary pages (Preloading_Attempt_PreviousPrimaryPage) to measure
// the impact of PreloadingAttempt on the page user is viewing.
// TODO(crbug.com/40227283): Extend this for non-primary page and inner
// WebContents preloading attempts.
virtual PreloadingAttempt* AddPreloadingAttempt(
PreloadingPredictor predictor,
PreloadingType preloading_type,
PreloadingURLMatchCallback url_match_predicate,
std::optional<PreloadingType> planned_max_preloading_type,
ukm::SourceId triggering_primary_page_source_id) = 0;
// Creates a new PreloadingPrediction. Same as above `url_predicate_callback`
// is passed by the caller to verify that both predicted and navigated URLs
// match. `confidence` signifies the confidence percentage of correct
// predictor's preloading prediction.
//
// `triggering_primary_page_source_id` is a UKM source ID of the page that
// triggered preloading. This is used for recording the metrics for user
// visible primary pages (Preloading_Prediction_PreviousPrimaryPage) to
// measure the impact of PreloadingPrediction on the page user is viewing.
virtual void AddPreloadingPrediction(
PreloadingPredictor predictor,
int confidence,
PreloadingURLMatchCallback url_match_predicate,
ukm::SourceId triggering_primary_page_source_id) = 0;
// To calculate the recall score of the `predictor`, we need to know if the
// `predictor` is potentially responsible for predicting the next navigation
// or not. Here, if caller provided `is_navigation_in_domain_callback`
// callback returns true for the navigation, it will be considered in the
// predictor's domain. The predictor's domain is the set of navigations a
// predictor is meant to handle (predict). For example, for Omnibox DUI, this
// is the set of navigations to history URLs started from the Omnibox
// (navigations where the user ends up choosing a Search query or where the
// user closes the Omnibox and clicks on a link in the page are not part of
// the domain of the Omnibox DUI predictor).
virtual void SetIsNavigationInDomainCallback(
PreloadingPredictor predictor,
PredictorDomainCallback is_navigation_in_domain_callback) = 0;
// This flag will be true if there's been at least 1 attempt to do a
// speculation-rules based prerender.
virtual bool HasSpeculationRulesPrerender() = 0;
// Called when the embedder is making a prediction with an ML model about
// whether a navigation to `url` will occur. The provided callback will be
// invoked on navigation with the result of whether the prediction would be
// accurate. If downsampling occurs, some callbacks may not be invoked, and
// the ones that are invoked will have the amount of sampling indicated in the
// `sampling_likelihood`.
virtual void OnPreloadingHeuristicsModelInput(
const GURL& url,
base::OnceCallback<void(std::optional<double> sampling_likelihood,
bool is_accurate_prediction)>
on_record_outcome) = 0;
protected:
virtual ~PreloadingData() = default;
};
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_PRELOADING_DATA_H_