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