blob: 2f570bcc160ac2eb899f52fcc2e521985bb15638 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_params.h"
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_features.h"
#include "chrome/common/chrome_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/prefs/pref_service.h"
#include "components/unified_consent/url_keyed_data_collection_consent_helper.h"
const char kIsolatedPrerenderLimitNSPSubresourcesCmdLineFlag[] =
"isolated-prerender-max-subresource-per-prerender";
const char kIsolatedPrerenderEnableNSPCmdLineFlag[] =
"isolated-prerender-nsp-enabled";
bool PrefetchProxyIsEnabled() {
return base::FeatureList::IsEnabled(features::kIsolatePrerenders);
}
GURL PrefetchProxyProxyHost() {
// Command line overrides take priority.
std::string cmd_line_value =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
"isolated-prerender-tunnel-proxy");
if (!cmd_line_value.empty()) {
GURL cmd_line_url(cmd_line_value);
if (cmd_line_url.is_valid()) {
return cmd_line_url;
}
LOG(ERROR) << "--isolated-prerender-tunnel-proxy value is invalid";
}
GURL url(base::GetFieldTrialParamValueByFeature(features::kIsolatePrerenders,
"proxy_host"));
if (url.is_valid() && url.SchemeIs(url::kHttpsScheme)) {
return url;
}
return GURL("https://tunnel.googlezip.net/");
}
std::string PrefetchProxyProxyHeaderKey() {
std::string header = base::GetFieldTrialParamValueByFeature(
features::kIsolatePrerenders, "proxy_header_key");
if (!header.empty()) {
return header;
}
return "chrome-tunnel";
}
bool PrefetchProxyOnlyForLiteMode() {
return base::GetFieldTrialParamByFeatureAsBool(features::kIsolatePrerenders,
"lite_mode_only", true);
}
bool PrefetchProxyNoStatePrefetchSubresources() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
kIsolatedPrerenderEnableNSPCmdLineFlag) ||
base::GetFieldTrialParamByFeatureAsBool(features::kIsolatePrerenders,
"do_no_state_prefetch", false);
}
absl::optional<size_t> PrefetchProxyMaximumNumberOfPrefetches() {
if (!PrefetchProxyIsEnabled()) {
return 0;
}
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
"isolated-prerender-unlimited-prefetches")) {
return absl::nullopt;
}
int max = base::GetFieldTrialParamByFeatureAsInt(features::kIsolatePrerenders,
"max_srp_prefetches", 1);
if (max < 0) {
return absl::nullopt;
}
return max;
}
absl::optional<size_t> PrefetchProxyMaximumNumberOfNoStatePrefetchAttempts() {
if (!PrefetchProxyIsEnabled() ||
!PrefetchProxyNoStatePrefetchSubresources()) {
return 0;
}
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
"isolated-prerender-unlimited-nsp")) {
return absl::nullopt;
}
int max = base::GetFieldTrialParamByFeatureAsInt(features::kIsolatePrerenders,
"max_nsp", 1);
if (max < 0) {
return absl::nullopt;
}
return max;
}
size_t PrefetchProxyMainframeBodyLengthLimit() {
return 1024 * base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerenders,
"max_mainframe_body_length_kb", 5 * 1024);
}
size_t PrefetchProxyMaximumNumberOfConcurrentPrefetches() {
return static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerenders, "max_concurrent_prefetches", 1));
}
base::TimeDelta PrefetchProxyCanaryCheckTimeout() {
return base::Milliseconds(base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerendersMustProbeOrigin, "canary_check_timeout_ms",
5 * 1000 /* 5 seconds */));
}
int PrefetchProxyCanaryCheckRetries() {
return base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerendersMustProbeOrigin, "canary_check_retries", 1);
}
bool PrefetchProxyCloseIdleSockets() {
return base::GetFieldTrialParamByFeatureAsBool(features::kIsolatePrerenders,
"close_idle_sockets", true);
}
base::TimeDelta PrefetchProxyTimeoutDuration() {
return base::Milliseconds(base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerenders, "prefetch_timeout_ms",
10 * 1000 /* 10 seconds */));
}
bool PrefetchProxyProbingEnabled() {
return base::FeatureList::IsEnabled(
features::kIsolatePrerendersMustProbeOrigin);
}
bool PrefetchProxyCanaryCheckEnabled() {
if (!base::FeatureList::IsEnabled(
features::kIsolatePrerendersMustProbeOrigin)) {
return false;
}
return base::GetFieldTrialParamByFeatureAsBool(
features::kIsolatePrerendersMustProbeOrigin, "do_canary", true);
}
bool PrefetchProxyTLSCanaryCheckEnabled() {
if (!PrefetchProxyCanaryCheckEnabled()) {
return false;
}
return base::GetFieldTrialParamByFeatureAsBool(
features::kIsolatePrerendersMustProbeOrigin, "do_tls_canary", false);
}
GURL PrefetchProxyTLSCanaryCheckURL() {
GURL url(base::GetFieldTrialParamValueByFeature(
features::kIsolatePrerendersMustProbeOrigin, "tls_canary_url"));
if (url.is_valid()) {
return url;
}
return GURL("http://tls.tunnel.check.googlezip.net/connect");
}
GURL PrefetchProxyDNSCanaryCheckURL() {
GURL url(base::GetFieldTrialParamValueByFeature(
features::kIsolatePrerendersMustProbeOrigin, "dns_canary_url"));
if (url.is_valid()) {
return url;
}
return GURL("http://dns.tunnel.check.googlezip.net/connect");
}
base::TimeDelta PrefetchProxyCanaryCheckCacheLifetime() {
return base::Hours(base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerendersMustProbeOrigin, "canary_cache_hours", 24));
}
size_t PrefetchProxyMaxSubresourcesPerPrerender() {
std::string cmd_line_value =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
kIsolatedPrerenderLimitNSPSubresourcesCmdLineFlag);
size_t cmd_line_parsed;
if (!cmd_line_value.empty() &&
base::StringToSizeT(cmd_line_value, &cmd_line_parsed)) {
return cmd_line_parsed;
}
return base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerenders, "max_subresource_count_per_prerender", 50);
}
bool PrefetchProxyStartsSpareRenderer() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
"isolated-prerender-start-spare-renderer") ||
base::GetFieldTrialParamByFeatureAsBool(features::kIsolatePrerenders,
"start_spare_renderer", false);
}
bool PrefetchProxyUseSpeculationRules() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
"isolated-prerender-use-speculation-rules") ||
base::GetFieldTrialParamByFeatureAsBool(
features::kIsolatePrerenders, "use_speculation_rules", false);
}
bool PrefetchProxyShouldPrefetchPosition(size_t position) {
std::string csv = base::GetFieldTrialParamValueByFeature(
features::kIsolatePrerenders, "prefetch_positions");
if (csv.empty()) {
return true;
}
// Using a static set that is parsed from |csv| causes tests to fail when the
// tests share the same process. This approach is faster than having to parse
// each value as a number then check for contains.
return base::Contains(base::SplitString(csv, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY),
base::NumberToString(position));
}
base::TimeDelta PrefetchProxyMaxRetryAfterDelta() {
int max_seconds = base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerenders, "max_retry_after_duration_secs",
1 * 60 * 60 * 24 * 7 /* 1 week */);
return base::Seconds(max_seconds);
}
bool PrefetchProxySendDecoyRequestForIneligiblePrefetch(
PrefService* pref_service) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
"prefetch-proxy-never-send-decoy-requests-for-testing")) {
return false;
}
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
"prefetch-proxy-always-send-decoy-requests-for-testing")) {
return true;
}
if (base::GetFieldTrialParamByFeatureAsBool(
features::kIsolatePrerenders, "disable_decoys_for_msbb", true)) {
std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>
helper = unified_consent::UrlKeyedDataCollectionConsentHelper::
NewAnonymizedDataCollectionConsentHelper(pref_service);
if (helper->IsEnabled()) {
// The user opted-in to Make Search and Browsing Better, no need to send
// a decoy request.
return false;
}
}
double probability = base::GetFieldTrialParamByFeatureAsDouble(
features::kIsolatePrerenders, "ineligible_decoy_request_probability",
1.0);
// Clamp to [0.0, 1.0].
probability = std::max(0.0, probability);
probability = std::min(1.0, probability);
// RandDouble returns [0.0, 1.0) so don't use <= here since that may return
// true when the probability is supposed to be 0 (i.e.: always false).
return base::RandDouble() < probability;
}
bool PrefetchProxyAllowAllDomains() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
"isolated-prerender-allow-all-domains");
}
base::TimeDelta PrefetchProxyCacheableDuration() {
return base::Seconds(base::GetFieldTrialParamByFeatureAsInt(
features::kIsolatePrerenders, "cacheable_duration", 300));
}
std::string PrefetchProxyServerExperimentGroup() {
return base::GetFieldTrialParamValueByFeature(features::kIsolatePrerenders,
"server_experiment_group");
}
bool PrefetchProxyUseIndividualNetworkContextsForEachPrefetch() {
return base::GetFieldTrialParamByFeatureAsBool(
features::kIsolatePrerenders, "use_individual_network_contexts", false);
}
bool PrefetchProxySupportNonPrivatePrefetches() {
// The non-private prefetches require individual network contexts.
return PrefetchProxyUseIndividualNetworkContextsForEachPrefetch() &&
base::GetFieldTrialParamByFeatureAsBool(
features::kIsolatePrerenders, "support_non_private_prefetches",
true);
}