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
56namespace {
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.
61class 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
69net::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
171class 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
199scoped_refptr<net::URLRequestContext>
200ConstructProxyScriptFetcherContext(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
221scoped_refptr<net::URLRequestContext>
222ConstructSystemRequestContext(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
244class 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
260SystemURLRequestContextGetter::SystemURLRequestContextGetter(
261    IOThread* io_thread)
262    : io_thread_(io_thread),
263      io_message_loop_proxy_(io_thread->message_loop_proxy()) {
264}
265
266SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {}
267
268net::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
277scoped_refptr<base::MessageLoopProxy>
278SystemURLRequestContextGetter::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.
284DISABLE_RUNNABLE_METHOD_REFCOUNT(IOThread);
285
286IOThread::Globals::Globals() {}
287
288IOThread::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.
292IOThread::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
319IOThread::~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
328IOThread::Globals* IOThread::globals() {
329  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
330  return globals_;
331}
332
333ChromeNetLog* IOThread::net_log() {
334  return net_log_;
335}
336
337void 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
355void 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
366void 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
379void IOThread::ChangedToOnTheRecord() {
380  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
381  message_loop()->PostTask(
382      FROM_HERE,
383      NewRunnableMethod(
384          this,
385          &IOThread::ChangedToOnTheRecordOnIOThread));
386}
387
388net::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
400void 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
409void 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
472void 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
548void 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
560net::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
587void 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
613void 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
632void 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
643void 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