blob: d096e4330121055a0c96b3ffd58738db7e072fb6 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 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/bind.h"
10#include "base/bind_helpers.h"
11#include "base/command_line.h"
12#include "base/compiler_specific.h"
13#include "base/debug/leak_tracker.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010014#include "base/debug/trace_event.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000015#include "base/logging.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010016#include "base/metrics/field_trial.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000017#include "base/prefs/pref_registry_simple.h"
18#include "base/prefs/pref_service.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000019#include "base/stl_util.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000020#include "base/strings/string_number_conversions.h"
21#include "base/strings/string_split.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010022#include "base/strings/string_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000023#include "base/threading/thread.h"
24#include "base/threading/worker_pool.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010025#include "base/time/default_tick_clock.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000026#include "build/build_config.h"
27#include "chrome/browser/browser_process.h"
28#include "chrome/browser/extensions/event_router_forwarder.h"
29#include "chrome/browser/net/async_dns_field_trial.h"
30#include "chrome/browser/net/basic_http_user_agent_settings.h"
31#include "chrome/browser/net/chrome_net_log.h"
32#include "chrome/browser/net/chrome_network_delegate.h"
33#include "chrome/browser/net/chrome_url_request_context.h"
34#include "chrome/browser/net/connect_interceptor.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000035#include "chrome/browser/net/dns_probe_service.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000036#include "chrome/browser/net/http_pipelining_compatibility_client.h"
37#include "chrome/browser/net/load_time_stats.h"
38#include "chrome/browser/net/pref_proxy_config_tracker.h"
39#include "chrome/browser/net/proxy_service_factory.h"
40#include "chrome/browser/net/sdch_dictionary_fetcher.h"
41#include "chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000042#include "chrome/browser/policy/policy_service.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000043#include "chrome/common/chrome_switches.h"
44#include "chrome/common/pref_names.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010045#include "chrome/common/url_constants.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000046#include "content/public/browser/browser_thread.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000047#include "net/base/host_mapping_rules.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000048#include "net/base/net_util.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010049#include "net/base/network_time_notifier.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000050#include "net/base/sdch_manager.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010051#include "net/cert/cert_verifier.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000052#include "net/cookies/cookie_monster.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010053#include "net/dns/host_cache.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000054#include "net/dns/host_resolver.h"
55#include "net/dns/mapped_host_resolver.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010056#include "net/ftp/ftp_network_layer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000057#include "net/http/http_auth_filter.h"
58#include "net/http/http_auth_handler_factory.h"
59#include "net/http/http_network_layer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000060#include "net/http/http_server_properties_impl.h"
61#include "net/proxy/proxy_config_service.h"
62#include "net/proxy/proxy_script_fetcher_impl.h"
63#include "net/proxy/proxy_service.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010064#include "net/socket/tcp_client_socket.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000065#include "net/spdy/spdy_session.h"
66#include "net/ssl/default_server_bound_cert_store.h"
67#include "net/ssl/server_bound_cert_service.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010068#include "net/url_request/data_protocol_handler.h"
69#include "net/url_request/file_protocol_handler.h"
70#include "net/url_request/ftp_protocol_handler.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000071#include "net/url_request/url_fetcher.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010072#include "net/url_request/url_request_job_factory_impl.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000073#include "net/url_request/url_request_throttler_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000074#include "net/websockets/websocket_job.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000075
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010076#if defined(OS_WIN)
77#include "win8/util/win8_util.h"
78#endif
79
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000080#if defined(ENABLE_CONFIGURATION_POLICY)
81#include "policy/policy_constants.h"
82#endif
83
84#if defined(USE_NSS) || defined(OS_IOS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +000085#include "net/ocsp/nss_ocsp.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000086#endif
87
88#if !defined(OS_IOS) && !defined(OS_ANDROID)
89#include "net/proxy/proxy_resolver_v8.h"
90#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +000091
Torne (Richard Coles)58218062012-11-14 11:43:16 +000092using content::BrowserThread;
93
94class SafeBrowsingURLRequestContext;
95
96// The IOThread object must outlive any tasks posted to the IO thread before the
97// Quit task, so base::Bind() calls are not refcounted.
98
99namespace {
100
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100101const char kQuicFieldTrialName[] = "QUIC";
102const char kQuicFieldTrialEnabledGroupName[] = "Enabled";
Ben Murdochbbcdd452013-07-25 10:06:34 +0100103const char kQuicFieldTrialHttpsEnabledGroupName[] = "HttpsEnabled";
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100104
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000105#if defined(OS_MACOSX) && !defined(OS_IOS)
106void ObserveKeychainEvents() {
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
108 net::CertDatabase::GetInstance()->SetMessageLoopForKeychainEvents();
109}
110#endif
111
112// Used for the "system" URLRequestContext.
113class SystemURLRequestContext : public net::URLRequestContext {
114 public:
115 SystemURLRequestContext() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000116#if defined(USE_NSS) || defined(OS_IOS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000117 net::SetURLRequestContextForNSSHttpIO(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000118#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000119 }
120
121 private:
122 virtual ~SystemURLRequestContext() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000123#if defined(USE_NSS) || defined(OS_IOS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000124 net::SetURLRequestContextForNSSHttpIO(NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000125#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000126 }
127};
128
129scoped_ptr<net::HostResolver> CreateGlobalHostResolver(net::NetLog* net_log) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100130 TRACE_EVENT0("startup", "IOThread::CreateGlobalHostResolver");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000131 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
132
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000133 net::HostResolver::Options options;
134
135 // Use the concurrency override from the command-line, if any.
136 if (command_line.HasSwitch(switches::kHostResolverParallelism)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000137 std::string s =
138 command_line.GetSwitchValueASCII(switches::kHostResolverParallelism);
139
140 // Parse the switch (it should be a positive integer formatted as decimal).
141 int n;
142 if (base::StringToInt(s, &n) && n > 0) {
143 options.max_concurrent_resolves = static_cast<size_t>(n);
144 } else {
145 LOG(ERROR) << "Invalid switch for host resolver parallelism: " << s;
146 }
147 }
148
149 // Use the retry attempts override from the command-line, if any.
150 if (command_line.HasSwitch(switches::kHostResolverRetryAttempts)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000151 std::string s =
152 command_line.GetSwitchValueASCII(switches::kHostResolverRetryAttempts);
153 // Parse the switch (it should be a non-negative integer).
154 int n;
155 if (base::StringToInt(s, &n) && n >= 0) {
156 options.max_retry_attempts = static_cast<size_t>(n);
157 } else {
158 LOG(ERROR) << "Invalid switch for host resolver retry attempts: " << s;
159 }
160 }
161
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000162 scoped_ptr<net::HostResolver> global_host_resolver(
163 net::HostResolver::CreateSystemResolver(options, net_log));
164
165 // Determine if we should disable IPv6 support.
Ben Murdoch9ab55632013-07-18 11:57:30 +0100166 if (command_line.HasSwitch(switches::kEnableIPv6)) {
167 // Disable IPv6 probing.
168 global_host_resolver->SetDefaultAddressFamily(
169 net::ADDRESS_FAMILY_UNSPECIFIED);
170 } else if (command_line.HasSwitch(switches::kDisableIPv6)) {
171 global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000172 }
173
174 // If hostname remappings were specified on the command-line, layer these
175 // rules on top of the real host resolver. This allows forwarding all requests
176 // through a designated test server.
177 if (!command_line.HasSwitch(switches::kHostResolverRules))
178 return global_host_resolver.PassAs<net::HostResolver>();
179
180 scoped_ptr<net::MappedHostResolver> remapped_resolver(
181 new net::MappedHostResolver(global_host_resolver.Pass()));
182 remapped_resolver->SetRulesFromString(
183 command_line.GetSwitchValueASCII(switches::kHostResolverRules));
184 return remapped_resolver.PassAs<net::HostResolver>();
185}
186
187// TODO(willchan): Remove proxy script fetcher context since it's not necessary
188// now that I got rid of refcounting URLRequestContexts.
189// See IOThread::Globals for details.
190net::URLRequestContext*
191ConstructProxyScriptFetcherContext(IOThread::Globals* globals,
192 net::NetLog* net_log) {
193 net::URLRequestContext* context = new net::URLRequestContext;
194 context->set_net_log(net_log);
195 context->set_host_resolver(globals->host_resolver.get());
196 context->set_cert_verifier(globals->cert_verifier.get());
197 context->set_transport_security_state(
198 globals->transport_security_state.get());
199 context->set_http_auth_handler_factory(
200 globals->http_auth_handler_factory.get());
201 context->set_proxy_service(globals->proxy_script_fetcher_proxy_service.get());
202 context->set_http_transaction_factory(
203 globals->proxy_script_fetcher_http_transaction_factory.get());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100204 context->set_job_factory(
205 globals->proxy_script_fetcher_url_request_job_factory.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000206 context->set_cookie_store(globals->system_cookie_store.get());
207 context->set_server_bound_cert_service(
208 globals->system_server_bound_cert_service.get());
209 context->set_network_delegate(globals->system_network_delegate.get());
210 context->set_http_user_agent_settings(
211 globals->http_user_agent_settings.get());
212 // TODO(rtenneti): We should probably use HttpServerPropertiesManager for the
213 // system URLRequestContext too. There's no reason this should be tied to a
214 // profile.
215 return context;
216}
217
218net::URLRequestContext*
219ConstructSystemRequestContext(IOThread::Globals* globals,
220 net::NetLog* net_log) {
221 net::URLRequestContext* context = new SystemURLRequestContext;
222 context->set_net_log(net_log);
223 context->set_host_resolver(globals->host_resolver.get());
224 context->set_cert_verifier(globals->cert_verifier.get());
225 context->set_transport_security_state(
226 globals->transport_security_state.get());
227 context->set_http_auth_handler_factory(
228 globals->http_auth_handler_factory.get());
229 context->set_proxy_service(globals->system_proxy_service.get());
230 context->set_http_transaction_factory(
231 globals->system_http_transaction_factory.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000232 context->set_cookie_store(globals->system_cookie_store.get());
233 context->set_server_bound_cert_service(
234 globals->system_server_bound_cert_service.get());
235 context->set_throttler_manager(globals->throttler_manager.get());
236 context->set_network_delegate(globals->system_network_delegate.get());
237 context->set_http_user_agent_settings(
238 globals->http_user_agent_settings.get());
239 return context;
240}
241
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000242int GetSwitchValueAsInt(const CommandLine& command_line,
243 const std::string& switch_name) {
244 int value;
245 if (!base::StringToInt(command_line.GetSwitchValueASCII(switch_name),
246 &value)) {
247 return 0;
248 }
249 return value;
250}
251
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000252} // namespace
253
254class IOThread::LoggingNetworkChangeObserver
255 : public net::NetworkChangeNotifier::IPAddressObserver,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000256 public net::NetworkChangeNotifier::ConnectionTypeObserver,
257 public net::NetworkChangeNotifier::NetworkChangeObserver {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000258 public:
259 // |net_log| must remain valid throughout our lifetime.
260 explicit LoggingNetworkChangeObserver(net::NetLog* net_log)
261 : net_log_(net_log) {
262 net::NetworkChangeNotifier::AddIPAddressObserver(this);
263 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000264 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000265 }
266
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000267 virtual ~LoggingNetworkChangeObserver() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000268 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
269 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000270 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000271 }
272
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000273 // NetworkChangeNotifier::IPAddressObserver implementation.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000274 virtual void OnIPAddressChanged() OVERRIDE {
275 VLOG(1) << "Observed a change to the network IP addresses";
276
277 net_log_->AddGlobalEntry(net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED);
278 }
279
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000280 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000281 virtual void OnConnectionTypeChanged(
282 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
283 std::string type_as_string =
284 net::NetworkChangeNotifier::ConnectionTypeToString(type);
285
286 VLOG(1) << "Observed a change to network connectivity state "
287 << type_as_string;
288
289 net_log_->AddGlobalEntry(
290 net::NetLog::TYPE_NETWORK_CONNECTIVITY_CHANGED,
291 net::NetLog::StringCallback("new_connection_type", &type_as_string));
292 }
293
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000294 // NetworkChangeNotifier::NetworkChangeObserver implementation.
295 virtual void OnNetworkChanged(
296 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
297 std::string type_as_string =
298 net::NetworkChangeNotifier::ConnectionTypeToString(type);
299
300 VLOG(1) << "Observed a network change to state " << type_as_string;
301
302 net_log_->AddGlobalEntry(
303 net::NetLog::TYPE_NETWORK_CHANGED,
304 net::NetLog::StringCallback("new_connection_type", &type_as_string));
305 }
306
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000307 private:
308 net::NetLog* net_log_;
309 DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver);
310};
311
312class SystemURLRequestContextGetter : public net::URLRequestContextGetter {
313 public:
314 explicit SystemURLRequestContextGetter(IOThread* io_thread);
315
316 // Implementation for net::UrlRequestContextGetter.
317 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
318 virtual scoped_refptr<base::SingleThreadTaskRunner>
319 GetNetworkTaskRunner() const OVERRIDE;
320
321 protected:
322 virtual ~SystemURLRequestContextGetter();
323
324 private:
325 IOThread* const io_thread_; // Weak pointer, owned by BrowserProcess.
326 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
327
328 base::debug::LeakTracker<SystemURLRequestContextGetter> leak_tracker_;
329};
330
331SystemURLRequestContextGetter::SystemURLRequestContextGetter(
332 IOThread* io_thread)
333 : io_thread_(io_thread),
334 network_task_runner_(
335 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
336}
337
338SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {}
339
340net::URLRequestContext* SystemURLRequestContextGetter::GetURLRequestContext() {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
342 DCHECK(io_thread_->globals()->system_request_context.get());
343
344 return io_thread_->globals()->system_request_context.get();
345}
346
347scoped_refptr<base::SingleThreadTaskRunner>
348SystemURLRequestContextGetter::GetNetworkTaskRunner() const {
349 return network_task_runner_;
350}
351
352IOThread::Globals::
353SystemRequestContextLeakChecker::SystemRequestContextLeakChecker(
354 Globals* globals)
355 : globals_(globals) {
356 DCHECK(globals_);
357}
358
359IOThread::Globals::
360SystemRequestContextLeakChecker::~SystemRequestContextLeakChecker() {
361 if (globals_->system_request_context.get())
362 globals_->system_request_context->AssertNoURLRequests();
363}
364
365IOThread::Globals::Globals()
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100366 : system_request_context_leak_checker(this),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000367 ignore_certificate_errors(false),
368 http_pipelining_enabled(false),
369 testing_fixed_http_port(0),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000370 testing_fixed_https_port(0),
371 enable_user_alternate_protocol_ports(false) {
372}
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000373
374IOThread::Globals::~Globals() {}
375
376// |local_state| is passed in explicitly in order to (1) reduce implicit
377// dependencies and (2) make IOThread more flexible for testing.
378IOThread::IOThread(
379 PrefService* local_state,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000380 policy::PolicyService* policy_service,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000381 ChromeNetLog* net_log,
382 extensions::EventRouterForwarder* extension_event_router_forwarder)
383 : net_log_(net_log),
384 extension_event_router_forwarder_(extension_event_router_forwarder),
385 globals_(NULL),
386 sdch_manager_(NULL),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000387 is_spdy_disabled_by_policy_(false),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100388 weak_factory_(this) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000389#if !defined(OS_IOS) && !defined(OS_ANDROID)
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100390#if defined(OS_WIN)
391 if (!win8::IsSingleWindowMetroMode())
392 net::ProxyResolverV8::RememberDefaultIsolate();
393 else
394 net::ProxyResolverV8::CreateIsolate();
395#else
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000396 net::ProxyResolverV8::RememberDefaultIsolate();
397#endif
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100398#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000399 auth_schemes_ = local_state->GetString(prefs::kAuthSchemes);
400 negotiate_disable_cname_lookup_ = local_state->GetBoolean(
401 prefs::kDisableAuthNegotiateCnameLookup);
402 negotiate_enable_port_ = local_state->GetBoolean(
403 prefs::kEnableAuthNegotiatePort);
404 auth_server_whitelist_ = local_state->GetString(prefs::kAuthServerWhitelist);
405 auth_delegate_whitelist_ = local_state->GetString(
406 prefs::kAuthNegotiateDelegateWhitelist);
407 gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName);
408 pref_proxy_config_tracker_.reset(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100409 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
410 local_state));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000411 ChromeNetworkDelegate::InitializePrefsOnUIThread(
412 &system_enable_referrers_,
413 NULL,
414 NULL,
415 local_state);
416 ssl_config_service_manager_.reset(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100417 SSLConfigServiceManager::CreateDefaultManager(local_state));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000418
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000419 base::Value* dns_client_enabled_default = new base::FundamentalValue(
420 chrome_browser_net::ConfigureAsyncDnsFieldTrial());
421 local_state->SetDefaultPrefValue(prefs::kBuiltInDnsClientEnabled,
422 dns_client_enabled_default);
423
424 dns_client_enabled_.Init(prefs::kBuiltInDnsClientEnabled,
425 local_state,
426 base::Bind(&IOThread::UpdateDnsClientEnabled,
427 base::Unretained(this)));
428 dns_client_enabled_.MoveToThread(
429 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
430
431#if defined(ENABLE_CONFIGURATION_POLICY)
432 is_spdy_disabled_by_policy_ = policy_service->GetPolicies(
433 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())).Get(
434 policy::key::kDisableSpdy) != NULL;
435#endif // ENABLE_CONFIGURATION_POLICY
436
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000437 BrowserThread::SetDelegate(BrowserThread::IO, this);
438}
439
440IOThread::~IOThread() {
441 // This isn't needed for production code, but in tests, IOThread may
442 // be multiply constructed.
443 BrowserThread::SetDelegate(BrowserThread::IO, NULL);
444
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000445 pref_proxy_config_tracker_->DetachFromPrefService();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000446 DCHECK(!globals_);
447}
448
449IOThread::Globals* IOThread::globals() {
450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
451 return globals_;
452}
453
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100454void IOThread::SetGlobalsForTesting(Globals* globals) {
455 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
456 DCHECK(!globals || !globals_);
457 globals_ = globals;
458}
459
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000460ChromeNetLog* IOThread::net_log() {
461 return net_log_;
462}
463
464void IOThread::ChangedToOnTheRecord() {
465 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
466 BrowserThread::PostTask(
467 BrowserThread::IO,
468 FROM_HERE,
469 base::Bind(&IOThread::ChangedToOnTheRecordOnIOThread,
470 base::Unretained(this)));
471}
472
473net::URLRequestContextGetter* IOThread::system_url_request_context_getter() {
474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100475 if (!system_url_request_context_getter_.get()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000476 InitSystemRequestContext();
477 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100478 return system_url_request_context_getter_.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000479}
480
481void IOThread::Init() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100482 // Prefer to use InitAsync unless you need initialization to block
483 // the UI thread
484}
485
486void IOThread::InitAsync() {
487 TRACE_EVENT0("startup", "IOThread::InitAsync");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000488 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
489
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000490#if defined(USE_NSS) || defined(OS_IOS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000491 net::SetMessageLoopForNSSHttpIO();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000492#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000493
494 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
495
496 DCHECK(!globals_);
497 globals_ = new Globals;
498
499 // Add an observer that will emit network change events to the ChromeNetLog.
500 // Assuming NetworkChangeNotifier dispatches in FIFO order, we should be
501 // logging the network change before other IO thread consumers respond to it.
502 network_change_observer_.reset(
503 new LoggingNetworkChangeObserver(net_log_));
504
505 // Setup the HistogramWatcher to run on the IO thread.
506 net::NetworkChangeNotifier::InitHistogramWatcher();
507
508 globals_->extension_event_router_forwarder =
509 extension_event_router_forwarder_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000510 ChromeNetworkDelegate* network_delegate =
511 new ChromeNetworkDelegate(extension_event_router_forwarder_,
512 &system_enable_referrers_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000513 if (command_line.HasSwitch(switches::kDisableExtensionsHttpThrottling))
514 network_delegate->NeverThrottleRequests();
515 globals_->system_network_delegate.reset(network_delegate);
516 globals_->host_resolver = CreateGlobalHostResolver(net_log_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000517 UpdateDnsClientEnabled();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000518 globals_->cert_verifier.reset(net::CertVerifier::CreateDefault());
519 globals_->transport_security_state.reset(new net::TransportSecurityState());
520 globals_->ssl_config_service = GetSSLConfigService();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000521 if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) {
522 spdyproxy_auth_origin_ =
523 command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthOrigin);
524 } else {
525#if defined(SPDY_PROXY_AUTH_ORIGIN)
526 spdyproxy_auth_origin_ = SPDY_PROXY_AUTH_ORIGIN;
527#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000528 }
529 globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory(
530 globals_->host_resolver.get()));
Ben Murdochca12bfa2013-07-23 11:17:05 +0100531 globals_->http_server_properties.reset(new net::HttpServerPropertiesImpl());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000532 // For the ProxyScriptFetcher, we use a direct ProxyService.
533 globals_->proxy_script_fetcher_proxy_service.reset(
534 net::ProxyService::CreateDirectWithNetLog(net_log_));
535 // In-memory cookie store.
536 globals_->system_cookie_store = new net::CookieMonster(NULL, NULL);
537 // In-memory server bound cert store.
538 globals_->system_server_bound_cert_service.reset(
539 new net::ServerBoundCertService(
540 new net::DefaultServerBoundCertStore(NULL),
541 base::WorkerPool::GetTaskRunner(true)));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000542 globals_->dns_probe_service.reset(new chrome_browser_net::DnsProbeService());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000543 globals_->load_time_stats.reset(new chrome_browser_net::LoadTimeStats());
544 globals_->host_mapping_rules.reset(new net::HostMappingRules());
545 globals_->http_user_agent_settings.reset(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000546 new BasicHttpUserAgentSettings(std::string()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000547 if (command_line.HasSwitch(switches::kHostRules)) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100548 TRACE_EVENT_BEGIN0("startup", "IOThread::InitAsync:SetRulesFromString");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000549 globals_->host_mapping_rules->SetRulesFromString(
550 command_line.GetSwitchValueASCII(switches::kHostRules));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100551 TRACE_EVENT_END0("startup", "IOThread::InitAsync:SetRulesFromString");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000552 }
553 if (command_line.HasSwitch(switches::kIgnoreCertificateErrors))
554 globals_->ignore_certificate_errors = true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000555 if (command_line.HasSwitch(switches::kTestingFixedHttpPort)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000556 globals_->testing_fixed_http_port =
557 GetSwitchValueAsInt(command_line, switches::kTestingFixedHttpPort);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000558 }
559 if (command_line.HasSwitch(switches::kTestingFixedHttpsPort)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000560 globals_->testing_fixed_https_port =
561 GetSwitchValueAsInt(command_line, switches::kTestingFixedHttpsPort);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000562 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100563 bool enable_quic = ShouldEnableQuic(command_line);
564 globals_->enable_quic.set(enable_quic);
Ben Murdochbbcdd452013-07-25 10:06:34 +0100565 if (enable_quic)
566 globals_->enable_quic_https.set(ShouldEnableQuicHttps(command_line));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100567 if (command_line.HasSwitch(switches::kOriginToForceQuicOn)) {
568 net::HostPortPair quic_origin =
569 net::HostPortPair::FromString(
570 command_line.GetSwitchValueASCII(switches::kOriginToForceQuicOn));
571 if (!quic_origin.IsEmpty()) {
572 globals_->origin_to_force_quic_on.set(quic_origin);
573 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000574 }
575 if (command_line.HasSwitch(
576 switches::kEnableUserAlternateProtocolPorts)) {
577 globals_->enable_user_alternate_protocol_ports = true;
578 }
579 InitializeNetworkOptions(command_line);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000580
581 net::HttpNetworkSession::Params session_params;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000582 InitializeNetworkSessionParams(&session_params);
583 session_params.net_log = net_log_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000584 session_params.proxy_service =
585 globals_->proxy_script_fetcher_proxy_service.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000586
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100587 TRACE_EVENT_BEGIN0("startup", "IOThread::InitAsync:HttpNetworkSession");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000588 scoped_refptr<net::HttpNetworkSession> network_session(
589 new net::HttpNetworkSession(session_params));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100590 globals_->proxy_script_fetcher_http_transaction_factory
591 .reset(new net::HttpNetworkLayer(network_session.get()));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100592 TRACE_EVENT_END0("startup", "IOThread::InitAsync:HttpNetworkSession");
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100593 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
594 new net::URLRequestJobFactoryImpl());
595 job_factory->SetProtocolHandler(chrome::kDataScheme,
596 new net::DataProtocolHandler());
597 job_factory->SetProtocolHandler(chrome::kFileScheme,
598 new net::FileProtocolHandler());
599#if !defined(DISABLE_FTP_SUPPORT)
600 globals_->proxy_script_fetcher_ftp_transaction_factory.reset(
601 new net::FtpNetworkLayer(globals_->host_resolver.get()));
602 job_factory->SetProtocolHandler(
603 chrome::kFtpScheme,
604 new net::FtpProtocolHandler(
605 globals_->proxy_script_fetcher_ftp_transaction_factory.get()));
606#endif
607 globals_->proxy_script_fetcher_url_request_job_factory =
608 job_factory.PassAs<net::URLRequestJobFactory>();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000609
610 globals_->throttler_manager.reset(new net::URLRequestThrottlerManager());
611 globals_->throttler_manager->set_net_log(net_log_);
612 // Always done in production, disabled only for unit tests.
613 globals_->throttler_manager->set_enable_thread_checks(true);
614
615 globals_->proxy_script_fetcher_context.reset(
616 ConstructProxyScriptFetcherContext(globals_, net_log_));
617
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100618 globals_->network_time_notifier.reset(
619 new net::NetworkTimeNotifier(
620 scoped_ptr<base::TickClock>(new base::DefaultTickClock())));
621
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000622 sdch_manager_ = new net::SdchManager();
623
624#if defined(OS_MACOSX) && !defined(OS_IOS)
625 // Start observing Keychain events. This needs to be done on the UI thread,
626 // as Keychain services requires a CFRunLoop.
627 BrowserThread::PostTask(BrowserThread::UI,
628 FROM_HERE,
629 base::Bind(&ObserveKeychainEvents));
630#endif
631
632 // InitSystemRequestContext turns right around and posts a task back
633 // to the IO thread, so we can't let it run until we know the IO
634 // thread has started.
635 //
636 // Note that since we are at BrowserThread::Init time, the UI thread
637 // is blocked waiting for the thread to start. Therefore, posting
638 // this task to the main thread's message loop here is guaranteed to
639 // get it onto the message loop while the IOThread object still
640 // exists. However, the message might not be processed on the UI
641 // thread until after IOThread is gone, so use a weak pointer.
642 BrowserThread::PostTask(BrowserThread::UI,
643 FROM_HERE,
644 base::Bind(&IOThread::InitSystemRequestContext,
645 weak_factory_.GetWeakPtr()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000646}
647
648void IOThread::CleanUp() {
649 base::debug::LeakTracker<SafeBrowsingURLRequestContext>::CheckForLeaks();
650
651 delete sdch_manager_;
652 sdch_manager_ = NULL;
653
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000654#if defined(USE_NSS) || defined(OS_IOS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000655 net::ShutdownNSSHttpIO();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000656#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000657
658 system_url_request_context_getter_ = NULL;
659
660 // Release objects that the net::URLRequestContext could have been pointing
661 // to.
662
663 // This must be reset before the ChromeNetLog is destroyed.
664 network_change_observer_.reset();
665
666 system_proxy_config_service_.reset();
667
668 delete globals_;
669 globals_ = NULL;
670
671 base::debug::LeakTracker<SystemURLRequestContextGetter>::CheckForLeaks();
672}
673
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000674void IOThread::InitializeNetworkOptions(const CommandLine& command_line) {
675 if (command_line.HasSwitch(switches::kEnableFileCookies)) {
676 // Enable cookie storage for file:// URLs. Must do this before the first
677 // Profile (and therefore the first CookieMonster) is created.
678 net::CookieMonster::EnableFileScheme();
679 }
680
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100681 // Only handle use-spdy command line flags if "spdy.disabled" preference is
682 // not disabled via policy.
683 if (!is_spdy_disabled_by_policy_) {
684 if (command_line.HasSwitch(switches::kEnableIPPooling))
685 globals_->enable_spdy_ip_pooling.set(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000686
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100687 if (command_line.HasSwitch(switches::kDisableIPPooling))
688 globals_->enable_spdy_ip_pooling.set(false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000689
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100690 if (command_line.HasSwitch(switches::kEnableSpdyCredentialFrames))
691 globals_->enable_spdy_credential_frames.set(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000692
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100693 if (command_line.HasSwitch(switches::kEnableWebSocketOverSpdy)) {
694 // Enable WebSocket over SPDY.
695 net::WebSocketJob::set_websocket_over_spdy_enabled(true);
696 }
697 if (command_line.HasSwitch(switches::kMaxSpdyConcurrentStreams)) {
698 globals_->max_spdy_concurrent_streams_limit.set(
699 GetSwitchValueAsInt(command_line,
700 switches::kMaxSpdyConcurrentStreams));
701 }
702 if (command_line.HasSwitch(switches::kTrustedSpdyProxy)) {
703 globals_->trusted_spdy_proxy.set(
704 command_line.GetSwitchValueASCII(switches::kTrustedSpdyProxy));
705 }
706 if (command_line.HasSwitch(switches::kIgnoreUrlFetcherCertRequests))
707 net::URLFetcher::SetIgnoreCertificateRequests(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000708
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100709 if (command_line.HasSwitch(switches::kUseSpdy)) {
710 std::string spdy_mode =
711 command_line.GetSwitchValueASCII(switches::kUseSpdy);
712 EnableSpdy(spdy_mode);
Ben Murdoch558790d2013-07-30 15:19:42 +0100713 } else if (command_line.HasSwitch(switches::kEnableHttp2Draft04)) {
714 net::HttpStreamFactory::EnableNpnHttp2Draft04();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100715 } else if (command_line.HasSwitch(switches::kEnableSpdy4a2)) {
716 net::HttpStreamFactory::EnableNpnSpdy4a2();
717 } else if (command_line.HasSwitch(switches::kDisableSpdy31)) {
718 net::HttpStreamFactory::EnableNpnSpdy3();
719 } else if (command_line.HasSwitch(switches::kEnableNpn)) {
720 net::HttpStreamFactory::EnableNpnSpdy();
721 } else if (command_line.HasSwitch(switches::kEnableNpnHttpOnly)) {
722 net::HttpStreamFactory::EnableNpnHttpOnly();
723 } else {
724 // Use SPDY/3.1 by default.
725 net::HttpStreamFactory::EnableNpnSpdy31();
726 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000727 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100728
729 // TODO(rch): Make the client socket factory a per-network session
730 // instance, constructed from a NetworkSession::Params, to allow us
731 // to move this option to IOThread::Globals &
732 // HttpNetworkSession::Params.
733 if (command_line.HasSwitch(switches::kEnableTcpFastOpen))
734 net::SetTCPFastOpenEnabled(true);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000735}
736
737void IOThread::EnableSpdy(const std::string& mode) {
738 static const char kOff[] = "off";
739 static const char kSSL[] = "ssl";
740 static const char kDisableSSL[] = "no-ssl";
741 static const char kDisablePing[] = "no-ping";
742 static const char kExclude[] = "exclude"; // Hosts to exclude
743 static const char kDisableCompression[] = "no-compress";
744 static const char kDisableAltProtocols[] = "no-alt-protocols";
745 static const char kForceAltProtocols[] = "force-alt-protocols";
746 static const char kSingleDomain[] = "single-domain";
747
748 static const char kInitialMaxConcurrentStreams[] = "init-max-streams";
749
750 std::vector<std::string> spdy_options;
751 base::SplitString(mode, ',', &spdy_options);
752
753 for (std::vector<std::string>::iterator it = spdy_options.begin();
754 it != spdy_options.end(); ++it) {
755 const std::string& element = *it;
756 std::vector<std::string> name_value;
757 base::SplitString(element, '=', &name_value);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100758 const std::string& option =
759 name_value.size() > 0 ? name_value[0] : std::string();
760 const std::string value =
761 name_value.size() > 1 ? name_value[1] : std::string();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000762
763 if (option == kOff) {
764 net::HttpStreamFactory::set_spdy_enabled(false);
765 } else if (option == kDisableSSL) {
766 globals_->spdy_default_protocol.set(net::kProtoSPDY2);
767 net::HttpStreamFactory::set_force_spdy_over_ssl(false);
768 net::HttpStreamFactory::set_force_spdy_always(true);
769 } else if (option == kSSL) {
770 globals_->spdy_default_protocol.set(net::kProtoSPDY2);
771 net::HttpStreamFactory::set_force_spdy_over_ssl(true);
772 net::HttpStreamFactory::set_force_spdy_always(true);
773 } else if (option == kDisablePing) {
774 globals_->enable_spdy_ping_based_connection_checking.set(false);
775 } else if (option == kExclude) {
776 net::HttpStreamFactory::add_forced_spdy_exclusion(value);
777 } else if (option == kDisableCompression) {
778 globals_->enable_spdy_compression.set(false);
779 } else if (option == kDisableAltProtocols) {
780 net::HttpStreamFactory::set_use_alternate_protocols(false);
781 } else if (option == kForceAltProtocols) {
782 net::PortAlternateProtocolPair pair;
783 pair.port = 443;
784 pair.protocol = net::NPN_SPDY_2;
785 net::HttpServerPropertiesImpl::ForceAlternateProtocol(pair);
786 } else if (option == kSingleDomain) {
787 DLOG(INFO) << "FORCING SINGLE DOMAIN";
788 globals_->force_spdy_single_domain.set(true);
789 } else if (option == kInitialMaxConcurrentStreams) {
790 int streams;
791 if (base::StringToInt(value, &streams))
792 globals_->initial_max_spdy_concurrent_streams.set(streams);
793 } else if (option.empty() && it == spdy_options.begin()) {
794 continue;
795 } else {
796 LOG(DFATAL) << "Unrecognized spdy option: " << option;
797 }
798 }
799}
800
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000801// static
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000802void IOThread::RegisterPrefs(PrefRegistrySimple* registry) {
803 registry->RegisterStringPref(prefs::kAuthSchemes,
804 "basic,digest,ntlm,negotiate,"
805 "spdyproxy");
806 registry->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup, false);
807 registry->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort, false);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100808 registry->RegisterStringPref(prefs::kAuthServerWhitelist, std::string());
809 registry->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist,
810 std::string());
811 registry->RegisterStringPref(prefs::kGSSAPILibraryName, std::string());
812 registry->RegisterStringPref(prefs::kSpdyProxyAuthOrigin, std::string());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000813 registry->RegisterBooleanPref(prefs::kEnableReferrers, true);
814 registry->RegisterInt64Pref(prefs::kHttpReceivedContentLength, 0);
815 registry->RegisterInt64Pref(prefs::kHttpOriginalContentLength, 0);
816#if defined(OS_ANDROID) || defined(OS_IOS)
817 registry->RegisterListPref(prefs::kDailyHttpOriginalContentLength);
818 registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100819 registry->RegisterListPref(
820 prefs::kDailyHttpReceivedContentLengthViaDataReductionProxy);
821 registry->RegisterListPref(
822 prefs::kDailyHttpReceivedContentLengthWithDataReductionProxyEnabled);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000823 registry->RegisterInt64Pref(prefs::kDailyHttpContentLengthLastUpdateDate, 0L);
824#endif
825 registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000826}
827
828net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory(
829 net::HostResolver* resolver) {
830 net::HttpAuthFilterWhitelist* auth_filter_default_credentials = NULL;
831 if (!auth_server_whitelist_.empty()) {
832 auth_filter_default_credentials =
833 new net::HttpAuthFilterWhitelist(auth_server_whitelist_);
834 }
835 net::HttpAuthFilterWhitelist* auth_filter_delegate = NULL;
836 if (!auth_delegate_whitelist_.empty()) {
837 auth_filter_delegate =
838 new net::HttpAuthFilterWhitelist(auth_delegate_whitelist_);
839 }
840 globals_->url_security_manager.reset(
841 net::URLSecurityManager::Create(auth_filter_default_credentials,
842 auth_filter_delegate));
843 std::vector<std::string> supported_schemes;
844 base::SplitString(auth_schemes_, ',', &supported_schemes);
845
846 scoped_ptr<net::HttpAuthHandlerRegistryFactory> registry_factory(
847 net::HttpAuthHandlerRegistryFactory::Create(
848 supported_schemes, globals_->url_security_manager.get(),
849 resolver, gssapi_library_name_, negotiate_disable_cname_lookup_,
850 negotiate_enable_port_));
851
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000852 if (!spdyproxy_auth_origin_.empty()) {
853 GURL origin_url(spdyproxy_auth_origin_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000854 if (origin_url.is_valid()) {
855 registry_factory->RegisterSchemeFactory(
856 "spdyproxy",
857 new spdyproxy::HttpAuthHandlerSpdyProxy::Factory(origin_url));
858 } else {
859 LOG(WARNING) << "Skipping creation of SpdyProxy auth handler since "
860 << "authorized origin is invalid: "
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000861 << spdyproxy_auth_origin_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000862 }
863 }
864
865 return registry_factory.release();
866}
867
868void IOThread::ClearHostCache() {
869 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
870
871 net::HostCache* host_cache = globals_->host_resolver->GetHostCache();
872 if (host_cache)
873 host_cache->clear();
874}
875
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000876void IOThread::InitializeNetworkSessionParams(
877 net::HttpNetworkSession::Params* params) {
878 params->host_resolver = globals_->host_resolver.get();
879 params->cert_verifier = globals_->cert_verifier.get();
880 params->server_bound_cert_service =
881 globals_->system_server_bound_cert_service.get();
882 params->transport_security_state = globals_->transport_security_state.get();
883 params->ssl_config_service = globals_->ssl_config_service.get();
884 params->http_auth_handler_factory = globals_->http_auth_handler_factory.get();
Ben Murdochca12bfa2013-07-23 11:17:05 +0100885 params->http_server_properties =
886 globals_->http_server_properties->GetWeakPtr();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000887 params->network_delegate = globals_->system_network_delegate.get();
888 params->host_mapping_rules = globals_->host_mapping_rules.get();
889 params->ignore_certificate_errors = globals_->ignore_certificate_errors;
890 params->http_pipelining_enabled = globals_->http_pipelining_enabled;
891 params->testing_fixed_http_port = globals_->testing_fixed_http_port;
892 params->testing_fixed_https_port = globals_->testing_fixed_https_port;
893
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000894 globals_->initial_max_spdy_concurrent_streams.CopyToIfSet(
895 &params->spdy_initial_max_concurrent_streams);
896 globals_->max_spdy_concurrent_streams_limit.CopyToIfSet(
897 &params->spdy_max_concurrent_streams_limit);
898 globals_->force_spdy_single_domain.CopyToIfSet(
899 &params->force_spdy_single_domain);
900 globals_->enable_spdy_ip_pooling.CopyToIfSet(
901 &params->enable_spdy_ip_pooling);
902 globals_->enable_spdy_credential_frames.CopyToIfSet(
903 &params->enable_spdy_credential_frames);
904 globals_->enable_spdy_compression.CopyToIfSet(
905 &params->enable_spdy_compression);
906 globals_->enable_spdy_ping_based_connection_checking.CopyToIfSet(
907 &params->enable_spdy_ping_based_connection_checking);
908 globals_->spdy_default_protocol.CopyToIfSet(
909 &params->spdy_default_protocol);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100910 globals_->trusted_spdy_proxy.CopyToIfSet(
911 &params->trusted_spdy_proxy);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000912 globals_->enable_quic.CopyToIfSet(&params->enable_quic);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100913 globals_->enable_quic_https.CopyToIfSet(&params->enable_quic_https);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100914 globals_->origin_to_force_quic_on.CopyToIfSet(
915 &params->origin_to_force_quic_on);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000916 params->enable_user_alternate_protocol_ports =
917 globals_->enable_user_alternate_protocol_ports;
918}
919
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000920net::SSLConfigService* IOThread::GetSSLConfigService() {
921 return ssl_config_service_manager_->Get();
922}
923
924void IOThread::ChangedToOnTheRecordOnIOThread() {
925 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
926
927 // Clear the host cache to avoid showing entries from the OTR session
928 // in about:net-internals.
929 ClearHostCache();
930}
931
932void IOThread::InitSystemRequestContext() {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100933 if (system_url_request_context_getter_.get())
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000934 return;
935 // If we're in unit_tests, IOThread may not be run.
936 if (!BrowserThread::IsMessageLoopValid(BrowserThread::IO))
937 return;
Ben Murdochca12bfa2013-07-23 11:17:05 +0100938 system_proxy_config_service_.reset(
939 ProxyServiceFactory::CreateProxyConfigService(
940 pref_proxy_config_tracker_.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000941 system_url_request_context_getter_ =
942 new SystemURLRequestContextGetter(this);
943 // Safe to post an unretained this pointer, since IOThread is
944 // guaranteed to outlive the IO BrowserThread.
945 BrowserThread::PostTask(
946 BrowserThread::IO,
947 FROM_HERE,
948 base::Bind(&IOThread::InitSystemRequestContextOnIOThread,
949 base::Unretained(this)));
950}
951
952void IOThread::InitSystemRequestContextOnIOThread() {
953 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
954 DCHECK(!globals_->system_proxy_service.get());
955 DCHECK(system_proxy_config_service_.get());
956
957 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
958 globals_->system_proxy_service.reset(
959 ProxyServiceFactory::CreateProxyService(
960 net_log_,
961 globals_->proxy_script_fetcher_context.get(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000962 globals_->system_network_delegate.get(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000963 system_proxy_config_service_.release(),
964 command_line));
965
966 net::HttpNetworkSession::Params system_params;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000967 InitializeNetworkSessionParams(&system_params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000968 system_params.net_log = net_log_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000969 system_params.proxy_service = globals_->system_proxy_service.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000970
971 globals_->system_http_transaction_factory.reset(
972 new net::HttpNetworkLayer(
973 new net::HttpNetworkSession(system_params)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000974 globals_->system_request_context.reset(
975 ConstructSystemRequestContext(globals_, net_log_));
976
977 sdch_manager_->set_sdch_fetcher(
978 new SdchDictionaryFetcher(system_url_request_context_getter_.get()));
979}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000980
981void IOThread::UpdateDnsClientEnabled() {
982 globals()->host_resolver->SetDnsClientEnabled(*dns_client_enabled_);
983}
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100984
985bool IOThread::ShouldEnableQuic(const CommandLine& command_line) {
986 // Always fetch the field trial group to ensure it is reported correctly.
987 // The command line flags will be associated with a group that is reported
988 // so long as trial is actually queried.
989 std::string quic_trial_group =
990 base::FieldTrialList::FindFullName(kQuicFieldTrialName);
991
992 if (command_line.HasSwitch(switches::kDisableQuic))
993 return false;
994
Ben Murdochbbcdd452013-07-25 10:06:34 +0100995 if (command_line.HasSwitch(switches::kEnableQuic))
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100996 return true;
997
Ben Murdochbbcdd452013-07-25 10:06:34 +0100998 // QUIC should be enabled if we are in either field trial group.
999 return quic_trial_group == kQuicFieldTrialEnabledGroupName ||
1000 quic_trial_group == kQuicFieldTrialHttpsEnabledGroupName;
1001}
1002
1003bool IOThread::ShouldEnableQuicHttps(const CommandLine& command_line) {
1004 // Always fetch the field trial group to ensure it is reported correctly.
1005 // The command line flags will be associated with a group that is reported
1006 // so long as trial is actually queried.
1007 std::string quic_trial_group =
1008 base::FieldTrialList::FindFullName(kQuicFieldTrialName);
1009
1010 if (command_line.HasSwitch(switches::kDisableQuicHttps))
1011 return false;
1012
1013 if (command_line.HasSwitch(switches::kEnableQuicHttps))
1014 return true;
1015
1016 // HTTPS over QUIC should only be enabled if we are in the https
1017 // field trial group.
1018 return quic_trial_group == kQuicFieldTrialHttpsEnabledGroupName;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001019}