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