Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2011 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/command_line.h"
     10 #include "base/debug/leak_tracker.h"
     11 #include "base/logging.h"
     12 #include "base/metrics/field_trial.h"
     13 #include "base/stl_util-inl.h"
     14 #include "base/string_number_conversions.h"
     15 #include "base/string_split.h"
     16 #include "base/string_util.h"
     17 #include "base/threading/thread_restrictions.h"
     18 #include "chrome/browser/browser_process.h"
     19 #include "chrome/browser/extensions/extension_event_router_forwarder.h"
     20 #include "chrome/browser/net/chrome_network_delegate.h"
     21 #include "chrome/browser/net/chrome_net_log.h"
     22 #include "chrome/browser/net/chrome_url_request_context.h"
     23 #include "chrome/browser/net/connect_interceptor.h"
     24 #include "chrome/browser/net/passive_log_collector.h"
     25 #include "chrome/browser/net/predictor_api.h"
     26 #include "chrome/browser/net/pref_proxy_config_service.h"
     27 #include "chrome/browser/net/proxy_service_factory.h"
     28 #include "chrome/browser/prefs/pref_service.h"
     29 #include "chrome/common/chrome_switches.h"
     30 #include "chrome/common/net/raw_host_resolver_proc.h"
     31 #include "chrome/common/net/url_fetcher.h"
     32 #include "chrome/common/pref_names.h"
     33 #include "content/browser/browser_thread.h"
     34 #include "content/browser/gpu_process_host.h"
     35 #include "content/browser/in_process_webkit/indexed_db_key_utility_client.h"
     36 #include "net/base/cert_verifier.h"
     37 #include "net/base/cookie_monster.h"
     38 #include "net/base/dnsrr_resolver.h"
     39 #include "net/base/host_cache.h"
     40 #include "net/base/host_resolver.h"
     41 #include "net/base/host_resolver_impl.h"
     42 #include "net/base/mapped_host_resolver.h"
     43 #include "net/base/net_util.h"
     44 #include "net/proxy/proxy_config_service.h"
     45 #include "net/ftp/ftp_network_layer.h"
     46 #include "net/http/http_auth_filter.h"
     47 #include "net/http/http_auth_handler_factory.h"
     48 #include "net/http/http_network_layer.h"
     49 #include "net/http/http_network_session.h"
     50 #if defined(USE_NSS)
     51 #include "net/ocsp/nss_ocsp.h"
     52 #endif  // defined(USE_NSS)
     53 #include "net/proxy/proxy_script_fetcher_impl.h"
     54 #include "webkit/glue/webkit_glue.h"
     55 
     56 namespace {
     57 
     58 // Custom URLRequestContext used by requests which aren't associated with a
     59 // particular profile. We need to use a subclass of URLRequestContext in order
     60 // to provide the correct User-Agent.
     61 class URLRequestContextWithUserAgent : public net::URLRequestContext {
     62  public:
     63   virtual const std::string& GetUserAgent(
     64       const GURL& url) const OVERRIDE {
     65     return webkit_glue::GetUserAgent(url);
     66   }
     67 };
     68 
     69 net::HostResolver* CreateGlobalHostResolver(net::NetLog* net_log) {
     70   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
     71 
     72   size_t parallelism = net::HostResolver::kDefaultParallelism;
     73 
     74   // Use the concurrency override from the command-line, if any.
     75   if (command_line.HasSwitch(switches::kHostResolverParallelism)) {
     76     std::string s =
     77         command_line.GetSwitchValueASCII(switches::kHostResolverParallelism);
     78 
     79     // Parse the switch (it should be a positive integer formatted as decimal).
     80     int n;
     81     if (base::StringToInt(s, &n) && n > 0) {
     82       parallelism = static_cast<size_t>(n);
     83     } else {
     84       LOG(ERROR) << "Invalid switch for host resolver parallelism: " << s;
     85     }
     86   } else {
     87     // Set up a field trial to see what impact the total number of concurrent
     88     // resolutions have on DNS resolutions.
     89     base::FieldTrial::Probability kDivisor = 1000;
     90     // For each option (i.e., non-default), we have a fixed probability.
     91     base::FieldTrial::Probability kProbabilityPerGroup = 100;  // 10%.
     92 
     93     // After June 30, 2011 builds, it will always be in default group
     94     // (parallel_default).
     95     scoped_refptr<base::FieldTrial> trial(
     96         new base::FieldTrial(
     97             "DnsParallelism", kDivisor, "parallel_default", 2011, 6, 30));
     98 
     99     // List options with different counts.
    100     // Firefox limits total to 8 in parallel, and default is currently 50.
    101     int parallel_6 = trial->AppendGroup("parallel_6", kProbabilityPerGroup);
    102     int parallel_7 = trial->AppendGroup("parallel_7", kProbabilityPerGroup);
    103     int parallel_8 = trial->AppendGroup("parallel_8", kProbabilityPerGroup);
    104     int parallel_9 = trial->AppendGroup("parallel_9", kProbabilityPerGroup);
    105     int parallel_10 = trial->AppendGroup("parallel_10", kProbabilityPerGroup);
    106     int parallel_14 = trial->AppendGroup("parallel_14", kProbabilityPerGroup);
    107     int parallel_20 = trial->AppendGroup("parallel_20", kProbabilityPerGroup);
    108 
    109     if (trial->group() == parallel_6)
    110       parallelism = 6;
    111     else if (trial->group() == parallel_7)
    112       parallelism = 7;
    113     else if (trial->group() == parallel_8)
    114       parallelism = 8;
    115     else if (trial->group() == parallel_9)
    116       parallelism = 9;
    117     else if (trial->group() == parallel_10)
    118       parallelism = 10;
    119     else if (trial->group() == parallel_14)
    120       parallelism = 14;
    121     else if (trial->group() == parallel_20)
    122       parallelism = 20;
    123   }
    124 
    125   // Use the specified DNS server for doing raw resolutions if requested
    126   // from the command-line.
    127   scoped_refptr<net::HostResolverProc> resolver_proc;
    128   if (command_line.HasSwitch(switches::kDnsServer)) {
    129     std::string dns_ip_string =
    130         command_line.GetSwitchValueASCII(switches::kDnsServer);
    131     net::IPAddressNumber dns_ip_number;
    132     if (net::ParseIPLiteralToNumber(dns_ip_string, &dns_ip_number)) {
    133       resolver_proc =
    134           new chrome_common_net::RawHostResolverProc(dns_ip_number, NULL);
    135     } else {
    136       LOG(ERROR) << "Invalid IP address specified for --dns-server: "
    137                  << dns_ip_string;
    138     }
    139   }
    140 
    141   net::HostResolver* global_host_resolver =
    142       net::CreateSystemHostResolver(parallelism, resolver_proc.get(), net_log);
    143 
    144   // Determine if we should disable IPv6 support.
    145   if (!command_line.HasSwitch(switches::kEnableIPv6)) {
    146     if (command_line.HasSwitch(switches::kDisableIPv6)) {
    147       global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4);
    148     } else {
    149       net::HostResolverImpl* host_resolver_impl =
    150           global_host_resolver->GetAsHostResolverImpl();
    151       if (host_resolver_impl != NULL) {
    152         // Use probe to decide if support is warranted.
    153         host_resolver_impl->ProbeIPv6Support();
    154       }
    155     }
    156   }
    157 
    158   // If hostname remappings were specified on the command-line, layer these
    159   // rules on top of the real host resolver. This allows forwarding all requests
    160   // through a designated test server.
    161   if (!command_line.HasSwitch(switches::kHostResolverRules))
    162     return global_host_resolver;
    163 
    164   net::MappedHostResolver* remapped_resolver =
    165       new net::MappedHostResolver(global_host_resolver);
    166   remapped_resolver->SetRulesFromString(
    167       command_line.GetSwitchValueASCII(switches::kHostResolverRules));
    168   return remapped_resolver;
    169 }
    170 
    171 class LoggingNetworkChangeObserver
    172     : public net::NetworkChangeNotifier::IPAddressObserver {
    173  public:
    174   // |net_log| must remain valid throughout our lifetime.
    175   explicit LoggingNetworkChangeObserver(net::NetLog* net_log)
    176       : net_log_(net_log) {
    177     net::NetworkChangeNotifier::AddIPAddressObserver(this);
    178   }
    179 
    180   ~LoggingNetworkChangeObserver() {
    181     net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
    182   }
    183 
    184   virtual void OnIPAddressChanged() {
    185     VLOG(1) << "Observed a change to the network IP addresses";
    186 
    187     net_log_->AddEntry(net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED,
    188                        base::TimeTicks::Now(),
    189                        net::NetLog::Source(),
    190                        net::NetLog::PHASE_NONE,
    191                        NULL);
    192   }
    193 
    194  private:
    195   net::NetLog* net_log_;
    196   DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver);
    197 };
    198 
    199 scoped_refptr<net::URLRequestContext>
    200 ConstructProxyScriptFetcherContext(IOThread::Globals* globals,
    201                                    net::NetLog* net_log) {
    202   scoped_refptr<net::URLRequestContext> context(
    203       new URLRequestContextWithUserAgent);
    204   context->set_net_log(net_log);
    205   context->set_host_resolver(globals->host_resolver.get());
    206   context->set_cert_verifier(globals->cert_verifier.get());
    207   context->set_dnsrr_resolver(globals->dnsrr_resolver.get());
    208   context->set_http_auth_handler_factory(
    209       globals->http_auth_handler_factory.get());
    210   context->set_proxy_service(globals->proxy_script_fetcher_proxy_service.get());
    211   context->set_http_transaction_factory(
    212       globals->proxy_script_fetcher_http_transaction_factory.get());
    213   context->set_ftp_transaction_factory(
    214       globals->proxy_script_fetcher_ftp_transaction_factory.get());
    215   // In-memory cookie store.
    216   context->set_cookie_store(new net::CookieMonster(NULL, NULL));
    217   context->set_network_delegate(globals->system_network_delegate.get());
    218   return context;
    219 }
    220 
    221 scoped_refptr<net::URLRequestContext>
    222 ConstructSystemRequestContext(IOThread::Globals* globals,
    223                               net::NetLog* net_log) {
    224   scoped_refptr<net::URLRequestContext> context(
    225       new URLRequestContextWithUserAgent);
    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_dnsrr_resolver(globals->dnsrr_resolver.get());
    230   context->set_http_auth_handler_factory(
    231       globals->http_auth_handler_factory.get());
    232   context->set_proxy_service(globals->system_proxy_service.get());
    233   context->set_http_transaction_factory(
    234       globals->system_http_transaction_factory.get());
    235   context->set_ftp_transaction_factory(
    236       globals->system_ftp_transaction_factory.get());
    237   // In-memory cookie store.
    238   context->set_cookie_store(new net::CookieMonster(NULL, NULL));
    239   return context;
    240 }
    241 
    242 }  // namespace
    243 
    244 class SystemURLRequestContextGetter : public net::URLRequestContextGetter {
    245  public:
    246   explicit SystemURLRequestContextGetter(IOThread* io_thread);
    247   virtual ~SystemURLRequestContextGetter();
    248 
    249   // Implementation for net::UrlRequestContextGetter.
    250   virtual net::URLRequestContext* GetURLRequestContext();
    251   virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const;
    252 
    253  private:
    254   IOThread* const io_thread_;  // Weak pointer, owned by BrowserProcess.
    255   scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
    256 
    257   base::debug::LeakTracker<SystemURLRequestContextGetter> leak_tracker_;
    258 };
    259 
    260 SystemURLRequestContextGetter::SystemURLRequestContextGetter(
    261     IOThread* io_thread)
    262     : io_thread_(io_thread),
    263       io_message_loop_proxy_(io_thread->message_loop_proxy()) {
    264 }
    265 
    266 SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {}
    267 
    268 net::URLRequestContext* SystemURLRequestContextGetter::GetURLRequestContext() {
    269   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    270 
    271   if (!io_thread_->globals()->system_request_context)
    272     io_thread_->InitSystemRequestContext();
    273 
    274   return io_thread_->globals()->system_request_context;
    275 }
    276 
    277 scoped_refptr<base::MessageLoopProxy>
    278 SystemURLRequestContextGetter::GetIOMessageLoopProxy() const {
    279   return io_message_loop_proxy_;
    280 }
    281 
    282 // The IOThread object must outlive any tasks posted to the IO thread before the
    283 // Quit task.
    284 DISABLE_RUNNABLE_METHOD_REFCOUNT(IOThread);
    285 
    286 IOThread::Globals::Globals() {}
    287 
    288 IOThread::Globals::~Globals() {}
    289 
    290 // |local_state| is passed in explicitly in order to (1) reduce implicit
    291 // dependencies and (2) make IOThread more flexible for testing.
    292 IOThread::IOThread(
    293     PrefService* local_state,
    294     ChromeNetLog* net_log,
    295     ExtensionEventRouterForwarder* extension_event_router_forwarder)
    296     : BrowserProcessSubThread(BrowserThread::IO),
    297       net_log_(net_log),
    298       extension_event_router_forwarder_(extension_event_router_forwarder),
    299       globals_(NULL),
    300       speculative_interceptor_(NULL),
    301       predictor_(NULL) {
    302   // We call RegisterPrefs() here (instead of inside browser_prefs.cc) to make
    303   // sure that everything is initialized in the right order.
    304   RegisterPrefs(local_state);
    305   auth_schemes_ = local_state->GetString(prefs::kAuthSchemes);
    306   negotiate_disable_cname_lookup_ = local_state->GetBoolean(
    307       prefs::kDisableAuthNegotiateCnameLookup);
    308   negotiate_enable_port_ = local_state->GetBoolean(
    309       prefs::kEnableAuthNegotiatePort);
    310   auth_server_whitelist_ = local_state->GetString(prefs::kAuthServerWhitelist);
    311   auth_delegate_whitelist_ = local_state->GetString(
    312       prefs::kAuthNegotiateDelegateWhitelist);
    313   gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName);
    314   pref_proxy_config_tracker_ = new PrefProxyConfigTracker(local_state);
    315   ChromeNetworkDelegate::InitializeReferrersEnabled(&system_enable_referrers_,
    316                                                     local_state);
    317 }
    318 
    319 IOThread::~IOThread() {
    320   if (pref_proxy_config_tracker_)
    321     pref_proxy_config_tracker_->DetachFromPrefService();
    322   // We cannot rely on our base class to stop the thread since we want our
    323   // CleanUp function to run.
    324   Stop();
    325   DCHECK(!globals_);
    326 }
    327 
    328 IOThread::Globals* IOThread::globals() {
    329   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    330   return globals_;
    331 }
    332 
    333 ChromeNetLog* IOThread::net_log() {
    334   return net_log_;
    335 }
    336 
    337 void IOThread::InitNetworkPredictor(
    338     bool prefetching_enabled,
    339     base::TimeDelta max_dns_queue_delay,
    340     size_t max_speculative_parallel_resolves,
    341     const chrome_common_net::UrlList& startup_urls,
    342     ListValue* referral_list,
    343     bool preconnect_enabled) {
    344   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    345   message_loop()->PostTask(
    346       FROM_HERE,
    347       NewRunnableMethod(
    348           this,
    349           &IOThread::InitNetworkPredictorOnIOThread,
    350           prefetching_enabled, max_dns_queue_delay,
    351           max_speculative_parallel_resolves,
    352           startup_urls, referral_list, preconnect_enabled));
    353 }
    354 
    355 void IOThread::RegisterURLRequestContextGetter(
    356     ChromeURLRequestContextGetter* url_request_context_getter) {
    357   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    358   std::list<ChromeURLRequestContextGetter*>::const_iterator it =
    359       std::find(url_request_context_getters_.begin(),
    360                 url_request_context_getters_.end(),
    361                 url_request_context_getter);
    362   DCHECK(it == url_request_context_getters_.end());
    363   url_request_context_getters_.push_back(url_request_context_getter);
    364 }
    365 
    366 void IOThread::UnregisterURLRequestContextGetter(
    367     ChromeURLRequestContextGetter* url_request_context_getter) {
    368   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    369   std::list<ChromeURLRequestContextGetter*>::iterator it =
    370       std::find(url_request_context_getters_.begin(),
    371                 url_request_context_getters_.end(),
    372                 url_request_context_getter);
    373   DCHECK(it != url_request_context_getters_.end());
    374   // This does not scale, but we shouldn't have many URLRequestContextGetters in
    375   // the first place, so this should be fine.
    376   url_request_context_getters_.erase(it);
    377 }
    378 
    379 void IOThread::ChangedToOnTheRecord() {
    380   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    381   message_loop()->PostTask(
    382       FROM_HERE,
    383       NewRunnableMethod(
    384           this,
    385           &IOThread::ChangedToOnTheRecordOnIOThread));
    386 }
    387 
    388 net::URLRequestContextGetter* IOThread::system_url_request_context_getter() {
    389   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    390   if (!system_url_request_context_getter_) {
    391     system_proxy_config_service_.reset(
    392         ProxyServiceFactory::CreateProxyConfigService(
    393             pref_proxy_config_tracker_));
    394     system_url_request_context_getter_ =
    395         new SystemURLRequestContextGetter(this);
    396   }
    397   return system_url_request_context_getter_;
    398 }
    399 
    400 void IOThread::ClearNetworkingHistory() {
    401   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    402   ClearHostCache();
    403   // Discard acrued data used to speculate in the future.
    404   chrome_browser_net::DiscardInitialNavigationHistory();
    405   if (predictor_)
    406     predictor_->DiscardAllResults();
    407 }
    408 
    409 void IOThread::Init() {
    410   // Though this thread is called the "IO" thread, it actually just routes
    411   // messages around; it shouldn't be allowed to perform any blocking disk I/O.
    412   base::ThreadRestrictions::SetIOAllowed(false);
    413 
    414   BrowserProcessSubThread::Init();
    415 
    416   DCHECK_EQ(MessageLoop::TYPE_IO, message_loop()->type());
    417 
    418 #if defined(USE_NSS)
    419   net::SetMessageLoopForOCSP();
    420 #endif  // defined(USE_NSS)
    421 
    422   DCHECK(!globals_);
    423   globals_ = new Globals;
    424 
    425   // Add an observer that will emit network change events to the ChromeNetLog.
    426   // Assuming NetworkChangeNotifier dispatches in FIFO order, we should be
    427   // logging the network change before other IO thread consumers respond to it.
    428   network_change_observer_.reset(
    429       new LoggingNetworkChangeObserver(net_log_));
    430 
    431   globals_->extension_event_router_forwarder =
    432       extension_event_router_forwarder_;
    433   globals_->system_network_delegate.reset(new ChromeNetworkDelegate(
    434       extension_event_router_forwarder_,
    435       Profile::kInvalidProfileId,
    436       &system_enable_referrers_,
    437       NULL));
    438   globals_->host_resolver.reset(
    439       CreateGlobalHostResolver(net_log_));
    440   globals_->cert_verifier.reset(new net::CertVerifier);
    441   globals_->dnsrr_resolver.reset(new net::DnsRRResolver);
    442   // TODO(willchan): Use the real SSLConfigService.
    443   globals_->ssl_config_service =
    444       net::SSLConfigService::CreateSystemSSLConfigService();
    445   globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory(
    446       globals_->host_resolver.get()));
    447   // For the ProxyScriptFetcher, we use a direct ProxyService.
    448   globals_->proxy_script_fetcher_proxy_service =
    449       net::ProxyService::CreateDirectWithNetLog(net_log_);
    450   net::HttpNetworkSession::Params session_params;
    451   session_params.host_resolver = globals_->host_resolver.get();
    452   session_params.cert_verifier = globals_->cert_verifier.get();
    453   session_params.proxy_service =
    454       globals_->proxy_script_fetcher_proxy_service.get();
    455   session_params.http_auth_handler_factory =
    456       globals_->http_auth_handler_factory.get();
    457   session_params.network_delegate = globals_->system_network_delegate.get();
    458   session_params.net_log = net_log_;
    459   session_params.ssl_config_service = globals_->ssl_config_service;
    460   scoped_refptr<net::HttpNetworkSession> network_session(
    461       new net::HttpNetworkSession(session_params));
    462   globals_->proxy_script_fetcher_http_transaction_factory.reset(
    463       new net::HttpNetworkLayer(network_session));
    464   globals_->proxy_script_fetcher_ftp_transaction_factory.reset(
    465       new net::FtpNetworkLayer(globals_->host_resolver.get()));
    466 
    467   scoped_refptr<net::URLRequestContext> proxy_script_fetcher_context =
    468       ConstructProxyScriptFetcherContext(globals_, net_log_);
    469   globals_->proxy_script_fetcher_context = proxy_script_fetcher_context;
    470 }
    471 
    472 void IOThread::CleanUp() {
    473   // Step 1: Kill all things that might be holding onto
    474   // net::URLRequest/net::URLRequestContexts.
    475 
    476 #if defined(USE_NSS)
    477   net::ShutdownOCSP();
    478 #endif  // defined(USE_NSS)
    479 
    480   // Destroy all URLRequests started by URLFetchers.
    481   URLFetcher::CancelAll();
    482 
    483   IndexedDBKeyUtilityClient::Shutdown();
    484 
    485   // If any child processes are still running, terminate them and
    486   // and delete the BrowserChildProcessHost instances to release whatever
    487   // IO thread only resources they are referencing.
    488   BrowserChildProcessHost::TerminateAll();
    489 
    490   std::list<ChromeURLRequestContextGetter*> url_request_context_getters;
    491   url_request_context_getters.swap(url_request_context_getters_);
    492   for (std::list<ChromeURLRequestContextGetter*>::iterator it =
    493        url_request_context_getters.begin();
    494        it != url_request_context_getters.end(); ++it) {
    495     ChromeURLRequestContextGetter* getter = *it;
    496     // Stop all pending certificate provenance check uploads
    497     net::DnsCertProvenanceChecker* checker =
    498         getter->GetURLRequestContext()->dns_cert_checker();
    499     if (checker)
    500       checker->Shutdown();
    501     getter->ReleaseURLRequestContext();
    502   }
    503 
    504   system_url_request_context_getter_ = NULL;
    505 
    506   // Step 2: Release objects that the net::URLRequestContext could have been
    507   // pointing to.
    508 
    509   // This must be reset before the ChromeNetLog is destroyed.
    510   network_change_observer_.reset();
    511 
    512   // Not initialized in Init().  May not be initialized.
    513   if (predictor_) {
    514     predictor_->Shutdown();
    515 
    516     // TODO(willchan): Stop reference counting Predictor.  It's owned by
    517     // IOThread now.
    518     predictor_->Release();
    519     predictor_ = NULL;
    520     chrome_browser_net::FreePredictorResources();
    521   }
    522 
    523   // Deletion will unregister this interceptor.
    524   delete speculative_interceptor_;
    525   speculative_interceptor_ = NULL;
    526 
    527   // TODO(eroman): hack for http://crbug.com/15513
    528   if (globals_->host_resolver->GetAsHostResolverImpl()) {
    529     globals_->host_resolver.get()->GetAsHostResolverImpl()->Shutdown();
    530   }
    531 
    532   system_proxy_config_service_.reset();
    533 
    534   delete globals_;
    535   globals_ = NULL;
    536 
    537   // net::URLRequest instances must NOT outlive the IO thread.
    538   base::debug::LeakTracker<net::URLRequest>::CheckForLeaks();
    539 
    540   base::debug::LeakTracker<SystemURLRequestContextGetter>::CheckForLeaks();
    541 
    542   // This will delete the |notification_service_|.  Make sure it's done after
    543   // anything else can reference it.
    544   BrowserProcessSubThread::CleanUp();
    545 }
    546 
    547 // static
    548 void IOThread::RegisterPrefs(PrefService* local_state) {
    549   local_state->RegisterStringPref(prefs::kAuthSchemes,
    550                                   "basic,digest,ntlm,negotiate");
    551   local_state->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup,
    552                                    false);
    553   local_state->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort, false);
    554   local_state->RegisterStringPref(prefs::kAuthServerWhitelist, "");
    555   local_state->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist, "");
    556   local_state->RegisterStringPref(prefs::kGSSAPILibraryName, "");
    557   local_state->RegisterBooleanPref(prefs::kEnableReferrers, true);
    558 }
    559 
    560 net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory(
    561     net::HostResolver* resolver) {
    562   net::HttpAuthFilterWhitelist* auth_filter_default_credentials = NULL;
    563   if (!auth_server_whitelist_.empty()) {
    564     auth_filter_default_credentials =
    565         new net::HttpAuthFilterWhitelist(auth_server_whitelist_);
    566   }
    567   net::HttpAuthFilterWhitelist* auth_filter_delegate = NULL;
    568   if (!auth_delegate_whitelist_.empty()) {
    569     auth_filter_delegate =
    570         new net::HttpAuthFilterWhitelist(auth_delegate_whitelist_);
    571   }
    572   globals_->url_security_manager.reset(
    573       net::URLSecurityManager::Create(auth_filter_default_credentials,
    574                                       auth_filter_delegate));
    575   std::vector<std::string> supported_schemes;
    576   base::SplitString(auth_schemes_, ',', &supported_schemes);
    577 
    578   return net::HttpAuthHandlerRegistryFactory::Create(
    579       supported_schemes,
    580       globals_->url_security_manager.get(),
    581       resolver,
    582       gssapi_library_name_,
    583       negotiate_disable_cname_lookup_,
    584       negotiate_enable_port_);
    585 }
    586 
    587 void IOThread::InitNetworkPredictorOnIOThread(
    588     bool prefetching_enabled,
    589     base::TimeDelta max_dns_queue_delay,
    590     size_t max_speculative_parallel_resolves,
    591     const chrome_common_net::UrlList& startup_urls,
    592     ListValue* referral_list,
    593     bool preconnect_enabled) {
    594   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    595   CHECK(!predictor_);
    596 
    597   chrome_browser_net::EnablePredictor(prefetching_enabled);
    598 
    599   predictor_ = new chrome_browser_net::Predictor(
    600       globals_->host_resolver.get(),
    601       max_dns_queue_delay,
    602       max_speculative_parallel_resolves,
    603       preconnect_enabled);
    604   predictor_->AddRef();
    605 
    606   // Speculative_interceptor_ is used to predict subresource usage.
    607   DCHECK(!speculative_interceptor_);
    608   speculative_interceptor_ = new chrome_browser_net::ConnectInterceptor;
    609 
    610   FinalizePredictorInitialization(predictor_, startup_urls, referral_list);
    611 }
    612 
    613 void IOThread::ChangedToOnTheRecordOnIOThread() {
    614   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    615 
    616   if (predictor_) {
    617     // Destroy all evidence of our OTR session.
    618     // Note: OTR mode never saves InitialNavigationHistory data.
    619     predictor_->Predictor::DiscardAllResults();
    620   }
    621 
    622   // Clear the host cache to avoid showing entries from the OTR session
    623   // in about:net-internals.
    624   ClearHostCache();
    625 
    626   // Clear all of the passively logged data.
    627   // TODO(eroman): this is a bit heavy handed, really all we need to do is
    628   //               clear the data pertaining to incognito context.
    629   net_log_->ClearAllPassivelyCapturedEvents();
    630 }
    631 
    632 void IOThread::ClearHostCache() {
    633   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    634 
    635   if (globals_->host_resolver->GetAsHostResolverImpl()) {
    636     net::HostCache* host_cache =
    637         globals_->host_resolver.get()->GetAsHostResolverImpl()->cache();
    638     if (host_cache)
    639       host_cache->clear();
    640   }
    641 }
    642 
    643 void IOThread::InitSystemRequestContext() {
    644   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    645   DCHECK(!globals_->system_proxy_service);
    646   DCHECK(system_proxy_config_service_.get());
    647 
    648   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    649   globals_->system_proxy_service =
    650       ProxyServiceFactory::CreateProxyService(
    651           net_log_,
    652           globals_->proxy_script_fetcher_context,
    653           system_proxy_config_service_.release(),
    654           command_line);
    655   net::HttpNetworkSession::Params system_params;
    656   system_params.host_resolver = globals_->host_resolver.get();
    657   system_params.cert_verifier = globals_->cert_verifier.get();
    658   system_params.dnsrr_resolver = globals_->dnsrr_resolver.get();
    659   system_params.dns_cert_checker = NULL;
    660   system_params.ssl_host_info_factory = NULL;
    661   system_params.proxy_service = globals_->system_proxy_service.get();
    662   system_params.ssl_config_service = globals_->ssl_config_service.get();
    663   system_params.http_auth_handler_factory =
    664       globals_->http_auth_handler_factory.get();
    665   system_params.network_delegate = globals_->system_network_delegate.get();
    666   system_params.net_log = net_log_;
    667   globals_->system_http_transaction_factory.reset(
    668       new net::HttpNetworkLayer(
    669           new net::HttpNetworkSession(system_params)));
    670   globals_->system_ftp_transaction_factory.reset(
    671       new net::FtpNetworkLayer(globals_->host_resolver.get()));
    672   globals_->system_request_context =
    673       ConstructSystemRequestContext(globals_, net_log_);
    674 }
    675