123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915 |
- // Copyright 2014 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 "components/cronet/url_request_context_config.h"
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include "base/json/json_reader.h"
- #include "base/json/json_writer.h"
- #include "base/logging.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/string_split.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/values.h"
- #include "build/build_config.h"
- #include "components/cronet/stale_host_resolver.h"
- #include "net/base/address_family.h"
- #include "net/cert/caching_cert_verifier.h"
- #include "net/cert/cert_verifier.h"
- #include "net/cert/cert_verify_proc.h"
- #include "net/cert/ct_policy_enforcer.h"
- #include "net/cert/ct_policy_status.h"
- #include "net/cert/multi_threaded_cert_verifier.h"
- #include "net/dns/context_host_resolver.h"
- #include "net/dns/host_resolver.h"
- #include "net/dns/mapped_host_resolver.h"
- #include "net/http/http_network_session.h"
- #include "net/http/http_server_properties.h"
- #include "net/log/net_log.h"
- #include "net/nqe/network_quality_estimator_params.h"
- #include "net/quic/set_quic_flag.h"
- #include "net/reporting/reporting_policy.h"
- #include "net/socket/ssl_client_socket.h"
- #include "net/ssl/ssl_key_logger_impl.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_tag.h"
- #include "net/url_request/url_request_context_builder.h"
- #include "url/origin.h"
- #if BUILDFLAG(ENABLE_REPORTING)
- #include "net/reporting/reporting_policy.h"
- #endif // BUILDFLAG(ENABLE_REPORTING)
- namespace cronet {
- namespace {
- // Name of disk cache directory.
- const base::FilePath::CharType kDiskCacheDirectoryName[] =
- FILE_PATH_LITERAL("disk_cache");
- const char kQuicFieldTrialName[] = "QUIC";
- const char kQuicConnectionOptions[] = "connection_options";
- const char kQuicClientConnectionOptions[] = "client_connection_options";
- const char kQuicStoreServerConfigsInProperties[] =
- "store_server_configs_in_properties";
- const char kQuicMaxServerConfigsStoredInProperties[] =
- "max_server_configs_stored_in_properties";
- const char kQuicIdleConnectionTimeoutSeconds[] =
- "idle_connection_timeout_seconds";
- const char kQuicMaxTimeBeforeCryptoHandshakeSeconds[] =
- "max_time_before_crypto_handshake_seconds";
- const char kQuicMaxIdleTimeBeforeCryptoHandshakeSeconds[] =
- "max_idle_time_before_crypto_handshake_seconds";
- const char kQuicCloseSessionsOnIpChange[] = "close_sessions_on_ip_change";
- const char kQuicGoAwaySessionsOnIpChange[] = "goaway_sessions_on_ip_change";
- const char kQuicAllowServerMigration[] = "allow_server_migration";
- const char kQuicMigrateSessionsOnNetworkChangeV2[] =
- "migrate_sessions_on_network_change_v2";
- const char kQuicMigrateIdleSessions[] = "migrate_idle_sessions";
- const char kQuicRetransmittableOnWireTimeoutMilliseconds[] =
- "retransmittable_on_wire_timeout_milliseconds";
- const char kQuicIdleSessionMigrationPeriodSeconds[] =
- "idle_session_migration_period_seconds";
- const char kQuicMaxTimeOnNonDefaultNetworkSeconds[] =
- "max_time_on_non_default_network_seconds";
- const char kQuicMaxMigrationsToNonDefaultNetworkOnWriteError[] =
- "max_migrations_to_non_default_network_on_write_error";
- const char kQuicMaxMigrationsToNonDefaultNetworkOnPathDegrading[] =
- "max_migrations_to_non_default_network_on_path_degrading";
- const char kQuicUserAgentId[] = "user_agent_id";
- const char kQuicMigrateSessionsEarlyV2[] = "migrate_sessions_early_v2";
- const char kQuicRetryOnAlternateNetworkBeforeHandshake[] =
- "retry_on_alternate_network_before_handshake";
- const char kQuicRaceStaleDNSOnConnection[] = "race_stale_dns_on_connection";
- const char kQuicDisableBidirectionalStreams[] =
- "quic_disable_bidirectional_streams";
- const char kQuicHostWhitelist[] = "host_whitelist";
- const char kQuicEnableSocketRecvOptimization[] =
- "enable_socket_recv_optimization";
- const char kQuicVersion[] = "quic_version";
- const char kQuicObsoleteVersionsAllowed[] = "obsolete_versions_allowed2";
- const char kQuicFlags[] = "set_quic_flags";
- const char kQuicIOSNetworkServiceType[] = "ios_network_service_type";
- const char kRetryWithoutAltSvcOnQuicErrors[] =
- "retry_without_alt_svc_on_quic_errors";
- const char kInitialDelayForBrokenAlternativeServiceSeconds[] =
- "initial_delay_for_broken_alternative_service_seconds";
- const char kExponentialBackoffOnInitialDelay[] =
- "exponential_backoff_on_initial_delay";
- const char kDelayMainJobWithAvailableSpdySession[] =
- "delay_main_job_with_available_spdy_session";
- // AsyncDNS experiment dictionary name.
- const char kAsyncDnsFieldTrialName[] = "AsyncDNS";
- // Name of boolean to enable AsyncDNS experiment.
- const char kAsyncDnsEnable[] = "enable";
- // Stale DNS (StaleHostResolver) experiment dictionary name.
- const char kStaleDnsFieldTrialName[] = "StaleDNS";
- // Name of boolean to enable stale DNS experiment.
- const char kStaleDnsEnable[] = "enable";
- // Name of integer delay in milliseconds before a stale DNS result will be
- // used.
- const char kStaleDnsDelayMs[] = "delay_ms";
- // Name of integer maximum age (past expiration) in milliseconds of a stale DNS
- // result that will be used, or 0 for no limit.
- const char kStaleDnsMaxExpiredTimeMs[] = "max_expired_time_ms";
- // Name of integer maximum times each stale DNS result can be used, or 0 for no
- // limit.
- const char kStaleDnsMaxStaleUses[] = "max_stale_uses";
- // Name of boolean to allow stale DNS results from other networks to be used on
- // the current network.
- const char kStaleDnsAllowOtherNetwork[] = "allow_other_network";
- // Name of boolean to enable persisting the DNS cache to disk.
- const char kStaleDnsPersist[] = "persist_to_disk";
- // Name of integer minimum time in milliseconds between writes to disk for DNS
- // cache persistence. Default value is one minute. Only relevant if
- // "persist_to_disk" is true.
- const char kStaleDnsPersistTimer[] = "persist_delay_ms";
- // Name of boolean to allow use of stale DNS results when network resolver
- // returns ERR_NAME_NOT_RESOLVED.
- const char kStaleDnsUseStaleOnNameNotResolved[] =
- "use_stale_on_name_not_resolved";
- // Rules to override DNS resolution. Intended for testing.
- // See explanation of format in net/dns/mapped_host_resolver.h.
- const char kHostResolverRulesFieldTrialName[] = "HostResolverRules";
- const char kHostResolverRules[] = "host_resolver_rules";
- // NetworkQualityEstimator (NQE) experiment dictionary name.
- const char kNetworkQualityEstimatorFieldTrialName[] = "NetworkQualityEstimator";
- // Network Error Logging experiment dictionary name.
- const char kNetworkErrorLoggingFieldTrialName[] = "NetworkErrorLogging";
- // Name of boolean to enable Reporting API.
- const char kNetworkErrorLoggingEnable[] = "enable";
- // Name of list of preloaded "Report-To" headers.
- const char kNetworkErrorLoggingPreloadedReportToHeaders[] =
- "preloaded_report_to_headers";
- // Name of list of preloaded "NEL" headers.
- const char kNetworkErrorLoggingPreloadedNELHeaders[] = "preloaded_nel_headers";
- // Name of key (for above two lists) for header origin.
- const char kNetworkErrorLoggingOrigin[] = "origin";
- // Name of key (for above two lists) for header value.
- const char kNetworkErrorLoggingValue[] = "value";
- // Disable IPv6 when on WiFi. This is a workaround for a known issue on certain
- // Android phones, and should not be necessary when not on one of those devices.
- // See https://crbug.com/696569 for details.
- const char kDisableIPv6OnWifi[] = "disable_ipv6_on_wifi";
- const char kSSLKeyLogFile[] = "ssl_key_log_file";
- const char kAllowPortMigration[] = "allow_port_migration";
- const char kDisableTlsZeroRtt[] = "disable_tls_zero_rtt";
- // Whether SPDY sessions should be closed or marked as going away upon relevant
- // network changes. When not specified, /net behavior varies depending on the
- // underlying OS.
- const char kSpdyGoAwayOnIpChange[] = "spdy_go_away_on_ip_change";
- // Whether the connection status of all bidirectional streams (created through
- // the Cronet engine) should be monitored.
- // The value must be an integer (> 0) and will be interpreted as a suggestion
- // for the period of the heartbeat signal. See
- // SpdySession#EnableBrokenConnectionDetection for more info.
- const char kBidiStreamDetectBrokenConnection[] =
- "bidi_stream_detect_broken_connection";
- const char kUseDnsHttpsSvcbFieldTrialName[] = "UseDnsHttpsSvcb";
- const char kUseDnsHttpsSvcbUseAlpn[] = "use_alpn";
- // Runtime flag to bypass Cronet's logging: When set to true logging calls will
- // be skipped. If missing, logging will happen.
- const char kSkipLogging[] = "skip_logging";
- // "goaway_sessions_on_ip_change" is default on for iOS unless overridden via
- // experimental options explicitly.
- #if BUILDFLAG(IS_IOS)
- const bool kDefaultQuicGoAwaySessionsOnIpChange = true;
- #else
- const bool kDefaultQuicGoAwaySessionsOnIpChange = false;
- #endif
- // Serializes a base::Value into a string that can be used as the value of
- // JFV-encoded HTTP header [1]. If |value| is a list, we remove the outermost
- // [] delimiters from the result.
- //
- // [1] https://tools.ietf.org/html/draft-reschke-http-jfv
- std::string SerializeJFVHeader(const base::Value& value) {
- std::string result;
- if (!base::JSONWriter::Write(value, &result))
- return std::string();
- if (value.is_list()) {
- DCHECK(result.size() >= 2);
- return result.substr(1, result.size() - 2);
- }
- return result;
- }
- std::vector<URLRequestContextConfig::PreloadedNelAndReportingHeader>
- ParseNetworkErrorLoggingHeaders(
- const base::Value::List& preloaded_headers_config) {
- std::vector<URLRequestContextConfig::PreloadedNelAndReportingHeader> result;
- for (const auto& preloaded_header_config : preloaded_headers_config) {
- if (!preloaded_header_config.is_dict())
- continue;
- const std::string* origin_config =
- preloaded_header_config.GetDict().FindString(
- kNetworkErrorLoggingOrigin);
- if (!origin_config)
- continue;
- GURL origin_url(*origin_config);
- if (!origin_url.is_valid())
- continue;
- auto origin = url::Origin::Create(origin_url);
- auto* value =
- preloaded_header_config.GetDict().Find(kNetworkErrorLoggingValue);
- if (!value)
- continue;
- result.push_back(URLRequestContextConfig::PreloadedNelAndReportingHeader(
- origin, SerializeJFVHeader(*value)));
- }
- return result;
- }
- // Applies |f| to the value contained by |maybe|, returns empty optional
- // otherwise.
- template <typename T, typename F>
- auto map(absl::optional<T> maybe, F&& f) {
- if (!maybe)
- return absl::optional<std::invoke_result_t<F, T>>();
- return absl::optional<std::invoke_result_t<F, T>>(f(maybe.value()));
- }
- } // namespace
- URLRequestContextConfig::QuicHint::QuicHint(const std::string& host,
- int port,
- int alternate_port)
- : host(host), port(port), alternate_port(alternate_port) {}
- URLRequestContextConfig::QuicHint::~QuicHint() {}
- URLRequestContextConfig::Pkp::Pkp(const std::string& host,
- bool include_subdomains,
- const base::Time& expiration_date)
- : host(host),
- include_subdomains(include_subdomains),
- expiration_date(expiration_date) {}
- URLRequestContextConfig::Pkp::~Pkp() {}
- URLRequestContextConfig::PreloadedNelAndReportingHeader::
- PreloadedNelAndReportingHeader(const url::Origin& origin, std::string value)
- : origin(origin), value(std::move(value)) {}
- URLRequestContextConfig::PreloadedNelAndReportingHeader::
- ~PreloadedNelAndReportingHeader() = default;
- URLRequestContextConfig::URLRequestContextConfig(
- bool enable_quic,
- const std::string& quic_user_agent_id,
- bool enable_spdy,
- bool enable_brotli,
- HttpCacheType http_cache,
- int http_cache_max_size,
- bool load_disable_cache,
- const std::string& storage_path,
- const std::string& accept_language,
- const std::string& user_agent,
- base::Value::Dict experimental_options,
- std::unique_ptr<net::CertVerifier> mock_cert_verifier,
- bool enable_network_quality_estimator,
- bool bypass_public_key_pinning_for_local_trust_anchors,
- absl::optional<double> network_thread_priority)
- : enable_quic(enable_quic),
- quic_user_agent_id(quic_user_agent_id),
- enable_spdy(enable_spdy),
- enable_brotli(enable_brotli),
- http_cache(http_cache),
- http_cache_max_size(http_cache_max_size),
- load_disable_cache(load_disable_cache),
- storage_path(storage_path),
- accept_language(accept_language),
- user_agent(user_agent),
- mock_cert_verifier(std::move(mock_cert_verifier)),
- enable_network_quality_estimator(enable_network_quality_estimator),
- bypass_public_key_pinning_for_local_trust_anchors(
- bypass_public_key_pinning_for_local_trust_anchors),
- effective_experimental_options(experimental_options.Clone()),
- experimental_options(std::move(experimental_options)),
- network_thread_priority(network_thread_priority),
- bidi_stream_detect_broken_connection(false),
- heartbeat_interval(base::Seconds(0)),
- skip_logging(false) {
- SetContextConfigExperimentalOptions();
- }
- URLRequestContextConfig::~URLRequestContextConfig() {}
- // static
- std::unique_ptr<URLRequestContextConfig>
- URLRequestContextConfig::CreateURLRequestContextConfig(
- bool enable_quic,
- const std::string& quic_user_agent_id,
- bool enable_spdy,
- bool enable_brotli,
- HttpCacheType http_cache,
- int http_cache_max_size,
- bool load_disable_cache,
- const std::string& storage_path,
- const std::string& accept_language,
- const std::string& user_agent,
- const std::string& unparsed_experimental_options,
- std::unique_ptr<net::CertVerifier> mock_cert_verifier,
- bool enable_network_quality_estimator,
- bool bypass_public_key_pinning_for_local_trust_anchors,
- absl::optional<double> network_thread_priority) {
- absl::optional<base::Value::Dict> experimental_options =
- ParseExperimentalOptions(unparsed_experimental_options);
- if (!experimental_options) {
- // For the time being maintain backward compatibility by only failing to
- // parse when DCHECKs are enabled.
- if (ExperimentalOptionsParsingIsAllowedToFail())
- return nullptr;
- else
- experimental_options = base::Value::Dict();
- }
- return base::WrapUnique(new URLRequestContextConfig(
- enable_quic, quic_user_agent_id, enable_spdy, enable_brotli, http_cache,
- http_cache_max_size, load_disable_cache, storage_path, accept_language,
- user_agent, std::move(experimental_options).value(),
- std::move(mock_cert_verifier), enable_network_quality_estimator,
- bypass_public_key_pinning_for_local_trust_anchors,
- network_thread_priority));
- }
- // static
- absl::optional<base::Value::Dict>
- URLRequestContextConfig::ParseExperimentalOptions(
- std::string unparsed_experimental_options) {
- // From a user perspective no experimental options means an empty string. The
- // underlying code instead expects and empty dictionary. Normalize this.
- if (unparsed_experimental_options.empty())
- unparsed_experimental_options = "{}";
- DVLOG(1) << "Experimental Options:" << unparsed_experimental_options;
- auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(
- unparsed_experimental_options);
- if (!parsed_json.has_value()) {
- LOG(ERROR) << "Parsing experimental options failed: '"
- << unparsed_experimental_options << "', error "
- << parsed_json.error().message;
- return absl::nullopt;
- }
- base::Value::Dict* experimental_options_dict = parsed_json->GetIfDict();
- if (!experimental_options_dict) {
- LOG(ERROR) << "Experimental options string is not a dictionary: "
- << *parsed_json;
- return absl::nullopt;
- }
- return std::move(*experimental_options_dict);
- }
- void URLRequestContextConfig::SetContextConfigExperimentalOptions() {
- const base::Value* heartbeat_interval_value =
- experimental_options.Find(kBidiStreamDetectBrokenConnection);
- if (heartbeat_interval_value) {
- if (!heartbeat_interval_value->is_int()) {
- LOG(ERROR) << "\"" << kBidiStreamDetectBrokenConnection
- << "\" config params \"" << heartbeat_interval_value
- << "\" is not an int";
- experimental_options.Remove(kBidiStreamDetectBrokenConnection);
- effective_experimental_options.Remove(kBidiStreamDetectBrokenConnection);
- } else {
- int heartbeat_interval_secs = heartbeat_interval_value->GetInt();
- heartbeat_interval = base::Seconds(heartbeat_interval_secs);
- bidi_stream_detect_broken_connection = heartbeat_interval_secs > 0;
- experimental_options.Remove(kBidiStreamDetectBrokenConnection);
- }
- }
- const base::Value* skip_logging_value =
- experimental_options.Find(kSkipLogging);
- if (skip_logging_value) {
- if (!skip_logging_value->is_bool()) {
- LOG(ERROR) << "\"" << kSkipLogging << "\" config params \""
- << skip_logging_value << "\" is not a bool";
- experimental_options.Remove(kSkipLogging);
- effective_experimental_options.Remove(kSkipLogging);
- } else {
- skip_logging = skip_logging_value->GetBool();
- experimental_options.Remove(kSkipLogging);
- }
- }
- }
- void URLRequestContextConfig::SetContextBuilderExperimentalOptions(
- net::URLRequestContextBuilder* context_builder,
- net::HttpNetworkSessionParams* session_params,
- net::QuicParams* quic_params,
- net::handles::NetworkHandle bound_network) {
- bool async_dns_enable = false;
- bool stale_dns_enable = false;
- bool host_resolver_rules_enable = false;
- bool disable_ipv6_on_wifi = false;
- bool nel_enable = false;
- bool is_network_bound = bound_network != net::handles::kInvalidNetworkHandle;
- absl::optional<net::HostResolver::HttpsSvcbOptions> https_svcb_options;
- StaleHostResolver::StaleOptions stale_dns_options;
- const std::string* host_resolver_rules_string;
- for (auto iter = experimental_options.begin();
- iter != experimental_options.end(); ++iter) {
- if (iter->first == kQuicFieldTrialName) {
- if (!iter->second.is_dict()) {
- LOG(ERROR) << "Quic config params \"" << iter->second
- << "\" is not a dictionary value";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- const base::Value::Dict& quic_args = iter->second.GetDict();
- const std::string* quic_version_string =
- quic_args.FindString(kQuicVersion);
- if (quic_version_string) {
- quic::ParsedQuicVersionVector supported_versions =
- quic::ParseQuicVersionVectorString(*quic_version_string);
- if (!quic_args.FindBool(kQuicObsoleteVersionsAllowed).value_or(false)) {
- quic::ParsedQuicVersionVector filtered_versions;
- quic::ParsedQuicVersionVector obsolete_versions =
- net::ObsoleteQuicVersions();
- for (const quic::ParsedQuicVersion& version : supported_versions) {
- if (std::find(obsolete_versions.begin(), obsolete_versions.end(),
- version) == obsolete_versions.end()) {
- filtered_versions.push_back(version);
- }
- }
- supported_versions = filtered_versions;
- }
- if (!supported_versions.empty())
- quic_params->supported_versions = supported_versions;
- }
- const std::string* quic_connection_options =
- quic_args.FindString(kQuicConnectionOptions);
- if (quic_connection_options) {
- quic_params->connection_options =
- quic::ParseQuicTagVector(*quic_connection_options);
- }
- const std::string* quic_client_connection_options =
- quic_args.FindString(kQuicClientConnectionOptions);
- if (quic_client_connection_options) {
- quic_params->client_connection_options =
- quic::ParseQuicTagVector(*quic_client_connection_options);
- }
- // TODO(rtenneti): Delete this option after apps stop using it.
- // Added this for backward compatibility.
- if (quic_args.FindBool(kQuicStoreServerConfigsInProperties)
- .value_or(false)) {
- quic_params->max_server_configs_stored_in_properties =
- net::kDefaultMaxQuicServerEntries;
- }
- quic_params->max_server_configs_stored_in_properties =
- static_cast<size_t>(
- quic_args.FindInt(kQuicMaxServerConfigsStoredInProperties)
- .value_or(
- quic_params->max_server_configs_stored_in_properties));
- quic_params->idle_connection_timeout =
- map(quic_args.FindInt(kQuicIdleConnectionTimeoutSeconds),
- base::Seconds<int>)
- .value_or(quic_params->idle_connection_timeout);
- quic_params->max_time_before_crypto_handshake =
- map(quic_args.FindInt(kQuicMaxTimeBeforeCryptoHandshakeSeconds),
- base::Seconds<int>)
- .value_or(quic_params->max_time_before_crypto_handshake);
- quic_params->max_idle_time_before_crypto_handshake =
- map(quic_args.FindInt(kQuicMaxIdleTimeBeforeCryptoHandshakeSeconds),
- base::Seconds<int>)
- .value_or(quic_params->max_idle_time_before_crypto_handshake);
- quic_params->close_sessions_on_ip_change =
- quic_args.FindBool(kQuicCloseSessionsOnIpChange)
- .value_or(quic_params->close_sessions_on_ip_change);
- if (quic_params->close_sessions_on_ip_change &&
- kDefaultQuicGoAwaySessionsOnIpChange) {
- // "close_sessions_on_ip_change" and "goaway_sessions_on_ip_change"
- // are mutually exclusive. Turn off the goaway option which is
- // default on for iOS if "close_sessions_on_ip_change" is set via
- // experimental options.
- quic_params->goaway_sessions_on_ip_change = false;
- }
- quic_params->goaway_sessions_on_ip_change =
- quic_args.FindBool(kQuicGoAwaySessionsOnIpChange)
- .value_or(quic_params->goaway_sessions_on_ip_change);
- quic_params->allow_server_migration =
- quic_args.FindBool(kQuicAllowServerMigration)
- .value_or(quic_params->allow_server_migration);
- const std::string* user_agent_id = quic_args.FindString(kQuicUserAgentId);
- if (user_agent_id) {
- quic_params->user_agent_id = *user_agent_id;
- }
- quic_params->enable_socket_recv_optimization =
- quic_args.FindBool(kQuicEnableSocketRecvOptimization)
- .value_or(quic_params->enable_socket_recv_optimization);
- absl::optional<bool> quic_migrate_sessions_on_network_change_v2_in =
- quic_args.FindBool(kQuicMigrateSessionsOnNetworkChangeV2);
- if (quic_migrate_sessions_on_network_change_v2_in.has_value()) {
- quic_params->migrate_sessions_on_network_change_v2 =
- quic_migrate_sessions_on_network_change_v2_in.value();
- quic_params->max_time_on_non_default_network =
- map(quic_args.FindInt(kQuicMaxTimeOnNonDefaultNetworkSeconds),
- base::Seconds<int>)
- .value_or(quic_params->max_time_on_non_default_network);
- quic_params->max_migrations_to_non_default_network_on_write_error =
- quic_args.FindInt(kQuicMaxMigrationsToNonDefaultNetworkOnWriteError)
- .value_or(
- quic_params
- ->max_migrations_to_non_default_network_on_write_error);
- quic_params->max_migrations_to_non_default_network_on_path_degrading =
- quic_args
- .FindInt(kQuicMaxMigrationsToNonDefaultNetworkOnPathDegrading)
- .value_or(
- quic_params
- ->max_migrations_to_non_default_network_on_path_degrading);
- }
- absl::optional<bool> quic_migrate_idle_sessions_in =
- quic_args.FindBool(kQuicMigrateIdleSessions);
- if (quic_migrate_idle_sessions_in.has_value()) {
- quic_params->migrate_idle_sessions =
- quic_migrate_idle_sessions_in.value();
- quic_params->idle_session_migration_period =
- map(quic_args.FindInt(kQuicIdleSessionMigrationPeriodSeconds),
- base::Seconds<int>)
- .value_or(quic_params->idle_session_migration_period);
- }
- quic_params->migrate_sessions_early_v2 =
- quic_args.FindBool(kQuicMigrateSessionsEarlyV2)
- .value_or(quic_params->migrate_sessions_early_v2);
- quic_params->retransmittable_on_wire_timeout =
- map(quic_args.FindInt(kQuicRetransmittableOnWireTimeoutMilliseconds),
- base::Milliseconds<int>)
- .value_or(quic_params->retransmittable_on_wire_timeout);
- quic_params->retry_on_alternate_network_before_handshake =
- quic_args.FindBool(kQuicRetryOnAlternateNetworkBeforeHandshake)
- .value_or(
- quic_params->retry_on_alternate_network_before_handshake);
- quic_params->race_stale_dns_on_connection =
- quic_args.FindBool(kQuicRaceStaleDNSOnConnection)
- .value_or(quic_params->race_stale_dns_on_connection);
- quic_params->allow_port_migration =
- quic_args.FindBool(kAllowPortMigration)
- .value_or(quic_params->allow_port_migration);
- quic_params->retry_without_alt_svc_on_quic_errors =
- quic_args.FindBool(kRetryWithoutAltSvcOnQuicErrors)
- .value_or(quic_params->retry_without_alt_svc_on_quic_errors);
- quic_params->initial_delay_for_broken_alternative_service = map(
- quic_args.FindInt(kInitialDelayForBrokenAlternativeServiceSeconds),
- base::Seconds<int>);
- quic_params->exponential_backoff_on_initial_delay =
- quic_args.FindBool(kExponentialBackoffOnInitialDelay);
- quic_params->delay_main_job_with_available_spdy_session =
- quic_args.FindBool(kDelayMainJobWithAvailableSpdySession)
- .value_or(
- quic_params->delay_main_job_with_available_spdy_session);
- quic_params->disable_tls_zero_rtt =
- quic_args.FindBool(kDisableTlsZeroRtt)
- .value_or(quic_params->disable_tls_zero_rtt);
- quic_params->disable_bidirectional_streams =
- quic_args.FindBool(kQuicDisableBidirectionalStreams)
- .value_or(quic_params->disable_bidirectional_streams);
- const std::string* quic_host_allowlist =
- quic_args.FindString(kQuicHostWhitelist);
- if (quic_host_allowlist) {
- std::vector<std::string> host_vector =
- base::SplitString(*quic_host_allowlist, ",", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL);
- session_params->quic_host_allowlist.clear();
- for (const std::string& host : host_vector) {
- session_params->quic_host_allowlist.insert(host);
- }
- }
- const std::string* quic_flags = quic_args.FindString(kQuicFlags);
- if (quic_flags) {
- for (const auto& flag :
- base::SplitString(*quic_flags, ",", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL)) {
- std::vector<std::string> tokens = base::SplitString(
- flag, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- if (tokens.size() != 2)
- continue;
- net::SetQuicFlagByName(tokens[0], tokens[1]);
- }
- }
- quic_params->ios_network_service_type =
- quic_args.FindInt(kQuicIOSNetworkServiceType)
- .value_or(quic_params->ios_network_service_type);
- } else if (iter->first == kAsyncDnsFieldTrialName) {
- if (!iter->second.is_dict()) {
- LOG(ERROR) << "\"" << iter->first << "\" config params \""
- << iter->second << "\" is not a dictionary value";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- const base::Value::Dict& async_dns_args = iter->second.GetDict();
- async_dns_enable =
- async_dns_args.FindBool(kAsyncDnsEnable).value_or(async_dns_enable);
- } else if (iter->first == kStaleDnsFieldTrialName) {
- if (!iter->second.is_dict()) {
- LOG(ERROR) << "\"" << iter->first << "\" config params \""
- << iter->second << "\" is not a dictionary value";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- const base::Value::Dict& stale_dns_args = iter->second.GetDict();
- stale_dns_enable =
- stale_dns_args.FindBool(kStaleDnsEnable).value_or(false);
- if (stale_dns_enable) {
- stale_dns_options.delay = map(stale_dns_args.FindInt(kStaleDnsDelayMs),
- base::Milliseconds<int>)
- .value_or(stale_dns_options.delay);
- stale_dns_options.max_expired_time =
- map(stale_dns_args.FindInt(kStaleDnsMaxExpiredTimeMs),
- base::Milliseconds<int>)
- .value_or(stale_dns_options.max_expired_time);
- stale_dns_options.max_stale_uses =
- stale_dns_args.FindInt(kStaleDnsMaxStaleUses)
- .value_or(stale_dns_options.max_stale_uses);
- stale_dns_options.allow_other_network =
- stale_dns_args.FindBool(kStaleDnsAllowOtherNetwork)
- .value_or(stale_dns_options.allow_other_network);
- enable_host_cache_persistence =
- stale_dns_args.FindBool(kStaleDnsPersist)
- .value_or(enable_host_cache_persistence);
- host_cache_persistence_delay_ms =
- stale_dns_args.FindInt(kStaleDnsPersistTimer)
- .value_or(host_cache_persistence_delay_ms);
- stale_dns_options.use_stale_on_name_not_resolved =
- stale_dns_args.FindBool(kStaleDnsUseStaleOnNameNotResolved)
- .value_or(stale_dns_options.use_stale_on_name_not_resolved);
- }
- } else if (iter->first == kHostResolverRulesFieldTrialName) {
- if (!iter->second.is_dict()) {
- LOG(ERROR) << "\"" << iter->first << "\" config params \""
- << iter->second << "\" is not a dictionary value";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- const base::Value::Dict& host_resolver_rules_args =
- iter->second.GetDict();
- host_resolver_rules_string =
- host_resolver_rules_args.FindString(kHostResolverRules);
- host_resolver_rules_enable = !!host_resolver_rules_string;
- } else if (iter->first == kUseDnsHttpsSvcbFieldTrialName) {
- if (!iter->second.is_dict()) {
- LOG(ERROR) << "\"" << iter->first << "\" config params \""
- << iter->second << "\" is not a dictionary value";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- const base::Value::Dict& args = iter->second.GetDict();
- https_svcb_options = net::HostResolver::HttpsSvcbOptions::FromDict(args);
- session_params->use_dns_https_svcb_alpn =
- args.FindBool(kUseDnsHttpsSvcbUseAlpn)
- .value_or(session_params->use_dns_https_svcb_alpn);
- } else if (iter->first == kNetworkErrorLoggingFieldTrialName) {
- if (!iter->second.is_dict()) {
- LOG(ERROR) << "\"" << iter->first << "\" config params \""
- << iter->second << "\" is not a dictionary value";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- const base::Value::Dict& nel_args = iter->second.GetDict();
- nel_enable =
- nel_args.FindBool(kNetworkErrorLoggingEnable).value_or(nel_enable);
- const auto* preloaded_report_to_headers_config =
- nel_args.FindList(kNetworkErrorLoggingPreloadedReportToHeaders);
- if (preloaded_report_to_headers_config) {
- preloaded_report_to_headers = ParseNetworkErrorLoggingHeaders(
- *preloaded_report_to_headers_config);
- }
- const auto* preloaded_nel_headers_config =
- nel_args.FindList(kNetworkErrorLoggingPreloadedNELHeaders);
- if (preloaded_nel_headers_config) {
- preloaded_nel_headers =
- ParseNetworkErrorLoggingHeaders(*preloaded_nel_headers_config);
- }
- } else if (iter->first == kDisableIPv6OnWifi) {
- if (!iter->second.is_bool()) {
- LOG(ERROR) << "\"" << iter->first << "\" config params \""
- << iter->second << "\" is not a bool";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- disable_ipv6_on_wifi = iter->second.GetBool();
- } else if (iter->first == kSSLKeyLogFile) {
- if (iter->second.is_string()) {
- base::FilePath ssl_key_log_file(
- base::FilePath::FromUTF8Unsafe(iter->second.GetString()));
- if (!ssl_key_log_file.empty()) {
- // SetSSLKeyLogger is only safe to call before any SSLClientSockets
- // are created. This should not be used if there are multiple
- // CronetEngine.
- // TODO(xunjieli): Expose this as a stable API after crbug.com/458365
- // is resolved.
- net::SSLClientSocket::SetSSLKeyLogger(
- std::make_unique<net::SSLKeyLoggerImpl>(ssl_key_log_file));
- }
- }
- } else if (iter->first == kNetworkQualityEstimatorFieldTrialName) {
- if (!iter->second.is_dict()) {
- LOG(ERROR) << "\"" << iter->first << "\" config params \""
- << iter->second << "\" is not a dictionary value";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- const base::Value::Dict& nqe_args = iter->second.GetDict();
- const std::string* nqe_option =
- nqe_args.FindString(net::kForceEffectiveConnectionType);
- if (nqe_option) {
- nqe_forced_effective_connection_type =
- net::GetEffectiveConnectionTypeForName(*nqe_option);
- if (!nqe_option->empty() && !nqe_forced_effective_connection_type) {
- LOG(ERROR) << "\"" << nqe_option
- << "\" is not a valid effective connection type value";
- }
- }
- } else if (iter->first == kSpdyGoAwayOnIpChange) {
- if (!iter->second.is_bool()) {
- LOG(ERROR) << "\"" << iter->first << "\" config params \""
- << iter->second << "\" is not a bool";
- effective_experimental_options.Remove(iter->first);
- continue;
- }
- session_params->spdy_go_away_on_ip_change = iter->second.GetBool();
- } else {
- LOG(WARNING) << "Unrecognized Cronet experimental option \""
- << iter->first << "\" with params \"" << iter->second;
- effective_experimental_options.Remove(iter->first);
- }
- }
- if (async_dns_enable || stale_dns_enable || host_resolver_rules_enable ||
- disable_ipv6_on_wifi || is_network_bound || https_svcb_options) {
- net::HostResolver::ManagerOptions host_resolver_manager_options;
- host_resolver_manager_options.insecure_dns_client_enabled =
- async_dns_enable;
- host_resolver_manager_options.check_ipv6_on_wifi = !disable_ipv6_on_wifi;
- if (https_svcb_options) {
- host_resolver_manager_options.https_svcb_options = https_svcb_options;
- }
- if (!is_network_bound) {
- std::unique_ptr<net::HostResolver> host_resolver;
- // TODO(crbug.com/934402): Consider using a shared HostResolverManager for
- // Cronet HostResolvers.
- if (stale_dns_enable) {
- DCHECK(!disable_ipv6_on_wifi);
- host_resolver = std::make_unique<StaleHostResolver>(
- net::HostResolver::CreateStandaloneContextResolver(
- net::NetLog::Get(), std::move(host_resolver_manager_options)),
- stale_dns_options);
- } else {
- host_resolver = net::HostResolver::CreateStandaloneResolver(
- net::NetLog::Get(), std::move(host_resolver_manager_options));
- }
- if (host_resolver_rules_enable) {
- std::unique_ptr<net::MappedHostResolver> remapped_resolver(
- new net::MappedHostResolver(std::move(host_resolver)));
- remapped_resolver->SetRulesFromString(*host_resolver_rules_string);
- host_resolver = std::move(remapped_resolver);
- }
- context_builder->set_host_resolver(std::move(host_resolver));
- } else {
- // `stale_dns_enable` and `host_resolver_rules_enable` are purposefully
- // ignored. Implementing them requires instantiating a special
- // HostResolver that wraps the real underlying resolver: that isn't
- // possible at the moment for network-bound contexts as they create a
- // special HostResolver internally and don't expose that.
- context_builder->BindToNetwork(bound_network,
- std::move(host_resolver_manager_options));
- }
- }
- #if BUILDFLAG(ENABLE_REPORTING)
- if (nel_enable) {
- auto policy = net::ReportingPolicy::Create();
- // Apps (like Cronet embedders) are generally allowed to run in the
- // background, even across network changes, so use more relaxed privacy
- // settings than when Reporting is running in the browser.
- policy->persist_reports_across_restarts = true;
- policy->persist_clients_across_restarts = true;
- policy->persist_reports_across_network_changes = true;
- policy->persist_clients_across_network_changes = true;
- context_builder->set_reporting_policy(std::move(policy));
- context_builder->set_network_error_logging_enabled(true);
- }
- #endif // BUILDFLAG(ENABLE_REPORTING)
- }
- void URLRequestContextConfig::ConfigureURLRequestContextBuilder(
- net::URLRequestContextBuilder* context_builder,
- net::handles::NetworkHandle bound_network) {
- std::string config_cache;
- if (http_cache != DISABLED) {
- net::URLRequestContextBuilder::HttpCacheParams cache_params;
- if (http_cache == DISK && !storage_path.empty()) {
- cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::DISK;
- cache_params.path = base::FilePath::FromUTF8Unsafe(storage_path)
- .Append(kDiskCacheDirectoryName);
- } else {
- cache_params.type =
- net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY;
- }
- cache_params.max_size = http_cache_max_size;
- context_builder->EnableHttpCache(cache_params);
- } else {
- context_builder->DisableHttpCache();
- }
- context_builder->set_accept_language(accept_language);
- context_builder->set_user_agent(user_agent);
- net::HttpNetworkSessionParams session_params;
- session_params.enable_http2 = enable_spdy;
- session_params.enable_quic = enable_quic;
- auto quic_context = std::make_unique<net::QuicContext>();
- if (enable_quic) {
- quic_context->params()->user_agent_id = quic_user_agent_id;
- // Note goaway sessions on ip change will be turned on by default
- // for iOS unless overrided via experiemental options.
- quic_context->params()->goaway_sessions_on_ip_change =
- kDefaultQuicGoAwaySessionsOnIpChange;
- }
- SetContextBuilderExperimentalOptions(context_builder, &session_params,
- quic_context->params(), bound_network);
- context_builder->set_http_network_session_params(session_params);
- context_builder->set_quic_context(std::move(quic_context));
- if (mock_cert_verifier)
- context_builder->SetCertVerifier(std::move(mock_cert_verifier));
- // Certificate Transparency is intentionally ignored in Cronet.
- // See //net/docs/certificate-transparency.md for more details.
- context_builder->set_ct_policy_enforcer(
- std::make_unique<net::DefaultCTPolicyEnforcer>());
- // TODO(mef): Use |config| to set cookies.
- }
- URLRequestContextConfigBuilder::URLRequestContextConfigBuilder() {}
- URLRequestContextConfigBuilder::~URLRequestContextConfigBuilder() {}
- std::unique_ptr<URLRequestContextConfig>
- URLRequestContextConfigBuilder::Build() {
- return URLRequestContextConfig::CreateURLRequestContextConfig(
- enable_quic, quic_user_agent_id, enable_spdy, enable_brotli, http_cache,
- http_cache_max_size, load_disable_cache, storage_path, accept_language,
- user_agent, experimental_options, std::move(mock_cert_verifier),
- enable_network_quality_estimator,
- bypass_public_key_pinning_for_local_trust_anchors,
- network_thread_priority);
- }
- } // namespace cronet
|