1 // 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/base64.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/compiler_specific.h"
14 #include "base/debug/leak_tracker.h"
15 #include "base/debug/trace_event.h"
16 #include "base/logging.h"
17 #include "base/metrics/field_trial.h"
18 #include "base/prefs/pref_registry_simple.h"
19 #include "base/prefs/pref_service.h"
20 #include "base/stl_util.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/string_piece.h"
23 #include "base/strings/string_split.h"
24 #include "base/strings/string_util.h"
25 #include "base/threading/sequenced_worker_pool.h"
26 #include "base/threading/thread.h"
27 #include "base/threading/worker_pool.h"
28 #include "base/time/time.h"
29 #include "build/build_config.h"
30 #include "chrome/browser/browser_process.h"
31 #include "chrome/browser/net/async_dns_field_trial.h"
32 #include "chrome/browser/net/chrome_net_log.h"
33 #include "chrome/browser/net/chrome_network_delegate.h"
34 #include "chrome/browser/net/connect_interceptor.h"
35 #include "chrome/browser/net/dns_probe_service.h"
36 #include "chrome/browser/net/pref_proxy_config_tracker.h"
37 #include "chrome/browser/net/proxy_service_factory.h"
38 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
39 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
40 #include "chrome/common/chrome_content_client.h"
41 #include "chrome/common/chrome_switches.h"
42 #include "chrome/common/chrome_version_info.h"
43 #include "chrome/common/pref_names.h"
44 #include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h"
45 #include "components/data_reduction_proxy/browser/data_reduction_proxy_delegate.h"
46 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h"
47 #include "components/data_reduction_proxy/browser/data_reduction_proxy_prefs.h"
48 #include "components/data_reduction_proxy/browser/data_reduction_proxy_protocol.h"
49 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
50 #include "components/policy/core/common/policy_service.h"
51 #include "components/variations/variations_associated_data.h"
52 #include "content/public/browser/browser_thread.h"
53 #include "content/public/browser/cookie_store_factory.h"
54 #include "net/base/host_mapping_rules.h"
55 #include "net/base/net_util.h"
56 #include "net/cert/cert_verifier.h"
57 #include "net/cert/cert_verify_proc.h"
58 #include "net/cert/ct_known_logs.h"
59 #include "net/cert/ct_log_verifier.h"
60 #include "net/cert/ct_verifier.h"
61 #include "net/cert/multi_log_ct_verifier.h"
62 #include "net/cert/multi_threaded_cert_verifier.h"
63 #include "net/cookies/cookie_store.h"
64 #include "net/dns/host_cache.h"
65 #include "net/dns/host_resolver.h"
66 #include "net/dns/mapped_host_resolver.h"
67 #include "net/ftp/ftp_network_layer.h"
68 #include "net/http/http_auth_filter.h"
69 #include "net/http/http_auth_handler_factory.h"
70 #include "net/http/http_network_layer.h"
71 #include "net/http/http_server_properties_impl.h"
72 #include "net/proxy/proxy_config_service.h"
73 #include "net/proxy/proxy_script_fetcher_impl.h"
74 #include "net/proxy/proxy_service.h"
75 #include "net/quic/crypto/crypto_protocol.h"
76 #include "net/quic/quic_protocol.h"
77 #include "net/socket/tcp_client_socket.h"
78 #include "net/spdy/spdy_session.h"
79 #include "net/ssl/channel_id_service.h"
80 #include "net/ssl/default_channel_id_store.h"
81 #include "net/url_request/data_protocol_handler.h"
82 #include "net/url_request/file_protocol_handler.h"
83 #include "net/url_request/ftp_protocol_handler.h"
84 #include "net/url_request/static_http_user_agent_settings.h"
85 #include "net/url_request/url_fetcher.h"
86 #include "net/url_request/url_request_context.h"
87 #include "net/url_request/url_request_context_getter.h"
88 #include "net/url_request/url_request_job_factory_impl.h"
89 #include "net/url_request/url_request_throttler_manager.h"
90 #include "url/url_constants.h"
91
92 #if defined(ENABLE_CONFIGURATION_POLICY)
93 #include "policy/policy_constants.h"
94 #endif
95
96 #if defined(ENABLE_EXTENSIONS)
97 #include "chrome/browser/extensions/event_router_forwarder.h"
98 #endif
99
100 #if defined(USE_NSS) || defined(OS_IOS)
101 #include "net/ocsp/nss_ocsp.h"
102 #endif
103
104 #if defined(OS_CHROMEOS)
105 #include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
106 #include "chromeos/network/host_resolver_impl_chromeos.h"
107 #endif
108
109 using content::BrowserThread;
110
111 class SafeBrowsingURLRequestContext;
112
113 // The IOThread object must outlive any tasks posted to the IO thread before the
114 // Quit task, so base::Bind() calls are not refcounted.
115
116 namespace {
117
118 const char kTCPFastOpenFieldTrialName[] = "TCPFastOpen";
119 const char kTCPFastOpenHttpsEnabledGroupName[] = "HttpsEnabled";
120
121 const char kQuicFieldTrialName[] = "QUIC";
122 const char kQuicFieldTrialEnabledGroupName[] = "Enabled";
123 const char kQuicFieldTrialHttpsEnabledGroupName[] = "HttpsEnabled";
124 const char kQuicFieldTrialPacketLengthSuffix[] = "BytePackets";
125 const char kQuicFieldTrialPacingSuffix[] = "WithPacing";
126 const char kQuicFieldTrialTimeBasedLossDetectionSuffix[] =
127 "WithTimeBasedLossDetection";
128
129 // The SPDY trial composes two different trial plus control groups:
130 // * A "holdback" group with SPDY disabled, and corresponding control
131 // (SPDY/3.1). The primary purpose of the holdback group is to encourage site
132 // operators to do feature detection rather than UA-sniffing. As such, this
133 // trial runs continuously.
134 // * A SPDY/4 experiment, for SPDY/4 (aka HTTP/2) vs SPDY/3.1 comparisons and
135 // eventual SPDY/4 deployment.
136 const char kSpdyFieldTrialName[] = "SPDY";
137 const char kSpdyFieldTrialHoldbackGroupNamePrefix[] = "SpdyDisabled";
138 const char kSpdyFieldTrialHoldbackControlGroupName[] = "Control";
139 const char kSpdyFieldTrialSpdy31GroupNamePrefix[] = "Spdy31Enabled";
140 const char kSpdyFieldTrialSpdy4GroupNamePrefix[] = "Spdy4Enabled";
141 const char kSpdyFieldTrialSpdy4ControlGroupName[] = "Spdy4Control";
142
143 #if defined(OS_MACOSX) && !defined(OS_IOS)
ObserveKeychainEvents()144 void ObserveKeychainEvents() {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146 net::CertDatabase::GetInstance()->SetMessageLoopForKeychainEvents();
147 }
148 #endif
149
150 // Used for the "system" URLRequestContext.
151 class SystemURLRequestContext : public net::URLRequestContext {
152 public:
SystemURLRequestContext()153 SystemURLRequestContext() {
154 #if defined(USE_NSS) || defined(OS_IOS)
155 net::SetURLRequestContextForNSSHttpIO(this);
156 #endif
157 }
158
159 private:
~SystemURLRequestContext()160 virtual ~SystemURLRequestContext() {
161 AssertNoURLRequests();
162 #if defined(USE_NSS) || defined(OS_IOS)
163 net::SetURLRequestContextForNSSHttpIO(NULL);
164 #endif
165 }
166 };
167
CreateGlobalHostResolver(net::NetLog * net_log)168 scoped_ptr<net::HostResolver> CreateGlobalHostResolver(net::NetLog* net_log) {
169 TRACE_EVENT0("startup", "IOThread::CreateGlobalHostResolver");
170 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
171
172 net::HostResolver::Options options;
173
174 // Use the concurrency override from the command-line, if any.
175 if (command_line.HasSwitch(switches::kHostResolverParallelism)) {
176 std::string s =
177 command_line.GetSwitchValueASCII(switches::kHostResolverParallelism);
178
179 // Parse the switch (it should be a positive integer formatted as decimal).
180 int n;
181 if (base::StringToInt(s, &n) && n > 0) {
182 options.max_concurrent_resolves = static_cast<size_t>(n);
183 } else {
184 LOG(ERROR) << "Invalid switch for host resolver parallelism: " << s;
185 }
186 }
187
188 // Use the retry attempts override from the command-line, if any.
189 if (command_line.HasSwitch(switches::kHostResolverRetryAttempts)) {
190 std::string s =
191 command_line.GetSwitchValueASCII(switches::kHostResolverRetryAttempts);
192 // Parse the switch (it should be a non-negative integer).
193 int n;
194 if (base::StringToInt(s, &n) && n >= 0) {
195 options.max_retry_attempts = static_cast<size_t>(n);
196 } else {
197 LOG(ERROR) << "Invalid switch for host resolver retry attempts: " << s;
198 }
199 }
200
201 scoped_ptr<net::HostResolver> global_host_resolver;
202 #if defined OS_CHROMEOS
203 global_host_resolver =
204 chromeos::HostResolverImplChromeOS::CreateSystemResolver(options,
205 net_log);
206 #else
207 global_host_resolver =
208 net::HostResolver::CreateSystemResolver(options, net_log);
209 #endif
210
211 // Determine if we should disable IPv6 support.
212 if (command_line.HasSwitch(switches::kEnableIPv6)) {
213 // Disable IPv6 probing.
214 global_host_resolver->SetDefaultAddressFamily(
215 net::ADDRESS_FAMILY_UNSPECIFIED);
216 } else if (command_line.HasSwitch(switches::kDisableIPv6)) {
217 global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4);
218 }
219
220 // If hostname remappings were specified on the command-line, layer these
221 // rules on top of the real host resolver. This allows forwarding all requests
222 // through a designated test server.
223 if (!command_line.HasSwitch(switches::kHostResolverRules))
224 return global_host_resolver.PassAs<net::HostResolver>();
225
226 scoped_ptr<net::MappedHostResolver> remapped_resolver(
227 new net::MappedHostResolver(global_host_resolver.Pass()));
228 remapped_resolver->SetRulesFromString(
229 command_line.GetSwitchValueASCII(switches::kHostResolverRules));
230 return remapped_resolver.PassAs<net::HostResolver>();
231 }
232
233 // TODO(willchan): Remove proxy script fetcher context since it's not necessary
234 // now that I got rid of refcounting URLRequestContexts.
235 // See IOThread::Globals for details.
236 net::URLRequestContext*
ConstructProxyScriptFetcherContext(IOThread::Globals * globals,net::NetLog * net_log)237 ConstructProxyScriptFetcherContext(IOThread::Globals* globals,
238 net::NetLog* net_log) {
239 net::URLRequestContext* context = new net::URLRequestContext;
240 context->set_net_log(net_log);
241 context->set_host_resolver(globals->host_resolver.get());
242 context->set_cert_verifier(globals->cert_verifier.get());
243 context->set_transport_security_state(
244 globals->transport_security_state.get());
245 context->set_cert_transparency_verifier(
246 globals->cert_transparency_verifier.get());
247 context->set_http_auth_handler_factory(
248 globals->http_auth_handler_factory.get());
249 context->set_proxy_service(globals->proxy_script_fetcher_proxy_service.get());
250 context->set_http_transaction_factory(
251 globals->proxy_script_fetcher_http_transaction_factory.get());
252 context->set_job_factory(
253 globals->proxy_script_fetcher_url_request_job_factory.get());
254 context->set_cookie_store(globals->system_cookie_store.get());
255 context->set_channel_id_service(
256 globals->system_channel_id_service.get());
257 context->set_network_delegate(globals->system_network_delegate.get());
258 context->set_http_user_agent_settings(
259 globals->http_user_agent_settings.get());
260 // TODO(rtenneti): We should probably use HttpServerPropertiesManager for the
261 // system URLRequestContext too. There's no reason this should be tied to a
262 // profile.
263 return context;
264 }
265
266 net::URLRequestContext*
ConstructSystemRequestContext(IOThread::Globals * globals,net::NetLog * net_log)267 ConstructSystemRequestContext(IOThread::Globals* globals,
268 net::NetLog* net_log) {
269 net::URLRequestContext* context = new SystemURLRequestContext;
270 context->set_net_log(net_log);
271 context->set_host_resolver(globals->host_resolver.get());
272 context->set_cert_verifier(globals->cert_verifier.get());
273 context->set_transport_security_state(
274 globals->transport_security_state.get());
275 context->set_cert_transparency_verifier(
276 globals->cert_transparency_verifier.get());
277 context->set_http_auth_handler_factory(
278 globals->http_auth_handler_factory.get());
279 context->set_proxy_service(globals->system_proxy_service.get());
280 context->set_http_transaction_factory(
281 globals->system_http_transaction_factory.get());
282 context->set_job_factory(globals->system_url_request_job_factory.get());
283 context->set_cookie_store(globals->system_cookie_store.get());
284 context->set_channel_id_service(
285 globals->system_channel_id_service.get());
286 context->set_throttler_manager(globals->throttler_manager.get());
287 context->set_network_delegate(globals->system_network_delegate.get());
288 context->set_http_user_agent_settings(
289 globals->http_user_agent_settings.get());
290 return context;
291 }
292
GetSwitchValueAsInt(const CommandLine & command_line,const std::string & switch_name)293 int GetSwitchValueAsInt(const CommandLine& command_line,
294 const std::string& switch_name) {
295 int value;
296 if (!base::StringToInt(command_line.GetSwitchValueASCII(switch_name),
297 &value)) {
298 return 0;
299 }
300 return value;
301 }
302
303 // Returns the value associated with |key| in |params| or "" if the
304 // key is not present in the map.
GetVariationParam(const std::map<std::string,std::string> & params,const std::string & key)305 const std::string& GetVariationParam(
306 const std::map<std::string, std::string>& params,
307 const std::string& key) {
308 std::map<std::string, std::string>::const_iterator it = params.find(key);
309 if (it == params.end())
310 return base::EmptyString();
311
312 return it->second;
313 }
314
315 } // namespace
316
317 class IOThread::LoggingNetworkChangeObserver
318 : public net::NetworkChangeNotifier::IPAddressObserver,
319 public net::NetworkChangeNotifier::ConnectionTypeObserver,
320 public net::NetworkChangeNotifier::NetworkChangeObserver {
321 public:
322 // |net_log| must remain valid throughout our lifetime.
LoggingNetworkChangeObserver(net::NetLog * net_log)323 explicit LoggingNetworkChangeObserver(net::NetLog* net_log)
324 : net_log_(net_log) {
325 net::NetworkChangeNotifier::AddIPAddressObserver(this);
326 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
327 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
328 }
329
~LoggingNetworkChangeObserver()330 virtual ~LoggingNetworkChangeObserver() {
331 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
332 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
333 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
334 }
335
336 // NetworkChangeNotifier::IPAddressObserver implementation.
OnIPAddressChanged()337 virtual void OnIPAddressChanged() OVERRIDE {
338 VLOG(1) << "Observed a change to the network IP addresses";
339
340 net_log_->AddGlobalEntry(net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED);
341 }
342
343 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
OnConnectionTypeChanged(net::NetworkChangeNotifier::ConnectionType type)344 virtual void OnConnectionTypeChanged(
345 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
346 std::string type_as_string =
347 net::NetworkChangeNotifier::ConnectionTypeToString(type);
348
349 VLOG(1) << "Observed a change to network connectivity state "
350 << type_as_string;
351
352 net_log_->AddGlobalEntry(
353 net::NetLog::TYPE_NETWORK_CONNECTIVITY_CHANGED,
354 net::NetLog::StringCallback("new_connection_type", &type_as_string));
355 }
356
357 // NetworkChangeNotifier::NetworkChangeObserver implementation.
OnNetworkChanged(net::NetworkChangeNotifier::ConnectionType type)358 virtual void OnNetworkChanged(
359 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
360 std::string type_as_string =
361 net::NetworkChangeNotifier::ConnectionTypeToString(type);
362
363 VLOG(1) << "Observed a network change to state " << type_as_string;
364
365 net_log_->AddGlobalEntry(
366 net::NetLog::TYPE_NETWORK_CHANGED,
367 net::NetLog::StringCallback("new_connection_type", &type_as_string));
368 }
369
370 private:
371 net::NetLog* net_log_;
372 DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver);
373 };
374
375 class SystemURLRequestContextGetter : public net::URLRequestContextGetter {
376 public:
377 explicit SystemURLRequestContextGetter(IOThread* io_thread);
378
379 // Implementation for net::UrlRequestContextGetter.
380 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
381 virtual scoped_refptr<base::SingleThreadTaskRunner>
382 GetNetworkTaskRunner() const OVERRIDE;
383
384 protected:
385 virtual ~SystemURLRequestContextGetter();
386
387 private:
388 IOThread* const io_thread_; // Weak pointer, owned by BrowserProcess.
389 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
390
391 base::debug::LeakTracker<SystemURLRequestContextGetter> leak_tracker_;
392 };
393
SystemURLRequestContextGetter(IOThread * io_thread)394 SystemURLRequestContextGetter::SystemURLRequestContextGetter(
395 IOThread* io_thread)
396 : io_thread_(io_thread),
397 network_task_runner_(
398 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
399 }
400
~SystemURLRequestContextGetter()401 SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {}
402
GetURLRequestContext()403 net::URLRequestContext* SystemURLRequestContextGetter::GetURLRequestContext() {
404 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
405 DCHECK(io_thread_->globals()->system_request_context.get());
406
407 return io_thread_->globals()->system_request_context.get();
408 }
409
410 scoped_refptr<base::SingleThreadTaskRunner>
GetNetworkTaskRunner() const411 SystemURLRequestContextGetter::GetNetworkTaskRunner() const {
412 return network_task_runner_;
413 }
414
415 IOThread::Globals::
SystemRequestContextLeakChecker(Globals * globals)416 SystemRequestContextLeakChecker::SystemRequestContextLeakChecker(
417 Globals* globals)
418 : globals_(globals) {
419 DCHECK(globals_);
420 }
421
422 IOThread::Globals::
~SystemRequestContextLeakChecker()423 SystemRequestContextLeakChecker::~SystemRequestContextLeakChecker() {
424 if (globals_->system_request_context.get())
425 globals_->system_request_context->AssertNoURLRequests();
426 }
427
Globals()428 IOThread::Globals::Globals()
429 : system_request_context_leak_checker(this),
430 enable_ssl_connect_job_waiting(false),
431 ignore_certificate_errors(false),
432 testing_fixed_http_port(0),
433 testing_fixed_https_port(0),
434 enable_user_alternate_protocol_ports(false) {
435 }
436
~Globals()437 IOThread::Globals::~Globals() {}
438
439 // |local_state| is passed in explicitly in order to (1) reduce implicit
440 // dependencies and (2) make IOThread more flexible for testing.
IOThread(PrefService * local_state,policy::PolicyService * policy_service,ChromeNetLog * net_log,extensions::EventRouterForwarder * extension_event_router_forwarder)441 IOThread::IOThread(
442 PrefService* local_state,
443 policy::PolicyService* policy_service,
444 ChromeNetLog* net_log,
445 extensions::EventRouterForwarder* extension_event_router_forwarder)
446 : net_log_(net_log),
447 #if defined(ENABLE_EXTENSIONS)
448 extension_event_router_forwarder_(extension_event_router_forwarder),
449 #endif
450 globals_(NULL),
451 is_spdy_disabled_by_policy_(false),
452 creation_time_(base::TimeTicks::Now()),
453 weak_factory_(this) {
454 auth_schemes_ = local_state->GetString(prefs::kAuthSchemes);
455 negotiate_disable_cname_lookup_ = local_state->GetBoolean(
456 prefs::kDisableAuthNegotiateCnameLookup);
457 negotiate_enable_port_ = local_state->GetBoolean(
458 prefs::kEnableAuthNegotiatePort);
459 auth_server_whitelist_ = local_state->GetString(prefs::kAuthServerWhitelist);
460 auth_delegate_whitelist_ = local_state->GetString(
461 prefs::kAuthNegotiateDelegateWhitelist);
462 gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName);
463 pref_proxy_config_tracker_.reset(
464 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
465 local_state));
466 ChromeNetworkDelegate::InitializePrefsOnUIThread(
467 &system_enable_referrers_,
468 NULL,
469 NULL,
470 local_state);
471 ssl_config_service_manager_.reset(
472 SSLConfigServiceManager::CreateDefaultManager(local_state));
473
474 base::Value* dns_client_enabled_default = new base::FundamentalValue(
475 chrome_browser_net::ConfigureAsyncDnsFieldTrial());
476 local_state->SetDefaultPrefValue(prefs::kBuiltInDnsClientEnabled,
477 dns_client_enabled_default);
478
479 dns_client_enabled_.Init(prefs::kBuiltInDnsClientEnabled,
480 local_state,
481 base::Bind(&IOThread::UpdateDnsClientEnabled,
482 base::Unretained(this)));
483 dns_client_enabled_.MoveToThread(
484 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
485
486 quick_check_enabled_.Init(prefs::kQuickCheckEnabled,
487 local_state);
488 quick_check_enabled_.MoveToThread(
489 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
490
491 #if defined(ENABLE_CONFIGURATION_POLICY)
492 is_spdy_disabled_by_policy_ = policy_service->GetPolicies(
493 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())).Get(
494 policy::key::kDisableSpdy) != NULL;
495 #endif // ENABLE_CONFIGURATION_POLICY
496
497 BrowserThread::SetDelegate(BrowserThread::IO, this);
498 }
499
~IOThread()500 IOThread::~IOThread() {
501 // This isn't needed for production code, but in tests, IOThread may
502 // be multiply constructed.
503 BrowserThread::SetDelegate(BrowserThread::IO, NULL);
504
505 pref_proxy_config_tracker_->DetachFromPrefService();
506 DCHECK(!globals_);
507 }
508
globals()509 IOThread::Globals* IOThread::globals() {
510 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
511 return globals_;
512 }
513
SetGlobalsForTesting(Globals * globals)514 void IOThread::SetGlobalsForTesting(Globals* globals) {
515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
516 DCHECK(!globals || !globals_);
517 globals_ = globals;
518 }
519
net_log()520 ChromeNetLog* IOThread::net_log() {
521 return net_log_;
522 }
523
ChangedToOnTheRecord()524 void IOThread::ChangedToOnTheRecord() {
525 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
526 BrowserThread::PostTask(
527 BrowserThread::IO,
528 FROM_HERE,
529 base::Bind(&IOThread::ChangedToOnTheRecordOnIOThread,
530 base::Unretained(this)));
531 }
532
system_url_request_context_getter()533 net::URLRequestContextGetter* IOThread::system_url_request_context_getter() {
534 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
535 if (!system_url_request_context_getter_.get()) {
536 InitSystemRequestContext();
537 }
538 return system_url_request_context_getter_.get();
539 }
540
Init()541 void IOThread::Init() {
542 // Prefer to use InitAsync unless you need initialization to block
543 // the UI thread
544 }
545
InitAsync()546 void IOThread::InitAsync() {
547 TRACE_EVENT0("startup", "IOThread::InitAsync");
548 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
549
550 #if defined(USE_NSS) || defined(OS_IOS)
551 net::SetMessageLoopForNSSHttpIO();
552 #endif
553
554 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
555
556 DCHECK(!globals_);
557 globals_ = new Globals;
558
559 // Add an observer that will emit network change events to the ChromeNetLog.
560 // Assuming NetworkChangeNotifier dispatches in FIFO order, we should be
561 // logging the network change before other IO thread consumers respond to it.
562 network_change_observer_.reset(
563 new LoggingNetworkChangeObserver(net_log_));
564
565 // Setup the HistogramWatcher to run on the IO thread.
566 net::NetworkChangeNotifier::InitHistogramWatcher();
567
568 #if defined(ENABLE_EXTENSIONS)
569 globals_->extension_event_router_forwarder =
570 extension_event_router_forwarder_;
571 #endif
572
573 ChromeNetworkDelegate* network_delegate =
574 new ChromeNetworkDelegate(extension_event_router_forwarder(),
575 &system_enable_referrers_);
576
577 if (command_line.HasSwitch(switches::kEnableClientHints))
578 network_delegate->SetEnableClientHints();
579
580 #if defined(ENABLE_EXTENSIONS)
581 if (command_line.HasSwitch(switches::kDisableExtensionsHttpThrottling))
582 network_delegate->NeverThrottleRequests();
583 #endif
584
585 globals_->system_network_delegate.reset(network_delegate);
586 globals_->host_resolver = CreateGlobalHostResolver(net_log_);
587 UpdateDnsClientEnabled();
588 #if defined(OS_CHROMEOS)
589 // Creates a CertVerifyProc that doesn't allow any profile-provided certs.
590 globals_->cert_verifier.reset(new net::MultiThreadedCertVerifier(
591 new chromeos::CertVerifyProcChromeOS()));
592 #else
593 globals_->cert_verifier.reset(new net::MultiThreadedCertVerifier(
594 net::CertVerifyProc::CreateDefault()));
595 #endif
596
597 globals_->transport_security_state.reset(new net::TransportSecurityState());
598
599 net::MultiLogCTVerifier* ct_verifier = new net::MultiLogCTVerifier();
600 globals_->cert_transparency_verifier.reset(ct_verifier);
601
602 // Add built-in logs
603 ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs());
604
605 // Add logs from command line
606 if (command_line.HasSwitch(switches::kCertificateTransparencyLog)) {
607 std::string switch_value = command_line.GetSwitchValueASCII(
608 switches::kCertificateTransparencyLog);
609 std::vector<std::string> logs;
610 base::SplitString(switch_value, ',', &logs);
611 for (std::vector<std::string>::iterator it = logs.begin(); it != logs.end();
612 ++it) {
613 const std::string& curr_log = *it;
614 size_t delim_pos = curr_log.find(":");
615 CHECK(delim_pos != std::string::npos)
616 << "CT log description not provided (switch format"
617 " is 'description:base64_key')";
618 std::string log_description(curr_log.substr(0, delim_pos));
619 std::string ct_public_key_data;
620 CHECK(base::Base64Decode(curr_log.substr(delim_pos + 1),
621 &ct_public_key_data))
622 << "Unable to decode CT public key.";
623 scoped_ptr<net::CTLogVerifier> external_log_verifier(
624 net::CTLogVerifier::Create(ct_public_key_data, log_description));
625 CHECK(external_log_verifier) << "Unable to parse CT public key.";
626 VLOG(1) << "Adding log with description " << log_description;
627 ct_verifier->AddLog(external_log_verifier.Pass());
628 }
629 }
630
631 globals_->ssl_config_service = GetSSLConfigService();
632
633 SetupDataReductionProxy(network_delegate);
634
635 globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory(
636 globals_->host_resolver.get()));
637 globals_->http_server_properties.reset(new net::HttpServerPropertiesImpl());
638 // For the ProxyScriptFetcher, we use a direct ProxyService.
639 globals_->proxy_script_fetcher_proxy_service.reset(
640 net::ProxyService::CreateDirectWithNetLog(net_log_));
641 // In-memory cookie store.
642 globals_->system_cookie_store =
643 content::CreateCookieStore(content::CookieStoreConfig());
644 // In-memory channel ID store.
645 globals_->system_channel_id_service.reset(
646 new net::ChannelIDService(
647 new net::DefaultChannelIDStore(NULL),
648 base::WorkerPool::GetTaskRunner(true)));
649 globals_->dns_probe_service.reset(new chrome_browser_net::DnsProbeService());
650 globals_->host_mapping_rules.reset(new net::HostMappingRules());
651 globals_->http_user_agent_settings.reset(
652 new net::StaticHttpUserAgentSettings(std::string(), GetUserAgent()));
653 if (command_line.HasSwitch(switches::kHostRules)) {
654 TRACE_EVENT_BEGIN0("startup", "IOThread::InitAsync:SetRulesFromString");
655 globals_->host_mapping_rules->SetRulesFromString(
656 command_line.GetSwitchValueASCII(switches::kHostRules));
657 TRACE_EVENT_END0("startup", "IOThread::InitAsync:SetRulesFromString");
658 }
659 if (command_line.HasSwitch(switches::kEnableSSLConnectJobWaiting))
660 globals_->enable_ssl_connect_job_waiting = true;
661 if (command_line.HasSwitch(switches::kIgnoreCertificateErrors))
662 globals_->ignore_certificate_errors = true;
663 if (command_line.HasSwitch(switches::kTestingFixedHttpPort)) {
664 globals_->testing_fixed_http_port =
665 GetSwitchValueAsInt(command_line, switches::kTestingFixedHttpPort);
666 }
667 if (command_line.HasSwitch(switches::kTestingFixedHttpsPort)) {
668 globals_->testing_fixed_https_port =
669 GetSwitchValueAsInt(command_line, switches::kTestingFixedHttpsPort);
670 }
671 ConfigureQuic(command_line);
672 if (command_line.HasSwitch(
673 switches::kEnableUserAlternateProtocolPorts)) {
674 globals_->enable_user_alternate_protocol_ports = true;
675 }
676 InitializeNetworkOptions(command_line);
677
678 net::HttpNetworkSession::Params session_params;
679 InitializeNetworkSessionParams(&session_params);
680 session_params.net_log = net_log_;
681 session_params.proxy_service =
682 globals_->proxy_script_fetcher_proxy_service.get();
683
684 TRACE_EVENT_BEGIN0("startup", "IOThread::InitAsync:HttpNetworkSession");
685 scoped_refptr<net::HttpNetworkSession> network_session(
686 new net::HttpNetworkSession(session_params));
687 globals_->proxy_script_fetcher_http_transaction_factory
688 .reset(new net::HttpNetworkLayer(network_session.get()));
689 TRACE_EVENT_END0("startup", "IOThread::InitAsync:HttpNetworkSession");
690 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
691 new net::URLRequestJobFactoryImpl());
692 job_factory->SetProtocolHandler(url::kDataScheme,
693 new net::DataProtocolHandler());
694 job_factory->SetProtocolHandler(
695 url::kFileScheme,
696 new net::FileProtocolHandler(
697 content::BrowserThread::GetBlockingPool()->
698 GetTaskRunnerWithShutdownBehavior(
699 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
700 #if !defined(DISABLE_FTP_SUPPORT)
701 globals_->proxy_script_fetcher_ftp_transaction_factory.reset(
702 new net::FtpNetworkLayer(globals_->host_resolver.get()));
703 job_factory->SetProtocolHandler(
704 url::kFtpScheme,
705 new net::FtpProtocolHandler(
706 globals_->proxy_script_fetcher_ftp_transaction_factory.get()));
707 #endif
708 globals_->proxy_script_fetcher_url_request_job_factory =
709 job_factory.PassAs<net::URLRequestJobFactory>();
710
711 globals_->throttler_manager.reset(new net::URLRequestThrottlerManager());
712 globals_->throttler_manager->set_net_log(net_log_);
713 // Always done in production, disabled only for unit tests.
714 globals_->throttler_manager->set_enable_thread_checks(true);
715
716 globals_->proxy_script_fetcher_context.reset(
717 ConstructProxyScriptFetcherContext(globals_, net_log_));
718
719 #if defined(OS_MACOSX) && !defined(OS_IOS)
720 // Start observing Keychain events. This needs to be done on the UI thread,
721 // as Keychain services requires a CFRunLoop.
722 BrowserThread::PostTask(BrowserThread::UI,
723 FROM_HERE,
724 base::Bind(&ObserveKeychainEvents));
725 #endif
726
727 // InitSystemRequestContext turns right around and posts a task back
728 // to the IO thread, so we can't let it run until we know the IO
729 // thread has started.
730 //
731 // Note that since we are at BrowserThread::Init time, the UI thread
732 // is blocked waiting for the thread to start. Therefore, posting
733 // this task to the main thread's message loop here is guaranteed to
734 // get it onto the message loop while the IOThread object still
735 // exists. However, the message might not be processed on the UI
736 // thread until after IOThread is gone, so use a weak pointer.
737 BrowserThread::PostTask(BrowserThread::UI,
738 FROM_HERE,
739 base::Bind(&IOThread::InitSystemRequestContext,
740 weak_factory_.GetWeakPtr()));
741 }
742
CleanUp()743 void IOThread::CleanUp() {
744 base::debug::LeakTracker<SafeBrowsingURLRequestContext>::CheckForLeaks();
745
746 #if defined(USE_NSS) || defined(OS_IOS)
747 net::ShutdownNSSHttpIO();
748 #endif
749
750 system_url_request_context_getter_ = NULL;
751
752 // Release objects that the net::URLRequestContext could have been pointing
753 // to.
754
755 // Shutdown the HistogramWatcher on the IO thread.
756 net::NetworkChangeNotifier::ShutdownHistogramWatcher();
757
758 // This must be reset before the ChromeNetLog is destroyed.
759 network_change_observer_.reset();
760
761 system_proxy_config_service_.reset();
762
763 delete globals_;
764 globals_ = NULL;
765
766 base::debug::LeakTracker<SystemURLRequestContextGetter>::CheckForLeaks();
767 }
768
InitializeNetworkOptions(const CommandLine & command_line)769 void IOThread::InitializeNetworkOptions(const CommandLine& command_line) {
770 // Only handle use-spdy command line flags if "spdy.disabled" preference is
771 // not disabled via policy.
772 if (is_spdy_disabled_by_policy_) {
773 base::FieldTrial* trial = base::FieldTrialList::Find(kSpdyFieldTrialName);
774 if (trial)
775 trial->Disable();
776 } else {
777 if (command_line.HasSwitch(switches::kTrustedSpdyProxy)) {
778 globals_->trusted_spdy_proxy.set(
779 command_line.GetSwitchValueASCII(switches::kTrustedSpdyProxy));
780 }
781 if (command_line.HasSwitch(switches::kIgnoreUrlFetcherCertRequests))
782 net::URLFetcher::SetIgnoreCertificateRequests(true);
783
784 if (command_line.HasSwitch(switches::kUseSpdy)) {
785 std::string spdy_mode =
786 command_line.GetSwitchValueASCII(switches::kUseSpdy);
787 EnableSpdy(spdy_mode);
788 } else if (command_line.HasSwitch(switches::kEnableSpdy4)) {
789 globals_->next_protos = net::NextProtosSpdy4Http2();
790 globals_->use_alternate_protocols.set(true);
791 } else if (command_line.HasSwitch(switches::kDisableSpdy31)) {
792 globals_->next_protos = net::NextProtosSpdy3();
793 globals_->use_alternate_protocols.set(true);
794 } else if (command_line.HasSwitch(switches::kEnableNpnHttpOnly)) {
795 globals_->next_protos = net::NextProtosHttpOnly();
796 globals_->use_alternate_protocols.set(false);
797 } else if (command_line.HasSwitch(switches::kEnableWebSocketOverSpdy)) {
798 // Use the current SPDY default (SPDY/3.1).
799 globals_->next_protos = net::NextProtosSpdy31();
800 globals_->use_alternate_protocols.set(true);
801 } else {
802 // No SPDY command-line flags have been specified. Examine trial groups.
803 ConfigureSpdyFromTrial(
804 base::FieldTrialList::FindFullName(kSpdyFieldTrialName), globals_);
805 }
806
807 if (command_line.HasSwitch(switches::kEnableWebSocketOverSpdy))
808 globals_->enable_websocket_over_spdy.set(true);
809 }
810
811 ConfigureTCPFastOpen(command_line);
812
813 // TODO(rch): Make the client socket factory a per-network session
814 // instance, constructed from a NetworkSession::Params, to allow us
815 // to move this option to IOThread::Globals &
816 // HttpNetworkSession::Params.
817 }
818
ConfigureTCPFastOpen(const CommandLine & command_line)819 void IOThread::ConfigureTCPFastOpen(const CommandLine& command_line) {
820 const std::string trial_group =
821 base::FieldTrialList::FindFullName(kTCPFastOpenFieldTrialName);
822 if (trial_group == kTCPFastOpenHttpsEnabledGroupName)
823 globals_->enable_tcp_fast_open_for_ssl.set(true);
824 bool always_enable_if_supported =
825 command_line.HasSwitch(switches::kEnableTcpFastOpen);
826 // Check for OS support of TCP FastOpen, and turn it on for all connections
827 // if indicated by user.
828 net::CheckSupportAndMaybeEnableTCPFastOpen(always_enable_if_supported);
829 }
830
ConfigureSpdyFromTrial(base::StringPiece spdy_trial_group,Globals * globals)831 void IOThread::ConfigureSpdyFromTrial(base::StringPiece spdy_trial_group,
832 Globals* globals) {
833 if (spdy_trial_group.starts_with(kSpdyFieldTrialHoldbackGroupNamePrefix)) {
834 // TODO(jgraettinger): Use net::NextProtosHttpOnly() instead?
835 net::HttpStreamFactory::set_spdy_enabled(false);
836 } else if (spdy_trial_group == kSpdyFieldTrialHoldbackControlGroupName) {
837 // Use the current SPDY default (SPDY/3.1).
838 globals->next_protos = net::NextProtosSpdy31();
839 globals->use_alternate_protocols.set(true);
840 } else if (spdy_trial_group.starts_with(
841 kSpdyFieldTrialSpdy31GroupNamePrefix)) {
842 globals->next_protos = net::NextProtosSpdy4Http2();
843 globals->use_alternate_protocols.set(true);
844 } else if (spdy_trial_group.starts_with(
845 kSpdyFieldTrialSpdy4GroupNamePrefix)) {
846 globals->next_protos = net::NextProtosSpdy4Http2();
847 globals->use_alternate_protocols.set(true);
848 } else if (spdy_trial_group == kSpdyFieldTrialSpdy4ControlGroupName) {
849 // This control group is pinned at SPDY/3.1.
850 globals->next_protos = net::NextProtosSpdy31();
851 globals->use_alternate_protocols.set(true);
852 } else {
853 // Use the current SPDY default (SPDY/3.1).
854 globals->next_protos = net::NextProtosSpdy31();
855 globals->use_alternate_protocols.set(true);
856 }
857 }
858
EnableSpdy(const std::string & mode)859 void IOThread::EnableSpdy(const std::string& mode) {
860 static const char kOff[] = "off";
861 static const char kSSL[] = "ssl";
862 static const char kDisableSSL[] = "no-ssl";
863 static const char kDisablePing[] = "no-ping";
864 static const char kExclude[] = "exclude"; // Hosts to exclude
865 static const char kDisableCompression[] = "no-compress";
866 static const char kDisableAltProtocols[] = "no-alt-protocols";
867 static const char kForceAltProtocols[] = "force-alt-protocols";
868 static const char kSingleDomain[] = "single-domain";
869
870 static const char kInitialMaxConcurrentStreams[] = "init-max-streams";
871
872 std::vector<std::string> spdy_options;
873 base::SplitString(mode, ',', &spdy_options);
874
875 for (std::vector<std::string>::iterator it = spdy_options.begin();
876 it != spdy_options.end(); ++it) {
877 const std::string& element = *it;
878 std::vector<std::string> name_value;
879 base::SplitString(element, '=', &name_value);
880 const std::string& option =
881 name_value.size() > 0 ? name_value[0] : std::string();
882 const std::string value =
883 name_value.size() > 1 ? name_value[1] : std::string();
884
885 if (option == kOff) {
886 net::HttpStreamFactory::set_spdy_enabled(false);
887 } else if (option == kDisableSSL) {
888 globals_->spdy_default_protocol.set(net::kProtoSPDY3);
889 globals_->force_spdy_over_ssl.set(false);
890 globals_->force_spdy_always.set(true);
891 } else if (option == kSSL) {
892 globals_->spdy_default_protocol.set(net::kProtoSPDY3);
893 globals_->force_spdy_over_ssl.set(true);
894 globals_->force_spdy_always.set(true);
895 } else if (option == kDisablePing) {
896 globals_->enable_spdy_ping_based_connection_checking.set(false);
897 } else if (option == kExclude) {
898 globals_->forced_spdy_exclusions.insert(
899 net::HostPortPair::FromURL(GURL(value)));
900 } else if (option == kDisableCompression) {
901 globals_->enable_spdy_compression.set(false);
902 } else if (option == kDisableAltProtocols) {
903 globals_->use_alternate_protocols.set(false);
904 } else if (option == kForceAltProtocols) {
905 net::AlternateProtocolInfo pair(443, net::NPN_SPDY_3, 1);
906 net::HttpServerPropertiesImpl::ForceAlternateProtocol(pair);
907 } else if (option == kSingleDomain) {
908 DVLOG(1) << "FORCING SINGLE DOMAIN";
909 globals_->force_spdy_single_domain.set(true);
910 } else if (option == kInitialMaxConcurrentStreams) {
911 int streams;
912 if (base::StringToInt(value, &streams))
913 globals_->initial_max_spdy_concurrent_streams.set(streams);
914 } else if (option.empty() && it == spdy_options.begin()) {
915 continue;
916 } else {
917 LOG(DFATAL) << "Unrecognized spdy option: " << option;
918 }
919 }
920 }
921
922 // static
RegisterPrefs(PrefRegistrySimple * registry)923 void IOThread::RegisterPrefs(PrefRegistrySimple* registry) {
924 registry->RegisterStringPref(prefs::kAuthSchemes,
925 "basic,digest,ntlm,negotiate,"
926 "spdyproxy");
927 registry->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup, false);
928 registry->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort, false);
929 registry->RegisterStringPref(prefs::kAuthServerWhitelist, std::string());
930 registry->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist,
931 std::string());
932 registry->RegisterStringPref(prefs::kGSSAPILibraryName, std::string());
933 registry->RegisterStringPref(
934 data_reduction_proxy::prefs::kDataReductionProxy, std::string());
935 registry->RegisterBooleanPref(prefs::kEnableReferrers, true);
936 data_reduction_proxy::RegisterPrefs(registry);
937 registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, true);
938 registry->RegisterBooleanPref(prefs::kQuickCheckEnabled, true);
939 }
940
CreateDefaultAuthHandlerFactory(net::HostResolver * resolver)941 net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory(
942 net::HostResolver* resolver) {
943 net::HttpAuthFilterWhitelist* auth_filter_default_credentials = NULL;
944 if (!auth_server_whitelist_.empty()) {
945 auth_filter_default_credentials =
946 new net::HttpAuthFilterWhitelist(auth_server_whitelist_);
947 }
948 net::HttpAuthFilterWhitelist* auth_filter_delegate = NULL;
949 if (!auth_delegate_whitelist_.empty()) {
950 auth_filter_delegate =
951 new net::HttpAuthFilterWhitelist(auth_delegate_whitelist_);
952 }
953 globals_->url_security_manager.reset(
954 net::URLSecurityManager::Create(auth_filter_default_credentials,
955 auth_filter_delegate));
956 std::vector<std::string> supported_schemes;
957 base::SplitString(auth_schemes_, ',', &supported_schemes);
958
959 scoped_ptr<net::HttpAuthHandlerRegistryFactory> registry_factory(
960 net::HttpAuthHandlerRegistryFactory::Create(
961 supported_schemes, globals_->url_security_manager.get(),
962 resolver, gssapi_library_name_, negotiate_disable_cname_lookup_,
963 negotiate_enable_port_));
964 return registry_factory.release();
965 }
966
ClearHostCache()967 void IOThread::ClearHostCache() {
968 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
969
970 net::HostCache* host_cache = globals_->host_resolver->GetHostCache();
971 if (host_cache)
972 host_cache->clear();
973 }
974
InitializeNetworkSessionParams(net::HttpNetworkSession::Params * params)975 void IOThread::InitializeNetworkSessionParams(
976 net::HttpNetworkSession::Params* params) {
977 InitializeNetworkSessionParamsFromGlobals(*globals_, params);
978 }
979
980 // static
InitializeNetworkSessionParamsFromGlobals(const IOThread::Globals & globals,net::HttpNetworkSession::Params * params)981 void IOThread::InitializeNetworkSessionParamsFromGlobals(
982 const IOThread::Globals& globals,
983 net::HttpNetworkSession::Params* params) {
984 params->host_resolver = globals.host_resolver.get();
985 params->cert_verifier = globals.cert_verifier.get();
986 params->channel_id_service = globals.system_channel_id_service.get();
987 params->transport_security_state = globals.transport_security_state.get();
988 params->ssl_config_service = globals.ssl_config_service.get();
989 params->http_auth_handler_factory = globals.http_auth_handler_factory.get();
990 params->http_server_properties =
991 globals.http_server_properties->GetWeakPtr();
992 params->network_delegate = globals.system_network_delegate.get();
993 params->host_mapping_rules = globals.host_mapping_rules.get();
994 params->enable_ssl_connect_job_waiting =
995 globals.enable_ssl_connect_job_waiting;
996 params->ignore_certificate_errors = globals.ignore_certificate_errors;
997 params->testing_fixed_http_port = globals.testing_fixed_http_port;
998 params->testing_fixed_https_port = globals.testing_fixed_https_port;
999 globals.enable_tcp_fast_open_for_ssl.CopyToIfSet(
1000 ¶ms->enable_tcp_fast_open_for_ssl);
1001
1002 globals.initial_max_spdy_concurrent_streams.CopyToIfSet(
1003 ¶ms->spdy_initial_max_concurrent_streams);
1004 globals.force_spdy_single_domain.CopyToIfSet(
1005 ¶ms->force_spdy_single_domain);
1006 globals.enable_spdy_compression.CopyToIfSet(
1007 ¶ms->enable_spdy_compression);
1008 globals.enable_spdy_ping_based_connection_checking.CopyToIfSet(
1009 ¶ms->enable_spdy_ping_based_connection_checking);
1010 globals.spdy_default_protocol.CopyToIfSet(
1011 ¶ms->spdy_default_protocol);
1012 params->next_protos = globals.next_protos;
1013 globals.trusted_spdy_proxy.CopyToIfSet(¶ms->trusted_spdy_proxy);
1014 globals.force_spdy_over_ssl.CopyToIfSet(¶ms->force_spdy_over_ssl);
1015 globals.force_spdy_always.CopyToIfSet(¶ms->force_spdy_always);
1016 params->forced_spdy_exclusions = globals.forced_spdy_exclusions;
1017 globals.use_alternate_protocols.CopyToIfSet(
1018 ¶ms->use_alternate_protocols);
1019 globals.alternate_protocol_probability_threshold.CopyToIfSet(
1020 ¶ms->alternate_protocol_probability_threshold);
1021 globals.enable_websocket_over_spdy.CopyToIfSet(
1022 ¶ms->enable_websocket_over_spdy);
1023
1024 globals.enable_quic.CopyToIfSet(¶ms->enable_quic);
1025 globals.enable_quic_time_based_loss_detection.CopyToIfSet(
1026 ¶ms->enable_quic_time_based_loss_detection);
1027 globals.quic_always_require_handshake_confirmation.CopyToIfSet(
1028 ¶ms->quic_always_require_handshake_confirmation);
1029 globals.quic_disable_connection_pooling.CopyToIfSet(
1030 ¶ms->quic_disable_connection_pooling);
1031 globals.enable_quic_port_selection.CopyToIfSet(
1032 ¶ms->enable_quic_port_selection);
1033 globals.quic_max_packet_length.CopyToIfSet(¶ms->quic_max_packet_length);
1034 globals.quic_user_agent_id.CopyToIfSet(¶ms->quic_user_agent_id);
1035 globals.quic_supported_versions.CopyToIfSet(
1036 ¶ms->quic_supported_versions);
1037 params->quic_connection_options = globals.quic_connection_options;
1038
1039 globals.origin_to_force_quic_on.CopyToIfSet(
1040 ¶ms->origin_to_force_quic_on);
1041 params->enable_user_alternate_protocol_ports =
1042 globals.enable_user_alternate_protocol_ports;
1043 params->proxy_delegate = globals.data_reduction_proxy_delegate.get();
1044 }
1045
creation_time() const1046 base::TimeTicks IOThread::creation_time() const {
1047 return creation_time_;
1048 }
1049
GetSSLConfigService()1050 net::SSLConfigService* IOThread::GetSSLConfigService() {
1051 return ssl_config_service_manager_->Get();
1052 }
1053
ChangedToOnTheRecordOnIOThread()1054 void IOThread::ChangedToOnTheRecordOnIOThread() {
1055 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1056
1057 // Clear the host cache to avoid showing entries from the OTR session
1058 // in about:net-internals.
1059 ClearHostCache();
1060 }
1061
InitSystemRequestContext()1062 void IOThread::InitSystemRequestContext() {
1063 if (system_url_request_context_getter_.get())
1064 return;
1065 // If we're in unit_tests, IOThread may not be run.
1066 if (!BrowserThread::IsMessageLoopValid(BrowserThread::IO))
1067 return;
1068 system_proxy_config_service_.reset(
1069 ProxyServiceFactory::CreateProxyConfigService(
1070 pref_proxy_config_tracker_.get()));
1071 system_url_request_context_getter_ =
1072 new SystemURLRequestContextGetter(this);
1073 // Safe to post an unretained this pointer, since IOThread is
1074 // guaranteed to outlive the IO BrowserThread.
1075 BrowserThread::PostTask(
1076 BrowserThread::IO,
1077 FROM_HERE,
1078 base::Bind(&IOThread::InitSystemRequestContextOnIOThread,
1079 base::Unretained(this)));
1080 }
1081
InitSystemRequestContextOnIOThread()1082 void IOThread::InitSystemRequestContextOnIOThread() {
1083 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1084 DCHECK(!globals_->system_proxy_service.get());
1085 DCHECK(system_proxy_config_service_.get());
1086
1087 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1088 globals_->system_proxy_service.reset(
1089 ProxyServiceFactory::CreateProxyService(
1090 net_log_,
1091 globals_->proxy_script_fetcher_context.get(),
1092 globals_->system_network_delegate.get(),
1093 system_proxy_config_service_.release(),
1094 command_line,
1095 quick_check_enabled_.GetValue()));
1096 DCHECK(globals_->data_reduction_proxy_params);
1097
1098 net::HttpNetworkSession::Params system_params;
1099 InitializeNetworkSessionParams(&system_params);
1100 system_params.net_log = net_log_;
1101 system_params.proxy_service = globals_->system_proxy_service.get();
1102
1103 globals_->system_http_transaction_factory.reset(
1104 new net::HttpNetworkLayer(
1105 new net::HttpNetworkSession(system_params)));
1106 globals_->system_url_request_job_factory.reset(
1107 new net::URLRequestJobFactoryImpl());
1108 globals_->system_request_context.reset(
1109 ConstructSystemRequestContext(globals_, net_log_));
1110 globals_->system_request_context->set_ssl_config_service(
1111 globals_->ssl_config_service.get());
1112 globals_->system_request_context->set_http_server_properties(
1113 globals_->http_server_properties->GetWeakPtr());
1114 }
1115
UpdateDnsClientEnabled()1116 void IOThread::UpdateDnsClientEnabled() {
1117 globals()->host_resolver->SetDnsClientEnabled(*dns_client_enabled_);
1118 }
1119
ConfigureQuic(const CommandLine & command_line)1120 void IOThread::ConfigureQuic(const CommandLine& command_line) {
1121 // Always fetch the field trial group to ensure it is reported correctly.
1122 // The command line flags will be associated with a group that is reported
1123 // so long as trial is actually queried.
1124 std::string group =
1125 base::FieldTrialList::FindFullName(kQuicFieldTrialName);
1126 VariationParameters params;
1127 if (!variations::GetVariationParams(kQuicFieldTrialName, ¶ms)) {
1128 params.clear();
1129 }
1130
1131 ConfigureQuicGlobals(command_line, group, params, globals_);
1132 }
1133
SetupDataReductionProxy(ChromeNetworkDelegate * network_delegate)1134 void IOThread::SetupDataReductionProxy(
1135 ChromeNetworkDelegate* network_delegate) {
1136 // TODO(kundaji): Move flags initialization to DataReductionProxyParams and
1137 // merge with flag initialization in
1138 // data_reduction_proxy_chrome_settings_factory.cc.
1139 int flags = data_reduction_proxy::DataReductionProxyParams::kAllowed |
1140 data_reduction_proxy::DataReductionProxyParams::kFallbackAllowed |
1141 data_reduction_proxy::DataReductionProxyParams::kAlternativeAllowed;
1142 if (data_reduction_proxy::DataReductionProxyParams::
1143 IsIncludedInPromoFieldTrial()) {
1144 flags |= data_reduction_proxy::DataReductionProxyParams::kPromoAllowed;
1145 }
1146 if (data_reduction_proxy::DataReductionProxyParams::
1147 IsIncludedInHoldbackFieldTrial()) {
1148 flags |= data_reduction_proxy::DataReductionProxyParams::kHoldback;
1149 }
1150 globals_->data_reduction_proxy_params.reset(
1151 new data_reduction_proxy::DataReductionProxyParams(flags));
1152 globals_->data_reduction_proxy_auth_request_handler.reset(
1153 new data_reduction_proxy::DataReductionProxyAuthRequestHandler(
1154 DataReductionProxyChromeSettings::GetClient(),
1155 globals_->data_reduction_proxy_params.get(),
1156 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)));
1157 globals_->data_reduction_proxy_delegate.reset(
1158 new data_reduction_proxy::DataReductionProxyDelegate(
1159 globals_->data_reduction_proxy_auth_request_handler.get()));
1160 // This is the same as in ProfileImplIOData except that we do not collect
1161 // usage stats.
1162 network_delegate->set_data_reduction_proxy_params(
1163 globals_->data_reduction_proxy_params.get());
1164 network_delegate->set_data_reduction_proxy_auth_request_handler(
1165 globals_->data_reduction_proxy_auth_request_handler.get());
1166 network_delegate->set_on_resolve_proxy_handler(
1167 base::Bind(data_reduction_proxy::OnResolveProxyHandler));
1168 }
1169
1170 // static
ConfigureQuicGlobals(const base::CommandLine & command_line,base::StringPiece quic_trial_group,const VariationParameters & quic_trial_params,IOThread::Globals * globals)1171 void IOThread::ConfigureQuicGlobals(
1172 const base::CommandLine& command_line,
1173 base::StringPiece quic_trial_group,
1174 const VariationParameters& quic_trial_params,
1175 IOThread::Globals* globals) {
1176 bool enable_quic = ShouldEnableQuic(command_line, quic_trial_group);
1177 globals->enable_quic.set(enable_quic);
1178 if (enable_quic) {
1179 globals->enable_quic_time_based_loss_detection.set(
1180 ShouldEnableQuicTimeBasedLossDetection(command_line, quic_trial_group,
1181 quic_trial_params));
1182 globals->quic_always_require_handshake_confirmation.set(
1183 ShouldQuicAlwaysRequireHandshakeConfirmation(quic_trial_params));
1184 globals->quic_disable_connection_pooling.set(
1185 ShouldQuicDisableConnectionPooling(quic_trial_params));
1186 globals->enable_quic_port_selection.set(
1187 ShouldEnableQuicPortSelection(command_line));
1188 globals->quic_connection_options =
1189 GetQuicConnectionOptions(command_line, quic_trial_params);
1190 if (ShouldEnableQuicPacing(command_line, quic_trial_group,
1191 quic_trial_params)) {
1192 globals->quic_connection_options.push_back(net::kPACE);
1193 }
1194 }
1195
1196 size_t max_packet_length = GetQuicMaxPacketLength(command_line,
1197 quic_trial_group,
1198 quic_trial_params);
1199 if (max_packet_length != 0) {
1200 globals->quic_max_packet_length.set(max_packet_length);
1201 }
1202
1203 std::string quic_user_agent_id =
1204 chrome::VersionInfo::GetVersionStringModifier();
1205 if (!quic_user_agent_id.empty())
1206 quic_user_agent_id.push_back(' ');
1207 chrome::VersionInfo version_info;
1208 quic_user_agent_id.append(version_info.ProductNameAndVersionForUserAgent());
1209 globals->quic_user_agent_id.set(quic_user_agent_id);
1210
1211 net::QuicVersion version = GetQuicVersion(command_line, quic_trial_params);
1212 if (version != net::QUIC_VERSION_UNSUPPORTED) {
1213 net::QuicVersionVector supported_versions;
1214 supported_versions.push_back(version);
1215 globals->quic_supported_versions.set(supported_versions);
1216 }
1217
1218 double threshold =
1219 GetAlternateProtocolProbabilityThreshold(command_line, quic_trial_params);
1220 if (threshold >=0 && threshold <= 1) {
1221 globals->alternate_protocol_probability_threshold.set(threshold);
1222 globals->http_server_properties->SetAlternateProtocolProbabilityThreshold(
1223 threshold);
1224 }
1225
1226 if (command_line.HasSwitch(switches::kOriginToForceQuicOn)) {
1227 net::HostPortPair quic_origin =
1228 net::HostPortPair::FromString(
1229 command_line.GetSwitchValueASCII(switches::kOriginToForceQuicOn));
1230 if (!quic_origin.IsEmpty()) {
1231 globals->origin_to_force_quic_on.set(quic_origin);
1232 }
1233 }
1234 }
1235
ShouldEnableQuic(const CommandLine & command_line,base::StringPiece quic_trial_group)1236 bool IOThread::ShouldEnableQuic(const CommandLine& command_line,
1237 base::StringPiece quic_trial_group) {
1238 if (command_line.HasSwitch(switches::kDisableQuic))
1239 return false;
1240
1241 if (command_line.HasSwitch(switches::kEnableQuic))
1242 return true;
1243
1244 return quic_trial_group.starts_with(kQuicFieldTrialEnabledGroupName) ||
1245 quic_trial_group.starts_with(kQuicFieldTrialHttpsEnabledGroupName);
1246 }
1247
ShouldEnableQuicPortSelection(const CommandLine & command_line)1248 bool IOThread::ShouldEnableQuicPortSelection(
1249 const CommandLine& command_line) {
1250 if (command_line.HasSwitch(switches::kDisableQuicPortSelection))
1251 return false;
1252
1253 if (command_line.HasSwitch(switches::kEnableQuicPortSelection))
1254 return true;
1255
1256 return false; // Default to disabling port selection on all channels.
1257 }
1258
ShouldEnableQuicPacing(const CommandLine & command_line,base::StringPiece quic_trial_group,const VariationParameters & quic_trial_params)1259 bool IOThread::ShouldEnableQuicPacing(
1260 const CommandLine& command_line,
1261 base::StringPiece quic_trial_group,
1262 const VariationParameters& quic_trial_params) {
1263 if (command_line.HasSwitch(switches::kEnableQuicPacing))
1264 return true;
1265
1266 if (command_line.HasSwitch(switches::kDisableQuicPacing))
1267 return false;
1268
1269 if (LowerCaseEqualsASCII(
1270 GetVariationParam(quic_trial_params, "enable_pacing"),
1271 "true"))
1272 return true;
1273
1274 return quic_trial_group.ends_with(kQuicFieldTrialPacingSuffix);
1275 }
1276
GetQuicConnectionOptions(const CommandLine & command_line,const VariationParameters & quic_trial_params)1277 net::QuicTagVector IOThread::GetQuicConnectionOptions(
1278 const CommandLine& command_line,
1279 const VariationParameters& quic_trial_params) {
1280 if (command_line.HasSwitch(switches::kQuicConnectionOptions)) {
1281 return ParseQuicConnectionOptions(
1282 command_line.GetSwitchValueASCII(switches::kQuicConnectionOptions));
1283 }
1284
1285 VariationParameters::const_iterator it =
1286 quic_trial_params.find("connection_options");
1287 if (it == quic_trial_params.end()) {
1288 // TODO(rch): remove support for deprecated congestion_options.
1289 it = quic_trial_params.find("congestion_options");
1290 if (it == quic_trial_params.end())
1291 return net::QuicTagVector();
1292 }
1293
1294 return ParseQuicConnectionOptions(it->second);
1295 }
1296
1297 // static
ParseQuicConnectionOptions(const std::string & connection_options)1298 net::QuicTagVector IOThread::ParseQuicConnectionOptions(
1299 const std::string& connection_options) {
1300 net::QuicTagVector options;
1301 std::vector<std::string> tokens;
1302 base::SplitString(connection_options, ',', &tokens);
1303 // Tokens are expected to be no more than 4 characters long, but we
1304 // handle overflow gracefully.
1305 for (std::vector<std::string>::iterator token = tokens.begin();
1306 token != tokens.end(); ++token) {
1307 uint32 option = 0;
1308 for (size_t i = token->length() ; i > 0; --i) {
1309 option <<= 8;
1310 option |= static_cast<unsigned char>((*token)[i - 1]);
1311 }
1312 options.push_back(static_cast<net::QuicTag>(option));
1313 }
1314 return options;
1315 }
1316
1317 // static
GetAlternateProtocolProbabilityThreshold(const base::CommandLine & command_line,const VariationParameters & quic_trial_params)1318 double IOThread::GetAlternateProtocolProbabilityThreshold(
1319 const base::CommandLine& command_line,
1320 const VariationParameters& quic_trial_params) {
1321 double value;
1322 if (command_line.HasSwitch(
1323 switches::kAlternateProtocolProbabilityThreshold)) {
1324 if (base::StringToDouble(
1325 command_line.GetSwitchValueASCII(
1326 switches::kAlternateProtocolProbabilityThreshold),
1327 &value)) {
1328 return value;
1329 }
1330 }
1331 if (command_line.HasSwitch(switches::kEnableQuic)) {
1332 return 0;
1333 }
1334 if (base::StringToDouble(
1335 GetVariationParam(quic_trial_params,
1336 "alternate_protocol_probability_threshold"),
1337 &value)) {
1338 return value;
1339 }
1340 return -1;
1341 }
1342
1343 // static
ShouldEnableQuicTimeBasedLossDetection(const CommandLine & command_line,base::StringPiece quic_trial_group,const VariationParameters & quic_trial_params)1344 bool IOThread::ShouldEnableQuicTimeBasedLossDetection(
1345 const CommandLine& command_line,
1346 base::StringPiece quic_trial_group,
1347 const VariationParameters& quic_trial_params) {
1348 if (command_line.HasSwitch(switches::kEnableQuicTimeBasedLossDetection))
1349 return true;
1350
1351 if (command_line.HasSwitch(switches::kDisableQuicTimeBasedLossDetection))
1352 return false;
1353
1354 if (LowerCaseEqualsASCII(
1355 GetVariationParam(quic_trial_params, "enable_time_based_loss_detection"),
1356 "true"))
1357 return true;
1358
1359 return quic_trial_group.ends_with(
1360 kQuicFieldTrialTimeBasedLossDetectionSuffix);
1361 }
1362
1363 // static
ShouldQuicAlwaysRequireHandshakeConfirmation(const VariationParameters & quic_trial_params)1364 bool IOThread::ShouldQuicAlwaysRequireHandshakeConfirmation(
1365 const VariationParameters& quic_trial_params) {
1366 return LowerCaseEqualsASCII(
1367 GetVariationParam(quic_trial_params,
1368 "always_require_handshake_confirmation"),
1369 "true");
1370 }
1371
1372 // static
ShouldQuicDisableConnectionPooling(const VariationParameters & quic_trial_params)1373 bool IOThread::ShouldQuicDisableConnectionPooling(
1374 const VariationParameters& quic_trial_params) {
1375 return LowerCaseEqualsASCII(
1376 GetVariationParam(quic_trial_params, "disable_connection_pooling"),
1377 "true");
1378 }
1379
1380 // static
GetQuicMaxPacketLength(const CommandLine & command_line,base::StringPiece quic_trial_group,const VariationParameters & quic_trial_params)1381 size_t IOThread::GetQuicMaxPacketLength(
1382 const CommandLine& command_line,
1383 base::StringPiece quic_trial_group,
1384 const VariationParameters& quic_trial_params) {
1385 if (command_line.HasSwitch(switches::kQuicMaxPacketLength)) {
1386 unsigned value;
1387 if (!base::StringToUint(
1388 command_line.GetSwitchValueASCII(switches::kQuicMaxPacketLength),
1389 &value)) {
1390 return 0;
1391 }
1392 return value;
1393 }
1394
1395 unsigned value;
1396 if (base::StringToUint(GetVariationParam(quic_trial_params,
1397 "max_packet_length"),
1398 &value)) {
1399 return value;
1400 }
1401
1402 // Format of the packet length group names is:
1403 // (Https)?Enabled<length>BytePackets.
1404 base::StringPiece length_str(quic_trial_group);
1405 if (length_str.starts_with(kQuicFieldTrialEnabledGroupName)) {
1406 length_str.remove_prefix(strlen(kQuicFieldTrialEnabledGroupName));
1407 } else if (length_str.starts_with(kQuicFieldTrialHttpsEnabledGroupName)) {
1408 length_str.remove_prefix(strlen(kQuicFieldTrialHttpsEnabledGroupName));
1409 } else {
1410 return 0;
1411 }
1412 if (!length_str.ends_with(kQuicFieldTrialPacketLengthSuffix)) {
1413 return 0;
1414 }
1415 length_str.remove_suffix(strlen(kQuicFieldTrialPacketLengthSuffix));
1416 if (!base::StringToUint(length_str, &value)) {
1417 return 0;
1418 }
1419 return value;
1420 }
1421
1422 // static
GetQuicVersion(const CommandLine & command_line,const VariationParameters & quic_trial_params)1423 net::QuicVersion IOThread::GetQuicVersion(
1424 const CommandLine& command_line,
1425 const VariationParameters& quic_trial_params) {
1426 if (command_line.HasSwitch(switches::kQuicVersion)) {
1427 return ParseQuicVersion(
1428 command_line.GetSwitchValueASCII(switches::kQuicVersion));
1429 }
1430
1431 return ParseQuicVersion(GetVariationParam(quic_trial_params, "quic_version"));
1432 }
1433
1434 // static
ParseQuicVersion(const std::string & quic_version)1435 net::QuicVersion IOThread::ParseQuicVersion(const std::string& quic_version) {
1436 net::QuicVersionVector supported_versions = net::QuicSupportedVersions();
1437 for (size_t i = 0; i < supported_versions.size(); ++i) {
1438 net::QuicVersion version = supported_versions[i];
1439 if (net::QuicVersionToString(version) == quic_version) {
1440 return version;
1441 }
1442 }
1443
1444 return net::QUIC_VERSION_UNSUPPORTED;
1445 }
1446