blob: f81652c5a2b618a38a3867ee44103abec92ab81e [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2022 The Chromium Authors
Max Curran18a6f2b2022-05-02 23:13:242// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Sreeja Kamishettyf66553a2022-07-14 17:41:275#include "content/browser/preloading/prefetch/prefetch_params.h"
Max Curran18a6f2b2022-05-02 23:13:246
Kouhei Ueno58165ea2023-11-13 03:41:077#include <string>
8
Max Curran18a6f2b2022-05-02 23:13:249#include "base/command_line.h"
10#include "base/metrics/field_trial_params.h"
Kouhei Ueno58165ea2023-11-13 03:41:0711#include "base/no_destructor.h"
Max Curran18a6f2b2022-05-02 23:13:2412#include "base/rand_util.h"
Taiyo Mizuhashi43066071f2025-04-25 23:40:2213#include "base/strings/strcat.h"
Sreeja Kamishettyf66553a2022-07-14 17:41:2714#include "content/browser/preloading/prefetch/prefetch_features.h"
Hiroshige Hayashizaki583b4962025-08-19 18:58:2615#include "content/browser/preloading/prefetch/prefetch_type.h"
Taiyo Mizuhashi6b0a4952024-03-18 22:40:3716#include "content/browser/preloading/preloading_trigger_type_impl.h"
kenoss0a0181a2024-08-16 18:51:3417#include "content/browser/preloading/prerender/prerender_features.h"
Adithya Srinivasane2677952023-07-26 17:29:5818#include "content/public/common/content_features.h"
Max Curran18a6f2b2022-05-02 23:13:2419
20namespace content {
21
Max Curranead64a62022-06-22 01:10:5222GURL PrefetchProxyHost(const GURL& default_proxy_url) {
Max Curran18a6f2b2022-05-02 23:13:2423 // Command line overrides take priority.
24 std::string cmd_line_value =
25 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
26 "isolated-prerender-tunnel-proxy");
27 if (!cmd_line_value.empty()) {
28 GURL cmd_line_url(cmd_line_value);
29 if (cmd_line_url.is_valid()) {
30 return cmd_line_url;
31 }
32 LOG(ERROR) << "--isolated-prerender-tunnel-proxy value is invalid";
33 }
34
Max Curranead64a62022-06-22 01:10:5235 return default_proxy_url;
Max Curran18a6f2b2022-05-02 23:13:2436}
37
Max Curran18a6f2b2022-05-02 23:13:2438std::string PrefetchProxyServerExperimentGroup() {
39 return base::GetFieldTrialParamValueByFeature(
40 features::kPrefetchUseContentRefactor, "server_experiment_group");
41}
42
Max Curranead64a62022-06-22 01:10:5243bool PrefetchAllowAllDomains() {
44 return base::GetFieldTrialParamByFeatureAsBool(
45 features::kPrefetchUseContentRefactor, "allow_all_domains",
46 false) ||
47 base::CommandLine::ForCurrentProcess()->HasSwitch(
48 "isolated-prerender-allow-all-domains");
49}
50
51bool PrefetchAllowAllDomainsForExtendedPreloading() {
52 return base::GetFieldTrialParamByFeatureAsBool(
53 features::kPrefetchUseContentRefactor,
Max Curran94511aa2022-08-10 20:28:2654 "allow_all_domains_for_extended_preloading", true);
Max Curranead64a62022-06-22 01:10:5255}
56
Max Curranead64a62022-06-22 01:10:5257bool PrefetchServiceSendDecoyRequestForIneligblePrefetch(
58 bool disabled_based_on_user_settings) {
Max Curran18a6f2b2022-05-02 23:13:2459 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
60 "prefetch-proxy-never-send-decoy-requests-for-testing")) {
61 return false;
62 }
63 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
64 "prefetch-proxy-always-send-decoy-requests-for-testing")) {
65 return true;
66 }
67
Max Curranead64a62022-06-22 01:10:5268 if (base::GetFieldTrialParamByFeatureAsBool(
69 features::kPrefetchUseContentRefactor,
70 "disable_decoys_based_on_user_settings", true) &&
71 disabled_based_on_user_settings) {
72 return false;
73 }
Max Curran18a6f2b2022-05-02 23:13:2474
75 double probability = base::GetFieldTrialParamByFeatureAsDouble(
76 features::kPrefetchUseContentRefactor,
77 "ineligible_decoy_request_probability", 1.0);
78
79 // Clamp to [0.0, 1.0].
80 probability = std::max(0.0, probability);
81 probability = std::min(1.0, probability);
82
83 // RandDouble returns [0.0, 1.0) so don't use <= here since that may return
84 // true when the probability is supposed to be 0 (i.e.: always false).
85 return base::RandDouble() < probability;
86}
87
88base::TimeDelta PrefetchTimeoutDuration() {
89 return base::Milliseconds(base::GetFieldTrialParamByFeatureAsInt(
90 features::kPrefetchUseContentRefactor, "prefetch_timeout_ms",
91 10 * 1000 /* 10 seconds */));
92}
93
94size_t PrefetchMainframeBodyLengthLimit() {
95 return 1024 * base::GetFieldTrialParamByFeatureAsInt(
96 features::kPrefetchUseContentRefactor,
97 "max_mainframe_body_length_kb", 5 * 1024);
98}
99
100bool PrefetchCloseIdleSockets() {
101 return base::GetFieldTrialParamByFeatureAsBool(
102 features::kPrefetchUseContentRefactor, "close_idle_sockets", true);
103}
104
Max Curran94511aa2022-08-10 20:28:26105bool PrefetchStartsSpareRenderer() {
106 return base::CommandLine::ForCurrentProcess()->HasSwitch(
107 "isolated-prerender-start-spare-renderer") ||
108 base::GetFieldTrialParamByFeatureAsBool(
109 features::kPrefetchUseContentRefactor, "start_spare_renderer",
110 true);
111}
112
elabadysayedf7d6b00f2025-02-05 11:27:00113base::TimeDelta PrefetchContainerDefaultTtlInPrefetchService() {
Max Curran18a6f2b2022-05-02 23:13:24114 // A value of 0 or less, indicates that |PrefetchService| should keep the
115 // prefetch forever.
116 return base::Seconds(base::GetFieldTrialParamByFeatureAsInt(
117 features::kPrefetchUseContentRefactor, "prefetch_container_lifetime_s",
118 10 * 60 /* 10 minutes */));
119}
120
Max Curran6b93426f2022-05-03 00:55:52121bool PrefetchServiceHTMLOnly() {
122 return base::GetFieldTrialParamByFeatureAsBool(
123 features::kPrefetchUseContentRefactor, "html_only", false);
124}
125
Kouhei Ueno58165ea2023-11-13 03:41:07126bool ShouldPrefetchBypassProxyForTestHost(std::string_view host) {
127 static const base::NoDestructor<std::string> bypass(
128 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
129 "bypass-prefetch-proxy-for-host"));
130 if (bypass->empty()) {
131 return false;
132 }
133 return host == *bypass;
Iman Saboorid74fb3c2022-07-21 15:34:38134}
135
Max Curranc4445fc2022-06-02 18:43:43136base::TimeDelta PrefetchCacheableDuration() {
137 return base::Seconds(base::GetFieldTrialParamByFeatureAsInt(
138 features::kPrefetchUseContentRefactor, "cacheable_duration", 300));
139}
140
Max Curran0146f852022-08-01 19:49:33141bool PrefetchProbingEnabled() {
142 return base::GetFieldTrialParamByFeatureAsBool(
Taiyo Mizuhashi576a62972025-06-23 11:09:25143 features::kPrefetchCanaryCheckerParams, "must_probe_origin", true);
Max Curran0146f852022-08-01 19:49:33144}
145
146bool PrefetchCanaryCheckEnabled() {
147 return base::GetFieldTrialParamByFeatureAsBool(
Taiyo Mizuhashi576a62972025-06-23 11:09:25148 features::kPrefetchCanaryCheckerParams, "do_canary", true);
Max Curran0146f852022-08-01 19:49:33149}
150
151bool PrefetchTLSCanaryCheckEnabled() {
152 return base::GetFieldTrialParamByFeatureAsBool(
Taiyo Mizuhashi576a62972025-06-23 11:09:25153 features::kPrefetchCanaryCheckerParams, "do_tls_canary", false);
Max Curran0146f852022-08-01 19:49:33154}
155
156GURL PrefetchTLSCanaryCheckURL(const GURL& default_tls_canary_check_url) {
157 GURL url(base::GetFieldTrialParamValueByFeature(
Taiyo Mizuhashi576a62972025-06-23 11:09:25158 features::kPrefetchCanaryCheckerParams, "tls_canary_url"));
Max Curran0146f852022-08-01 19:49:33159 if (url.is_valid())
160 return url;
161
162 return default_tls_canary_check_url;
163}
164
165GURL PrefetchDNSCanaryCheckURL(const GURL& default_dns_canary_check_url) {
166 GURL url(base::GetFieldTrialParamValueByFeature(
Taiyo Mizuhashi576a62972025-06-23 11:09:25167 features::kPrefetchCanaryCheckerParams, "dns_canary_url"));
Max Curran0146f852022-08-01 19:49:33168 if (url.is_valid())
169 return url;
170
171 return default_dns_canary_check_url;
172}
173
174base::TimeDelta PrefetchCanaryCheckCacheLifetime() {
175 return base::Hours(base::GetFieldTrialParamByFeatureAsInt(
Taiyo Mizuhashi576a62972025-06-23 11:09:25176 features::kPrefetchCanaryCheckerParams, "canary_cache_hours", 24));
Max Curran0146f852022-08-01 19:49:33177}
178
179base::TimeDelta PrefetchCanaryCheckTimeout() {
180 return base::Milliseconds(base::GetFieldTrialParamByFeatureAsInt(
Taiyo Mizuhashi576a62972025-06-23 11:09:25181 features::kPrefetchCanaryCheckerParams, "canary_check_timeout_ms",
Max Curran0146f852022-08-01 19:49:33182 5 * 1000 /* 5 seconds */));
183}
184
185int PrefetchCanaryCheckRetries() {
186 return base::GetFieldTrialParamByFeatureAsInt(
Taiyo Mizuhashi576a62972025-06-23 11:09:25187 features::kPrefetchCanaryCheckerParams, "canary_check_retries", 1);
Max Curran0146f852022-08-01 19:49:33188}
189
Taiyo Mizuhashicd08a8f2025-06-10 17:27:32190base::TimeDelta PrefetchBlockUntilHeadTimeout(
191 const PrefetchType& prefetch_type,
192 bool should_disable_block_until_head_timeout,
193 bool is_nav_prerender) {
194 // If the caller of prefetches requests to disable the timeout, follow that.
195 if (should_disable_block_until_head_timeout) {
196 return base::Seconds(0);
197 }
198
kenoss5cc0bcf72025-03-26 04:04:33199 // Don't set a timeout for prerender because
200 //
201 // - The intention of prefetch ahead of prerender is not sending additional
202 // fetch request. The options of the behavior of the timeout case are
203 // 1. (Current behavior) Making prerender fail, or 2. Falling back to
204 // network.
205 // - 1 reduces the prerender activation rate.
206 //
207 // For more details, see
208 // https://docs.google.com/document/d/1ZP7lYrtqZL9jC2xXieNY_UBMJL1sCrfmzTB8K6v4sD4/edit?resourcekey=0-fkbeQhkT3PhBb9FnnPgnZA&tab=t.wphan8fb23kr
209 if (!features::kPrerender2FallbackPrefetchUseBlockUntilHeadTimetout.Get() &&
210 is_nav_prerender) {
211 return base::Seconds(0);
212 }
213
Max Currane6679ca2023-06-06 19:01:39214 int timeout_in_milliseconds = 0;
Taiyo Mizuhashi6b0a4952024-03-18 22:40:37215 if (IsSpeculationRuleType(prefetch_type.trigger_type())) {
216 switch (prefetch_type.GetEagerness()) {
Takashi Nakayama978f0a152025-06-17 08:26:25217 case blink::mojom::SpeculationEagerness::kImmediate:
Taiyo Mizuhashi6b0a4952024-03-18 22:40:37218 timeout_in_milliseconds = base::GetFieldTrialParamByFeatureAsInt(
219 features::kPrefetchUseContentRefactor,
Takashi Nakayamac96a5de2025-06-24 04:07:43220 "block_until_head_timeout_immediate_prefetch", 1000);
Taiyo Mizuhashi6b0a4952024-03-18 22:40:37221 break;
Takashi Nakayama8ec9dbf2025-06-27 04:03:15222 case blink::mojom::SpeculationEagerness::kEager:
223 timeout_in_milliseconds = base::GetFieldTrialParamByFeatureAsInt(
224 features::kPrefetchUseContentRefactor,
225 "block_until_head_timeout_eager_prefetch", 1000);
226 break;
Taiyo Mizuhashi6b0a4952024-03-18 22:40:37227 case blink::mojom::SpeculationEagerness::kModerate:
228 timeout_in_milliseconds = base::GetFieldTrialParamByFeatureAsInt(
229 features::kPrefetchUseContentRefactor,
Kouhei Uenoc3f69a52024-07-05 03:57:20230 "block_until_head_timeout_moderate_prefetch", 0);
Taiyo Mizuhashi6b0a4952024-03-18 22:40:37231 break;
232 case blink::mojom::SpeculationEagerness::kConservative:
233 timeout_in_milliseconds = base::GetFieldTrialParamByFeatureAsInt(
234 features::kPrefetchUseContentRefactor,
Kouhei Uenoc3f69a52024-07-05 03:57:20235 "block_until_head_timeout_conservative_prefetch", 0);
Taiyo Mizuhashi6b0a4952024-03-18 22:40:37236 break;
237 }
238 } else {
239 timeout_in_milliseconds = base::GetFieldTrialParamByFeatureAsInt(
240 features::kPrefetchUseContentRefactor,
241 "block_until_head_timeout_embedder_prefetch", 1000);
Max Currane6679ca2023-06-06 19:01:39242 }
243 return base::Milliseconds(timeout_in_milliseconds);
244}
245
Taiyo Mizuhashi43066071f2025-04-25 23:40:22246// These strings (including `embedder_histogram_suffix`) are persisted to logs.
Takashi Nakayamac8183502025-08-04 14:18:50247// LINT.IfChange(GetMetricsSuffixTriggerTypeAndEagerness)
Taiyo Mizuhashi43066071f2025-04-25 23:40:22248std::string GetMetricsSuffixTriggerTypeAndEagerness(
249 const PrefetchType prefetch_type,
250 const std::optional<std::string>& embedder_histogram_suffix) {
251 switch (prefetch_type.trigger_type()) {
252 case PreloadingTriggerType::kSpeculationRule:
253 switch (prefetch_type.GetEagerness()) {
Takashi Nakayama978f0a152025-06-17 08:26:25254 case blink::mojom::SpeculationEagerness::kImmediate:
Takashi Nakayamac8183502025-08-04 14:18:50255 return "SpeculationRule_Immediate2";
Takashi Nakayama9eb7988f2025-06-25 06:14:00256 case blink::mojom::SpeculationEagerness::kEager:
Takashi Nakayamac8183502025-08-04 14:18:50257 return "SpeculationRule_Eager2";
Taiyo Mizuhashi43066071f2025-04-25 23:40:22258 case blink::mojom::SpeculationEagerness::kModerate:
259 return "SpeculationRule_Moderate";
260 case blink::mojom::SpeculationEagerness::kConservative:
261 return "SpeculationRule_Conservative";
262 }
263 case PreloadingTriggerType::kSpeculationRuleFromIsolatedWorld:
264 switch (prefetch_type.GetEagerness()) {
Takashi Nakayama978f0a152025-06-17 08:26:25265 case blink::mojom::SpeculationEagerness::kImmediate:
Takashi Nakayamac8183502025-08-04 14:18:50266 return "SpeculationRule_Immediate2";
Takashi Nakayama9eb7988f2025-06-25 06:14:00267 case blink::mojom::SpeculationEagerness::kEager:
Takashi Nakayamac8183502025-08-04 14:18:50268 return "SpeculationRule_Eager2";
Taiyo Mizuhashi43066071f2025-04-25 23:40:22269 case blink::mojom::SpeculationEagerness::kModerate:
270 return "SpeculationRuleFromIsolatedWorld_Moderate";
271 case blink::mojom::SpeculationEagerness::kConservative:
272 return "SpeculationRuleFromIsolatedWorld_Conservative";
273 }
274 case PreloadingTriggerType::kSpeculationRuleFromAutoSpeculationRules:
275 switch (prefetch_type.GetEagerness()) {
Takashi Nakayama978f0a152025-06-17 08:26:25276 case blink::mojom::SpeculationEagerness::kImmediate:
Takashi Nakayamac8183502025-08-04 14:18:50277 return "SpeculationRule_Immediate2";
Takashi Nakayama9eb7988f2025-06-25 06:14:00278 case blink::mojom::SpeculationEagerness::kEager:
Takashi Nakayamac8183502025-08-04 14:18:50279 return "SpeculationRule_Eager2";
Taiyo Mizuhashi43066071f2025-04-25 23:40:22280 case blink::mojom::SpeculationEagerness::kModerate:
281 return "SpeculationRuleFromAutoSpeculationRules_Moderate";
282 case blink::mojom::SpeculationEagerness::kConservative:
283 return "SpeculationRuleFromAutoSpeculationRules_Conservative";
284 }
285 case PreloadingTriggerType::kEmbedder:
286 CHECK(!embedder_histogram_suffix.value().empty());
287 return base::StrCat({"Embedder_", embedder_histogram_suffix.value()});
Max Currand74e811f2023-06-01 19:40:04288 }
289}
Taiyo Mizuhashi43066071f2025-04-25 23:40:22290// LINT.ThenChange(//tools/metrics/histograms/metadata/prefetch/histograms.xml:TriggerTypeAndEagerness)
Max Currand74e811f2023-06-01 19:40:04291
Kouhei Uenod47c0bbc2023-11-15 23:16:17292bool PrefetchNIKScopeEnabled() {
293 return base::FeatureList::IsEnabled(features::kPrefetchNIKScope);
294}
295
kenoss420b465a2024-11-21 13:17:15296size_t GetPrefetchDataPipeTeeBodySizeLimit() {
kenoss767341b2025-07-01 10:35:32297 return static_cast<size_t>(features::kPrefetchReusableBodySizeLimit.Get());
kenoss420b465a2024-11-21 13:17:15298}
299
kenoss1b8ebc22025-04-04 00:11:35300bool UsePrefetchScheduler() {
kenoss1eb925f2025-04-04 05:49:56301 return base::FeatureList::IsEnabled(features::kPrefetchScheduler) ||
302 features::kPrerender2FallbackPrefetchSchedulerPolicy.Get() !=
Taiyo Mizuhashid13f8ca2025-06-23 13:29:02303 features::Prerender2FallbackPrefetchSchedulerPolicy::kNotUse ||
304 base::FeatureList::IsEnabled(
Taiyo Mizuhashi98e3dea2025-06-23 18:32:58305 features::kWebViewPrefetchHighestPrefetchPriority) ||
306 base::FeatureList::IsEnabled(
307 features::kPrefetchMultipleActiveSetSizeLimitForBase);
kenoss1b8ebc22025-04-04 00:11:35308}
309
Max Curran18a6f2b2022-05-02 23:13:24310} // namespace content