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