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