url_request_context_config.cc 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/cronet/url_request_context_config.h"
  5. #include <memory>
  6. #include <type_traits>
  7. #include <utility>
  8. #include "base/json/json_reader.h"
  9. #include "base/json/json_writer.h"
  10. #include "base/logging.h"
  11. #include "base/strings/string_number_conversions.h"
  12. #include "base/strings/string_piece.h"
  13. #include "base/strings/string_split.h"
  14. #include "base/task/sequenced_task_runner.h"
  15. #include "base/values.h"
  16. #include "build/build_config.h"
  17. #include "components/cronet/stale_host_resolver.h"
  18. #include "net/base/address_family.h"
  19. #include "net/cert/caching_cert_verifier.h"
  20. #include "net/cert/cert_verifier.h"
  21. #include "net/cert/cert_verify_proc.h"
  22. #include "net/cert/ct_policy_enforcer.h"
  23. #include "net/cert/ct_policy_status.h"
  24. #include "net/cert/multi_threaded_cert_verifier.h"
  25. #include "net/dns/context_host_resolver.h"
  26. #include "net/dns/host_resolver.h"
  27. #include "net/dns/mapped_host_resolver.h"
  28. #include "net/http/http_network_session.h"
  29. #include "net/http/http_server_properties.h"
  30. #include "net/log/net_log.h"
  31. #include "net/nqe/network_quality_estimator_params.h"
  32. #include "net/quic/set_quic_flag.h"
  33. #include "net/reporting/reporting_policy.h"
  34. #include "net/socket/ssl_client_socket.h"
  35. #include "net/ssl/ssl_key_logger_impl.h"
  36. #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
  37. #include "net/third_party/quiche/src/quiche/quic/core/quic_tag.h"
  38. #include "net/url_request/url_request_context_builder.h"
  39. #include "url/origin.h"
  40. #if BUILDFLAG(ENABLE_REPORTING)
  41. #include "net/reporting/reporting_policy.h"
  42. #endif // BUILDFLAG(ENABLE_REPORTING)
  43. namespace cronet {
  44. namespace {
  45. // Name of disk cache directory.
  46. const base::FilePath::CharType kDiskCacheDirectoryName[] =
  47. FILE_PATH_LITERAL("disk_cache");
  48. const char kQuicFieldTrialName[] = "QUIC";
  49. const char kQuicConnectionOptions[] = "connection_options";
  50. const char kQuicClientConnectionOptions[] = "client_connection_options";
  51. const char kQuicStoreServerConfigsInProperties[] =
  52. "store_server_configs_in_properties";
  53. const char kQuicMaxServerConfigsStoredInProperties[] =
  54. "max_server_configs_stored_in_properties";
  55. const char kQuicIdleConnectionTimeoutSeconds[] =
  56. "idle_connection_timeout_seconds";
  57. const char kQuicMaxTimeBeforeCryptoHandshakeSeconds[] =
  58. "max_time_before_crypto_handshake_seconds";
  59. const char kQuicMaxIdleTimeBeforeCryptoHandshakeSeconds[] =
  60. "max_idle_time_before_crypto_handshake_seconds";
  61. const char kQuicCloseSessionsOnIpChange[] = "close_sessions_on_ip_change";
  62. const char kQuicGoAwaySessionsOnIpChange[] = "goaway_sessions_on_ip_change";
  63. const char kQuicAllowServerMigration[] = "allow_server_migration";
  64. const char kQuicMigrateSessionsOnNetworkChangeV2[] =
  65. "migrate_sessions_on_network_change_v2";
  66. const char kQuicMigrateIdleSessions[] = "migrate_idle_sessions";
  67. const char kQuicRetransmittableOnWireTimeoutMilliseconds[] =
  68. "retransmittable_on_wire_timeout_milliseconds";
  69. const char kQuicIdleSessionMigrationPeriodSeconds[] =
  70. "idle_session_migration_period_seconds";
  71. const char kQuicMaxTimeOnNonDefaultNetworkSeconds[] =
  72. "max_time_on_non_default_network_seconds";
  73. const char kQuicMaxMigrationsToNonDefaultNetworkOnWriteError[] =
  74. "max_migrations_to_non_default_network_on_write_error";
  75. const char kQuicMaxMigrationsToNonDefaultNetworkOnPathDegrading[] =
  76. "max_migrations_to_non_default_network_on_path_degrading";
  77. const char kQuicUserAgentId[] = "user_agent_id";
  78. const char kQuicMigrateSessionsEarlyV2[] = "migrate_sessions_early_v2";
  79. const char kQuicRetryOnAlternateNetworkBeforeHandshake[] =
  80. "retry_on_alternate_network_before_handshake";
  81. const char kQuicRaceStaleDNSOnConnection[] = "race_stale_dns_on_connection";
  82. const char kQuicDisableBidirectionalStreams[] =
  83. "quic_disable_bidirectional_streams";
  84. const char kQuicHostWhitelist[] = "host_whitelist";
  85. const char kQuicEnableSocketRecvOptimization[] =
  86. "enable_socket_recv_optimization";
  87. const char kQuicVersion[] = "quic_version";
  88. const char kQuicObsoleteVersionsAllowed[] = "obsolete_versions_allowed2";
  89. const char kQuicFlags[] = "set_quic_flags";
  90. const char kQuicIOSNetworkServiceType[] = "ios_network_service_type";
  91. const char kRetryWithoutAltSvcOnQuicErrors[] =
  92. "retry_without_alt_svc_on_quic_errors";
  93. const char kInitialDelayForBrokenAlternativeServiceSeconds[] =
  94. "initial_delay_for_broken_alternative_service_seconds";
  95. const char kExponentialBackoffOnInitialDelay[] =
  96. "exponential_backoff_on_initial_delay";
  97. const char kDelayMainJobWithAvailableSpdySession[] =
  98. "delay_main_job_with_available_spdy_session";
  99. // AsyncDNS experiment dictionary name.
  100. const char kAsyncDnsFieldTrialName[] = "AsyncDNS";
  101. // Name of boolean to enable AsyncDNS experiment.
  102. const char kAsyncDnsEnable[] = "enable";
  103. // Stale DNS (StaleHostResolver) experiment dictionary name.
  104. const char kStaleDnsFieldTrialName[] = "StaleDNS";
  105. // Name of boolean to enable stale DNS experiment.
  106. const char kStaleDnsEnable[] = "enable";
  107. // Name of integer delay in milliseconds before a stale DNS result will be
  108. // used.
  109. const char kStaleDnsDelayMs[] = "delay_ms";
  110. // Name of integer maximum age (past expiration) in milliseconds of a stale DNS
  111. // result that will be used, or 0 for no limit.
  112. const char kStaleDnsMaxExpiredTimeMs[] = "max_expired_time_ms";
  113. // Name of integer maximum times each stale DNS result can be used, or 0 for no
  114. // limit.
  115. const char kStaleDnsMaxStaleUses[] = "max_stale_uses";
  116. // Name of boolean to allow stale DNS results from other networks to be used on
  117. // the current network.
  118. const char kStaleDnsAllowOtherNetwork[] = "allow_other_network";
  119. // Name of boolean to enable persisting the DNS cache to disk.
  120. const char kStaleDnsPersist[] = "persist_to_disk";
  121. // Name of integer minimum time in milliseconds between writes to disk for DNS
  122. // cache persistence. Default value is one minute. Only relevant if
  123. // "persist_to_disk" is true.
  124. const char kStaleDnsPersistTimer[] = "persist_delay_ms";
  125. // Name of boolean to allow use of stale DNS results when network resolver
  126. // returns ERR_NAME_NOT_RESOLVED.
  127. const char kStaleDnsUseStaleOnNameNotResolved[] =
  128. "use_stale_on_name_not_resolved";
  129. // Rules to override DNS resolution. Intended for testing.
  130. // See explanation of format in net/dns/mapped_host_resolver.h.
  131. const char kHostResolverRulesFieldTrialName[] = "HostResolverRules";
  132. const char kHostResolverRules[] = "host_resolver_rules";
  133. // NetworkQualityEstimator (NQE) experiment dictionary name.
  134. const char kNetworkQualityEstimatorFieldTrialName[] = "NetworkQualityEstimator";
  135. // Network Error Logging experiment dictionary name.
  136. const char kNetworkErrorLoggingFieldTrialName[] = "NetworkErrorLogging";
  137. // Name of boolean to enable Reporting API.
  138. const char kNetworkErrorLoggingEnable[] = "enable";
  139. // Name of list of preloaded "Report-To" headers.
  140. const char kNetworkErrorLoggingPreloadedReportToHeaders[] =
  141. "preloaded_report_to_headers";
  142. // Name of list of preloaded "NEL" headers.
  143. const char kNetworkErrorLoggingPreloadedNELHeaders[] = "preloaded_nel_headers";
  144. // Name of key (for above two lists) for header origin.
  145. const char kNetworkErrorLoggingOrigin[] = "origin";
  146. // Name of key (for above two lists) for header value.
  147. const char kNetworkErrorLoggingValue[] = "value";
  148. // Disable IPv6 when on WiFi. This is a workaround for a known issue on certain
  149. // Android phones, and should not be necessary when not on one of those devices.
  150. // See https://crbug.com/696569 for details.
  151. const char kDisableIPv6OnWifi[] = "disable_ipv6_on_wifi";
  152. const char kSSLKeyLogFile[] = "ssl_key_log_file";
  153. const char kAllowPortMigration[] = "allow_port_migration";
  154. const char kDisableTlsZeroRtt[] = "disable_tls_zero_rtt";
  155. // Whether SPDY sessions should be closed or marked as going away upon relevant
  156. // network changes. When not specified, /net behavior varies depending on the
  157. // underlying OS.
  158. const char kSpdyGoAwayOnIpChange[] = "spdy_go_away_on_ip_change";
  159. // Whether the connection status of all bidirectional streams (created through
  160. // the Cronet engine) should be monitored.
  161. // The value must be an integer (> 0) and will be interpreted as a suggestion
  162. // for the period of the heartbeat signal. See
  163. // SpdySession#EnableBrokenConnectionDetection for more info.
  164. const char kBidiStreamDetectBrokenConnection[] =
  165. "bidi_stream_detect_broken_connection";
  166. const char kUseDnsHttpsSvcbFieldTrialName[] = "UseDnsHttpsSvcb";
  167. const char kUseDnsHttpsSvcbUseAlpn[] = "use_alpn";
  168. // Runtime flag to bypass Cronet's logging: When set to true logging calls will
  169. // be skipped. If missing, logging will happen.
  170. const char kSkipLogging[] = "skip_logging";
  171. // "goaway_sessions_on_ip_change" is default on for iOS unless overridden via
  172. // experimental options explicitly.
  173. #if BUILDFLAG(IS_IOS)
  174. const bool kDefaultQuicGoAwaySessionsOnIpChange = true;
  175. #else
  176. const bool kDefaultQuicGoAwaySessionsOnIpChange = false;
  177. #endif
  178. // Serializes a base::Value into a string that can be used as the value of
  179. // JFV-encoded HTTP header [1]. If |value| is a list, we remove the outermost
  180. // [] delimiters from the result.
  181. //
  182. // [1] https://tools.ietf.org/html/draft-reschke-http-jfv
  183. std::string SerializeJFVHeader(const base::Value& value) {
  184. std::string result;
  185. if (!base::JSONWriter::Write(value, &result))
  186. return std::string();
  187. if (value.is_list()) {
  188. DCHECK(result.size() >= 2);
  189. return result.substr(1, result.size() - 2);
  190. }
  191. return result;
  192. }
  193. std::vector<URLRequestContextConfig::PreloadedNelAndReportingHeader>
  194. ParseNetworkErrorLoggingHeaders(
  195. const base::Value::List& preloaded_headers_config) {
  196. std::vector<URLRequestContextConfig::PreloadedNelAndReportingHeader> result;
  197. for (const auto& preloaded_header_config : preloaded_headers_config) {
  198. if (!preloaded_header_config.is_dict())
  199. continue;
  200. const std::string* origin_config =
  201. preloaded_header_config.GetDict().FindString(
  202. kNetworkErrorLoggingOrigin);
  203. if (!origin_config)
  204. continue;
  205. GURL origin_url(*origin_config);
  206. if (!origin_url.is_valid())
  207. continue;
  208. auto origin = url::Origin::Create(origin_url);
  209. auto* value =
  210. preloaded_header_config.GetDict().Find(kNetworkErrorLoggingValue);
  211. if (!value)
  212. continue;
  213. result.push_back(URLRequestContextConfig::PreloadedNelAndReportingHeader(
  214. origin, SerializeJFVHeader(*value)));
  215. }
  216. return result;
  217. }
  218. // Applies |f| to the value contained by |maybe|, returns empty optional
  219. // otherwise.
  220. template <typename T, typename F>
  221. auto map(absl::optional<T> maybe, F&& f) {
  222. if (!maybe)
  223. return absl::optional<std::invoke_result_t<F, T>>();
  224. return absl::optional<std::invoke_result_t<F, T>>(f(maybe.value()));
  225. }
  226. } // namespace
  227. URLRequestContextConfig::QuicHint::QuicHint(const std::string& host,
  228. int port,
  229. int alternate_port)
  230. : host(host), port(port), alternate_port(alternate_port) {}
  231. URLRequestContextConfig::QuicHint::~QuicHint() {}
  232. URLRequestContextConfig::Pkp::Pkp(const std::string& host,
  233. bool include_subdomains,
  234. const base::Time& expiration_date)
  235. : host(host),
  236. include_subdomains(include_subdomains),
  237. expiration_date(expiration_date) {}
  238. URLRequestContextConfig::Pkp::~Pkp() {}
  239. URLRequestContextConfig::PreloadedNelAndReportingHeader::
  240. PreloadedNelAndReportingHeader(const url::Origin& origin, std::string value)
  241. : origin(origin), value(std::move(value)) {}
  242. URLRequestContextConfig::PreloadedNelAndReportingHeader::
  243. ~PreloadedNelAndReportingHeader() = default;
  244. URLRequestContextConfig::URLRequestContextConfig(
  245. bool enable_quic,
  246. const std::string& quic_user_agent_id,
  247. bool enable_spdy,
  248. bool enable_brotli,
  249. HttpCacheType http_cache,
  250. int http_cache_max_size,
  251. bool load_disable_cache,
  252. const std::string& storage_path,
  253. const std::string& accept_language,
  254. const std::string& user_agent,
  255. base::Value::Dict experimental_options,
  256. std::unique_ptr<net::CertVerifier> mock_cert_verifier,
  257. bool enable_network_quality_estimator,
  258. bool bypass_public_key_pinning_for_local_trust_anchors,
  259. absl::optional<double> network_thread_priority)
  260. : enable_quic(enable_quic),
  261. quic_user_agent_id(quic_user_agent_id),
  262. enable_spdy(enable_spdy),
  263. enable_brotli(enable_brotli),
  264. http_cache(http_cache),
  265. http_cache_max_size(http_cache_max_size),
  266. load_disable_cache(load_disable_cache),
  267. storage_path(storage_path),
  268. accept_language(accept_language),
  269. user_agent(user_agent),
  270. mock_cert_verifier(std::move(mock_cert_verifier)),
  271. enable_network_quality_estimator(enable_network_quality_estimator),
  272. bypass_public_key_pinning_for_local_trust_anchors(
  273. bypass_public_key_pinning_for_local_trust_anchors),
  274. effective_experimental_options(experimental_options.Clone()),
  275. experimental_options(std::move(experimental_options)),
  276. network_thread_priority(network_thread_priority),
  277. bidi_stream_detect_broken_connection(false),
  278. heartbeat_interval(base::Seconds(0)),
  279. skip_logging(false) {
  280. SetContextConfigExperimentalOptions();
  281. }
  282. URLRequestContextConfig::~URLRequestContextConfig() {}
  283. // static
  284. std::unique_ptr<URLRequestContextConfig>
  285. URLRequestContextConfig::CreateURLRequestContextConfig(
  286. bool enable_quic,
  287. const std::string& quic_user_agent_id,
  288. bool enable_spdy,
  289. bool enable_brotli,
  290. HttpCacheType http_cache,
  291. int http_cache_max_size,
  292. bool load_disable_cache,
  293. const std::string& storage_path,
  294. const std::string& accept_language,
  295. const std::string& user_agent,
  296. const std::string& unparsed_experimental_options,
  297. std::unique_ptr<net::CertVerifier> mock_cert_verifier,
  298. bool enable_network_quality_estimator,
  299. bool bypass_public_key_pinning_for_local_trust_anchors,
  300. absl::optional<double> network_thread_priority) {
  301. absl::optional<base::Value::Dict> experimental_options =
  302. ParseExperimentalOptions(unparsed_experimental_options);
  303. if (!experimental_options) {
  304. // For the time being maintain backward compatibility by only failing to
  305. // parse when DCHECKs are enabled.
  306. if (ExperimentalOptionsParsingIsAllowedToFail())
  307. return nullptr;
  308. else
  309. experimental_options = base::Value::Dict();
  310. }
  311. return base::WrapUnique(new URLRequestContextConfig(
  312. enable_quic, quic_user_agent_id, enable_spdy, enable_brotli, http_cache,
  313. http_cache_max_size, load_disable_cache, storage_path, accept_language,
  314. user_agent, std::move(experimental_options).value(),
  315. std::move(mock_cert_verifier), enable_network_quality_estimator,
  316. bypass_public_key_pinning_for_local_trust_anchors,
  317. network_thread_priority));
  318. }
  319. // static
  320. absl::optional<base::Value::Dict>
  321. URLRequestContextConfig::ParseExperimentalOptions(
  322. std::string unparsed_experimental_options) {
  323. // From a user perspective no experimental options means an empty string. The
  324. // underlying code instead expects and empty dictionary. Normalize this.
  325. if (unparsed_experimental_options.empty())
  326. unparsed_experimental_options = "{}";
  327. DVLOG(1) << "Experimental Options:" << unparsed_experimental_options;
  328. auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(
  329. unparsed_experimental_options);
  330. if (!parsed_json.has_value()) {
  331. LOG(ERROR) << "Parsing experimental options failed: '"
  332. << unparsed_experimental_options << "', error "
  333. << parsed_json.error().message;
  334. return absl::nullopt;
  335. }
  336. base::Value::Dict* experimental_options_dict = parsed_json->GetIfDict();
  337. if (!experimental_options_dict) {
  338. LOG(ERROR) << "Experimental options string is not a dictionary: "
  339. << *parsed_json;
  340. return absl::nullopt;
  341. }
  342. return std::move(*experimental_options_dict);
  343. }
  344. void URLRequestContextConfig::SetContextConfigExperimentalOptions() {
  345. const base::Value* heartbeat_interval_value =
  346. experimental_options.Find(kBidiStreamDetectBrokenConnection);
  347. if (heartbeat_interval_value) {
  348. if (!heartbeat_interval_value->is_int()) {
  349. LOG(ERROR) << "\"" << kBidiStreamDetectBrokenConnection
  350. << "\" config params \"" << heartbeat_interval_value
  351. << "\" is not an int";
  352. experimental_options.Remove(kBidiStreamDetectBrokenConnection);
  353. effective_experimental_options.Remove(kBidiStreamDetectBrokenConnection);
  354. } else {
  355. int heartbeat_interval_secs = heartbeat_interval_value->GetInt();
  356. heartbeat_interval = base::Seconds(heartbeat_interval_secs);
  357. bidi_stream_detect_broken_connection = heartbeat_interval_secs > 0;
  358. experimental_options.Remove(kBidiStreamDetectBrokenConnection);
  359. }
  360. }
  361. const base::Value* skip_logging_value =
  362. experimental_options.Find(kSkipLogging);
  363. if (skip_logging_value) {
  364. if (!skip_logging_value->is_bool()) {
  365. LOG(ERROR) << "\"" << kSkipLogging << "\" config params \""
  366. << skip_logging_value << "\" is not a bool";
  367. experimental_options.Remove(kSkipLogging);
  368. effective_experimental_options.Remove(kSkipLogging);
  369. } else {
  370. skip_logging = skip_logging_value->GetBool();
  371. experimental_options.Remove(kSkipLogging);
  372. }
  373. }
  374. }
  375. void URLRequestContextConfig::SetContextBuilderExperimentalOptions(
  376. net::URLRequestContextBuilder* context_builder,
  377. net::HttpNetworkSessionParams* session_params,
  378. net::QuicParams* quic_params,
  379. net::handles::NetworkHandle bound_network) {
  380. bool async_dns_enable = false;
  381. bool stale_dns_enable = false;
  382. bool host_resolver_rules_enable = false;
  383. bool disable_ipv6_on_wifi = false;
  384. bool nel_enable = false;
  385. bool is_network_bound = bound_network != net::handles::kInvalidNetworkHandle;
  386. absl::optional<net::HostResolver::HttpsSvcbOptions> https_svcb_options;
  387. StaleHostResolver::StaleOptions stale_dns_options;
  388. const std::string* host_resolver_rules_string;
  389. for (auto iter = experimental_options.begin();
  390. iter != experimental_options.end(); ++iter) {
  391. if (iter->first == kQuicFieldTrialName) {
  392. if (!iter->second.is_dict()) {
  393. LOG(ERROR) << "Quic config params \"" << iter->second
  394. << "\" is not a dictionary value";
  395. effective_experimental_options.Remove(iter->first);
  396. continue;
  397. }
  398. const base::Value::Dict& quic_args = iter->second.GetDict();
  399. const std::string* quic_version_string =
  400. quic_args.FindString(kQuicVersion);
  401. if (quic_version_string) {
  402. quic::ParsedQuicVersionVector supported_versions =
  403. quic::ParseQuicVersionVectorString(*quic_version_string);
  404. if (!quic_args.FindBool(kQuicObsoleteVersionsAllowed).value_or(false)) {
  405. quic::ParsedQuicVersionVector filtered_versions;
  406. quic::ParsedQuicVersionVector obsolete_versions =
  407. net::ObsoleteQuicVersions();
  408. for (const quic::ParsedQuicVersion& version : supported_versions) {
  409. if (std::find(obsolete_versions.begin(), obsolete_versions.end(),
  410. version) == obsolete_versions.end()) {
  411. filtered_versions.push_back(version);
  412. }
  413. }
  414. supported_versions = filtered_versions;
  415. }
  416. if (!supported_versions.empty())
  417. quic_params->supported_versions = supported_versions;
  418. }
  419. const std::string* quic_connection_options =
  420. quic_args.FindString(kQuicConnectionOptions);
  421. if (quic_connection_options) {
  422. quic_params->connection_options =
  423. quic::ParseQuicTagVector(*quic_connection_options);
  424. }
  425. const std::string* quic_client_connection_options =
  426. quic_args.FindString(kQuicClientConnectionOptions);
  427. if (quic_client_connection_options) {
  428. quic_params->client_connection_options =
  429. quic::ParseQuicTagVector(*quic_client_connection_options);
  430. }
  431. // TODO(rtenneti): Delete this option after apps stop using it.
  432. // Added this for backward compatibility.
  433. if (quic_args.FindBool(kQuicStoreServerConfigsInProperties)
  434. .value_or(false)) {
  435. quic_params->max_server_configs_stored_in_properties =
  436. net::kDefaultMaxQuicServerEntries;
  437. }
  438. quic_params->max_server_configs_stored_in_properties =
  439. static_cast<size_t>(
  440. quic_args.FindInt(kQuicMaxServerConfigsStoredInProperties)
  441. .value_or(
  442. quic_params->max_server_configs_stored_in_properties));
  443. quic_params->idle_connection_timeout =
  444. map(quic_args.FindInt(kQuicIdleConnectionTimeoutSeconds),
  445. base::Seconds<int>)
  446. .value_or(quic_params->idle_connection_timeout);
  447. quic_params->max_time_before_crypto_handshake =
  448. map(quic_args.FindInt(kQuicMaxTimeBeforeCryptoHandshakeSeconds),
  449. base::Seconds<int>)
  450. .value_or(quic_params->max_time_before_crypto_handshake);
  451. quic_params->max_idle_time_before_crypto_handshake =
  452. map(quic_args.FindInt(kQuicMaxIdleTimeBeforeCryptoHandshakeSeconds),
  453. base::Seconds<int>)
  454. .value_or(quic_params->max_idle_time_before_crypto_handshake);
  455. quic_params->close_sessions_on_ip_change =
  456. quic_args.FindBool(kQuicCloseSessionsOnIpChange)
  457. .value_or(quic_params->close_sessions_on_ip_change);
  458. if (quic_params->close_sessions_on_ip_change &&
  459. kDefaultQuicGoAwaySessionsOnIpChange) {
  460. // "close_sessions_on_ip_change" and "goaway_sessions_on_ip_change"
  461. // are mutually exclusive. Turn off the goaway option which is
  462. // default on for iOS if "close_sessions_on_ip_change" is set via
  463. // experimental options.
  464. quic_params->goaway_sessions_on_ip_change = false;
  465. }
  466. quic_params->goaway_sessions_on_ip_change =
  467. quic_args.FindBool(kQuicGoAwaySessionsOnIpChange)
  468. .value_or(quic_params->goaway_sessions_on_ip_change);
  469. quic_params->allow_server_migration =
  470. quic_args.FindBool(kQuicAllowServerMigration)
  471. .value_or(quic_params->allow_server_migration);
  472. const std::string* user_agent_id = quic_args.FindString(kQuicUserAgentId);
  473. if (user_agent_id) {
  474. quic_params->user_agent_id = *user_agent_id;
  475. }
  476. quic_params->enable_socket_recv_optimization =
  477. quic_args.FindBool(kQuicEnableSocketRecvOptimization)
  478. .value_or(quic_params->enable_socket_recv_optimization);
  479. absl::optional<bool> quic_migrate_sessions_on_network_change_v2_in =
  480. quic_args.FindBool(kQuicMigrateSessionsOnNetworkChangeV2);
  481. if (quic_migrate_sessions_on_network_change_v2_in.has_value()) {
  482. quic_params->migrate_sessions_on_network_change_v2 =
  483. quic_migrate_sessions_on_network_change_v2_in.value();
  484. quic_params->max_time_on_non_default_network =
  485. map(quic_args.FindInt(kQuicMaxTimeOnNonDefaultNetworkSeconds),
  486. base::Seconds<int>)
  487. .value_or(quic_params->max_time_on_non_default_network);
  488. quic_params->max_migrations_to_non_default_network_on_write_error =
  489. quic_args.FindInt(kQuicMaxMigrationsToNonDefaultNetworkOnWriteError)
  490. .value_or(
  491. quic_params
  492. ->max_migrations_to_non_default_network_on_write_error);
  493. quic_params->max_migrations_to_non_default_network_on_path_degrading =
  494. quic_args
  495. .FindInt(kQuicMaxMigrationsToNonDefaultNetworkOnPathDegrading)
  496. .value_or(
  497. quic_params
  498. ->max_migrations_to_non_default_network_on_path_degrading);
  499. }
  500. absl::optional<bool> quic_migrate_idle_sessions_in =
  501. quic_args.FindBool(kQuicMigrateIdleSessions);
  502. if (quic_migrate_idle_sessions_in.has_value()) {
  503. quic_params->migrate_idle_sessions =
  504. quic_migrate_idle_sessions_in.value();
  505. quic_params->idle_session_migration_period =
  506. map(quic_args.FindInt(kQuicIdleSessionMigrationPeriodSeconds),
  507. base::Seconds<int>)
  508. .value_or(quic_params->idle_session_migration_period);
  509. }
  510. quic_params->migrate_sessions_early_v2 =
  511. quic_args.FindBool(kQuicMigrateSessionsEarlyV2)
  512. .value_or(quic_params->migrate_sessions_early_v2);
  513. quic_params->retransmittable_on_wire_timeout =
  514. map(quic_args.FindInt(kQuicRetransmittableOnWireTimeoutMilliseconds),
  515. base::Milliseconds<int>)
  516. .value_or(quic_params->retransmittable_on_wire_timeout);
  517. quic_params->retry_on_alternate_network_before_handshake =
  518. quic_args.FindBool(kQuicRetryOnAlternateNetworkBeforeHandshake)
  519. .value_or(
  520. quic_params->retry_on_alternate_network_before_handshake);
  521. quic_params->race_stale_dns_on_connection =
  522. quic_args.FindBool(kQuicRaceStaleDNSOnConnection)
  523. .value_or(quic_params->race_stale_dns_on_connection);
  524. quic_params->allow_port_migration =
  525. quic_args.FindBool(kAllowPortMigration)
  526. .value_or(quic_params->allow_port_migration);
  527. quic_params->retry_without_alt_svc_on_quic_errors =
  528. quic_args.FindBool(kRetryWithoutAltSvcOnQuicErrors)
  529. .value_or(quic_params->retry_without_alt_svc_on_quic_errors);
  530. quic_params->initial_delay_for_broken_alternative_service = map(
  531. quic_args.FindInt(kInitialDelayForBrokenAlternativeServiceSeconds),
  532. base::Seconds<int>);
  533. quic_params->exponential_backoff_on_initial_delay =
  534. quic_args.FindBool(kExponentialBackoffOnInitialDelay);
  535. quic_params->delay_main_job_with_available_spdy_session =
  536. quic_args.FindBool(kDelayMainJobWithAvailableSpdySession)
  537. .value_or(
  538. quic_params->delay_main_job_with_available_spdy_session);
  539. quic_params->disable_tls_zero_rtt =
  540. quic_args.FindBool(kDisableTlsZeroRtt)
  541. .value_or(quic_params->disable_tls_zero_rtt);
  542. quic_params->disable_bidirectional_streams =
  543. quic_args.FindBool(kQuicDisableBidirectionalStreams)
  544. .value_or(quic_params->disable_bidirectional_streams);
  545. const std::string* quic_host_allowlist =
  546. quic_args.FindString(kQuicHostWhitelist);
  547. if (quic_host_allowlist) {
  548. std::vector<std::string> host_vector =
  549. base::SplitString(*quic_host_allowlist, ",", base::TRIM_WHITESPACE,
  550. base::SPLIT_WANT_ALL);
  551. session_params->quic_host_allowlist.clear();
  552. for (const std::string& host : host_vector) {
  553. session_params->quic_host_allowlist.insert(host);
  554. }
  555. }
  556. const std::string* quic_flags = quic_args.FindString(kQuicFlags);
  557. if (quic_flags) {
  558. for (const auto& flag :
  559. base::SplitString(*quic_flags, ",", base::TRIM_WHITESPACE,
  560. base::SPLIT_WANT_ALL)) {
  561. std::vector<std::string> tokens = base::SplitString(
  562. flag, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  563. if (tokens.size() != 2)
  564. continue;
  565. net::SetQuicFlagByName(tokens[0], tokens[1]);
  566. }
  567. }
  568. quic_params->ios_network_service_type =
  569. quic_args.FindInt(kQuicIOSNetworkServiceType)
  570. .value_or(quic_params->ios_network_service_type);
  571. } else if (iter->first == kAsyncDnsFieldTrialName) {
  572. if (!iter->second.is_dict()) {
  573. LOG(ERROR) << "\"" << iter->first << "\" config params \""
  574. << iter->second << "\" is not a dictionary value";
  575. effective_experimental_options.Remove(iter->first);
  576. continue;
  577. }
  578. const base::Value::Dict& async_dns_args = iter->second.GetDict();
  579. async_dns_enable =
  580. async_dns_args.FindBool(kAsyncDnsEnable).value_or(async_dns_enable);
  581. } else if (iter->first == kStaleDnsFieldTrialName) {
  582. if (!iter->second.is_dict()) {
  583. LOG(ERROR) << "\"" << iter->first << "\" config params \""
  584. << iter->second << "\" is not a dictionary value";
  585. effective_experimental_options.Remove(iter->first);
  586. continue;
  587. }
  588. const base::Value::Dict& stale_dns_args = iter->second.GetDict();
  589. stale_dns_enable =
  590. stale_dns_args.FindBool(kStaleDnsEnable).value_or(false);
  591. if (stale_dns_enable) {
  592. stale_dns_options.delay = map(stale_dns_args.FindInt(kStaleDnsDelayMs),
  593. base::Milliseconds<int>)
  594. .value_or(stale_dns_options.delay);
  595. stale_dns_options.max_expired_time =
  596. map(stale_dns_args.FindInt(kStaleDnsMaxExpiredTimeMs),
  597. base::Milliseconds<int>)
  598. .value_or(stale_dns_options.max_expired_time);
  599. stale_dns_options.max_stale_uses =
  600. stale_dns_args.FindInt(kStaleDnsMaxStaleUses)
  601. .value_or(stale_dns_options.max_stale_uses);
  602. stale_dns_options.allow_other_network =
  603. stale_dns_args.FindBool(kStaleDnsAllowOtherNetwork)
  604. .value_or(stale_dns_options.allow_other_network);
  605. enable_host_cache_persistence =
  606. stale_dns_args.FindBool(kStaleDnsPersist)
  607. .value_or(enable_host_cache_persistence);
  608. host_cache_persistence_delay_ms =
  609. stale_dns_args.FindInt(kStaleDnsPersistTimer)
  610. .value_or(host_cache_persistence_delay_ms);
  611. stale_dns_options.use_stale_on_name_not_resolved =
  612. stale_dns_args.FindBool(kStaleDnsUseStaleOnNameNotResolved)
  613. .value_or(stale_dns_options.use_stale_on_name_not_resolved);
  614. }
  615. } else if (iter->first == kHostResolverRulesFieldTrialName) {
  616. if (!iter->second.is_dict()) {
  617. LOG(ERROR) << "\"" << iter->first << "\" config params \""
  618. << iter->second << "\" is not a dictionary value";
  619. effective_experimental_options.Remove(iter->first);
  620. continue;
  621. }
  622. const base::Value::Dict& host_resolver_rules_args =
  623. iter->second.GetDict();
  624. host_resolver_rules_string =
  625. host_resolver_rules_args.FindString(kHostResolverRules);
  626. host_resolver_rules_enable = !!host_resolver_rules_string;
  627. } else if (iter->first == kUseDnsHttpsSvcbFieldTrialName) {
  628. if (!iter->second.is_dict()) {
  629. LOG(ERROR) << "\"" << iter->first << "\" config params \""
  630. << iter->second << "\" is not a dictionary value";
  631. effective_experimental_options.Remove(iter->first);
  632. continue;
  633. }
  634. const base::Value::Dict& args = iter->second.GetDict();
  635. https_svcb_options = net::HostResolver::HttpsSvcbOptions::FromDict(args);
  636. session_params->use_dns_https_svcb_alpn =
  637. args.FindBool(kUseDnsHttpsSvcbUseAlpn)
  638. .value_or(session_params->use_dns_https_svcb_alpn);
  639. } else if (iter->first == kNetworkErrorLoggingFieldTrialName) {
  640. if (!iter->second.is_dict()) {
  641. LOG(ERROR) << "\"" << iter->first << "\" config params \""
  642. << iter->second << "\" is not a dictionary value";
  643. effective_experimental_options.Remove(iter->first);
  644. continue;
  645. }
  646. const base::Value::Dict& nel_args = iter->second.GetDict();
  647. nel_enable =
  648. nel_args.FindBool(kNetworkErrorLoggingEnable).value_or(nel_enable);
  649. const auto* preloaded_report_to_headers_config =
  650. nel_args.FindList(kNetworkErrorLoggingPreloadedReportToHeaders);
  651. if (preloaded_report_to_headers_config) {
  652. preloaded_report_to_headers = ParseNetworkErrorLoggingHeaders(
  653. *preloaded_report_to_headers_config);
  654. }
  655. const auto* preloaded_nel_headers_config =
  656. nel_args.FindList(kNetworkErrorLoggingPreloadedNELHeaders);
  657. if (preloaded_nel_headers_config) {
  658. preloaded_nel_headers =
  659. ParseNetworkErrorLoggingHeaders(*preloaded_nel_headers_config);
  660. }
  661. } else if (iter->first == kDisableIPv6OnWifi) {
  662. if (!iter->second.is_bool()) {
  663. LOG(ERROR) << "\"" << iter->first << "\" config params \""
  664. << iter->second << "\" is not a bool";
  665. effective_experimental_options.Remove(iter->first);
  666. continue;
  667. }
  668. disable_ipv6_on_wifi = iter->second.GetBool();
  669. } else if (iter->first == kSSLKeyLogFile) {
  670. if (iter->second.is_string()) {
  671. base::FilePath ssl_key_log_file(
  672. base::FilePath::FromUTF8Unsafe(iter->second.GetString()));
  673. if (!ssl_key_log_file.empty()) {
  674. // SetSSLKeyLogger is only safe to call before any SSLClientSockets
  675. // are created. This should not be used if there are multiple
  676. // CronetEngine.
  677. // TODO(xunjieli): Expose this as a stable API after crbug.com/458365
  678. // is resolved.
  679. net::SSLClientSocket::SetSSLKeyLogger(
  680. std::make_unique<net::SSLKeyLoggerImpl>(ssl_key_log_file));
  681. }
  682. }
  683. } else if (iter->first == kNetworkQualityEstimatorFieldTrialName) {
  684. if (!iter->second.is_dict()) {
  685. LOG(ERROR) << "\"" << iter->first << "\" config params \""
  686. << iter->second << "\" is not a dictionary value";
  687. effective_experimental_options.Remove(iter->first);
  688. continue;
  689. }
  690. const base::Value::Dict& nqe_args = iter->second.GetDict();
  691. const std::string* nqe_option =
  692. nqe_args.FindString(net::kForceEffectiveConnectionType);
  693. if (nqe_option) {
  694. nqe_forced_effective_connection_type =
  695. net::GetEffectiveConnectionTypeForName(*nqe_option);
  696. if (!nqe_option->empty() && !nqe_forced_effective_connection_type) {
  697. LOG(ERROR) << "\"" << nqe_option
  698. << "\" is not a valid effective connection type value";
  699. }
  700. }
  701. } else if (iter->first == kSpdyGoAwayOnIpChange) {
  702. if (!iter->second.is_bool()) {
  703. LOG(ERROR) << "\"" << iter->first << "\" config params \""
  704. << iter->second << "\" is not a bool";
  705. effective_experimental_options.Remove(iter->first);
  706. continue;
  707. }
  708. session_params->spdy_go_away_on_ip_change = iter->second.GetBool();
  709. } else {
  710. LOG(WARNING) << "Unrecognized Cronet experimental option \""
  711. << iter->first << "\" with params \"" << iter->second;
  712. effective_experimental_options.Remove(iter->first);
  713. }
  714. }
  715. if (async_dns_enable || stale_dns_enable || host_resolver_rules_enable ||
  716. disable_ipv6_on_wifi || is_network_bound || https_svcb_options) {
  717. net::HostResolver::ManagerOptions host_resolver_manager_options;
  718. host_resolver_manager_options.insecure_dns_client_enabled =
  719. async_dns_enable;
  720. host_resolver_manager_options.check_ipv6_on_wifi = !disable_ipv6_on_wifi;
  721. if (https_svcb_options) {
  722. host_resolver_manager_options.https_svcb_options = https_svcb_options;
  723. }
  724. if (!is_network_bound) {
  725. std::unique_ptr<net::HostResolver> host_resolver;
  726. // TODO(crbug.com/934402): Consider using a shared HostResolverManager for
  727. // Cronet HostResolvers.
  728. if (stale_dns_enable) {
  729. DCHECK(!disable_ipv6_on_wifi);
  730. host_resolver = std::make_unique<StaleHostResolver>(
  731. net::HostResolver::CreateStandaloneContextResolver(
  732. net::NetLog::Get(), std::move(host_resolver_manager_options)),
  733. stale_dns_options);
  734. } else {
  735. host_resolver = net::HostResolver::CreateStandaloneResolver(
  736. net::NetLog::Get(), std::move(host_resolver_manager_options));
  737. }
  738. if (host_resolver_rules_enable) {
  739. std::unique_ptr<net::MappedHostResolver> remapped_resolver(
  740. new net::MappedHostResolver(std::move(host_resolver)));
  741. remapped_resolver->SetRulesFromString(*host_resolver_rules_string);
  742. host_resolver = std::move(remapped_resolver);
  743. }
  744. context_builder->set_host_resolver(std::move(host_resolver));
  745. } else {
  746. // `stale_dns_enable` and `host_resolver_rules_enable` are purposefully
  747. // ignored. Implementing them requires instantiating a special
  748. // HostResolver that wraps the real underlying resolver: that isn't
  749. // possible at the moment for network-bound contexts as they create a
  750. // special HostResolver internally and don't expose that.
  751. context_builder->BindToNetwork(bound_network,
  752. std::move(host_resolver_manager_options));
  753. }
  754. }
  755. #if BUILDFLAG(ENABLE_REPORTING)
  756. if (nel_enable) {
  757. auto policy = net::ReportingPolicy::Create();
  758. // Apps (like Cronet embedders) are generally allowed to run in the
  759. // background, even across network changes, so use more relaxed privacy
  760. // settings than when Reporting is running in the browser.
  761. policy->persist_reports_across_restarts = true;
  762. policy->persist_clients_across_restarts = true;
  763. policy->persist_reports_across_network_changes = true;
  764. policy->persist_clients_across_network_changes = true;
  765. context_builder->set_reporting_policy(std::move(policy));
  766. context_builder->set_network_error_logging_enabled(true);
  767. }
  768. #endif // BUILDFLAG(ENABLE_REPORTING)
  769. }
  770. void URLRequestContextConfig::ConfigureURLRequestContextBuilder(
  771. net::URLRequestContextBuilder* context_builder,
  772. net::handles::NetworkHandle bound_network) {
  773. std::string config_cache;
  774. if (http_cache != DISABLED) {
  775. net::URLRequestContextBuilder::HttpCacheParams cache_params;
  776. if (http_cache == DISK && !storage_path.empty()) {
  777. cache_params.type = net::URLRequestContextBuilder::HttpCacheParams::DISK;
  778. cache_params.path = base::FilePath::FromUTF8Unsafe(storage_path)
  779. .Append(kDiskCacheDirectoryName);
  780. } else {
  781. cache_params.type =
  782. net::URLRequestContextBuilder::HttpCacheParams::IN_MEMORY;
  783. }
  784. cache_params.max_size = http_cache_max_size;
  785. context_builder->EnableHttpCache(cache_params);
  786. } else {
  787. context_builder->DisableHttpCache();
  788. }
  789. context_builder->set_accept_language(accept_language);
  790. context_builder->set_user_agent(user_agent);
  791. net::HttpNetworkSessionParams session_params;
  792. session_params.enable_http2 = enable_spdy;
  793. session_params.enable_quic = enable_quic;
  794. auto quic_context = std::make_unique<net::QuicContext>();
  795. if (enable_quic) {
  796. quic_context->params()->user_agent_id = quic_user_agent_id;
  797. // Note goaway sessions on ip change will be turned on by default
  798. // for iOS unless overrided via experiemental options.
  799. quic_context->params()->goaway_sessions_on_ip_change =
  800. kDefaultQuicGoAwaySessionsOnIpChange;
  801. }
  802. SetContextBuilderExperimentalOptions(context_builder, &session_params,
  803. quic_context->params(), bound_network);
  804. context_builder->set_http_network_session_params(session_params);
  805. context_builder->set_quic_context(std::move(quic_context));
  806. if (mock_cert_verifier)
  807. context_builder->SetCertVerifier(std::move(mock_cert_verifier));
  808. // Certificate Transparency is intentionally ignored in Cronet.
  809. // See //net/docs/certificate-transparency.md for more details.
  810. context_builder->set_ct_policy_enforcer(
  811. std::make_unique<net::DefaultCTPolicyEnforcer>());
  812. // TODO(mef): Use |config| to set cookies.
  813. }
  814. URLRequestContextConfigBuilder::URLRequestContextConfigBuilder() {}
  815. URLRequestContextConfigBuilder::~URLRequestContextConfigBuilder() {}
  816. std::unique_ptr<URLRequestContextConfig>
  817. URLRequestContextConfigBuilder::Build() {
  818. return URLRequestContextConfig::CreateURLRequestContextConfig(
  819. enable_quic, quic_user_agent_id, enable_spdy, enable_brotli, http_cache,
  820. http_cache_max_size, load_disable_cache, storage_path, accept_language,
  821. user_agent, experimental_options, std::move(mock_cert_verifier),
  822. enable_network_quality_estimator,
  823. bypass_public_key_pinning_for_local_trust_anchors,
  824. network_thread_priority);
  825. }
  826. } // namespace cronet