Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / io_thread.cc
blobaf4638314d5caf594a42e38d32c6d9f553983766
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.
5 #include "chrome/browser/io_thread.h"
7 #include <vector>
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_split.h"
23 #include "base/strings/string_util.h"
24 #include "base/threading/sequenced_worker_pool.h"
25 #include "base/threading/thread.h"
26 #include "base/threading/worker_pool.h"
27 #include "base/time/default_tick_clock.h"
28 #include "build/build_config.h"
29 #include "chrome/browser/browser_process.h"
30 #include "chrome/browser/extensions/event_router_forwarder.h"
31 #include "chrome/browser/net/async_dns_field_trial.h"
32 #include "chrome/browser/net/basic_http_user_agent_settings.h"
33 #include "chrome/browser/net/chrome_net_log.h"
34 #include "chrome/browser/net/chrome_network_delegate.h"
35 #include "chrome/browser/net/chrome_url_request_context.h"
36 #include "chrome/browser/net/connect_interceptor.h"
37 #include "chrome/browser/net/dns_probe_service.h"
38 #include "chrome/browser/net/http_pipelining_compatibility_client.h"
39 #include "chrome/browser/net/pref_proxy_config_tracker.h"
40 #include "chrome/browser/net/proxy_service_factory.h"
41 #include "chrome/browser/net/sdch_dictionary_fetcher.h"
42 #include "chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.h"
43 #include "chrome/common/chrome_switches.h"
44 #include "chrome/common/pref_names.h"
45 #include "chrome/common/url_constants.h"
46 #include "components/policy/core/common/policy_service.h"
47 #include "content/public/browser/browser_thread.h"
48 #include "content/public/browser/cookie_store_factory.h"
49 #include "net/base/host_mapping_rules.h"
50 #include "net/base/net_util.h"
51 #include "net/base/network_time_notifier.h"
52 #include "net/base/sdch_manager.h"
53 #include "net/cert/cert_verifier.h"
54 #include "net/cert/ct_known_logs.h"
55 #include "net/cert/ct_verifier.h"
56 #include "net/cookies/cookie_store.h"
57 #include "net/dns/host_cache.h"
58 #include "net/dns/host_resolver.h"
59 #include "net/dns/mapped_host_resolver.h"
60 #include "net/ftp/ftp_network_layer.h"
61 #include "net/http/http_auth_filter.h"
62 #include "net/http/http_auth_handler_factory.h"
63 #include "net/http/http_network_layer.h"
64 #include "net/http/http_server_properties_impl.h"
65 #include "net/proxy/proxy_config_service.h"
66 #include "net/proxy/proxy_script_fetcher_impl.h"
67 #include "net/proxy/proxy_service.h"
68 #include "net/quic/quic_protocol.h"
69 #include "net/socket/tcp_client_socket.h"
70 #include "net/spdy/spdy_session.h"
71 #include "net/ssl/default_server_bound_cert_store.h"
72 #include "net/ssl/server_bound_cert_service.h"
73 #include "net/url_request/data_protocol_handler.h"
74 #include "net/url_request/file_protocol_handler.h"
75 #include "net/url_request/ftp_protocol_handler.h"
76 #include "net/url_request/url_fetcher.h"
77 #include "net/url_request/url_request_job_factory_impl.h"
78 #include "net/url_request/url_request_throttler_manager.h"
79 #include "net/websockets/websocket_job.h"
81 #if defined(OS_WIN)
82 #include "win8/util/win8_util.h"
83 #endif
85 #if defined(ENABLE_CONFIGURATION_POLICY)
86 #include "policy/policy_constants.h"
87 #endif
89 #if !defined(USE_OPENSSL)
90 #include "net/cert/ct_log_verifier.h"
91 #include "net/cert/multi_log_ct_verifier.h"
92 #endif
94 #if defined(USE_NSS) || defined(OS_IOS)
95 #include "net/ocsp/nss_ocsp.h"
96 #endif
98 #if !defined(OS_IOS) && !defined(OS_ANDROID)
99 #include "net/proxy/proxy_resolver_v8.h"
100 #endif
102 #if defined(OS_ANDROID) || defined(OS_IOS)
103 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_settings.h"
104 #endif
106 using content::BrowserThread;
108 class SafeBrowsingURLRequestContext;
110 // The IOThread object must outlive any tasks posted to the IO thread before the
111 // Quit task, so base::Bind() calls are not refcounted.
113 namespace {
115 const char kQuicFieldTrialName[] = "QUIC";
116 const char kQuicFieldTrialEnabledGroupName[] = "Enabled";
117 const char kQuicFieldTrialHttpsEnabledGroupName[] = "HttpsEnabled";
118 const char kQuicFieldTrialPacketLengthSuffix[] = "BytePackets";
120 const char kSpdyFieldTrialName[] = "SPDY";
121 const char kSpdyFieldTrialDisabledGroupName[] = "SpdyDisabled";
123 #if defined(OS_MACOSX) && !defined(OS_IOS)
124 void ObserveKeychainEvents() {
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
126 net::CertDatabase::GetInstance()->SetMessageLoopForKeychainEvents();
128 #endif
130 // Used for the "system" URLRequestContext.
131 class SystemURLRequestContext : public net::URLRequestContext {
132 public:
133 SystemURLRequestContext() {
134 #if defined(USE_NSS) || defined(OS_IOS)
135 net::SetURLRequestContextForNSSHttpIO(this);
136 #endif
139 private:
140 virtual ~SystemURLRequestContext() {
141 #if defined(USE_NSS) || defined(OS_IOS)
142 net::SetURLRequestContextForNSSHttpIO(NULL);
143 #endif
147 scoped_ptr<net::HostResolver> CreateGlobalHostResolver(net::NetLog* net_log) {
148 TRACE_EVENT0("startup", "IOThread::CreateGlobalHostResolver");
149 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
151 net::HostResolver::Options options;
153 // Use the concurrency override from the command-line, if any.
154 if (command_line.HasSwitch(switches::kHostResolverParallelism)) {
155 std::string s =
156 command_line.GetSwitchValueASCII(switches::kHostResolverParallelism);
158 // Parse the switch (it should be a positive integer formatted as decimal).
159 int n;
160 if (base::StringToInt(s, &n) && n > 0) {
161 options.max_concurrent_resolves = static_cast<size_t>(n);
162 } else {
163 LOG(ERROR) << "Invalid switch for host resolver parallelism: " << s;
167 // Use the retry attempts override from the command-line, if any.
168 if (command_line.HasSwitch(switches::kHostResolverRetryAttempts)) {
169 std::string s =
170 command_line.GetSwitchValueASCII(switches::kHostResolverRetryAttempts);
171 // Parse the switch (it should be a non-negative integer).
172 int n;
173 if (base::StringToInt(s, &n) && n >= 0) {
174 options.max_retry_attempts = static_cast<size_t>(n);
175 } else {
176 LOG(ERROR) << "Invalid switch for host resolver retry attempts: " << s;
180 scoped_ptr<net::HostResolver> global_host_resolver(
181 net::HostResolver::CreateSystemResolver(options, net_log));
183 // Determine if we should disable IPv6 support.
184 if (command_line.HasSwitch(switches::kEnableIPv6)) {
185 // Disable IPv6 probing.
186 global_host_resolver->SetDefaultAddressFamily(
187 net::ADDRESS_FAMILY_UNSPECIFIED);
188 } else if (command_line.HasSwitch(switches::kDisableIPv6)) {
189 global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4);
192 // If hostname remappings were specified on the command-line, layer these
193 // rules on top of the real host resolver. This allows forwarding all requests
194 // through a designated test server.
195 if (!command_line.HasSwitch(switches::kHostResolverRules))
196 return global_host_resolver.PassAs<net::HostResolver>();
198 scoped_ptr<net::MappedHostResolver> remapped_resolver(
199 new net::MappedHostResolver(global_host_resolver.Pass()));
200 remapped_resolver->SetRulesFromString(
201 command_line.GetSwitchValueASCII(switches::kHostResolverRules));
202 return remapped_resolver.PassAs<net::HostResolver>();
205 // TODO(willchan): Remove proxy script fetcher context since it's not necessary
206 // now that I got rid of refcounting URLRequestContexts.
207 // See IOThread::Globals for details.
208 net::URLRequestContext*
209 ConstructProxyScriptFetcherContext(IOThread::Globals* globals,
210 net::NetLog* net_log) {
211 net::URLRequestContext* context = new net::URLRequestContext;
212 context->set_net_log(net_log);
213 context->set_host_resolver(globals->host_resolver.get());
214 context->set_cert_verifier(globals->cert_verifier.get());
215 context->set_transport_security_state(
216 globals->transport_security_state.get());
217 context->set_cert_transparency_verifier(
218 globals->cert_transparency_verifier.get());
219 context->set_http_auth_handler_factory(
220 globals->http_auth_handler_factory.get());
221 context->set_proxy_service(globals->proxy_script_fetcher_proxy_service.get());
222 context->set_http_transaction_factory(
223 globals->proxy_script_fetcher_http_transaction_factory.get());
224 context->set_job_factory(
225 globals->proxy_script_fetcher_url_request_job_factory.get());
226 context->set_cookie_store(globals->system_cookie_store.get());
227 context->set_server_bound_cert_service(
228 globals->system_server_bound_cert_service.get());
229 context->set_network_delegate(globals->system_network_delegate.get());
230 context->set_http_user_agent_settings(
231 globals->http_user_agent_settings.get());
232 // TODO(rtenneti): We should probably use HttpServerPropertiesManager for the
233 // system URLRequestContext too. There's no reason this should be tied to a
234 // profile.
235 return context;
238 net::URLRequestContext*
239 ConstructSystemRequestContext(IOThread::Globals* globals,
240 net::NetLog* net_log) {
241 net::URLRequestContext* context = new SystemURLRequestContext;
242 context->set_net_log(net_log);
243 context->set_host_resolver(globals->host_resolver.get());
244 context->set_cert_verifier(globals->cert_verifier.get());
245 context->set_transport_security_state(
246 globals->transport_security_state.get());
247 context->set_cert_transparency_verifier(
248 globals->cert_transparency_verifier.get());
249 context->set_http_auth_handler_factory(
250 globals->http_auth_handler_factory.get());
251 context->set_proxy_service(globals->system_proxy_service.get());
252 context->set_http_transaction_factory(
253 globals->system_http_transaction_factory.get());
254 context->set_cookie_store(globals->system_cookie_store.get());
255 context->set_server_bound_cert_service(
256 globals->system_server_bound_cert_service.get());
257 context->set_throttler_manager(globals->throttler_manager.get());
258 context->set_network_delegate(globals->system_network_delegate.get());
259 context->set_http_user_agent_settings(
260 globals->http_user_agent_settings.get());
261 return context;
264 int GetSwitchValueAsInt(const CommandLine& command_line,
265 const std::string& switch_name) {
266 int value;
267 if (!base::StringToInt(command_line.GetSwitchValueASCII(switch_name),
268 &value)) {
269 return 0;
271 return value;
274 } // namespace
276 class IOThread::LoggingNetworkChangeObserver
277 : public net::NetworkChangeNotifier::IPAddressObserver,
278 public net::NetworkChangeNotifier::ConnectionTypeObserver,
279 public net::NetworkChangeNotifier::NetworkChangeObserver {
280 public:
281 // |net_log| must remain valid throughout our lifetime.
282 explicit LoggingNetworkChangeObserver(net::NetLog* net_log)
283 : net_log_(net_log) {
284 net::NetworkChangeNotifier::AddIPAddressObserver(this);
285 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
286 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
289 virtual ~LoggingNetworkChangeObserver() {
290 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
291 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
292 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
295 // NetworkChangeNotifier::IPAddressObserver implementation.
296 virtual void OnIPAddressChanged() OVERRIDE {
297 VLOG(1) << "Observed a change to the network IP addresses";
299 net_log_->AddGlobalEntry(net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED);
302 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
303 virtual void OnConnectionTypeChanged(
304 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
305 std::string type_as_string =
306 net::NetworkChangeNotifier::ConnectionTypeToString(type);
308 VLOG(1) << "Observed a change to network connectivity state "
309 << type_as_string;
311 net_log_->AddGlobalEntry(
312 net::NetLog::TYPE_NETWORK_CONNECTIVITY_CHANGED,
313 net::NetLog::StringCallback("new_connection_type", &type_as_string));
316 // NetworkChangeNotifier::NetworkChangeObserver implementation.
317 virtual void OnNetworkChanged(
318 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
319 std::string type_as_string =
320 net::NetworkChangeNotifier::ConnectionTypeToString(type);
322 VLOG(1) << "Observed a network change to state " << type_as_string;
324 net_log_->AddGlobalEntry(
325 net::NetLog::TYPE_NETWORK_CHANGED,
326 net::NetLog::StringCallback("new_connection_type", &type_as_string));
329 private:
330 net::NetLog* net_log_;
331 DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver);
334 class SystemURLRequestContextGetter : public net::URLRequestContextGetter {
335 public:
336 explicit SystemURLRequestContextGetter(IOThread* io_thread);
338 // Implementation for net::UrlRequestContextGetter.
339 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
340 virtual scoped_refptr<base::SingleThreadTaskRunner>
341 GetNetworkTaskRunner() const OVERRIDE;
343 protected:
344 virtual ~SystemURLRequestContextGetter();
346 private:
347 IOThread* const io_thread_; // Weak pointer, owned by BrowserProcess.
348 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
350 base::debug::LeakTracker<SystemURLRequestContextGetter> leak_tracker_;
353 SystemURLRequestContextGetter::SystemURLRequestContextGetter(
354 IOThread* io_thread)
355 : io_thread_(io_thread),
356 network_task_runner_(
357 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
360 SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {}
362 net::URLRequestContext* SystemURLRequestContextGetter::GetURLRequestContext() {
363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
364 DCHECK(io_thread_->globals()->system_request_context.get());
366 return io_thread_->globals()->system_request_context.get();
369 scoped_refptr<base::SingleThreadTaskRunner>
370 SystemURLRequestContextGetter::GetNetworkTaskRunner() const {
371 return network_task_runner_;
374 IOThread::Globals::
375 SystemRequestContextLeakChecker::SystemRequestContextLeakChecker(
376 Globals* globals)
377 : globals_(globals) {
378 DCHECK(globals_);
381 IOThread::Globals::
382 SystemRequestContextLeakChecker::~SystemRequestContextLeakChecker() {
383 if (globals_->system_request_context.get())
384 globals_->system_request_context->AssertNoURLRequests();
387 IOThread::Globals::Globals()
388 : system_request_context_leak_checker(this),
389 ignore_certificate_errors(false),
390 http_pipelining_enabled(false),
391 testing_fixed_http_port(0),
392 testing_fixed_https_port(0),
393 enable_user_alternate_protocol_ports(false) {
396 IOThread::Globals::~Globals() {}
398 // |local_state| is passed in explicitly in order to (1) reduce implicit
399 // dependencies and (2) make IOThread more flexible for testing.
400 IOThread::IOThread(
401 PrefService* local_state,
402 policy::PolicyService* policy_service,
403 ChromeNetLog* net_log,
404 extensions::EventRouterForwarder* extension_event_router_forwarder)
405 : net_log_(net_log),
406 extension_event_router_forwarder_(extension_event_router_forwarder),
407 globals_(NULL),
408 sdch_manager_(NULL),
409 is_spdy_disabled_by_policy_(false),
410 weak_factory_(this) {
411 #if !defined(OS_IOS) && !defined(OS_ANDROID)
412 #if defined(OS_WIN)
413 if (!win8::IsSingleWindowMetroMode())
414 net::ProxyResolverV8::RememberDefaultIsolate();
415 else
416 net::ProxyResolverV8::CreateIsolate();
417 #else
418 net::ProxyResolverV8::RememberDefaultIsolate();
419 #endif
420 #endif
421 auth_schemes_ = local_state->GetString(prefs::kAuthSchemes);
422 negotiate_disable_cname_lookup_ = local_state->GetBoolean(
423 prefs::kDisableAuthNegotiateCnameLookup);
424 negotiate_enable_port_ = local_state->GetBoolean(
425 prefs::kEnableAuthNegotiatePort);
426 auth_server_whitelist_ = local_state->GetString(prefs::kAuthServerWhitelist);
427 auth_delegate_whitelist_ = local_state->GetString(
428 prefs::kAuthNegotiateDelegateWhitelist);
429 gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName);
430 pref_proxy_config_tracker_.reset(
431 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
432 local_state));
433 ChromeNetworkDelegate::InitializePrefsOnUIThread(
434 &system_enable_referrers_,
435 NULL,
436 NULL,
437 local_state);
438 ssl_config_service_manager_.reset(
439 SSLConfigServiceManager::CreateDefaultManager(local_state));
441 base::Value* dns_client_enabled_default = new base::FundamentalValue(
442 chrome_browser_net::ConfigureAsyncDnsFieldTrial());
443 local_state->SetDefaultPrefValue(prefs::kBuiltInDnsClientEnabled,
444 dns_client_enabled_default);
446 dns_client_enabled_.Init(prefs::kBuiltInDnsClientEnabled,
447 local_state,
448 base::Bind(&IOThread::UpdateDnsClientEnabled,
449 base::Unretained(this)));
450 dns_client_enabled_.MoveToThread(
451 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
453 quick_check_enabled_.Init(prefs::kQuickCheckEnabled,
454 local_state);
455 quick_check_enabled_.MoveToThread(
456 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
458 #if defined(ENABLE_CONFIGURATION_POLICY)
459 is_spdy_disabled_by_policy_ = policy_service->GetPolicies(
460 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())).Get(
461 policy::key::kDisableSpdy) != NULL;
462 #endif // ENABLE_CONFIGURATION_POLICY
464 BrowserThread::SetDelegate(BrowserThread::IO, this);
467 IOThread::~IOThread() {
468 // This isn't needed for production code, but in tests, IOThread may
469 // be multiply constructed.
470 BrowserThread::SetDelegate(BrowserThread::IO, NULL);
472 pref_proxy_config_tracker_->DetachFromPrefService();
473 DCHECK(!globals_);
476 IOThread::Globals* IOThread::globals() {
477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
478 return globals_;
481 void IOThread::SetGlobalsForTesting(Globals* globals) {
482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
483 DCHECK(!globals || !globals_);
484 globals_ = globals;
487 ChromeNetLog* IOThread::net_log() {
488 return net_log_;
491 void IOThread::ChangedToOnTheRecord() {
492 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
493 BrowserThread::PostTask(
494 BrowserThread::IO,
495 FROM_HERE,
496 base::Bind(&IOThread::ChangedToOnTheRecordOnIOThread,
497 base::Unretained(this)));
500 net::URLRequestContextGetter* IOThread::system_url_request_context_getter() {
501 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
502 if (!system_url_request_context_getter_.get()) {
503 InitSystemRequestContext();
505 return system_url_request_context_getter_.get();
508 void IOThread::Init() {
509 // Prefer to use InitAsync unless you need initialization to block
510 // the UI thread
513 void IOThread::InitAsync() {
514 TRACE_EVENT0("startup", "IOThread::InitAsync");
515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
517 #if defined(USE_NSS) || defined(OS_IOS)
518 net::SetMessageLoopForNSSHttpIO();
519 #endif
521 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
523 DCHECK(!globals_);
524 globals_ = new Globals;
526 // Add an observer that will emit network change events to the ChromeNetLog.
527 // Assuming NetworkChangeNotifier dispatches in FIFO order, we should be
528 // logging the network change before other IO thread consumers respond to it.
529 network_change_observer_.reset(
530 new LoggingNetworkChangeObserver(net_log_));
532 // Setup the HistogramWatcher to run on the IO thread.
533 net::NetworkChangeNotifier::InitHistogramWatcher();
535 globals_->extension_event_router_forwarder =
536 extension_event_router_forwarder_;
537 ChromeNetworkDelegate* network_delegate =
538 new ChromeNetworkDelegate(extension_event_router_forwarder_,
539 &system_enable_referrers_);
540 if (command_line.HasSwitch(switches::kEnableClientHints))
541 network_delegate->SetEnableClientHints();
542 if (command_line.HasSwitch(switches::kDisableExtensionsHttpThrottling))
543 network_delegate->NeverThrottleRequests();
544 globals_->system_network_delegate.reset(network_delegate);
545 globals_->host_resolver = CreateGlobalHostResolver(net_log_);
546 UpdateDnsClientEnabled();
547 globals_->cert_verifier.reset(net::CertVerifier::CreateDefault());
548 globals_->transport_security_state.reset(new net::TransportSecurityState());
549 #if !defined(USE_OPENSSL)
550 // For now, Certificate Transparency is only implemented for platforms
551 // that use NSS.
552 net::MultiLogCTVerifier* ct_verifier = new net::MultiLogCTVerifier();
553 globals_->cert_transparency_verifier.reset(ct_verifier);
555 // Add built-in logs
556 ct_verifier->AddLog(net::ct::CreateGooglePilotLogVerifier().Pass());
557 ct_verifier->AddLog(net::ct::CreateGoogleAviatorLogVerifier().Pass());
558 ct_verifier->AddLog(net::ct::CreateGoogleRocketeerLogVerifier().Pass());
560 // Add logs from command line
561 if (command_line.HasSwitch(switches::kCertificateTransparencyLog)) {
562 std::string switch_value = command_line.GetSwitchValueASCII(
563 switches::kCertificateTransparencyLog);
564 size_t delim_pos = switch_value.find(":");
565 CHECK(delim_pos != std::string::npos)
566 << "CT log description not provided (switch format"
567 " is 'description:base64_key')";
568 std::string log_description(switch_value.substr(0, delim_pos));
569 std::string ct_public_key_data;
570 CHECK(base::Base64Decode(
571 switch_value.substr(delim_pos + 1),
572 &ct_public_key_data)) << "Unable to decode CT public key.";
573 scoped_ptr<net::CTLogVerifier> external_log_verifier(
574 net::CTLogVerifier::Create(ct_public_key_data, log_description));
575 CHECK(external_log_verifier) << "Unable to parse CT public key.";
576 ct_verifier->AddLog(external_log_verifier.Pass());
578 #else
579 if (command_line.HasSwitch(switches::kCertificateTransparencyLog)) {
580 LOG(DFATAL) << "Certificate Transparency is not yet supported in Chrome "
581 "builds using OpenSSL.";
583 #endif
584 globals_->ssl_config_service = GetSSLConfigService();
585 #if defined(OS_ANDROID) || defined(OS_IOS)
586 if (DataReductionProxySettings::IsDataReductionProxyAllowed()) {
587 spdyproxy_auth_origins_ =
588 DataReductionProxySettings::GetDataReductionProxies();
590 #endif // defined(OS_ANDROID) || defined(OS_IOS)
591 globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory(
592 globals_->host_resolver.get()));
593 globals_->http_server_properties.reset(new net::HttpServerPropertiesImpl());
594 // For the ProxyScriptFetcher, we use a direct ProxyService.
595 globals_->proxy_script_fetcher_proxy_service.reset(
596 net::ProxyService::CreateDirectWithNetLog(net_log_));
597 // In-memory cookie store.
598 globals_->system_cookie_store =
599 content::CreateCookieStore(content::CookieStoreConfig());
600 // In-memory server bound cert store.
601 globals_->system_server_bound_cert_service.reset(
602 new net::ServerBoundCertService(
603 new net::DefaultServerBoundCertStore(NULL),
604 base::WorkerPool::GetTaskRunner(true)));
605 globals_->dns_probe_service.reset(new chrome_browser_net::DnsProbeService());
606 globals_->host_mapping_rules.reset(new net::HostMappingRules());
607 globals_->http_user_agent_settings.reset(
608 new BasicHttpUserAgentSettings(std::string()));
609 if (command_line.HasSwitch(switches::kHostRules)) {
610 TRACE_EVENT_BEGIN0("startup", "IOThread::InitAsync:SetRulesFromString");
611 globals_->host_mapping_rules->SetRulesFromString(
612 command_line.GetSwitchValueASCII(switches::kHostRules));
613 TRACE_EVENT_END0("startup", "IOThread::InitAsync:SetRulesFromString");
615 if (command_line.HasSwitch(switches::kIgnoreCertificateErrors))
616 globals_->ignore_certificate_errors = true;
617 if (command_line.HasSwitch(switches::kTestingFixedHttpPort)) {
618 globals_->testing_fixed_http_port =
619 GetSwitchValueAsInt(command_line, switches::kTestingFixedHttpPort);
621 if (command_line.HasSwitch(switches::kTestingFixedHttpsPort)) {
622 globals_->testing_fixed_https_port =
623 GetSwitchValueAsInt(command_line, switches::kTestingFixedHttpsPort);
625 ConfigureQuic(command_line);
626 if (command_line.HasSwitch(
627 switches::kEnableUserAlternateProtocolPorts)) {
628 globals_->enable_user_alternate_protocol_ports = true;
630 InitializeNetworkOptions(command_line);
632 net::HttpNetworkSession::Params session_params;
633 InitializeNetworkSessionParams(&session_params);
634 session_params.net_log = net_log_;
635 session_params.proxy_service =
636 globals_->proxy_script_fetcher_proxy_service.get();
638 TRACE_EVENT_BEGIN0("startup", "IOThread::InitAsync:HttpNetworkSession");
639 scoped_refptr<net::HttpNetworkSession> network_session(
640 new net::HttpNetworkSession(session_params));
641 globals_->proxy_script_fetcher_http_transaction_factory
642 .reset(new net::HttpNetworkLayer(network_session.get()));
643 TRACE_EVENT_END0("startup", "IOThread::InitAsync:HttpNetworkSession");
644 scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
645 new net::URLRequestJobFactoryImpl());
646 job_factory->SetProtocolHandler(chrome::kDataScheme,
647 new net::DataProtocolHandler());
648 job_factory->SetProtocolHandler(
649 content::kFileScheme,
650 new net::FileProtocolHandler(
651 content::BrowserThread::GetBlockingPool()->
652 GetTaskRunnerWithShutdownBehavior(
653 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
654 #if !defined(DISABLE_FTP_SUPPORT)
655 globals_->proxy_script_fetcher_ftp_transaction_factory.reset(
656 new net::FtpNetworkLayer(globals_->host_resolver.get()));
657 job_factory->SetProtocolHandler(
658 content::kFtpScheme,
659 new net::FtpProtocolHandler(
660 globals_->proxy_script_fetcher_ftp_transaction_factory.get()));
661 #endif
662 globals_->proxy_script_fetcher_url_request_job_factory =
663 job_factory.PassAs<net::URLRequestJobFactory>();
665 globals_->throttler_manager.reset(new net::URLRequestThrottlerManager());
666 globals_->throttler_manager->set_net_log(net_log_);
667 // Always done in production, disabled only for unit tests.
668 globals_->throttler_manager->set_enable_thread_checks(true);
670 globals_->proxy_script_fetcher_context.reset(
671 ConstructProxyScriptFetcherContext(globals_, net_log_));
673 globals_->network_time_notifier.reset(
674 new net::NetworkTimeNotifier(
675 scoped_ptr<base::TickClock>(new base::DefaultTickClock())));
677 sdch_manager_ = new net::SdchManager();
679 #if defined(OS_MACOSX) && !defined(OS_IOS)
680 // Start observing Keychain events. This needs to be done on the UI thread,
681 // as Keychain services requires a CFRunLoop.
682 BrowserThread::PostTask(BrowserThread::UI,
683 FROM_HERE,
684 base::Bind(&ObserveKeychainEvents));
685 #endif
687 // InitSystemRequestContext turns right around and posts a task back
688 // to the IO thread, so we can't let it run until we know the IO
689 // thread has started.
691 // Note that since we are at BrowserThread::Init time, the UI thread
692 // is blocked waiting for the thread to start. Therefore, posting
693 // this task to the main thread's message loop here is guaranteed to
694 // get it onto the message loop while the IOThread object still
695 // exists. However, the message might not be processed on the UI
696 // thread until after IOThread is gone, so use a weak pointer.
697 BrowserThread::PostTask(BrowserThread::UI,
698 FROM_HERE,
699 base::Bind(&IOThread::InitSystemRequestContext,
700 weak_factory_.GetWeakPtr()));
703 void IOThread::CleanUp() {
704 base::debug::LeakTracker<SafeBrowsingURLRequestContext>::CheckForLeaks();
706 delete sdch_manager_;
707 sdch_manager_ = NULL;
709 #if defined(USE_NSS) || defined(OS_IOS)
710 net::ShutdownNSSHttpIO();
711 #endif
713 system_url_request_context_getter_ = NULL;
715 // Release objects that the net::URLRequestContext could have been pointing
716 // to.
718 // This must be reset before the ChromeNetLog is destroyed.
719 network_change_observer_.reset();
721 system_proxy_config_service_.reset();
723 delete globals_;
724 globals_ = NULL;
726 base::debug::LeakTracker<SystemURLRequestContextGetter>::CheckForLeaks();
729 void IOThread::InitializeNetworkOptions(const CommandLine& command_line) {
730 // Only handle use-spdy command line flags if "spdy.disabled" preference is
731 // not disabled via policy.
732 if (is_spdy_disabled_by_policy_) {
733 base::FieldTrial* trial = base::FieldTrialList::Find(kSpdyFieldTrialName);
734 if (trial)
735 trial->Disable();
736 } else {
737 std::string spdy_trial_group =
738 base::FieldTrialList::FindFullName(kSpdyFieldTrialName);
740 if (command_line.HasSwitch(switches::kEnableIPPooling))
741 globals_->enable_spdy_ip_pooling.set(true);
743 if (command_line.HasSwitch(switches::kDisableIPPooling))
744 globals_->enable_spdy_ip_pooling.set(false);
746 if (command_line.HasSwitch(switches::kEnableWebSocketOverSpdy)) {
747 // Enable WebSocket over SPDY.
748 net::WebSocketJob::set_websocket_over_spdy_enabled(true);
751 if (command_line.HasSwitch(switches::kMaxSpdyConcurrentStreams)) {
752 globals_->max_spdy_concurrent_streams_limit.set(
753 GetSwitchValueAsInt(command_line,
754 switches::kMaxSpdyConcurrentStreams));
756 if (command_line.HasSwitch(switches::kTrustedSpdyProxy)) {
757 globals_->trusted_spdy_proxy.set(
758 command_line.GetSwitchValueASCII(switches::kTrustedSpdyProxy));
760 if (command_line.HasSwitch(switches::kIgnoreUrlFetcherCertRequests))
761 net::URLFetcher::SetIgnoreCertificateRequests(true);
763 if (command_line.HasSwitch(switches::kUseSpdy)) {
764 std::string spdy_mode =
765 command_line.GetSwitchValueASCII(switches::kUseSpdy);
766 EnableSpdy(spdy_mode);
767 } else if (command_line.HasSwitch(switches::kEnableHttp2Draft04)) {
768 net::HttpStreamFactory::EnableNpnHttp2Draft04();
769 } else if (command_line.HasSwitch(switches::kEnableSpdy4a2)) {
770 net::HttpStreamFactory::EnableNpnSpdy4a2();
771 } else if (command_line.HasSwitch(switches::kDisableSpdy31)) {
772 net::HttpStreamFactory::EnableNpnSpdy3();
773 } else if (command_line.HasSwitch(switches::kEnableSpdy2)) {
774 net::HttpStreamFactory::EnableNpnSpdy31WithSpdy2();
775 } else if (command_line.HasSwitch(switches::kEnableNpnHttpOnly)) {
776 net::HttpStreamFactory::EnableNpnHttpOnly();
777 } else {
778 if (spdy_trial_group == kSpdyFieldTrialDisabledGroupName &&
779 !command_line.HasSwitch(switches::kEnableWebSocketOverSpdy)) {
780 net::HttpStreamFactory::set_spdy_enabled(false);
781 } else {
782 // Use SPDY/3.1 by default.
783 net::HttpStreamFactory::EnableNpnSpdy31();
788 // TODO(rch): Make the client socket factory a per-network session
789 // instance, constructed from a NetworkSession::Params, to allow us
790 // to move this option to IOThread::Globals &
791 // HttpNetworkSession::Params.
792 if (command_line.HasSwitch(switches::kEnableTcpFastOpen))
793 net::SetTCPFastOpenEnabled(true);
796 void IOThread::EnableSpdy(const std::string& mode) {
797 static const char kOff[] = "off";
798 static const char kSSL[] = "ssl";
799 static const char kDisableSSL[] = "no-ssl";
800 static const char kDisablePing[] = "no-ping";
801 static const char kExclude[] = "exclude"; // Hosts to exclude
802 static const char kDisableCompression[] = "no-compress";
803 static const char kDisableAltProtocols[] = "no-alt-protocols";
804 static const char kForceAltProtocols[] = "force-alt-protocols";
805 static const char kSingleDomain[] = "single-domain";
807 static const char kInitialMaxConcurrentStreams[] = "init-max-streams";
809 std::vector<std::string> spdy_options;
810 base::SplitString(mode, ',', &spdy_options);
812 for (std::vector<std::string>::iterator it = spdy_options.begin();
813 it != spdy_options.end(); ++it) {
814 const std::string& element = *it;
815 std::vector<std::string> name_value;
816 base::SplitString(element, '=', &name_value);
817 const std::string& option =
818 name_value.size() > 0 ? name_value[0] : std::string();
819 const std::string value =
820 name_value.size() > 1 ? name_value[1] : std::string();
822 if (option == kOff) {
823 net::HttpStreamFactory::set_spdy_enabled(false);
824 } else if (option == kDisableSSL) {
825 globals_->spdy_default_protocol.set(net::kProtoSPDY3);
826 net::HttpStreamFactory::set_force_spdy_over_ssl(false);
827 net::HttpStreamFactory::set_force_spdy_always(true);
828 } else if (option == kSSL) {
829 globals_->spdy_default_protocol.set(net::kProtoSPDY3);
830 net::HttpStreamFactory::set_force_spdy_over_ssl(true);
831 net::HttpStreamFactory::set_force_spdy_always(true);
832 } else if (option == kDisablePing) {
833 globals_->enable_spdy_ping_based_connection_checking.set(false);
834 } else if (option == kExclude) {
835 net::HttpStreamFactory::add_forced_spdy_exclusion(value);
836 } else if (option == kDisableCompression) {
837 globals_->enable_spdy_compression.set(false);
838 } else if (option == kDisableAltProtocols) {
839 net::HttpStreamFactory::set_use_alternate_protocols(false);
840 } else if (option == kForceAltProtocols) {
841 net::PortAlternateProtocolPair pair;
842 pair.port = 443;
843 pair.protocol = net::NPN_SPDY_3;
844 net::HttpServerPropertiesImpl::ForceAlternateProtocol(pair);
845 } else if (option == kSingleDomain) {
846 DVLOG(1) << "FORCING SINGLE DOMAIN";
847 globals_->force_spdy_single_domain.set(true);
848 } else if (option == kInitialMaxConcurrentStreams) {
849 int streams;
850 if (base::StringToInt(value, &streams))
851 globals_->initial_max_spdy_concurrent_streams.set(streams);
852 } else if (option.empty() && it == spdy_options.begin()) {
853 continue;
854 } else {
855 LOG(DFATAL) << "Unrecognized spdy option: " << option;
860 // static
861 void IOThread::RegisterPrefs(PrefRegistrySimple* registry) {
862 registry->RegisterStringPref(prefs::kAuthSchemes,
863 "basic,digest,ntlm,negotiate,"
864 "spdyproxy");
865 registry->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup, false);
866 registry->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort, false);
867 registry->RegisterStringPref(prefs::kAuthServerWhitelist, std::string());
868 registry->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist,
869 std::string());
870 registry->RegisterStringPref(prefs::kGSSAPILibraryName, std::string());
871 registry->RegisterStringPref(prefs::kSpdyProxyAuthOrigin, std::string());
872 registry->RegisterBooleanPref(prefs::kEnableReferrers, true);
873 registry->RegisterInt64Pref(prefs::kHttpReceivedContentLength, 0);
874 registry->RegisterInt64Pref(prefs::kHttpOriginalContentLength, 0);
875 #if defined(OS_ANDROID) || defined(OS_IOS)
876 registry->RegisterListPref(prefs::kDailyHttpOriginalContentLength);
877 registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength);
878 registry->RegisterListPref(
879 prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled);
880 registry->RegisterListPref(
881 prefs::kDailyContentLengthWithDataReductionProxyEnabled);
882 registry->RegisterListPref(
883 prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled);
884 registry->RegisterListPref(
885 prefs::kDailyContentLengthShortBypassWithDataReductionProxyEnabled);
886 registry->RegisterListPref(
887 prefs::kDailyContentLengthLongBypassWithDataReductionProxyEnabled);
888 registry->RegisterListPref(
889 prefs::kDailyContentLengthUnknownWithDataReductionProxyEnabled);
890 registry->RegisterListPref(
891 prefs::kDailyOriginalContentLengthViaDataReductionProxy);
892 registry->RegisterListPref(
893 prefs::kDailyContentLengthViaDataReductionProxy);
894 registry->RegisterInt64Pref(prefs::kDailyHttpContentLengthLastUpdateDate, 0L);
895 #endif
896 registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, true);
897 registry->RegisterBooleanPref(prefs::kQuickCheckEnabled, true);
900 net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory(
901 net::HostResolver* resolver) {
902 net::HttpAuthFilterWhitelist* auth_filter_default_credentials = NULL;
903 if (!auth_server_whitelist_.empty()) {
904 auth_filter_default_credentials =
905 new net::HttpAuthFilterWhitelist(auth_server_whitelist_);
907 net::HttpAuthFilterWhitelist* auth_filter_delegate = NULL;
908 if (!auth_delegate_whitelist_.empty()) {
909 auth_filter_delegate =
910 new net::HttpAuthFilterWhitelist(auth_delegate_whitelist_);
912 globals_->url_security_manager.reset(
913 net::URLSecurityManager::Create(auth_filter_default_credentials,
914 auth_filter_delegate));
915 std::vector<std::string> supported_schemes;
916 base::SplitString(auth_schemes_, ',', &supported_schemes);
918 scoped_ptr<net::HttpAuthHandlerRegistryFactory> registry_factory(
919 net::HttpAuthHandlerRegistryFactory::Create(
920 supported_schemes, globals_->url_security_manager.get(),
921 resolver, gssapi_library_name_, negotiate_disable_cname_lookup_,
922 negotiate_enable_port_));
924 if (!spdyproxy_auth_origins_.empty()) {
925 registry_factory->RegisterSchemeFactory(
926 "spdyproxy",
927 new spdyproxy::HttpAuthHandlerSpdyProxy::Factory(
928 spdyproxy_auth_origins_));
931 return registry_factory.release();
934 void IOThread::ClearHostCache() {
935 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
937 net::HostCache* host_cache = globals_->host_resolver->GetHostCache();
938 if (host_cache)
939 host_cache->clear();
942 void IOThread::InitializeNetworkSessionParams(
943 net::HttpNetworkSession::Params* params) {
944 params->host_resolver = globals_->host_resolver.get();
945 params->cert_verifier = globals_->cert_verifier.get();
946 params->server_bound_cert_service =
947 globals_->system_server_bound_cert_service.get();
948 params->transport_security_state = globals_->transport_security_state.get();
949 params->ssl_config_service = globals_->ssl_config_service.get();
950 params->http_auth_handler_factory = globals_->http_auth_handler_factory.get();
951 params->http_server_properties =
952 globals_->http_server_properties->GetWeakPtr();
953 params->network_delegate = globals_->system_network_delegate.get();
954 params->host_mapping_rules = globals_->host_mapping_rules.get();
955 params->ignore_certificate_errors = globals_->ignore_certificate_errors;
956 params->http_pipelining_enabled = globals_->http_pipelining_enabled;
957 params->testing_fixed_http_port = globals_->testing_fixed_http_port;
958 params->testing_fixed_https_port = globals_->testing_fixed_https_port;
960 globals_->initial_max_spdy_concurrent_streams.CopyToIfSet(
961 &params->spdy_initial_max_concurrent_streams);
962 globals_->max_spdy_concurrent_streams_limit.CopyToIfSet(
963 &params->spdy_max_concurrent_streams_limit);
964 globals_->force_spdy_single_domain.CopyToIfSet(
965 &params->force_spdy_single_domain);
966 globals_->enable_spdy_ip_pooling.CopyToIfSet(
967 &params->enable_spdy_ip_pooling);
968 globals_->enable_spdy_compression.CopyToIfSet(
969 &params->enable_spdy_compression);
970 globals_->enable_spdy_ping_based_connection_checking.CopyToIfSet(
971 &params->enable_spdy_ping_based_connection_checking);
972 globals_->spdy_default_protocol.CopyToIfSet(
973 &params->spdy_default_protocol);
974 globals_->trusted_spdy_proxy.CopyToIfSet(
975 &params->trusted_spdy_proxy);
976 globals_->enable_quic.CopyToIfSet(&params->enable_quic);
977 globals_->enable_quic_https.CopyToIfSet(&params->enable_quic_https);
978 globals_->quic_max_packet_length.CopyToIfSet(&params->quic_max_packet_length);
979 globals_->quic_supported_versions.CopyToIfSet(
980 &params->quic_supported_versions);
981 globals_->origin_to_force_quic_on.CopyToIfSet(
982 &params->origin_to_force_quic_on);
983 params->enable_user_alternate_protocol_ports =
984 globals_->enable_user_alternate_protocol_ports;
987 net::SSLConfigService* IOThread::GetSSLConfigService() {
988 return ssl_config_service_manager_->Get();
991 void IOThread::ChangedToOnTheRecordOnIOThread() {
992 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
994 // Clear the host cache to avoid showing entries from the OTR session
995 // in about:net-internals.
996 ClearHostCache();
999 void IOThread::InitSystemRequestContext() {
1000 if (system_url_request_context_getter_.get())
1001 return;
1002 // If we're in unit_tests, IOThread may not be run.
1003 if (!BrowserThread::IsMessageLoopValid(BrowserThread::IO))
1004 return;
1005 system_proxy_config_service_.reset(
1006 ProxyServiceFactory::CreateProxyConfigService(
1007 pref_proxy_config_tracker_.get()));
1008 system_url_request_context_getter_ =
1009 new SystemURLRequestContextGetter(this);
1010 // Safe to post an unretained this pointer, since IOThread is
1011 // guaranteed to outlive the IO BrowserThread.
1012 BrowserThread::PostTask(
1013 BrowserThread::IO,
1014 FROM_HERE,
1015 base::Bind(&IOThread::InitSystemRequestContextOnIOThread,
1016 base::Unretained(this)));
1019 void IOThread::InitSystemRequestContextOnIOThread() {
1020 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1021 DCHECK(!globals_->system_proxy_service.get());
1022 DCHECK(system_proxy_config_service_.get());
1024 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1025 globals_->system_proxy_service.reset(
1026 ProxyServiceFactory::CreateProxyService(
1027 net_log_,
1028 globals_->proxy_script_fetcher_context.get(),
1029 globals_->system_network_delegate.get(),
1030 system_proxy_config_service_.release(),
1031 command_line,
1032 quick_check_enabled_.GetValue()));
1034 net::HttpNetworkSession::Params system_params;
1035 InitializeNetworkSessionParams(&system_params);
1036 system_params.net_log = net_log_;
1037 system_params.proxy_service = globals_->system_proxy_service.get();
1039 globals_->system_http_transaction_factory.reset(
1040 new net::HttpNetworkLayer(
1041 new net::HttpNetworkSession(system_params)));
1042 globals_->system_request_context.reset(
1043 ConstructSystemRequestContext(globals_, net_log_));
1045 sdch_manager_->set_sdch_fetcher(
1046 new SdchDictionaryFetcher(system_url_request_context_getter_.get()));
1049 void IOThread::UpdateDnsClientEnabled() {
1050 globals()->host_resolver->SetDnsClientEnabled(*dns_client_enabled_);
1053 void IOThread::ConfigureQuic(const CommandLine& command_line) {
1054 // Always fetch the field trial group to ensure it is reported correctly.
1055 // The command line flags will be associated with a group that is reported
1056 // so long as trial is actually queried.
1057 std::string quic_trial_group =
1058 base::FieldTrialList::FindFullName(kQuicFieldTrialName);
1060 bool enable_quic = ShouldEnableQuic(command_line, quic_trial_group);
1061 globals_->enable_quic.set(enable_quic);
1062 if (enable_quic) {
1063 globals_->enable_quic_https.set(
1064 ShouldEnableQuicHttps(command_line, quic_trial_group));
1067 size_t max_packet_length = GetQuicMaxPacketLength(command_line,
1068 quic_trial_group);
1069 if (max_packet_length != 0) {
1070 globals_->quic_max_packet_length.set(max_packet_length);
1073 net::QuicVersion version = GetQuicVersion(command_line);
1074 if (version != net::QUIC_VERSION_UNSUPPORTED) {
1075 net::QuicVersionVector supported_versions;
1076 supported_versions.push_back(version);
1077 globals_->quic_supported_versions.set(supported_versions);
1080 if (command_line.HasSwitch(switches::kOriginToForceQuicOn)) {
1081 net::HostPortPair quic_origin =
1082 net::HostPortPair::FromString(
1083 command_line.GetSwitchValueASCII(switches::kOriginToForceQuicOn));
1084 if (!quic_origin.IsEmpty()) {
1085 globals_->origin_to_force_quic_on.set(quic_origin);
1090 bool IOThread::ShouldEnableQuic(const CommandLine& command_line,
1091 base::StringPiece quic_trial_group) {
1092 if (command_line.HasSwitch(switches::kDisableQuic))
1093 return false;
1095 if (command_line.HasSwitch(switches::kEnableQuic))
1096 return true;
1098 return quic_trial_group.starts_with(kQuicFieldTrialEnabledGroupName) ||
1099 quic_trial_group.starts_with(kQuicFieldTrialHttpsEnabledGroupName);
1102 bool IOThread::ShouldEnableQuicHttps(const CommandLine& command_line,
1103 base::StringPiece quic_trial_group) {
1104 if (command_line.HasSwitch(switches::kDisableQuicHttps))
1105 return false;
1107 if (command_line.HasSwitch(switches::kEnableQuicHttps))
1108 return true;
1110 return quic_trial_group.starts_with(kQuicFieldTrialHttpsEnabledGroupName);
1113 size_t IOThread::GetQuicMaxPacketLength(const CommandLine& command_line,
1114 base::StringPiece quic_trial_group) {
1115 if (command_line.HasSwitch(switches::kQuicMaxPacketLength)) {
1116 unsigned value;
1117 if (!base::StringToUint(
1118 command_line.GetSwitchValueASCII(switches::kQuicMaxPacketLength),
1119 &value)) {
1120 return 0;
1122 return value;
1125 // Format of the packet length group names is:
1126 // (Https)?Enabled<length>BytePackets.
1127 base::StringPiece length_str(quic_trial_group);
1128 if (length_str.starts_with(kQuicFieldTrialEnabledGroupName)) {
1129 length_str.remove_prefix(strlen(kQuicFieldTrialEnabledGroupName));
1130 } else if (length_str.starts_with(kQuicFieldTrialHttpsEnabledGroupName)) {
1131 length_str.remove_prefix(strlen(kQuicFieldTrialHttpsEnabledGroupName));
1132 } else {
1133 return 0;
1135 if (!length_str.ends_with(kQuicFieldTrialPacketLengthSuffix)) {
1136 return 0;
1138 length_str.remove_suffix(strlen(kQuicFieldTrialPacketLengthSuffix));
1139 unsigned value;
1140 if (!base::StringToUint(length_str, &value)) {
1141 return 0;
1143 return value;
1146 net::QuicVersion IOThread::GetQuicVersion(const CommandLine& command_line) {
1147 if (!command_line.HasSwitch(switches::kQuicVersion)) {
1148 return net::QUIC_VERSION_UNSUPPORTED;
1150 net::QuicVersionVector supported_versions = net::QuicSupportedVersions();
1151 std::string version_flag =
1152 command_line.GetSwitchValueASCII(switches::kQuicVersion);
1153 for (size_t i = 0; i < supported_versions.size(); ++i) {
1154 net::QuicVersion version = supported_versions[i];
1155 if (net::QuicVersionToString(version) == version_flag) {
1156 return version;
1159 return net::QUIC_VERSION_UNSUPPORTED;