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