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"
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"
82 #include "win8/util/win8_util.h"
85 #if defined(ENABLE_CONFIGURATION_POLICY)
86 #include "policy/policy_constants.h"
89 #if !defined(USE_OPENSSL)
90 #include "net/cert/ct_log_verifier.h"
91 #include "net/cert/multi_log_ct_verifier.h"
94 #if defined(USE_NSS) || defined(OS_IOS)
95 #include "net/ocsp/nss_ocsp.h"
98 #if !defined(OS_IOS) && !defined(OS_ANDROID)
99 #include "net/proxy/proxy_resolver_v8.h"
102 #if defined(OS_ANDROID) || defined(OS_IOS)
103 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_settings.h"
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.
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();
130 // Used for the "system" URLRequestContext.
131 class SystemURLRequestContext
: public net::URLRequestContext
{
133 SystemURLRequestContext() {
134 #if defined(USE_NSS) || defined(OS_IOS)
135 net::SetURLRequestContextForNSSHttpIO(this);
140 virtual ~SystemURLRequestContext() {
141 #if defined(USE_NSS) || defined(OS_IOS)
142 net::SetURLRequestContextForNSSHttpIO(NULL
);
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
)) {
156 command_line
.GetSwitchValueASCII(switches::kHostResolverParallelism
);
158 // Parse the switch (it should be a positive integer formatted as decimal).
160 if (base::StringToInt(s
, &n
) && n
> 0) {
161 options
.max_concurrent_resolves
= static_cast<size_t>(n
);
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
)) {
170 command_line
.GetSwitchValueASCII(switches::kHostResolverRetryAttempts
);
171 // Parse the switch (it should be a non-negative integer).
173 if (base::StringToInt(s
, &n
) && n
>= 0) {
174 options
.max_retry_attempts
= static_cast<size_t>(n
);
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
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());
264 int GetSwitchValueAsInt(const CommandLine
& command_line
,
265 const std::string
& switch_name
) {
267 if (!base::StringToInt(command_line
.GetSwitchValueASCII(switch_name
),
276 class IOThread::LoggingNetworkChangeObserver
277 : public net::NetworkChangeNotifier::IPAddressObserver
,
278 public net::NetworkChangeNotifier::ConnectionTypeObserver
,
279 public net::NetworkChangeNotifier::NetworkChangeObserver
{
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 "
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
));
330 net::NetLog
* net_log_
;
331 DISALLOW_COPY_AND_ASSIGN(LoggingNetworkChangeObserver
);
334 class SystemURLRequestContextGetter
: public net::URLRequestContextGetter
{
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
;
344 virtual ~SystemURLRequestContextGetter();
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(
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_
;
375 SystemRequestContextLeakChecker::SystemRequestContextLeakChecker(
377 : globals_(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.
401 PrefService
* local_state
,
402 policy::PolicyService
* policy_service
,
403 ChromeNetLog
* net_log
,
404 extensions::EventRouterForwarder
* extension_event_router_forwarder
)
406 extension_event_router_forwarder_(extension_event_router_forwarder
),
409 is_spdy_disabled_by_policy_(false),
410 weak_factory_(this) {
411 #if !defined(OS_IOS) && !defined(OS_ANDROID)
413 if (!win8::IsSingleWindowMetroMode())
414 net::ProxyResolverV8::RememberDefaultIsolate();
416 net::ProxyResolverV8::CreateIsolate();
418 net::ProxyResolverV8::RememberDefaultIsolate();
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(
433 ChromeNetworkDelegate::InitializePrefsOnUIThread(
434 &system_enable_referrers_
,
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
,
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
,
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();
476 IOThread::Globals
* IOThread::globals() {
477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
481 void IOThread::SetGlobalsForTesting(Globals
* globals
) {
482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
483 DCHECK(!globals
|| !globals_
);
487 ChromeNetLog
* IOThread::net_log() {
491 void IOThread::ChangedToOnTheRecord() {
492 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
493 BrowserThread::PostTask(
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
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();
521 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
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
552 net::MultiLogCTVerifier
* ct_verifier
= new net::MultiLogCTVerifier();
553 globals_
->cert_transparency_verifier
.reset(ct_verifier
);
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());
579 if (command_line
.HasSwitch(switches::kCertificateTransparencyLog
)) {
580 LOG(DFATAL
) << "Certificate Transparency is not yet supported in Chrome "
581 "builds using OpenSSL.";
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(
659 new net::FtpProtocolHandler(
660 globals_
->proxy_script_fetcher_ftp_transaction_factory
.get()));
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
,
684 base::Bind(&ObserveKeychainEvents
));
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
,
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();
713 system_url_request_context_getter_
= NULL
;
715 // Release objects that the net::URLRequestContext could have been pointing
718 // This must be reset before the ChromeNetLog is destroyed.
719 network_change_observer_
.reset();
721 system_proxy_config_service_
.reset();
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
);
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();
778 if (spdy_trial_group
== kSpdyFieldTrialDisabledGroupName
&&
779 !command_line
.HasSwitch(switches::kEnableWebSocketOverSpdy
)) {
780 net::HttpStreamFactory::set_spdy_enabled(false);
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
;
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
) {
850 if (base::StringToInt(value
, &streams
))
851 globals_
->initial_max_spdy_concurrent_streams
.set(streams
);
852 } else if (option
.empty() && it
== spdy_options
.begin()) {
855 LOG(DFATAL
) << "Unrecognized spdy option: " << option
;
861 void IOThread::RegisterPrefs(PrefRegistrySimple
* registry
) {
862 registry
->RegisterStringPref(prefs::kAuthSchemes
,
863 "basic,digest,ntlm,negotiate,"
865 registry
->RegisterBooleanPref(prefs::kDisableAuthNegotiateCnameLookup
, false);
866 registry
->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort
, false);
867 registry
->RegisterStringPref(prefs::kAuthServerWhitelist
, std::string());
868 registry
->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist
,
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);
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(
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();
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 ¶ms
->spdy_initial_max_concurrent_streams
);
962 globals_
->max_spdy_concurrent_streams_limit
.CopyToIfSet(
963 ¶ms
->spdy_max_concurrent_streams_limit
);
964 globals_
->force_spdy_single_domain
.CopyToIfSet(
965 ¶ms
->force_spdy_single_domain
);
966 globals_
->enable_spdy_ip_pooling
.CopyToIfSet(
967 ¶ms
->enable_spdy_ip_pooling
);
968 globals_
->enable_spdy_compression
.CopyToIfSet(
969 ¶ms
->enable_spdy_compression
);
970 globals_
->enable_spdy_ping_based_connection_checking
.CopyToIfSet(
971 ¶ms
->enable_spdy_ping_based_connection_checking
);
972 globals_
->spdy_default_protocol
.CopyToIfSet(
973 ¶ms
->spdy_default_protocol
);
974 globals_
->trusted_spdy_proxy
.CopyToIfSet(
975 ¶ms
->trusted_spdy_proxy
);
976 globals_
->enable_quic
.CopyToIfSet(¶ms
->enable_quic
);
977 globals_
->enable_quic_https
.CopyToIfSet(¶ms
->enable_quic_https
);
978 globals_
->quic_max_packet_length
.CopyToIfSet(¶ms
->quic_max_packet_length
);
979 globals_
->quic_supported_versions
.CopyToIfSet(
980 ¶ms
->quic_supported_versions
);
981 globals_
->origin_to_force_quic_on
.CopyToIfSet(
982 ¶ms
->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.
999 void IOThread::InitSystemRequestContext() {
1000 if (system_url_request_context_getter_
.get())
1002 // If we're in unit_tests, IOThread may not be run.
1003 if (!BrowserThread::IsMessageLoopValid(BrowserThread::IO
))
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(
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(
1028 globals_
->proxy_script_fetcher_context
.get(),
1029 globals_
->system_network_delegate
.get(),
1030 system_proxy_config_service_
.release(),
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
);
1063 globals_
->enable_quic_https
.set(
1064 ShouldEnableQuicHttps(command_line
, quic_trial_group
));
1067 size_t max_packet_length
= GetQuicMaxPacketLength(command_line
,
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
))
1095 if (command_line
.HasSwitch(switches::kEnableQuic
))
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
))
1107 if (command_line
.HasSwitch(switches::kEnableQuicHttps
))
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
)) {
1117 if (!base::StringToUint(
1118 command_line
.GetSwitchValueASCII(switches::kQuicMaxPacketLength
),
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
));
1135 if (!length_str
.ends_with(kQuicFieldTrialPacketLengthSuffix
)) {
1138 length_str
.remove_suffix(strlen(kQuicFieldTrialPacketLengthSuffix
));
1140 if (!base::StringToUint(length_str
, &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
) {
1159 return net::QUIC_VERSION_UNSUPPORTED
;