1 // Copyright (c) 2012 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 5 #include "chrome/browser/io_thread.h" 6 7 #include <vector> 8 9 #include "base/base64.h" 10 #include "base/bind.h" 11 #include "base/bind_helpers.h" 12 #include "base/command_line.h" 13 #include "base/compiler_specific.h" 14 #include "base/debug/leak_tracker.h" 15 #include "base/debug/trace_event.h" 16 #include "base/logging.h" 17 #include "base/metrics/field_trial.h" 18 #include "base/prefs/pref_registry_simple.h" 19 #include "base/prefs/pref_service.h" 20 #include "base/stl_util.h" 21 #include "base/strings/string_number_conversions.h" 22 #include "base/strings/string_split.h" 23 #include "base/strings/string_util.h" 24 #include "base/threading/sequenced_worker_pool.h" 25 #include "base/threading/thread.h" 26 #include "base/threading/worker_pool.h" 27 #include "base/time/time.h" 28 #include "build/build_config.h" 29 #include "chrome/browser/browser_process.h" 30 #include "chrome/browser/extensions/event_router_forwarder.h" 31 #include "chrome/browser/net/async_dns_field_trial.h" 32 #include "chrome/browser/net/chrome_net_log.h" 33 #include "chrome/browser/net/chrome_network_delegate.h" 34 #include "chrome/browser/net/chrome_url_request_context.h" 35 #include "chrome/browser/net/connect_interceptor.h" 36 #include "chrome/browser/net/dns_probe_service.h" 37 #include "chrome/browser/net/pref_proxy_config_tracker.h" 38 #include "chrome/browser/net/proxy_service_factory.h" 39 #include "chrome/common/chrome_content_client.h" 40 #include "chrome/common/chrome_switches.h" 41 #include "chrome/common/chrome_version_info.h" 42 #include "chrome/common/pref_names.h" 43 #include "components/data_reduction_proxy/browser/data_reduction_proxy_prefs.h" 44 #include "components/data_reduction_proxy/browser/http_auth_handler_data_reduction_proxy.h" 45 #include "components/policy/core/common/policy_service.h" 46 #include "content/public/browser/browser_thread.h" 47 #include "content/public/browser/cookie_store_factory.h" 48 #include "net/base/host_mapping_rules.h" 49 #include "net/base/net_util.h" 50 #include "net/cert/cert_verifier.h" 51 #include "net/cert/cert_verify_proc.h" 52 #include "net/cert/ct_known_logs.h" 53 #include "net/cert/ct_verifier.h" 54 #include "net/cert/multi_threaded_cert_verifier.h" 55 #include "net/cookies/cookie_store.h" 56 #include "net/dns/host_cache.h" 57 #include "net/dns/host_resolver.h" 58 #include "net/dns/mapped_host_resolver.h" 59 #include "net/ftp/ftp_network_layer.h" 60 #include "net/http/http_auth_filter.h" 61 #include "net/http/http_auth_handler_factory.h" 62 #include "net/http/http_network_layer.h" 63 #include "net/http/http_server_properties_impl.h" 64 #include "net/proxy/proxy_config_service.h" 65 #include "net/proxy/proxy_script_fetcher_impl.h" 66 #include "net/proxy/proxy_service.h" 67 #include "net/quic/quic_protocol.h" 68 #include "net/socket/tcp_client_socket.h" 69 #include "net/spdy/spdy_session.h" 70 #include "net/ssl/default_server_bound_cert_store.h" 71 #include "net/ssl/server_bound_cert_service.h" 72 #include "net/url_request/data_protocol_handler.h" 73 #include "net/url_request/file_protocol_handler.h" 74 #include "net/url_request/ftp_protocol_handler.h" 75 #include "net/url_request/static_http_user_agent_settings.h" 76 #include "net/url_request/url_fetcher.h" 77 #include "net/url_request/url_request_job_factory_impl.h" 78 #include "net/url_request/url_request_throttler_manager.h" 79 #include "url/url_constants.h" 80 81 #if defined(ENABLE_CONFIGURATION_POLICY) 82 #include "policy/policy_constants.h" 83 #endif 84 85 #if !defined(USE_OPENSSL) 86 #include "net/cert/ct_log_verifier.h" 87 #include "net/cert/multi_log_ct_verifier.h" 88 #endif 89 90 #if defined(USE_NSS) || defined(OS_IOS) 91 #include "net/ocsp/nss_ocsp.h" 92 #endif 93 94 #if defined(OS_ANDROID) || defined(OS_IOS) 95 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h" 96 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h" 97 #endif 98 99 #if defined(OS_CHROMEOS) 100 #include "chrome/browser/chromeos/login/users/user_manager.h" 101 #include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h" 102 #include "chromeos/network/host_resolver_impl_chromeos.h" 103 #endif 104 105 using content::BrowserThread; 106 107 #if defined(OS_ANDROID) || defined(OS_IOS) 108 using data_reduction_proxy::DataReductionProxyParams; 109 using data_reduction_proxy::DataReductionProxySettings; 110 #endif 111 112 class SafeBrowsingURLRequestContext; 113 114 // The IOThread object must outlive any tasks posted to the IO thread before the 115 // Quit task, so base::Bind() calls are not refcounted. 116 117 namespace { 118 119 const char kQuicFieldTrialName[] = "QUIC"; 120 const char kQuicFieldTrialEnabledGroupName[] = "Enabled"; 121 const char kQuicFieldTrialHttpsEnabledGroupName[] = "HttpsEnabled"; 122 const char kQuicFieldTrialPacketLengthSuffix[] = "BytePackets"; 123 const char kQuicFieldTrialPacingSuffix[] = "WithPacing"; 124 const char kQuicFieldTrialTimeBasedLossDetectionSuffix[] = 125 "WithTimeBasedLossDetection"; 126 127 const char kSpdyFieldTrialName[] = "SPDY"; 128 const char kSpdyFieldTrialDisabledGroupName[] = "SpdyDisabled"; 129 130 #if defined(OS_MACOSX) && !defined(OS_IOS) 131 void ObserveKeychainEvents() { 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 133 net::CertDatabase::GetInstance()->SetMessageLoopForKeychainEvents(); 134 } 135 #endif 136 137 // Used for the "system" URLRequestContext. 138 class SystemURLRequestContext : public net::URLRequestContext { 139 public: 140 SystemURLRequestContext() { 141 #if defined(USE_NSS) || defined(OS_IOS) 142 net::SetURLRequestContextForNSSHttpIO(this); 143 #endif 144 } 145 146 private: 147 virtual ~SystemURLRequestContext() { 148 #if defined(USE_NSS) || defined(OS_IOS) 149 net::SetURLRequestContextForNSSHttpIO(NULL); 150 #endif 151 } 152 }; 153 154 scoped_ptr<net::HostResolver> CreateGlobalHostResolver(net::NetLog* net_log) { 155 TRACE_EVENT0("startup", "IOThread::CreateGlobalHostResolver"); 156 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 157 158 net::HostResolver::Options options; 159 160 // Use the concurrency override from the command-line, if any. 161 if (command_line.HasSwitch(switches::kHostResolverParallelism)) { 162 std::string s = 163 command_line.GetSwitchValueASCII(switches::kHostResolverParallelism); 164 165 // Parse the switch (it should be a positive integer formatted as decimal). 166 int n; 167 if (base::StringToInt(s, &n) && n > 0) { 168 options.max_concurrent_resolves = static_cast<size_t>(n); 169 } else { 170 LOG(ERROR) << "Invalid switch for host resolver parallelism: " << s; 171 } 172 } 173 174 // Use the retry attempts override from the command-line, if any. 175 if (command_line.HasSwitch(switches::kHostResolverRetryAttempts)) { 176 std::string s = 177 command_line.GetSwitchValueASCII(switches::kHostResolverRetryAttempts); 178 // Parse the switch (it should be a non-negative integer). 179 int n; 180 if (base::StringToInt(s, &n) && n >= 0) { 181 options.max_retry_attempts = static_cast<size_t>(n); 182 } else { 183 LOG(ERROR) << "Invalid switch for host resolver retry attempts: " << s; 184 } 185 } 186 187 scoped_ptr<net::HostResolver> global_host_resolver; 188 #if defined OS_CHROMEOS 189 global_host_resolver = 190 chromeos::HostResolverImplChromeOS::CreateSystemResolver(options, 191 net_log); 192 #else 193 global_host_resolver = 194 net::HostResolver::CreateSystemResolver(options, net_log); 195 #endif 196 197 // Determine if we should disable IPv6 support. 198 if (command_line.HasSwitch(switches::kEnableIPv6)) { 199 // Disable IPv6 probing. 200 global_host_resolver->SetDefaultAddressFamily( 201 net::ADDRESS_FAMILY_UNSPECIFIED); 202 } else if (command_line.HasSwitch(switches::kDisableIPv6)) { 203 global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4); 204 } 205 206 // If hostname remappings were specified on the command-line, layer these 207 // rules on top of the real host resolver. This allows forwarding all requests 208 // through a designated test server. 209 if (!command_line.HasSwitch(switches::kHostResolverRules)) 210 return global_host_resolver.PassAs<net::HostResolver>(); 211 212 scoped_ptr<net::MappedHostResolver> remapped_resolver( 213 new net::MappedHostResolver(global_host_resolver.Pass())); 214 remapped_resolver->SetRulesFromString( 215 command_line.GetSwitchValueASCII(switches::kHostResolverRules)); 216 return remapped_resolver.PassAs<net::HostResolver>(); 217 } 218 219 // TODO(willchan): Remove proxy script fetcher context since it's not necessary 220 // now that I got rid of refcounting URLRequestContexts. 221 // See IOThread::Globals for details. 222 net::URLRequestContext* 223 ConstructProxyScriptFetcherContext(IOThread::Globals* globals, 224 net::NetLog* net_log) { 225 net::URLRequestContext* context = new net::URLRequestContext; 226 context->set_net_log(net_log); 227 context->set_host_resolver(globals->host_resolver.get()); 228 context->set_cert_verifier(globals->cert_verifier.get()); 229 context->set_transport_security_state( 230 globals->transport_security_state.get()); 231 context->set_cert_transparency_verifier( 232 globals->cert_transparency_verifier.get()); 233 context->set_http_auth_handler_factory( 234 globals->http_auth_handler_factory.get()); 235 context->set_proxy_service(globals->proxy_script_fetcher_proxy_service.get()); 236 context->set_http_transaction_factory( 237 globals->proxy_script_fetcher_http_transaction_factory.get()); 238 context->set_job_factory( 239 globals->proxy_script_fetcher_url_request_job_factory.get()); 240 context->set_cookie_store(globals->system_cookie_store.get()); 241 context->set_server_bound_cert_service( 242 globals->system_server_bound_cert_service.get()); 243 context->set_network_delegate(globals->system_network_delegate.get()); 244 context->set_http_user_agent_settings( 245 globals->http_user_agent_settings.get()); 246 // TODO(rtenneti): We should probably use HttpServerPropertiesManager for the 247 // system URLRequestContext too. There's no reason this should be tied to a 248 // profile. 249 return context; 250 } 251 252 net::URLRequestContext* 253 ConstructSystemRequestContext(IOThread::Globals* globals, 254 net::NetLog* net_log) { 255 net::URLRequestContext* context = new SystemURLRequestContext; 256 context->set_net_log(net_log); 257 context->set_host_resolver(globals->host_resolver.get()); 258 context->set_cert_verifier(globals->cert_verifier.get()); 259 context->set_transport_security_state( 260 globals->transport_security_state.get()); 261 context->set_cert_transparency_verifier( 262 globals->cert_transparency_verifier.get()); 263 context->set_http_auth_handler_factory( 264 globals->http_auth_handler_factory.get()); 265 context->set_proxy_service(globals->system_proxy_service.get()); 266 context->set_http_transaction_factory( 267 globals->system_http_transaction_factory.get()); 268 context->set_job_factory(globals->system_url_request_job_factory.get()); 269 context->set_cookie_store(globals->system_cookie_store.get()); 270 context->set_server_bound_cert_service( 271 globals->system_server_bound_cert_service.get()); 272 context->set_throttler_manager(globals->throttler_manager.get()); 273 context->set_network_delegate(globals->system_network_delegate.get()); 274 context->set_http_user_agent_settings( 275 globals->http_user_agent_settings.get()); 276 return context; 277 } 278 279 int GetSwitchValueAsInt(const CommandLine& command_line, 280 const std::string& switch_name) { 281 int value; 282 if (!base::StringToInt(command_line.GetSwitchValueASCII(switch_name), 283 &value)) { 284 return 0; 285 } 286 return value; 287 } 288 289 } // namespace 290 291 class IOThread::LoggingNetworkChangeObserver 292 : public net::NetworkChangeNotifier::IPAddressObserver, 293 public net::NetworkChangeNotifier::ConnectionTypeObserver, 294 public net::NetworkChangeNotifier::NetworkChangeObserver { 295 public: 296 // |net_log| must remain valid throughout our lifetime. 297 explicit LoggingNetworkChangeObserver(net::NetLog* net_log) 298 : net_log_(net_log) { 299 net::NetworkChangeNotifier::AddIPAddressObserver(this); 300 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); 301 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); 302 } 303 304 virtual ~LoggingNetworkChangeObserver() { 305 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 306 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); 307 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 308 } 309 310 // NetworkChangeNotifier::IPAddressObserver implementation. 311 virtual void OnIPAddressChanged() OVERRIDE { 312 VLOG(1) << "Observed a change to the network IP addresses"; 313 314 net_log_->AddGlobalEntry(net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED); 315 } 316 317 // NetworkChangeNotifier::ConnectionTypeObserver implementation. 318 virtual void OnConnectionTypeChanged( 319 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE { 320 std::string type_as_string = 321 net::NetworkChangeNotifier::ConnectionTypeToString(type); 322 323 VLOG(1) << "Observed a change to network connectivity state " 324 << type_as_string; 325 326 net_log_->AddGlobalEntry( 327 net::NetLog::TYPE_NETWORK_CONNECTIVITY_CHANGED, 328 net::NetLog::StringCallback("new_connection_type", &type_as_string)); 329 } 330 331 // NetworkChangeNotifier::NetworkChangeObserver implementation. 332 virtual void OnNetworkChanged( 333 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE { 334 std::string type_as_string = 335 net::NetworkChangeNotifier::ConnectionTypeToString(type); 336 337 VLOG(1) << "Observed a network change to state " << type_as_string; 338 339 net_log_->AddGlobalEntry( 340 net::NetLog::TYPE_NETWORK_CHANGED, 341 net::NetLog::StringCallback("new_connection_type", &type_as_string)); 342 } 343 344 private: 345 net::NetLog* net_log_; 346 DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver); 347 }; 348 349 class SystemURLRequestContextGetter : public net::URLRequestContextGetter { 350 public: 351 explicit SystemURLRequestContextGetter(IOThread* io_thread); 352 353 // Implementation for net::UrlRequestContextGetter. 354 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE; 355 virtual scoped_refptr<base::SingleThreadTaskRunner> 356 GetNetworkTaskRunner() const OVERRIDE; 357 358 protected: 359 virtual ~SystemURLRequestContextGetter(); 360 361 private: 362 IOThread* const io_thread_; // Weak pointer, owned by BrowserProcess. 363 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; 364 365 base::debug::LeakTracker<SystemURLRequestContextGetter> leak_tracker_; 366 }; 367 368 SystemURLRequestContextGetter::SystemURLRequestContextGetter( 369 IOThread* io_thread) 370 : io_thread_(io_thread), 371 network_task_runner_( 372 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) { 373 } 374 375 SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {} 376 377 net::URLRequestContext* SystemURLRequestContextGetter::GetURLRequestContext() { 378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 379 DCHECK(io_thread_->globals()->system_request_context.get()); 380 381 return io_thread_->globals()->system_request_context.get(); 382 } 383 384 scoped_refptr<base::SingleThreadTaskRunner> 385 SystemURLRequestContextGetter::GetNetworkTaskRunner() const { 386 return network_task_runner_; 387 } 388 389 IOThread::Globals:: 390 SystemRequestContextLeakChecker::SystemRequestContextLeakChecker( 391 Globals* globals) 392 : globals_(globals) { 393 DCHECK(globals_); 394 } 395 396 IOThread::Globals:: 397 SystemRequestContextLeakChecker::~SystemRequestContextLeakChecker() { 398 if (globals_->system_request_context.get()) 399 globals_->system_request_context->AssertNoURLRequests(); 400 } 401 402 IOThread::Globals::Globals() 403 : system_request_context_leak_checker(this), 404 ignore_certificate_errors(false), 405 testing_fixed_http_port(0), 406 testing_fixed_https_port(0), 407 enable_user_alternate_protocol_ports(false) { 408 } 409 410 IOThread::Globals::~Globals() {} 411 412 // |local_state| is passed in explicitly in order to (1) reduce implicit 413 // dependencies and (2) make IOThread more flexible for testing. 414 IOThread::IOThread( 415 PrefService* local_state, 416 policy::PolicyService* policy_service, 417 ChromeNetLog* net_log, 418 extensions::EventRouterForwarder* extension_event_router_forwarder) 419 : net_log_(net_log), 420 extension_event_router_forwarder_(extension_event_router_forwarder), 421 globals_(NULL), 422 is_spdy_disabled_by_policy_(false), 423 weak_factory_(this), 424 creation_time_(base::TimeTicks::Now()) { 425 auth_schemes_ = local_state->GetString(prefs::kAuthSchemes); 426 negotiate_disable_cname_lookup_ = local_state->GetBoolean( 427 prefs::kDisableAuthNegotiateCnameLookup); 428 negotiate_enable_port_ = local_state->GetBoolean( 429 prefs::kEnableAuthNegotiatePort); 430 auth_server_whitelist_ = local_state->GetString(prefs::kAuthServerWhitelist); 431 auth_delegate_whitelist_ = local_state->GetString( 432 prefs::kAuthNegotiateDelegateWhitelist); 433 gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName); 434 pref_proxy_config_tracker_.reset( 435 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState( 436 local_state)); 437 ChromeNetworkDelegate::InitializePrefsOnUIThread( 438 &system_enable_referrers_, 439 NULL, 440 NULL, 441 local_state); 442 ssl_config_service_manager_.reset( 443 SSLConfigServiceManager::CreateDefaultManager(local_state)); 444 445 base::Value* dns_client_enabled_default = new base::FundamentalValue( 446 chrome_browser_net::ConfigureAsyncDnsFieldTrial()); 447 local_state->SetDefaultPrefValue(prefs::kBuiltInDnsClientEnabled, 448 dns_client_enabled_default); 449 450 dns_client_enabled_.Init(prefs::kBuiltInDnsClientEnabled, 451 local_state, 452 base::Bind(&IOThread::UpdateDnsClientEnabled, 453 base::Unretained(this))); 454 dns_client_enabled_.MoveToThread( 455 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 456 457 quick_check_enabled_.Init(prefs::kQuickCheckEnabled, 458 local_state); 459 quick_check_enabled_.MoveToThread( 460 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 461 462 #if defined(ENABLE_CONFIGURATION_POLICY) 463 is_spdy_disabled_by_policy_ = policy_service->GetPolicies( 464 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())).Get( 465 policy::key::kDisableSpdy) != NULL; 466 #endif // ENABLE_CONFIGURATION_POLICY 467 468 BrowserThread::SetDelegate(BrowserThread::IO, this); 469 } 470 471 IOThread::~IOThread() { 472 // This isn't needed for production code, but in tests, IOThread may 473 // be multiply constructed. 474 BrowserThread::SetDelegate(BrowserThread::IO, NULL); 475 476 pref_proxy_config_tracker_->DetachFromPrefService(); 477 DCHECK(!globals_); 478 } 479 480 IOThread::Globals* IOThread::globals() { 481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 482 return globals_; 483 } 484 485 void IOThread::SetGlobalsForTesting(Globals* globals) { 486 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 487 DCHECK(!globals || !globals_); 488 globals_ = globals; 489 } 490 491 ChromeNetLog* IOThread::net_log() { 492 return net_log_; 493 } 494 495 void IOThread::ChangedToOnTheRecord() { 496 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 497 BrowserThread::PostTask( 498 BrowserThread::IO, 499 FROM_HERE, 500 base::Bind(&IOThread::ChangedToOnTheRecordOnIOThread, 501 base::Unretained(this))); 502 } 503 504 net::URLRequestContextGetter* IOThread::system_url_request_context_getter() { 505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 506 if (!system_url_request_context_getter_.get()) { 507 InitSystemRequestContext(); 508 } 509 return system_url_request_context_getter_.get(); 510 } 511 512 void IOThread::Init() { 513 // Prefer to use InitAsync unless you need initialization to block 514 // the UI thread 515 } 516 517 void IOThread::InitAsync() { 518 TRACE_EVENT0("startup", "IOThread::InitAsync"); 519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 520 521 #if defined(USE_NSS) || defined(OS_IOS) 522 net::SetMessageLoopForNSSHttpIO(); 523 #endif 524 525 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 526 527 DCHECK(!globals_); 528 globals_ = new Globals; 529 530 // Add an observer that will emit network change events to the ChromeNetLog. 531 // Assuming NetworkChangeNotifier dispatches in FIFO order, we should be 532 // logging the network change before other IO thread consumers respond to it. 533 network_change_observer_.reset( 534 new LoggingNetworkChangeObserver(net_log_)); 535 536 // Setup the HistogramWatcher to run on the IO thread. 537 net::NetworkChangeNotifier::InitHistogramWatcher(); 538 539 globals_->extension_event_router_forwarder = 540 extension_event_router_forwarder_; 541 ChromeNetworkDelegate* network_delegate = 542 new ChromeNetworkDelegate(extension_event_router_forwarder_, 543 &system_enable_referrers_); 544 if (command_line.HasSwitch(switches::kEnableClientHints)) 545 network_delegate->SetEnableClientHints(); 546 if (command_line.HasSwitch(switches::kDisableExtensionsHttpThrottling)) 547 network_delegate->NeverThrottleRequests(); 548 globals_->system_network_delegate.reset(network_delegate); 549 globals_->host_resolver = CreateGlobalHostResolver(net_log_); 550 UpdateDnsClientEnabled(); 551 #if defined(OS_CHROMEOS) 552 // Creates a CertVerifyProc that doesn't allow any profile-provided certs. 553 globals_->cert_verifier.reset(new net::MultiThreadedCertVerifier( 554 new chromeos::CertVerifyProcChromeOS())); 555 #else 556 globals_->cert_verifier.reset(new net::MultiThreadedCertVerifier( 557 net::CertVerifyProc::CreateDefault())); 558 #endif 559 560 globals_->transport_security_state.reset(new net::TransportSecurityState()); 561 #if !defined(USE_OPENSSL) 562 // For now, Certificate Transparency is only implemented for platforms 563 // that use NSS. 564 net::MultiLogCTVerifier* ct_verifier = new net::MultiLogCTVerifier(); 565 globals_->cert_transparency_verifier.reset(ct_verifier); 566 567 // Add built-in logs 568 ct_verifier->AddLog(net::ct::CreateGooglePilotLogVerifier().Pass()); 569 ct_verifier->AddLog(net::ct::CreateGoogleAviatorLogVerifier().Pass()); 570 ct_verifier->AddLog(net::ct::CreateGoogleRocketeerLogVerifier().Pass()); 571 572 // Add logs from command line 573 if (command_line.HasSwitch(switches::kCertificateTransparencyLog)) { 574 std::string switch_value = command_line.GetSwitchValueASCII( 575 switches::kCertificateTransparencyLog); 576 std::vector<std::string> logs; 577 base::SplitString(switch_value, ',', &logs); 578 for (std::vector<std::string>::iterator it = logs.begin(); it != logs.end(); 579 ++it) { 580 const std::string& curr_log = *it; 581 size_t delim_pos = curr_log.find(":"); 582 CHECK(delim_pos != std::string::npos) 583 << "CT log description not provided (switch format" 584 " is 'description:base64_key')"; 585 std::string log_description(curr_log.substr(0, delim_pos)); 586 std::string ct_public_key_data; 587 CHECK(base::Base64Decode(curr_log.substr(delim_pos + 1), 588 &ct_public_key_data)) 589 << "Unable to decode CT public key."; 590 scoped_ptr<net::CTLogVerifier> external_log_verifier( 591 net::CTLogVerifier::Create(ct_public_key_data, log_description)); 592 CHECK(external_log_verifier) << "Unable to parse CT public key."; 593 VLOG(1) << "Adding log with description " << log_description; 594 ct_verifier->AddLog(external_log_verifier.Pass()); 595 } 596 } 597 #else 598 if (command_line.HasSwitch(switches::kCertificateTransparencyLog)) { 599 LOG(DFATAL) << "Certificate Transparency is not yet supported in Chrome " 600 "builds using OpenSSL."; 601 } 602 #endif 603 globals_->ssl_config_service = GetSSLConfigService(); 604 #if defined(OS_ANDROID) || defined(OS_IOS) 605 #if defined(SPDY_PROXY_AUTH_ORIGIN) 606 int drp_flags = DataReductionProxyParams::kFallbackAllowed; 607 if (DataReductionProxyParams::IsIncludedInFieldTrial()) 608 drp_flags |= DataReductionProxyParams::kAllowed; 609 if (DataReductionProxyParams::IsIncludedInAlternativeFieldTrial()) 610 drp_flags |= DataReductionProxyParams::kAlternativeAllowed; 611 if (DataReductionProxyParams::IsIncludedInPromoFieldTrial()) 612 drp_flags |= DataReductionProxyParams::kPromoAllowed; 613 globals_->data_reduction_proxy_params.reset( 614 new DataReductionProxyParams(drp_flags)); 615 network_delegate->set_data_reduction_proxy_params( 616 globals_->data_reduction_proxy_params.get()); 617 #endif // defined(SPDY_PROXY_AUTH_ORIGIN) 618 #endif // defined(OS_ANDROID) || defined(OS_IOS) 619 globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory( 620 globals_->host_resolver.get())); 621 globals_->http_server_properties.reset(new net::HttpServerPropertiesImpl()); 622 // For the ProxyScriptFetcher, we use a direct ProxyService. 623 globals_->proxy_script_fetcher_proxy_service.reset( 624 net::ProxyService::CreateDirectWithNetLog(net_log_)); 625 // In-memory cookie store. 626 globals_->system_cookie_store = 627 content::CreateCookieStore(content::CookieStoreConfig()); 628 // In-memory server bound cert store. 629 globals_->system_server_bound_cert_service.reset( 630 new net::ServerBoundCertService( 631 new net::DefaultServerBoundCertStore(NULL), 632 base::WorkerPool::GetTaskRunner(true))); 633 globals_->dns_probe_service.reset(new chrome_browser_net::DnsProbeService()); 634 globals_->host_mapping_rules.reset(new net::HostMappingRules()); 635 globals_->http_user_agent_settings.reset( 636 new net::StaticHttpUserAgentSettings(std::string(), GetUserAgent())); 637 if (command_line.HasSwitch(switches::kHostRules)) { 638 TRACE_EVENT_BEGIN0("startup", "IOThread::InitAsync:SetRulesFromString"); 639 globals_->host_mapping_rules->SetRulesFromString( 640 command_line.GetSwitchValueASCII(switches::kHostRules)); 641 TRACE_EVENT_END0("startup", "IOThread::InitAsync:SetRulesFromString"); 642 } 643 if (command_line.HasSwitch(switches::kIgnoreCertificateErrors)) 644 globals_->ignore_certificate_errors = true; 645 if (command_line.HasSwitch(switches::kTestingFixedHttpPort)) { 646 globals_->testing_fixed_http_port = 647 GetSwitchValueAsInt(command_line, switches::kTestingFixedHttpPort); 648 } 649 if (command_line.HasSwitch(switches::kTestingFixedHttpsPort)) { 650 globals_->testing_fixed_https_port = 651 GetSwitchValueAsInt(command_line, switches::kTestingFixedHttpsPort); 652 } 653 ConfigureQuic(command_line); 654 if (command_line.HasSwitch( 655 switches::kEnableUserAlternateProtocolPorts)) { 656 globals_->enable_user_alternate_protocol_ports = true; 657 } 658 InitializeNetworkOptions(command_line); 659 660 net::HttpNetworkSession::Params session_params; 661 InitializeNetworkSessionParams(&session_params); 662 session_params.net_log = net_log_; 663 session_params.proxy_service = 664 globals_->proxy_script_fetcher_proxy_service.get(); 665 666 TRACE_EVENT_BEGIN0("startup", "IOThread::InitAsync:HttpNetworkSession"); 667 scoped_refptr<net::HttpNetworkSession> network_session( 668 new net::HttpNetworkSession(session_params)); 669 globals_->proxy_script_fetcher_http_transaction_factory 670 .reset(new net::HttpNetworkLayer(network_session.get())); 671 TRACE_EVENT_END0("startup", "IOThread::InitAsync:HttpNetworkSession"); 672 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory( 673 new net::URLRequestJobFactoryImpl()); 674 job_factory->SetProtocolHandler(url::kDataScheme, 675 new net::DataProtocolHandler()); 676 job_factory->SetProtocolHandler( 677 url::kFileScheme, 678 new net::FileProtocolHandler( 679 content::BrowserThread::GetBlockingPool()-> 680 GetTaskRunnerWithShutdownBehavior( 681 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); 682 #if !defined(DISABLE_FTP_SUPPORT) 683 globals_->proxy_script_fetcher_ftp_transaction_factory.reset( 684 new net::FtpNetworkLayer(globals_->host_resolver.get())); 685 job_factory->SetProtocolHandler( 686 url::kFtpScheme, 687 new net::FtpProtocolHandler( 688 globals_->proxy_script_fetcher_ftp_transaction_factory.get())); 689 #endif 690 globals_->proxy_script_fetcher_url_request_job_factory = 691 job_factory.PassAs<net::URLRequestJobFactory>(); 692 693 globals_->throttler_manager.reset(new net::URLRequestThrottlerManager()); 694 globals_->throttler_manager->set_net_log(net_log_); 695 // Always done in production, disabled only for unit tests. 696 globals_->throttler_manager->set_enable_thread_checks(true); 697 698 globals_->proxy_script_fetcher_context.reset( 699 ConstructProxyScriptFetcherContext(globals_, net_log_)); 700 701 #if defined(OS_MACOSX) && !defined(OS_IOS) 702 // Start observing Keychain events. This needs to be done on the UI thread, 703 // as Keychain services requires a CFRunLoop. 704 BrowserThread::PostTask(BrowserThread::UI, 705 FROM_HERE, 706 base::Bind(&ObserveKeychainEvents)); 707 #endif 708 709 // InitSystemRequestContext turns right around and posts a task back 710 // to the IO thread, so we can't let it run until we know the IO 711 // thread has started. 712 // 713 // Note that since we are at BrowserThread::Init time, the UI thread 714 // is blocked waiting for the thread to start. Therefore, posting 715 // this task to the main thread's message loop here is guaranteed to 716 // get it onto the message loop while the IOThread object still 717 // exists. However, the message might not be processed on the UI 718 // thread until after IOThread is gone, so use a weak pointer. 719 BrowserThread::PostTask(BrowserThread::UI, 720 FROM_HERE, 721 base::Bind(&IOThread::InitSystemRequestContext, 722 weak_factory_.GetWeakPtr())); 723 } 724 725 void IOThread::CleanUp() { 726 base::debug::LeakTracker<SafeBrowsingURLRequestContext>::CheckForLeaks(); 727 728 #if defined(USE_NSS) || defined(OS_IOS) 729 net::ShutdownNSSHttpIO(); 730 #endif 731 732 system_url_request_context_getter_ = NULL; 733 734 // Release objects that the net::URLRequestContext could have been pointing 735 // to. 736 737 // Shutdown the HistogramWatcher on the IO thread. 738 net::NetworkChangeNotifier::ShutdownHistogramWatcher(); 739 740 // This must be reset before the ChromeNetLog is destroyed. 741 network_change_observer_.reset(); 742 743 system_proxy_config_service_.reset(); 744 745 delete globals_; 746 globals_ = NULL; 747 748 base::debug::LeakTracker<SystemURLRequestContextGetter>::CheckForLeaks(); 749 } 750 751 void IOThread::InitializeNetworkOptions(const CommandLine& command_line) { 752 // Only handle use-spdy command line flags if "spdy.disabled" preference is 753 // not disabled via policy. 754 if (is_spdy_disabled_by_policy_) { 755 base::FieldTrial* trial = base::FieldTrialList::Find(kSpdyFieldTrialName); 756 if (trial) 757 trial->Disable(); 758 } else { 759 std::string spdy_trial_group = 760 base::FieldTrialList::FindFullName(kSpdyFieldTrialName); 761 762 if (command_line.HasSwitch(switches::kTrustedSpdyProxy)) { 763 globals_->trusted_spdy_proxy.set( 764 command_line.GetSwitchValueASCII(switches::kTrustedSpdyProxy)); 765 } 766 if (command_line.HasSwitch(switches::kIgnoreUrlFetcherCertRequests)) 767 net::URLFetcher::SetIgnoreCertificateRequests(true); 768 769 if (command_line.HasSwitch(switches::kUseSpdy)) { 770 std::string spdy_mode = 771 command_line.GetSwitchValueASCII(switches::kUseSpdy); 772 EnableSpdy(spdy_mode); 773 } else if (command_line.HasSwitch(switches::kEnableSpdy4)) { 774 globals_->next_protos = net::NextProtosSpdy4Http2(); 775 globals_->use_alternate_protocols.set(true); 776 } else if (command_line.HasSwitch(switches::kDisableSpdy31)) { 777 globals_->next_protos = net::NextProtosSpdy3(); 778 globals_->use_alternate_protocols.set(true); 779 } else if (command_line.HasSwitch(switches::kEnableNpnHttpOnly)) { 780 globals_->next_protos = net::NextProtosHttpOnly(); 781 globals_->use_alternate_protocols.set(false); 782 } else { 783 if (spdy_trial_group == kSpdyFieldTrialDisabledGroupName && 784 !command_line.HasSwitch(switches::kEnableWebSocketOverSpdy)) { 785 net::HttpStreamFactory::set_spdy_enabled(false); 786 } else { 787 // Use SPDY/3.1 by default. 788 globals_->next_protos = net::NextProtosSpdy31(); 789 globals_->use_alternate_protocols.set(true); 790 } 791 } 792 793 if (command_line.HasSwitch(switches::kEnableWebSocketOverSpdy)) 794 globals_->enable_websocket_over_spdy.set(true); 795 } 796 797 // TODO(rch): Make the client socket factory a per-network session 798 // instance, constructed from a NetworkSession::Params, to allow us 799 // to move this option to IOThread::Globals & 800 // HttpNetworkSession::Params. 801 if (command_line.HasSwitch(switches::kEnableTcpFastOpen)) 802 net::SetTCPFastOpenEnabled(true); 803 } 804 805 void IOThread::EnableSpdy(const std::string& mode) { 806 static const char kOff[] = "off"; 807 static const char kSSL[] = "ssl"; 808 static const char kDisableSSL[] = "no-ssl"; 809 static const char kDisablePing[] = "no-ping"; 810 static const char kExclude[] = "exclude"; // Hosts to exclude 811 static const char kDisableCompression[] = "no-compress"; 812 static const char kDisableAltProtocols[] = "no-alt-protocols"; 813 static const char kForceAltProtocols[] = "force-alt-protocols"; 814 static const char kSingleDomain[] = "single-domain"; 815 816 static const char kInitialMaxConcurrentStreams[] = "init-max-streams"; 817 818 std::vector<std::string> spdy_options; 819 base::SplitString(mode, ',', &spdy_options); 820 821 for (std::vector<std::string>::iterator it = spdy_options.begin(); 822 it != spdy_options.end(); ++it) { 823 const std::string& element = *it; 824 std::vector<std::string> name_value; 825 base::SplitString(element, '=', &name_value); 826 const std::string& option = 827 name_value.size() > 0 ? name_value[0] : std::string(); 828 const std::string value = 829 name_value.size() > 1 ? name_value[1] : std::string(); 830 831 if (option == kOff) { 832 net::HttpStreamFactory::set_spdy_enabled(false); 833 } else if (option == kDisableSSL) { 834 globals_->spdy_default_protocol.set(net::kProtoSPDY3); 835 globals_->force_spdy_over_ssl.set(false); 836 globals_->force_spdy_always.set(true); 837 } else if (option == kSSL) { 838 globals_->spdy_default_protocol.set(net::kProtoSPDY3); 839 globals_->force_spdy_over_ssl.set(true); 840 globals_->force_spdy_always.set(true); 841 } else if (option == kDisablePing) { 842 globals_->enable_spdy_ping_based_connection_checking.set(false); 843 } else if (option == kExclude) { 844 globals_->forced_spdy_exclusions.insert( 845 net::HostPortPair::FromURL(GURL(value))); 846 } else if (option == kDisableCompression) { 847 globals_->enable_spdy_compression.set(false); 848 } else if (option == kDisableAltProtocols) { 849 globals_->use_alternate_protocols.set(false); 850 } else if (option == kForceAltProtocols) { 851 net::PortAlternateProtocolPair pair; 852 pair.port = 443; 853 pair.protocol = net::NPN_SPDY_3; 854 net::HttpServerPropertiesImpl::ForceAlternateProtocol(pair); 855 } else if (option == kSingleDomain) { 856 DVLOG(1) << "FORCING SINGLE DOMAIN"; 857 globals_->force_spdy_single_domain.set(true); 858 } else if (option == kInitialMaxConcurrentStreams) { 859 int streams; 860 if (base::StringToInt(value, &streams)) 861 globals_->initial_max_spdy_concurrent_streams.set(streams); 862 } else if (option.empty() && it == spdy_options.begin()) { 863 continue; 864 } else { 865 LOG(DFATAL) << "Unrecognized spdy option: " << option; 866 } 867 } 868 } 869 870 // static 871 void IOThread::RegisterPrefs(PrefRegistrySimple* registry) { 872 registry->RegisterStringPref(prefs::kAuthSchemes, 873 "basic,digest,ntlm,negotiate," 874 "spdyproxy"); 875 registry->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup, false); 876 registry->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort, false); 877 registry->RegisterStringPref(prefs::kAuthServerWhitelist, std::string()); 878 registry->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist, 879 std::string()); 880 registry->RegisterStringPref(prefs::kGSSAPILibraryName, std::string()); 881 registry->RegisterStringPref( 882 data_reduction_proxy::prefs::kDataReductionProxy, std::string()); 883 registry->RegisterBooleanPref(prefs::kEnableReferrers, true); 884 data_reduction_proxy::RegisterPrefs(registry); 885 registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, true); 886 registry->RegisterBooleanPref(prefs::kQuickCheckEnabled, true); 887 } 888 889 net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory( 890 net::HostResolver* resolver) { 891 net::HttpAuthFilterWhitelist* auth_filter_default_credentials = NULL; 892 if (!auth_server_whitelist_.empty()) { 893 auth_filter_default_credentials = 894 new net::HttpAuthFilterWhitelist(auth_server_whitelist_); 895 } 896 net::HttpAuthFilterWhitelist* auth_filter_delegate = NULL; 897 if (!auth_delegate_whitelist_.empty()) { 898 auth_filter_delegate = 899 new net::HttpAuthFilterWhitelist(auth_delegate_whitelist_); 900 } 901 globals_->url_security_manager.reset( 902 net::URLSecurityManager::Create(auth_filter_default_credentials, 903 auth_filter_delegate)); 904 std::vector<std::string> supported_schemes; 905 base::SplitString(auth_schemes_, ',', &supported_schemes); 906 907 scoped_ptr<net::HttpAuthHandlerRegistryFactory> registry_factory( 908 net::HttpAuthHandlerRegistryFactory::Create( 909 supported_schemes, globals_->url_security_manager.get(), 910 resolver, gssapi_library_name_, negotiate_disable_cname_lookup_, 911 negotiate_enable_port_)); 912 913 if (globals_->data_reduction_proxy_params.get()) { 914 std::vector<GURL> data_reduction_proxies = 915 globals_->data_reduction_proxy_params->GetAllowedProxies(); 916 if (!data_reduction_proxies.empty()) { 917 registry_factory->RegisterSchemeFactory( 918 "spdyproxy", 919 new data_reduction_proxy::HttpAuthHandlerDataReductionProxy::Factory( 920 data_reduction_proxies)); 921 } 922 } 923 924 return registry_factory.release(); 925 } 926 927 void IOThread::ClearHostCache() { 928 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 929 930 net::HostCache* host_cache = globals_->host_resolver->GetHostCache(); 931 if (host_cache) 932 host_cache->clear(); 933 } 934 935 void IOThread::InitializeNetworkSessionParams( 936 net::HttpNetworkSession::Params* params) { 937 params->host_resolver = globals_->host_resolver.get(); 938 params->cert_verifier = globals_->cert_verifier.get(); 939 params->server_bound_cert_service = 940 globals_->system_server_bound_cert_service.get(); 941 params->transport_security_state = globals_->transport_security_state.get(); 942 params->ssl_config_service = globals_->ssl_config_service.get(); 943 params->http_auth_handler_factory = globals_->http_auth_handler_factory.get(); 944 params->http_server_properties = 945 globals_->http_server_properties->GetWeakPtr(); 946 params->network_delegate = globals_->system_network_delegate.get(); 947 params->host_mapping_rules = globals_->host_mapping_rules.get(); 948 params->ignore_certificate_errors = globals_->ignore_certificate_errors; 949 params->testing_fixed_http_port = globals_->testing_fixed_http_port; 950 params->testing_fixed_https_port = globals_->testing_fixed_https_port; 951 952 globals_->initial_max_spdy_concurrent_streams.CopyToIfSet( 953 ¶ms->spdy_initial_max_concurrent_streams); 954 globals_->force_spdy_single_domain.CopyToIfSet( 955 ¶ms->force_spdy_single_domain); 956 globals_->enable_spdy_compression.CopyToIfSet( 957 ¶ms->enable_spdy_compression); 958 globals_->enable_spdy_ping_based_connection_checking.CopyToIfSet( 959 ¶ms->enable_spdy_ping_based_connection_checking); 960 globals_->spdy_default_protocol.CopyToIfSet( 961 ¶ms->spdy_default_protocol); 962 params->next_protos = globals_->next_protos; 963 globals_->trusted_spdy_proxy.CopyToIfSet(¶ms->trusted_spdy_proxy); 964 globals_->force_spdy_over_ssl.CopyToIfSet(¶ms->force_spdy_over_ssl); 965 globals_->force_spdy_always.CopyToIfSet(¶ms->force_spdy_always); 966 globals_->forced_spdy_exclusions = params->forced_spdy_exclusions; 967 globals_->use_alternate_protocols.CopyToIfSet( 968 ¶ms->use_alternate_protocols); 969 globals_->enable_websocket_over_spdy.CopyToIfSet( 970 ¶ms->enable_websocket_over_spdy); 971 972 globals_->enable_quic.CopyToIfSet(¶ms->enable_quic); 973 globals_->enable_quic_https.CopyToIfSet(¶ms->enable_quic_https); 974 globals_->enable_quic_pacing.CopyToIfSet( 975 ¶ms->enable_quic_pacing); 976 globals_->enable_quic_time_based_loss_detection.CopyToIfSet( 977 ¶ms->enable_quic_time_based_loss_detection); 978 globals_->enable_quic_persist_server_info.CopyToIfSet( 979 ¶ms->enable_quic_persist_server_info); 980 globals_->enable_quic_port_selection.CopyToIfSet( 981 ¶ms->enable_quic_port_selection); 982 globals_->quic_max_packet_length.CopyToIfSet(¶ms->quic_max_packet_length); 983 globals_->quic_user_agent_id.CopyToIfSet(¶ms->quic_user_agent_id); 984 globals_->quic_supported_versions.CopyToIfSet( 985 ¶ms->quic_supported_versions); 986 globals_->origin_to_force_quic_on.CopyToIfSet( 987 ¶ms->origin_to_force_quic_on); 988 params->enable_user_alternate_protocol_ports = 989 globals_->enable_user_alternate_protocol_ports; 990 } 991 992 base::TimeTicks IOThread::creation_time() const { 993 return creation_time_; 994 } 995 996 net::SSLConfigService* IOThread::GetSSLConfigService() { 997 return ssl_config_service_manager_->Get(); 998 } 999 1000 void IOThread::ChangedToOnTheRecordOnIOThread() { 1001 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1002 1003 // Clear the host cache to avoid showing entries from the OTR session 1004 // in about:net-internals. 1005 ClearHostCache(); 1006 } 1007 1008 void IOThread::InitSystemRequestContext() { 1009 if (system_url_request_context_getter_.get()) 1010 return; 1011 // If we're in unit_tests, IOThread may not be run. 1012 if (!BrowserThread::IsMessageLoopValid(BrowserThread::IO)) 1013 return; 1014 system_proxy_config_service_.reset( 1015 ProxyServiceFactory::CreateProxyConfigService( 1016 pref_proxy_config_tracker_.get())); 1017 system_url_request_context_getter_ = 1018 new SystemURLRequestContextGetter(this); 1019 // Safe to post an unretained this pointer, since IOThread is 1020 // guaranteed to outlive the IO BrowserThread. 1021 BrowserThread::PostTask( 1022 BrowserThread::IO, 1023 FROM_HERE, 1024 base::Bind(&IOThread::InitSystemRequestContextOnIOThread, 1025 base::Unretained(this))); 1026 } 1027 1028 void IOThread::InitSystemRequestContextOnIOThread() { 1029 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1030 DCHECK(!globals_->system_proxy_service.get()); 1031 DCHECK(system_proxy_config_service_.get()); 1032 1033 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 1034 globals_->system_proxy_service.reset( 1035 ProxyServiceFactory::CreateProxyService( 1036 net_log_, 1037 globals_->proxy_script_fetcher_context.get(), 1038 globals_->system_network_delegate.get(), 1039 system_proxy_config_service_.release(), 1040 command_line, 1041 quick_check_enabled_.GetValue())); 1042 1043 net::HttpNetworkSession::Params system_params; 1044 InitializeNetworkSessionParams(&system_params); 1045 system_params.net_log = net_log_; 1046 system_params.proxy_service = globals_->system_proxy_service.get(); 1047 1048 globals_->system_http_transaction_factory.reset( 1049 new net::HttpNetworkLayer( 1050 new net::HttpNetworkSession(system_params))); 1051 globals_->system_url_request_job_factory.reset( 1052 new net::URLRequestJobFactoryImpl()); 1053 globals_->system_request_context.reset( 1054 ConstructSystemRequestContext(globals_, net_log_)); 1055 } 1056 1057 void IOThread::UpdateDnsClientEnabled() { 1058 globals()->host_resolver->SetDnsClientEnabled(*dns_client_enabled_); 1059 } 1060 1061 void IOThread::ConfigureQuic(const CommandLine& command_line) { 1062 // Always fetch the field trial group to ensure it is reported correctly. 1063 // The command line flags will be associated with a group that is reported 1064 // so long as trial is actually queried. 1065 std::string quic_trial_group = 1066 base::FieldTrialList::FindFullName(kQuicFieldTrialName); 1067 1068 bool enable_quic = ShouldEnableQuic(command_line, quic_trial_group); 1069 globals_->enable_quic.set(enable_quic); 1070 if (enable_quic) { 1071 globals_->enable_quic_https.set( 1072 ShouldEnableQuicHttps(command_line, quic_trial_group)); 1073 globals_->enable_quic_pacing.set( 1074 ShouldEnableQuicPacing(command_line, quic_trial_group)); 1075 globals_->enable_quic_time_based_loss_detection.set( 1076 ShouldEnableQuicTimeBasedLossDetection(command_line, quic_trial_group)); 1077 globals_->enable_quic_persist_server_info.set( 1078 ShouldEnableQuicPersistServerInfo(command_line)); 1079 globals_->enable_quic_port_selection.set( 1080 ShouldEnableQuicPortSelection(command_line)); 1081 } 1082 1083 size_t max_packet_length = GetQuicMaxPacketLength(command_line, 1084 quic_trial_group); 1085 if (max_packet_length != 0) { 1086 globals_->quic_max_packet_length.set(max_packet_length); 1087 } 1088 1089 std::string quic_user_agent_id = 1090 chrome::VersionInfo::GetVersionStringModifier(); 1091 quic_user_agent_id.append(1, ' '); 1092 chrome::VersionInfo version_info; 1093 quic_user_agent_id.append(version_info.ProductNameAndVersionForUserAgent()); 1094 globals_->quic_user_agent_id.set(quic_user_agent_id); 1095 1096 net::QuicVersion version = GetQuicVersion(command_line); 1097 if (version != net::QUIC_VERSION_UNSUPPORTED) { 1098 net::QuicVersionVector supported_versions; 1099 supported_versions.push_back(version); 1100 globals_->quic_supported_versions.set(supported_versions); 1101 } 1102 1103 if (command_line.HasSwitch(switches::kOriginToForceQuicOn)) { 1104 net::HostPortPair quic_origin = 1105 net::HostPortPair::FromString( 1106 command_line.GetSwitchValueASCII(switches::kOriginToForceQuicOn)); 1107 if (!quic_origin.IsEmpty()) { 1108 globals_->origin_to_force_quic_on.set(quic_origin); 1109 } 1110 } 1111 } 1112 1113 bool IOThread::ShouldEnableQuic(const CommandLine& command_line, 1114 base::StringPiece quic_trial_group) { 1115 if (command_line.HasSwitch(switches::kDisableQuic)) 1116 return false; 1117 1118 if (command_line.HasSwitch(switches::kEnableQuic)) 1119 return true; 1120 1121 return quic_trial_group.starts_with(kQuicFieldTrialEnabledGroupName) || 1122 quic_trial_group.starts_with(kQuicFieldTrialHttpsEnabledGroupName); 1123 } 1124 1125 bool IOThread::ShouldEnableQuicHttps(const CommandLine& command_line, 1126 base::StringPiece quic_trial_group) { 1127 if (command_line.HasSwitch(switches::kDisableQuicHttps)) 1128 return false; 1129 1130 if (command_line.HasSwitch(switches::kEnableQuicHttps)) 1131 return true; 1132 1133 return quic_trial_group.starts_with(kQuicFieldTrialHttpsEnabledGroupName); 1134 } 1135 1136 bool IOThread::ShouldEnableQuicPortSelection( 1137 const CommandLine& command_line) { 1138 if (command_line.HasSwitch(switches::kDisableQuicPortSelection)) 1139 return false; 1140 1141 if (command_line.HasSwitch(switches::kEnableQuicPortSelection)) 1142 return true; 1143 1144 return false; // Default to disabling port selection on all channels. 1145 } 1146 1147 bool IOThread::ShouldEnableQuicPacing(const CommandLine& command_line, 1148 base::StringPiece quic_trial_group) { 1149 if (command_line.HasSwitch(switches::kEnableQuicPacing)) 1150 return true; 1151 1152 if (command_line.HasSwitch(switches::kDisableQuicPacing)) 1153 return false; 1154 1155 return quic_trial_group.ends_with(kQuicFieldTrialPacingSuffix); 1156 } 1157 1158 bool IOThread::ShouldEnableQuicTimeBasedLossDetection( 1159 const CommandLine& command_line, 1160 base::StringPiece quic_trial_group) { 1161 if (command_line.HasSwitch(switches::kEnableQuicTimeBasedLossDetection)) 1162 return true; 1163 1164 if (command_line.HasSwitch(switches::kDisableQuicTimeBasedLossDetection)) 1165 return false; 1166 1167 return quic_trial_group.ends_with( 1168 kQuicFieldTrialTimeBasedLossDetectionSuffix); 1169 } 1170 1171 // TODO(rtenneti): Delete this method after the merge. 1172 bool IOThread::ShouldEnableQuicPersistServerInfo( 1173 const CommandLine& command_line) { 1174 return true; 1175 } 1176 1177 size_t IOThread::GetQuicMaxPacketLength(const CommandLine& command_line, 1178 base::StringPiece quic_trial_group) { 1179 if (command_line.HasSwitch(switches::kQuicMaxPacketLength)) { 1180 unsigned value; 1181 if (!base::StringToUint( 1182 command_line.GetSwitchValueASCII(switches::kQuicMaxPacketLength), 1183 &value)) { 1184 return 0; 1185 } 1186 return value; 1187 } 1188 1189 // Format of the packet length group names is: 1190 // (Https)?Enabled<length>BytePackets. 1191 base::StringPiece length_str(quic_trial_group); 1192 if (length_str.starts_with(kQuicFieldTrialEnabledGroupName)) { 1193 length_str.remove_prefix(strlen(kQuicFieldTrialEnabledGroupName)); 1194 } else if (length_str.starts_with(kQuicFieldTrialHttpsEnabledGroupName)) { 1195 length_str.remove_prefix(strlen(kQuicFieldTrialHttpsEnabledGroupName)); 1196 } else { 1197 return 0; 1198 } 1199 if (!length_str.ends_with(kQuicFieldTrialPacketLengthSuffix)) { 1200 return 0; 1201 } 1202 length_str.remove_suffix(strlen(kQuicFieldTrialPacketLengthSuffix)); 1203 unsigned value; 1204 if (!base::StringToUint(length_str, &value)) { 1205 return 0; 1206 } 1207 return value; 1208 } 1209 1210 net::QuicVersion IOThread::GetQuicVersion(const CommandLine& command_line) { 1211 if (!command_line.HasSwitch(switches::kQuicVersion)) { 1212 return net::QUIC_VERSION_UNSUPPORTED; 1213 } 1214 net::QuicVersionVector supported_versions = net::QuicSupportedVersions(); 1215 std::string version_flag = 1216 command_line.GetSwitchValueASCII(switches::kQuicVersion); 1217 for (size_t i = 0; i < supported_versions.size(); ++i) { 1218 net::QuicVersion version = supported_versions[i]; 1219 if (net::QuicVersionToString(version) == version_flag) { 1220 return version; 1221 } 1222 } 1223 return net::QUIC_VERSION_UNSUPPORTED; 1224 } 1225