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