172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/connection_tester.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/compiler_specific.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/task.h" 123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h" 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/importer/firefox_proxy_settings.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h" 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/cert_verifier.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/cookie_monster.h" 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/dnsrr_resolver.h" 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/host_resolver.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_resolver_impl.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/io_buffer.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/ssl_config_service_defaults.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/ftp/ftp_network_layer.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_auth_handler_factory.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_cache.h" 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/http/http_network_session.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/proxy/proxy_config_service_fixed.h" 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/proxy/proxy_script_fetcher_impl.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ExperimentURLRequestContext ------------------------------------------------ 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// An instance of ExperimentURLRequestContext is created for each experiment 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// run by ConnectionTester. The class initializes network dependencies according 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to the specified "experiment". 4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass ExperimentURLRequestContext : public net::URLRequestContext { 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen explicit ExperimentURLRequestContext( 4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net::URLRequestContext* proxy_request_context) 4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : proxy_request_context_(proxy_request_context) {} 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int Init(const ConnectionTester::Experiment& experiment) { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a custom HostResolver for this experiment. 51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen net::HostResolver* host_resolver_tmp = NULL; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = CreateHostResolver(experiment.host_resolver_experiment, 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &host_resolver_tmp); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != net::OK) 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; // Failure. 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_host_resolver(host_resolver_tmp); 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a custom ProxyService for this this experiment. 59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen scoped_refptr<net::ProxyService> proxy_service_tmp = NULL; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = CreateProxyService(experiment.proxy_settings_experiment, 61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &proxy_service_tmp); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != net::OK) 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; // Failure. 64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_proxy_service(proxy_service_tmp); 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The rest of the dependencies are standard, and don't depend on the 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // experiment being run. 68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_cert_verifier(new net::CertVerifier); 69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_dnsrr_resolver(new net::DnsRRResolver); 70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_ftp_transaction_factory(new net::FtpNetworkLayer(host_resolver_tmp)); 71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_ssl_config_service(new net::SSLConfigServiceDefaults); 72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault( 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen host_resolver_tmp)); 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net::HttpNetworkSession::Params session_params; 76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen session_params.host_resolver = host_resolver_tmp; 77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen session_params.dnsrr_resolver = dnsrr_resolver(); 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen session_params.cert_verifier = cert_verifier(); 79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen session_params.proxy_service = proxy_service_tmp; 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen session_params.http_auth_handler_factory = http_auth_handler_factory(); 81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen session_params.ssl_config_service = ssl_config_service(); 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_refptr<net::HttpNetworkSession> network_session( 8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen new net::HttpNetworkSession(session_params)); 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_http_transaction_factory(new net::HttpCache( 8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen network_session, 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen net::HttpCache::DefaultBackend::InMemory(0))); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // In-memory cookie store. 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set_cookie_store(new net::CookieMonster(NULL, NULL)); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~ExperimentURLRequestContext() { 95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete ftp_transaction_factory(); 96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete http_transaction_factory(); 97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete http_auth_handler_factory(); 98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete dnsrr_resolver(); 99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete cert_verifier(); 100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete host_resolver(); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates a host resolver for |experiment|. On success returns net::OK and 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fills |host_resolver| with a new pointer. Otherwise returns a network 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // error code. 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int CreateHostResolver( 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConnectionTester::HostResolverExperiment experiment, 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net::HostResolver** host_resolver) { 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a vanilla HostResolver that disables caching. 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t kMaxJobs = 50u; 112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net::HostResolverImpl* impl = 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick new net::HostResolverImpl(NULL, NULL, kMaxJobs, NULL); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *host_resolver = impl; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Modify it slightly based on the experiment being run. 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (experiment) { 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ConnectionTester::HOST_RESOLVER_EXPERIMENT_PLAIN: 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ConnectionTester::HOST_RESOLVER_EXPERIMENT_DISABLE_IPV6: 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch impl->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ConnectionTester::HOST_RESOLVER_EXPERIMENT_IPV6_PROBE: { 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that we don't use impl->ProbeIPv6Support() since that finishes 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // asynchronously and may not take effect in time for the test. 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // So instead we will probe synchronously (might take 100-200 ms). 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::AddressFamily family = net::IPv6Supported() ? 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::ADDRESS_FAMILY_UNSPECIFIED : net::ADDRESS_FAMILY_IPV4; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch impl->SetDefaultAddressFamily(family); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::ERR_UNEXPECTED; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates a proxy config service for |experiment|. On success returns net::OK 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and fills |config_service| with a new pointer. Otherwise returns a network 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // error code. 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int CreateProxyConfigService( 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConnectionTester::ProxySettingsExperiment experiment, 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<net::ProxyConfigService>* config_service) { 14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_ptr<base::ThreadRestrictions::ScopedAllowIO> allow_io; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (experiment) { 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ConnectionTester::PROXY_EXPERIMENT_USE_SYSTEM_SETTINGS: 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CreateSystemProxyConfigService(config_service); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ConnectionTester::PROXY_EXPERIMENT_USE_FIREFOX_SETTINGS: 15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // http://crbug.com/67664: This call can lead to blocking IO on the IO 15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // thread. This is a bug and should be fixed. 15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen allow_io.reset(new base::ThreadRestrictions::ScopedAllowIO); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CreateFirefoxProxyConfigService(config_service); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ConnectionTester::PROXY_EXPERIMENT_USE_AUTO_DETECT: 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch config_service->reset(new net::ProxyConfigServiceFixed( 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::ProxyConfig::CreateAutoDetect())); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ConnectionTester::PROXY_EXPERIMENT_USE_DIRECT: 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch config_service->reset(new net::ProxyConfigServiceFixed( 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::ProxyConfig::CreateDirect())); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::ERR_UNEXPECTED; 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates a proxy service for |experiment|. On success returns net::OK 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and fills |config_service| with a new pointer. Otherwise returns a network 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // error code. 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int CreateProxyService( 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConnectionTester::ProxySettingsExperiment experiment, 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<net::ProxyService>* proxy_service) { 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create an appropriate proxy config service. 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<net::ProxyConfigService> config_service; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = CreateProxyConfigService(experiment, &config_service); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != net::OK) 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; // Failure. 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (CommandLine::ForCurrentProcess()->HasSwitch( 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switches::kSingleProcess)) { 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can't create a standard proxy resolver in single-process mode. 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Rather than falling-back to some other implementation, fail. 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::ERR_NOT_IMPLEMENTED; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *proxy_service = net::ProxyService::CreateUsingV8ProxyResolver( 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick config_service.release(), 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 0u, 19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen new net::ProxyScriptFetcherImpl(proxy_request_context_), 191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick host_resolver(), 192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NULL); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates a proxy config service that pulls from the system proxy settings. 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // On success returns net::OK and fills |config_service| with a new pointer. 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Otherwise returns a network error code. 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int CreateSystemProxyConfigService( 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<net::ProxyConfigService>* config_service) { 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(eroman): This is not supported on Linux yet, because of how 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // construction needs ot happen on the UI thread. 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::ERR_NOT_IMPLEMENTED; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch config_service->reset( 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::ProxyService::CreateSystemProxyConfigService( 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MessageLoop::current(), NULL)); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates a fixed proxy config service that is initialized using Firefox's 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // current proxy settings. On success returns net::OK and fills 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |config_service| with a new pointer. Otherwise returns a network error 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // code. 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int CreateFirefoxProxyConfigService( 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<net::ProxyConfigService>* config_service) { 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fetch Firefox's proxy settings (can fail if Firefox is not installed). 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FirefoxProxySettings firefox_settings; 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!FirefoxProxySettings::GetSettings(&firefox_settings)) 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::ERR_FILE_NOT_FOUND; 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FirefoxProxySettings::SYSTEM == firefox_settings.config_type()) 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CreateSystemProxyConfigService(config_service); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::ProxyConfig config; 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (firefox_settings.ToProxyConfig(&config)) { 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch config_service->reset(new net::ProxyConfigServiceFixed(config)); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::OK; 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return net::ERR_FAILED; 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const scoped_refptr<net::URLRequestContext> proxy_request_context_; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ConnectionTester::TestRunner ---------------------------------------------- 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TestRunner is a helper class for running an individual experiment. It can 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// be deleted any time after it is started, and this will abort the request. 24621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass ConnectionTester::TestRunner : public net::URLRequest::Delegate { 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |tester| must remain alive throughout the TestRunner's lifetime. 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |tester| will be notified of completion. 25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen explicit TestRunner(ConnectionTester* tester) 25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : tester_(tester), 25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Starts running |experiment|. Notifies tester->OnExperimentCompleted() when 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it is done. 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Run(const Experiment& experiment); 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Overridden from net::URLRequest::Delegate: 25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual void OnResponseStarted(net::URLRequest* request); 26021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual void OnReadCompleted(net::URLRequest* request, int bytes_read); 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(eroman): handle cases requiring authentication. 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The number of bytes to read each response body chunk. 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kReadBufferSize = 1024; 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Starts reading the response's body (and keeps reading until an error or 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // end of stream). 26921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void ReadBody(net::URLRequest* request); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when the request has completed (for both success and failure). 27221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void OnResponseCompleted(net::URLRequest* request); 27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void OnExperimentCompletedWithResult(int result); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConnectionTester* tester_; 27621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_ptr<net::URLRequest> request_; 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ScopedRunnableMethodFactory<TestRunner> method_factory_; 27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(TestRunner); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ConnectionTester::TestRunner::OnResponseStarted(net::URLRequest* request) { 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!request->status().is_success()) { 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnResponseCompleted(request); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start reading the body. 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReadBody(request); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ConnectionTester::TestRunner::OnReadCompleted(net::URLRequest* request, 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_read) { 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes_read <= 0) { 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnResponseCompleted(request); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Keep reading until the stream is closed. Throw the data read away. 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReadBody(request); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ConnectionTester::TestRunner::ReadBody(net::URLRequest* request) { 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Read the response body |kReadBufferSize| bytes at a time. 306513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::IOBuffer> unused_buffer( 307513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new net::IOBuffer(kReadBufferSize)); 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_bytes; 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->Read(unused_buffer, kReadBufferSize, &num_bytes)) { 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnReadCompleted(request, num_bytes); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (!request->status().is_io_pending()) { 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Read failed synchronously. 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnResponseCompleted(request); 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ConnectionTester::TestRunner::OnResponseCompleted( 31821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen net::URLRequest* request) { 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int result = net::OK; 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!request->status().is_success()) { 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(net::ERR_IO_PENDING, request->status().os_error()); 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result = request->status().os_error(); 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Post a task to notify the parent rather than handling it right away, 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // to avoid re-entrancy problems with URLRequest. (Don't want the caller 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // to end up deleting the URLRequest while in the middle of processing). 32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MessageLoop::current()->PostTask( 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FROM_HERE, 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen method_factory_.NewRunnableMethod( 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &TestRunner::OnExperimentCompletedWithResult, result)); 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ConnectionTester::TestRunner::OnExperimentCompletedWithResult(int result) { 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tester_->OnExperimentCompleted(result); 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConnectionTester::TestRunner::Run(const Experiment& experiment) { 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Try to create a net::URLRequestContext for this experiment. 340513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<ExperimentURLRequestContext> context( 34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen new ExperimentURLRequestContext(tester_->proxy_request_context_)); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = context->Init(experiment); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != net::OK) { 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Complete the experiment with a failure. 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tester_->OnExperimentCompleted(rv); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fetch a request using the experimental context. 35021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen request_.reset(new net::URLRequest(experiment.url, this)); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request_->set_context(context); 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request_->Start(); 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ConnectionTester ---------------------------------------------------------- 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenConnectionTester::ConnectionTester( 35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Delegate* delegate, 35972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net::URLRequestContext* proxy_request_context) 36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : delegate_(delegate), proxy_request_context_(proxy_request_context) { 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(delegate); 36221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(proxy_request_context); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochConnectionTester::~ConnectionTester() { 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cancellation happens automatically by deleting test_runner_. 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConnectionTester::RunAllTests(const GURL& url) { 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Select all possible experiments to run. (In no particular order). 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It is possible that some of these experiments are actually duplicates. 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetAllPossibleExperimentCombinations(url, &remaining_experiments_); 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnStartConnectionTestSuite(); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartNextExperiment(); 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring16 ConnectionTester::ProxySettingsExperimentDescription( 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProxySettingsExperiment experiment) { 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(eroman): Use proper string resources. 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (experiment) { 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PROXY_EXPERIMENT_USE_DIRECT: 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ASCIIToUTF16("Don't use any proxy"); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PROXY_EXPERIMENT_USE_SYSTEM_SETTINGS: 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ASCIIToUTF16("Use system proxy settings"); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PROXY_EXPERIMENT_USE_FIREFOX_SETTINGS: 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ASCIIToUTF16("Use Firefox's proxy settings"); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case PROXY_EXPERIMENT_USE_AUTO_DETECT: 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ASCIIToUTF16("Auto-detect proxy settings"); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return string16(); 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring16 ConnectionTester::HostResolverExperimentDescription( 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HostResolverExperiment experiment) { 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(eroman): Use proper string resources. 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (experiment) { 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case HOST_RESOLVER_EXPERIMENT_PLAIN: 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return string16(); 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case HOST_RESOLVER_EXPERIMENT_DISABLE_IPV6: 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ASCIIToUTF16("Disable IPv6 host resolving"); 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case HOST_RESOLVER_EXPERIMENT_IPV6_PROBE: 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ASCIIToUTF16("Probe for IPv6 host resolving"); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return string16(); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConnectionTester::GetAllPossibleExperimentCombinations( 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConnectionTester::ExperimentList* list) { 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list->clear(); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t resolver_experiment = 0; 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resolver_experiment < HOST_RESOLVER_EXPERIMENT_COUNT; 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++resolver_experiment) { 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t proxy_experiment = 0; 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proxy_experiment < PROXY_EXPERIMENT_COUNT; 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++proxy_experiment) { 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Experiment experiment( 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url, 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<ProxySettingsExperiment>(proxy_experiment), 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<HostResolverExperiment>(resolver_experiment)); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list->push_back(experiment); 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConnectionTester::StartNextExperiment() { 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!remaining_experiments_.empty()); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!current_test_runner_.get()); 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnStartConnectionTestExperiment(current_experiment()); 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_test_runner_.reset(new TestRunner(this)); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_test_runner_->Run(current_experiment()); 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ConnectionTester::OnExperimentCompleted(int result) { 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Experiment current = current_experiment(); 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Advance to the next experiment. 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch remaining_experiments_.erase(remaining_experiments_.begin()); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_test_runner_.reset(); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notify the delegate of completion. 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnCompletedConnectionTestExperiment(current, result); 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (remaining_experiments_.empty()) { 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->OnCompletedConnectionTestSuite(); 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartNextExperiment(); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 460