• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
GetUserAgent(const GURL & url) const63   virtual const std::string& GetUserAgent(
64       const GURL& url) const OVERRIDE {
65     return webkit_glue::GetUserAgent(url);
66   }
67 };
68 
CreateGlobalHostResolver(net::NetLog * net_log)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.
LoggingNetworkChangeObserver(net::NetLog * net_log)175   explicit LoggingNetworkChangeObserver(net::NetLog* net_log)
176       : net_log_(net_log) {
177     net::NetworkChangeNotifier::AddIPAddressObserver(this);
178   }
179 
~LoggingNetworkChangeObserver()180   ~LoggingNetworkChangeObserver() {
181     net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
182   }
183 
OnIPAddressChanged()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>
ConstructProxyScriptFetcherContext(IOThread::Globals * globals,net::NetLog * net_log)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>
ConstructSystemRequestContext(IOThread::Globals * globals,net::NetLog * net_log)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 
SystemURLRequestContextGetter(IOThread * io_thread)260 SystemURLRequestContextGetter::SystemURLRequestContextGetter(
261     IOThread* io_thread)
262     : io_thread_(io_thread),
263       io_message_loop_proxy_(io_thread->message_loop_proxy()) {
264 }
265 
~SystemURLRequestContextGetter()266 SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {}
267 
GetURLRequestContext()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>
GetIOMessageLoopProxy() const278 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 
Globals()286 IOThread::Globals::Globals() {}
287 
~Globals()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.
IOThread(PrefService * local_state,ChromeNetLog * net_log,ExtensionEventRouterForwarder * extension_event_router_forwarder)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 
~IOThread()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 
globals()328 IOThread::Globals* IOThread::globals() {
329   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
330   return globals_;
331 }
332 
net_log()333 ChromeNetLog* IOThread::net_log() {
334   return net_log_;
335 }
336 
InitNetworkPredictor(bool prefetching_enabled,base::TimeDelta max_dns_queue_delay,size_t max_speculative_parallel_resolves,const chrome_common_net::UrlList & startup_urls,ListValue * referral_list,bool preconnect_enabled)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 
RegisterURLRequestContextGetter(ChromeURLRequestContextGetter * url_request_context_getter)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 
UnregisterURLRequestContextGetter(ChromeURLRequestContextGetter * url_request_context_getter)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 
ChangedToOnTheRecord()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 
system_url_request_context_getter()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 
ClearNetworkingHistory()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 
Init()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 
CleanUp()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
RegisterPrefs(PrefService * local_state)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 
CreateDefaultAuthHandlerFactory(net::HostResolver * resolver)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 
InitNetworkPredictorOnIOThread(bool prefetching_enabled,base::TimeDelta max_dns_queue_delay,size_t max_speculative_parallel_resolves,const chrome_common_net::UrlList & startup_urls,ListValue * referral_list,bool preconnect_enabled)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 
ChangedToOnTheRecordOnIOThread()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 
ClearHostCache()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 
InitSystemRequestContext()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