Upstream version 11.39.250.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / io_thread.cc
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)
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:
153   SystemURLRequestContext() {
154 #if defined(USE_NSS) || defined(OS_IOS)
155     net::SetURLRequestContextForNSSHttpIO(this);
156 #endif
157   }
158
159  private:
160   virtual ~SystemURLRequestContext() {
161     AssertNoURLRequests();
162 #if defined(USE_NSS) || defined(OS_IOS)
163     net::SetURLRequestContextForNSSHttpIO(NULL);
164 #endif
165   }
166 };
167
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*
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*
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
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.
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.
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
330   virtual ~LoggingNetworkChangeObserver() {
331     net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
332     net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
333     net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
334   }
335
336   // NetworkChangeNotifier::IPAddressObserver implementation.
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.
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.
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
394 SystemURLRequestContextGetter::SystemURLRequestContextGetter(
395     IOThread* io_thread)
396     : io_thread_(io_thread),
397       network_task_runner_(
398           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
399 }
400
401 SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {}
402
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>
411 SystemURLRequestContextGetter::GetNetworkTaskRunner() const {
412   return network_task_runner_;
413 }
414
415 IOThread::Globals::
416 SystemRequestContextLeakChecker::SystemRequestContextLeakChecker(
417     Globals* globals)
418     : globals_(globals) {
419   DCHECK(globals_);
420 }
421
422 IOThread::Globals::
423 SystemRequestContextLeakChecker::~SystemRequestContextLeakChecker() {
424   if (globals_->system_request_context.get())
425     globals_->system_request_context->AssertNoURLRequests();
426 }
427
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
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.
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
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
509 IOThread::Globals* IOThread::globals() {
510   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
511   return globals_;
512 }
513
514 void IOThread::SetGlobalsForTesting(Globals* globals) {
515   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
516   DCHECK(!globals || !globals_);
517   globals_ = globals;
518 }
519
520 ChromeNetLog* IOThread::net_log() {
521   return net_log_;
522 }
523
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
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
541 void IOThread::Init() {
542   // Prefer to use InitAsync unless you need initialization to block
543   // the UI thread
544 }
545
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
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
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
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
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
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
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
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
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
975 void IOThread::InitializeNetworkSessionParams(
976     net::HttpNetworkSession::Params* params) {
977   InitializeNetworkSessionParamsFromGlobals(*globals_, params);
978 }
979
980 // static
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       &params->enable_tcp_fast_open_for_ssl);
1001
1002   globals.initial_max_spdy_concurrent_streams.CopyToIfSet(
1003       &params->spdy_initial_max_concurrent_streams);
1004   globals.force_spdy_single_domain.CopyToIfSet(
1005       &params->force_spdy_single_domain);
1006   globals.enable_spdy_compression.CopyToIfSet(
1007       &params->enable_spdy_compression);
1008   globals.enable_spdy_ping_based_connection_checking.CopyToIfSet(
1009       &params->enable_spdy_ping_based_connection_checking);
1010   globals.spdy_default_protocol.CopyToIfSet(
1011       &params->spdy_default_protocol);
1012   params->next_protos = globals.next_protos;
1013   globals.trusted_spdy_proxy.CopyToIfSet(&params->trusted_spdy_proxy);
1014   globals.force_spdy_over_ssl.CopyToIfSet(&params->force_spdy_over_ssl);
1015   globals.force_spdy_always.CopyToIfSet(&params->force_spdy_always);
1016   params->forced_spdy_exclusions = globals.forced_spdy_exclusions;
1017   globals.use_alternate_protocols.CopyToIfSet(
1018       &params->use_alternate_protocols);
1019   globals.alternate_protocol_probability_threshold.CopyToIfSet(
1020       &params->alternate_protocol_probability_threshold);
1021   globals.enable_websocket_over_spdy.CopyToIfSet(
1022       &params->enable_websocket_over_spdy);
1023
1024   globals.enable_quic.CopyToIfSet(&params->enable_quic);
1025   globals.enable_quic_time_based_loss_detection.CopyToIfSet(
1026       &params->enable_quic_time_based_loss_detection);
1027   globals.quic_always_require_handshake_confirmation.CopyToIfSet(
1028       &params->quic_always_require_handshake_confirmation);
1029   globals.quic_disable_connection_pooling.CopyToIfSet(
1030       &params->quic_disable_connection_pooling);
1031   globals.enable_quic_port_selection.CopyToIfSet(
1032       &params->enable_quic_port_selection);
1033   globals.quic_max_packet_length.CopyToIfSet(&params->quic_max_packet_length);
1034   globals.quic_user_agent_id.CopyToIfSet(&params->quic_user_agent_id);
1035   globals.quic_supported_versions.CopyToIfSet(
1036       &params->quic_supported_versions);
1037   params->quic_connection_options = globals.quic_connection_options;
1038
1039   globals.origin_to_force_quic_on.CopyToIfSet(
1040       &params->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
1046 base::TimeTicks IOThread::creation_time() const {
1047   return creation_time_;
1048 }
1049
1050 net::SSLConfigService* IOThread::GetSSLConfigService() {
1051   return ssl_config_service_manager_->Get();
1052 }
1053
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
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
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
1116 void IOThread::UpdateDnsClientEnabled() {
1117   globals()->host_resolver->SetDnsClientEnabled(*dns_client_enabled_);
1118 }
1119
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, &params)) {
1128     params.clear();
1129   }
1130
1131   ConfigureQuicGlobals(command_line, group, params, globals_);
1132 }
1133
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }