| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/io_thread.h" |
| |
| #include <vector> |
| |
| #include "base/command_line.h" |
| #include "base/debug/leak_tracker.h" |
| #include "base/logging.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/stl_util-inl.h" |
| #include "base/string_number_conversions.h" |
| #include "base/string_split.h" |
| #include "base/string_util.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/extensions/extension_event_router_forwarder.h" |
| #include "chrome/browser/net/chrome_network_delegate.h" |
| #include "chrome/browser/net/chrome_net_log.h" |
| #include "chrome/browser/net/chrome_url_request_context.h" |
| #include "chrome/browser/net/connect_interceptor.h" |
| #include "chrome/browser/net/passive_log_collector.h" |
| #include "chrome/browser/net/predictor_api.h" |
| #include "chrome/browser/net/pref_proxy_config_service.h" |
| #include "chrome/browser/net/proxy_service_factory.h" |
| #include "chrome/browser/prefs/pref_service.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/net/raw_host_resolver_proc.h" |
| #include "chrome/common/net/url_fetcher.h" |
| #include "chrome/common/pref_names.h" |
| #include "content/browser/browser_thread.h" |
| #include "content/browser/gpu_process_host.h" |
| #include "content/browser/in_process_webkit/indexed_db_key_utility_client.h" |
| #include "net/base/cert_verifier.h" |
| #include "net/base/cookie_monster.h" |
| #include "net/base/dnsrr_resolver.h" |
| #include "net/base/host_cache.h" |
| #include "net/base/host_resolver.h" |
| #include "net/base/host_resolver_impl.h" |
| #include "net/base/mapped_host_resolver.h" |
| #include "net/base/net_util.h" |
| #include "net/proxy/proxy_config_service.h" |
| #include "net/ftp/ftp_network_layer.h" |
| #include "net/http/http_auth_filter.h" |
| #include "net/http/http_auth_handler_factory.h" |
| #include "net/http/http_network_layer.h" |
| #include "net/http/http_network_session.h" |
| #if defined(USE_NSS) |
| #include "net/ocsp/nss_ocsp.h" |
| #endif // defined(USE_NSS) |
| #include "net/proxy/proxy_script_fetcher_impl.h" |
| #include "webkit/glue/webkit_glue.h" |
| |
| namespace { |
| |
| // Custom URLRequestContext used by requests which aren't associated with a |
| // particular profile. We need to use a subclass of URLRequestContext in order |
| // to provide the correct User-Agent. |
| class URLRequestContextWithUserAgent : public net::URLRequestContext { |
| public: |
| virtual const std::string& GetUserAgent( |
| const GURL& url) const OVERRIDE { |
| return webkit_glue::GetUserAgent(url); |
| } |
| }; |
| |
| net::HostResolver* CreateGlobalHostResolver(net::NetLog* net_log) { |
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| |
| size_t parallelism = net::HostResolver::kDefaultParallelism; |
| |
| // Use the concurrency override from the command-line, if any. |
| if (command_line.HasSwitch(switches::kHostResolverParallelism)) { |
| std::string s = |
| command_line.GetSwitchValueASCII(switches::kHostResolverParallelism); |
| |
| // Parse the switch (it should be a positive integer formatted as decimal). |
| int n; |
| if (base::StringToInt(s, &n) && n > 0) { |
| parallelism = static_cast<size_t>(n); |
| } else { |
| LOG(ERROR) << "Invalid switch for host resolver parallelism: " << s; |
| } |
| } else { |
| // Set up a field trial to see what impact the total number of concurrent |
| // resolutions have on DNS resolutions. |
| base::FieldTrial::Probability kDivisor = 1000; |
| // For each option (i.e., non-default), we have a fixed probability. |
| base::FieldTrial::Probability kProbabilityPerGroup = 100; // 10%. |
| |
| // After June 30, 2011 builds, it will always be in default group |
| // (parallel_default). |
| scoped_refptr<base::FieldTrial> trial( |
| new base::FieldTrial( |
| "DnsParallelism", kDivisor, "parallel_default", 2011, 6, 30)); |
| |
| // List options with different counts. |
| // Firefox limits total to 8 in parallel, and default is currently 50. |
| int parallel_6 = trial->AppendGroup("parallel_6", kProbabilityPerGroup); |
| int parallel_7 = trial->AppendGroup("parallel_7", kProbabilityPerGroup); |
| int parallel_8 = trial->AppendGroup("parallel_8", kProbabilityPerGroup); |
| int parallel_9 = trial->AppendGroup("parallel_9", kProbabilityPerGroup); |
| int parallel_10 = trial->AppendGroup("parallel_10", kProbabilityPerGroup); |
| int parallel_14 = trial->AppendGroup("parallel_14", kProbabilityPerGroup); |
| int parallel_20 = trial->AppendGroup("parallel_20", kProbabilityPerGroup); |
| |
| if (trial->group() == parallel_6) |
| parallelism = 6; |
| else if (trial->group() == parallel_7) |
| parallelism = 7; |
| else if (trial->group() == parallel_8) |
| parallelism = 8; |
| else if (trial->group() == parallel_9) |
| parallelism = 9; |
| else if (trial->group() == parallel_10) |
| parallelism = 10; |
| else if (trial->group() == parallel_14) |
| parallelism = 14; |
| else if (trial->group() == parallel_20) |
| parallelism = 20; |
| } |
| |
| // Use the specified DNS server for doing raw resolutions if requested |
| // from the command-line. |
| scoped_refptr<net::HostResolverProc> resolver_proc; |
| if (command_line.HasSwitch(switches::kDnsServer)) { |
| std::string dns_ip_string = |
| command_line.GetSwitchValueASCII(switches::kDnsServer); |
| net::IPAddressNumber dns_ip_number; |
| if (net::ParseIPLiteralToNumber(dns_ip_string, &dns_ip_number)) { |
| resolver_proc = |
| new chrome_common_net::RawHostResolverProc(dns_ip_number, NULL); |
| } else { |
| LOG(ERROR) << "Invalid IP address specified for --dns-server: " |
| << dns_ip_string; |
| } |
| } |
| |
| net::HostResolver* global_host_resolver = |
| net::CreateSystemHostResolver(parallelism, resolver_proc.get(), net_log); |
| |
| // Determine if we should disable IPv6 support. |
| if (!command_line.HasSwitch(switches::kEnableIPv6)) { |
| if (command_line.HasSwitch(switches::kDisableIPv6)) { |
| global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4); |
| } else { |
| net::HostResolverImpl* host_resolver_impl = |
| global_host_resolver->GetAsHostResolverImpl(); |
| if (host_resolver_impl != NULL) { |
| // Use probe to decide if support is warranted. |
| host_resolver_impl->ProbeIPv6Support(); |
| } |
| } |
| } |
| |
| // If hostname remappings were specified on the command-line, layer these |
| // rules on top of the real host resolver. This allows forwarding all requests |
| // through a designated test server. |
| if (!command_line.HasSwitch(switches::kHostResolverRules)) |
| return global_host_resolver; |
| |
| net::MappedHostResolver* remapped_resolver = |
| new net::MappedHostResolver(global_host_resolver); |
| remapped_resolver->SetRulesFromString( |
| command_line.GetSwitchValueASCII(switches::kHostResolverRules)); |
| return remapped_resolver; |
| } |
| |
| class LoggingNetworkChangeObserver |
| : public net::NetworkChangeNotifier::IPAddressObserver { |
| public: |
| // |net_log| must remain valid throughout our lifetime. |
| explicit LoggingNetworkChangeObserver(net::NetLog* net_log) |
| : net_log_(net_log) { |
| net::NetworkChangeNotifier::AddIPAddressObserver(this); |
| } |
| |
| ~LoggingNetworkChangeObserver() { |
| net::NetworkChangeNotifier::RemoveIPAddressObserver(this); |
| } |
| |
| virtual void OnIPAddressChanged() { |
| VLOG(1) << "Observed a change to the network IP addresses"; |
| |
| net_log_->AddEntry(net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED, |
| base::TimeTicks::Now(), |
| net::NetLog::Source(), |
| net::NetLog::PHASE_NONE, |
| NULL); |
| } |
| |
| private: |
| net::NetLog* net_log_; |
| DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver); |
| }; |
| |
| scoped_refptr<net::URLRequestContext> |
| ConstructProxyScriptFetcherContext(IOThread::Globals* globals, |
| net::NetLog* net_log) { |
| scoped_refptr<net::URLRequestContext> context( |
| new URLRequestContextWithUserAgent); |
| context->set_net_log(net_log); |
| context->set_host_resolver(globals->host_resolver.get()); |
| context->set_cert_verifier(globals->cert_verifier.get()); |
| context->set_dnsrr_resolver(globals->dnsrr_resolver.get()); |
| context->set_http_auth_handler_factory( |
| globals->http_auth_handler_factory.get()); |
| context->set_proxy_service(globals->proxy_script_fetcher_proxy_service.get()); |
| context->set_http_transaction_factory( |
| globals->proxy_script_fetcher_http_transaction_factory.get()); |
| context->set_ftp_transaction_factory( |
| globals->proxy_script_fetcher_ftp_transaction_factory.get()); |
| // In-memory cookie store. |
| context->set_cookie_store(new net::CookieMonster(NULL, NULL)); |
| context->set_network_delegate(globals->system_network_delegate.get()); |
| return context; |
| } |
| |
| scoped_refptr<net::URLRequestContext> |
| ConstructSystemRequestContext(IOThread::Globals* globals, |
| net::NetLog* net_log) { |
| scoped_refptr<net::URLRequestContext> context( |
| new URLRequestContextWithUserAgent); |
| context->set_net_log(net_log); |
| context->set_host_resolver(globals->host_resolver.get()); |
| context->set_cert_verifier(globals->cert_verifier.get()); |
| context->set_dnsrr_resolver(globals->dnsrr_resolver.get()); |
| context->set_http_auth_handler_factory( |
| globals->http_auth_handler_factory.get()); |
| context->set_proxy_service(globals->system_proxy_service.get()); |
| context->set_http_transaction_factory( |
| globals->system_http_transaction_factory.get()); |
| context->set_ftp_transaction_factory( |
| globals->system_ftp_transaction_factory.get()); |
| // In-memory cookie store. |
| context->set_cookie_store(new net::CookieMonster(NULL, NULL)); |
| return context; |
| } |
| |
| } // namespace |
| |
| class SystemURLRequestContextGetter : public net::URLRequestContextGetter { |
| public: |
| explicit SystemURLRequestContextGetter(IOThread* io_thread); |
| virtual ~SystemURLRequestContextGetter(); |
| |
| // Implementation for net::UrlRequestContextGetter. |
| virtual net::URLRequestContext* GetURLRequestContext(); |
| virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const; |
| |
| private: |
| IOThread* const io_thread_; // Weak pointer, owned by BrowserProcess. |
| scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; |
| |
| base::debug::LeakTracker<SystemURLRequestContextGetter> leak_tracker_; |
| }; |
| |
| SystemURLRequestContextGetter::SystemURLRequestContextGetter( |
| IOThread* io_thread) |
| : io_thread_(io_thread), |
| io_message_loop_proxy_(io_thread->message_loop_proxy()) { |
| } |
| |
| SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {} |
| |
| net::URLRequestContext* SystemURLRequestContextGetter::GetURLRequestContext() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| if (!io_thread_->globals()->system_request_context) |
| io_thread_->InitSystemRequestContext(); |
| |
| return io_thread_->globals()->system_request_context; |
| } |
| |
| scoped_refptr<base::MessageLoopProxy> |
| SystemURLRequestContextGetter::GetIOMessageLoopProxy() const { |
| return io_message_loop_proxy_; |
| } |
| |
| // The IOThread object must outlive any tasks posted to the IO thread before the |
| // Quit task. |
| DISABLE_RUNNABLE_METHOD_REFCOUNT(IOThread); |
| |
| IOThread::Globals::Globals() {} |
| |
| IOThread::Globals::~Globals() {} |
| |
| // |local_state| is passed in explicitly in order to (1) reduce implicit |
| // dependencies and (2) make IOThread more flexible for testing. |
| IOThread::IOThread( |
| PrefService* local_state, |
| ChromeNetLog* net_log, |
| ExtensionEventRouterForwarder* extension_event_router_forwarder) |
| : BrowserProcessSubThread(BrowserThread::IO), |
| net_log_(net_log), |
| extension_event_router_forwarder_(extension_event_router_forwarder), |
| globals_(NULL), |
| speculative_interceptor_(NULL), |
| predictor_(NULL) { |
| // We call RegisterPrefs() here (instead of inside browser_prefs.cc) to make |
| // sure that everything is initialized in the right order. |
| RegisterPrefs(local_state); |
| auth_schemes_ = local_state->GetString(prefs::kAuthSchemes); |
| negotiate_disable_cname_lookup_ = local_state->GetBoolean( |
| prefs::kDisableAuthNegotiateCnameLookup); |
| negotiate_enable_port_ = local_state->GetBoolean( |
| prefs::kEnableAuthNegotiatePort); |
| auth_server_whitelist_ = local_state->GetString(prefs::kAuthServerWhitelist); |
| auth_delegate_whitelist_ = local_state->GetString( |
| prefs::kAuthNegotiateDelegateWhitelist); |
| gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName); |
| pref_proxy_config_tracker_ = new PrefProxyConfigTracker(local_state); |
| ChromeNetworkDelegate::InitializeReferrersEnabled(&system_enable_referrers_, |
| local_state); |
| } |
| |
| IOThread::~IOThread() { |
| if (pref_proxy_config_tracker_) |
| pref_proxy_config_tracker_->DetachFromPrefService(); |
| // We cannot rely on our base class to stop the thread since we want our |
| // CleanUp function to run. |
| Stop(); |
| DCHECK(!globals_); |
| } |
| |
| IOThread::Globals* IOThread::globals() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| return globals_; |
| } |
| |
| ChromeNetLog* IOThread::net_log() { |
| return net_log_; |
| } |
| |
| void IOThread::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) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| message_loop()->PostTask( |
| FROM_HERE, |
| NewRunnableMethod( |
| this, |
| &IOThread::InitNetworkPredictorOnIOThread, |
| prefetching_enabled, max_dns_queue_delay, |
| max_speculative_parallel_resolves, |
| startup_urls, referral_list, preconnect_enabled)); |
| } |
| |
| void IOThread::RegisterURLRequestContextGetter( |
| ChromeURLRequestContextGetter* url_request_context_getter) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| std::list<ChromeURLRequestContextGetter*>::const_iterator it = |
| std::find(url_request_context_getters_.begin(), |
| url_request_context_getters_.end(), |
| url_request_context_getter); |
| DCHECK(it == url_request_context_getters_.end()); |
| url_request_context_getters_.push_back(url_request_context_getter); |
| } |
| |
| void IOThread::UnregisterURLRequestContextGetter( |
| ChromeURLRequestContextGetter* url_request_context_getter) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| std::list<ChromeURLRequestContextGetter*>::iterator it = |
| std::find(url_request_context_getters_.begin(), |
| url_request_context_getters_.end(), |
| url_request_context_getter); |
| DCHECK(it != url_request_context_getters_.end()); |
| // This does not scale, but we shouldn't have many URLRequestContextGetters in |
| // the first place, so this should be fine. |
| url_request_context_getters_.erase(it); |
| } |
| |
| void IOThread::ChangedToOnTheRecord() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| message_loop()->PostTask( |
| FROM_HERE, |
| NewRunnableMethod( |
| this, |
| &IOThread::ChangedToOnTheRecordOnIOThread)); |
| } |
| |
| net::URLRequestContextGetter* IOThread::system_url_request_context_getter() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| if (!system_url_request_context_getter_) { |
| system_proxy_config_service_.reset( |
| ProxyServiceFactory::CreateProxyConfigService( |
| pref_proxy_config_tracker_)); |
| system_url_request_context_getter_ = |
| new SystemURLRequestContextGetter(this); |
| } |
| return system_url_request_context_getter_; |
| } |
| |
| void IOThread::ClearNetworkingHistory() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| ClearHostCache(); |
| // Discard acrued data used to speculate in the future. |
| chrome_browser_net::DiscardInitialNavigationHistory(); |
| if (predictor_) |
| predictor_->DiscardAllResults(); |
| } |
| |
| void IOThread::Init() { |
| // Though this thread is called the "IO" thread, it actually just routes |
| // messages around; it shouldn't be allowed to perform any blocking disk I/O. |
| base::ThreadRestrictions::SetIOAllowed(false); |
| |
| BrowserProcessSubThread::Init(); |
| |
| DCHECK_EQ(MessageLoop::TYPE_IO, message_loop()->type()); |
| |
| #if defined(USE_NSS) |
| net::SetMessageLoopForOCSP(); |
| #endif // defined(USE_NSS) |
| |
| DCHECK(!globals_); |
| globals_ = new Globals; |
| |
| // Add an observer that will emit network change events to the ChromeNetLog. |
| // Assuming NetworkChangeNotifier dispatches in FIFO order, we should be |
| // logging the network change before other IO thread consumers respond to it. |
| network_change_observer_.reset( |
| new LoggingNetworkChangeObserver(net_log_)); |
| |
| globals_->extension_event_router_forwarder = |
| extension_event_router_forwarder_; |
| globals_->system_network_delegate.reset(new ChromeNetworkDelegate( |
| extension_event_router_forwarder_, |
| Profile::kInvalidProfileId, |
| &system_enable_referrers_, |
| NULL)); |
| globals_->host_resolver.reset( |
| CreateGlobalHostResolver(net_log_)); |
| globals_->cert_verifier.reset(new net::CertVerifier); |
| globals_->dnsrr_resolver.reset(new net::DnsRRResolver); |
| // TODO(willchan): Use the real SSLConfigService. |
| globals_->ssl_config_service = |
| net::SSLConfigService::CreateSystemSSLConfigService(); |
| globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory( |
| globals_->host_resolver.get())); |
| // For the ProxyScriptFetcher, we use a direct ProxyService. |
| globals_->proxy_script_fetcher_proxy_service = |
| net::ProxyService::CreateDirectWithNetLog(net_log_); |
| net::HttpNetworkSession::Params session_params; |
| session_params.host_resolver = globals_->host_resolver.get(); |
| session_params.cert_verifier = globals_->cert_verifier.get(); |
| session_params.proxy_service = |
| globals_->proxy_script_fetcher_proxy_service.get(); |
| session_params.http_auth_handler_factory = |
| globals_->http_auth_handler_factory.get(); |
| session_params.network_delegate = globals_->system_network_delegate.get(); |
| session_params.net_log = net_log_; |
| session_params.ssl_config_service = globals_->ssl_config_service; |
| scoped_refptr<net::HttpNetworkSession> network_session( |
| new net::HttpNetworkSession(session_params)); |
| globals_->proxy_script_fetcher_http_transaction_factory.reset( |
| new net::HttpNetworkLayer(network_session)); |
| globals_->proxy_script_fetcher_ftp_transaction_factory.reset( |
| new net::FtpNetworkLayer(globals_->host_resolver.get())); |
| |
| scoped_refptr<net::URLRequestContext> proxy_script_fetcher_context = |
| ConstructProxyScriptFetcherContext(globals_, net_log_); |
| globals_->proxy_script_fetcher_context = proxy_script_fetcher_context; |
| } |
| |
| void IOThread::CleanUp() { |
| // Step 1: Kill all things that might be holding onto |
| // net::URLRequest/net::URLRequestContexts. |
| |
| #if defined(USE_NSS) |
| net::ShutdownOCSP(); |
| #endif // defined(USE_NSS) |
| |
| // Destroy all URLRequests started by URLFetchers. |
| URLFetcher::CancelAll(); |
| |
| IndexedDBKeyUtilityClient::Shutdown(); |
| |
| // If any child processes are still running, terminate them and |
| // and delete the BrowserChildProcessHost instances to release whatever |
| // IO thread only resources they are referencing. |
| BrowserChildProcessHost::TerminateAll(); |
| |
| std::list<ChromeURLRequestContextGetter*> url_request_context_getters; |
| url_request_context_getters.swap(url_request_context_getters_); |
| for (std::list<ChromeURLRequestContextGetter*>::iterator it = |
| url_request_context_getters.begin(); |
| it != url_request_context_getters.end(); ++it) { |
| ChromeURLRequestContextGetter* getter = *it; |
| // Stop all pending certificate provenance check uploads |
| net::DnsCertProvenanceChecker* checker = |
| getter->GetURLRequestContext()->dns_cert_checker(); |
| if (checker) |
| checker->Shutdown(); |
| getter->ReleaseURLRequestContext(); |
| } |
| |
| system_url_request_context_getter_ = NULL; |
| |
| // Step 2: Release objects that the net::URLRequestContext could have been |
| // pointing to. |
| |
| // This must be reset before the ChromeNetLog is destroyed. |
| network_change_observer_.reset(); |
| |
| // Not initialized in Init(). May not be initialized. |
| if (predictor_) { |
| predictor_->Shutdown(); |
| |
| // TODO(willchan): Stop reference counting Predictor. It's owned by |
| // IOThread now. |
| predictor_->Release(); |
| predictor_ = NULL; |
| chrome_browser_net::FreePredictorResources(); |
| } |
| |
| // Deletion will unregister this interceptor. |
| delete speculative_interceptor_; |
| speculative_interceptor_ = NULL; |
| |
| // TODO(eroman): hack for http://crbug.com/15513 |
| if (globals_->host_resolver->GetAsHostResolverImpl()) { |
| globals_->host_resolver.get()->GetAsHostResolverImpl()->Shutdown(); |
| } |
| |
| system_proxy_config_service_.reset(); |
| |
| delete globals_; |
| globals_ = NULL; |
| |
| // net::URLRequest instances must NOT outlive the IO thread. |
| base::debug::LeakTracker<net::URLRequest>::CheckForLeaks(); |
| |
| base::debug::LeakTracker<SystemURLRequestContextGetter>::CheckForLeaks(); |
| |
| // This will delete the |notification_service_|. Make sure it's done after |
| // anything else can reference it. |
| BrowserProcessSubThread::CleanUp(); |
| } |
| |
| // static |
| void IOThread::RegisterPrefs(PrefService* local_state) { |
| local_state->RegisterStringPref(prefs::kAuthSchemes, |
| "basic,digest,ntlm,negotiate"); |
| local_state->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup, |
| false); |
| local_state->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort, false); |
| local_state->RegisterStringPref(prefs::kAuthServerWhitelist, ""); |
| local_state->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist, ""); |
| local_state->RegisterStringPref(prefs::kGSSAPILibraryName, ""); |
| local_state->RegisterBooleanPref(prefs::kEnableReferrers, true); |
| } |
| |
| net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory( |
| net::HostResolver* resolver) { |
| net::HttpAuthFilterWhitelist* auth_filter_default_credentials = NULL; |
| if (!auth_server_whitelist_.empty()) { |
| auth_filter_default_credentials = |
| new net::HttpAuthFilterWhitelist(auth_server_whitelist_); |
| } |
| net::HttpAuthFilterWhitelist* auth_filter_delegate = NULL; |
| if (!auth_delegate_whitelist_.empty()) { |
| auth_filter_delegate = |
| new net::HttpAuthFilterWhitelist(auth_delegate_whitelist_); |
| } |
| globals_->url_security_manager.reset( |
| net::URLSecurityManager::Create(auth_filter_default_credentials, |
| auth_filter_delegate)); |
| std::vector<std::string> supported_schemes; |
| base::SplitString(auth_schemes_, ',', &supported_schemes); |
| |
| return net::HttpAuthHandlerRegistryFactory::Create( |
| supported_schemes, |
| globals_->url_security_manager.get(), |
| resolver, |
| gssapi_library_name_, |
| negotiate_disable_cname_lookup_, |
| negotiate_enable_port_); |
| } |
| |
| void IOThread::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) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| CHECK(!predictor_); |
| |
| chrome_browser_net::EnablePredictor(prefetching_enabled); |
| |
| predictor_ = new chrome_browser_net::Predictor( |
| globals_->host_resolver.get(), |
| max_dns_queue_delay, |
| max_speculative_parallel_resolves, |
| preconnect_enabled); |
| predictor_->AddRef(); |
| |
| // Speculative_interceptor_ is used to predict subresource usage. |
| DCHECK(!speculative_interceptor_); |
| speculative_interceptor_ = new chrome_browser_net::ConnectInterceptor; |
| |
| FinalizePredictorInitialization(predictor_, startup_urls, referral_list); |
| } |
| |
| void IOThread::ChangedToOnTheRecordOnIOThread() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| if (predictor_) { |
| // Destroy all evidence of our OTR session. |
| // Note: OTR mode never saves InitialNavigationHistory data. |
| predictor_->Predictor::DiscardAllResults(); |
| } |
| |
| // Clear the host cache to avoid showing entries from the OTR session |
| // in about:net-internals. |
| ClearHostCache(); |
| |
| // Clear all of the passively logged data. |
| // TODO(eroman): this is a bit heavy handed, really all we need to do is |
| // clear the data pertaining to incognito context. |
| net_log_->ClearAllPassivelyCapturedEvents(); |
| } |
| |
| void IOThread::ClearHostCache() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| if (globals_->host_resolver->GetAsHostResolverImpl()) { |
| net::HostCache* host_cache = |
| globals_->host_resolver.get()->GetAsHostResolverImpl()->cache(); |
| if (host_cache) |
| host_cache->clear(); |
| } |
| } |
| |
| void IOThread::InitSystemRequestContext() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| DCHECK(!globals_->system_proxy_service); |
| DCHECK(system_proxy_config_service_.get()); |
| |
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| globals_->system_proxy_service = |
| ProxyServiceFactory::CreateProxyService( |
| net_log_, |
| globals_->proxy_script_fetcher_context, |
| system_proxy_config_service_.release(), |
| command_line); |
| net::HttpNetworkSession::Params system_params; |
| system_params.host_resolver = globals_->host_resolver.get(); |
| system_params.cert_verifier = globals_->cert_verifier.get(); |
| system_params.dnsrr_resolver = globals_->dnsrr_resolver.get(); |
| system_params.dns_cert_checker = NULL; |
| system_params.ssl_host_info_factory = NULL; |
| system_params.proxy_service = globals_->system_proxy_service.get(); |
| system_params.ssl_config_service = globals_->ssl_config_service.get(); |
| system_params.http_auth_handler_factory = |
| globals_->http_auth_handler_factory.get(); |
| system_params.network_delegate = globals_->system_network_delegate.get(); |
| system_params.net_log = net_log_; |
| globals_->system_http_transaction_factory.reset( |
| new net::HttpNetworkLayer( |
| new net::HttpNetworkSession(system_params))); |
| globals_->system_ftp_transaction_factory.reset( |
| new net::FtpNetworkLayer(globals_->host_resolver.get())); |
| globals_->system_request_context = |
| ConstructSystemRequestContext(globals_, net_log_); |
| } |