1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_NET_CONNECTION_TESTER_H_ 6 #define CHROME_BROWSER_NET_CONNECTION_TESTER_H_ 7 #pragma once 8 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "googleurl/src/gurl.h" 14 #include "net/base/completion_callback.h" 15 16 namespace net { 17 class URLRequestContext; 18 } // namespace net 19 20 // ConnectionTester runs a suite of tests (also called "experiments"), 21 // to try and discover why loading a particular URL is failing with an error 22 // code. 23 // 24 // For example, one reason why the URL might have failed, is that the 25 // network requires the URL to be routed through a proxy, however chrome is 26 // not configured for that. 27 // 28 // The above issue might be detected by running test that fetches the URL using 29 // auto-detect and seeing if it works this time. Or even by retrieving the 30 // settings from another installed browser and trying with those. 31 // 32 // USAGE: 33 // 34 // To run the test suite, create an instance of ConnectionTester and then call 35 // RunAllTests(). 36 // 37 // This starts a sequence of tests, which will complete asynchronously. 38 // The ConnectionTester object can be deleted at any time, and it will abort 39 // any of the in-progress tests. 40 // 41 // As tests are started or completed, notification will be sent through the 42 // "Delegate" object. 43 44 class ConnectionTester { 45 public: 46 // This enum lists the possible proxy settings configurations. 47 enum ProxySettingsExperiment { 48 // Do not use any proxy. 49 PROXY_EXPERIMENT_USE_DIRECT = 0, 50 51 // Use the system proxy settings. 52 PROXY_EXPERIMENT_USE_SYSTEM_SETTINGS, 53 54 // Use Firefox's proxy settings if they are available. 55 PROXY_EXPERIMENT_USE_FIREFOX_SETTINGS, 56 57 // Use proxy auto-detect. 58 PROXY_EXPERIMENT_USE_AUTO_DETECT, 59 60 PROXY_EXPERIMENT_COUNT, 61 }; 62 63 // This enum lists the possible host resolving configurations. 64 enum HostResolverExperiment { 65 // Use a default host resolver implementation. 66 HOST_RESOLVER_EXPERIMENT_PLAIN = 0, 67 68 // Disable IPv6 host resolving. 69 HOST_RESOLVER_EXPERIMENT_DISABLE_IPV6, 70 71 // Probe for IPv6 support. 72 HOST_RESOLVER_EXPERIMENT_IPV6_PROBE, 73 74 HOST_RESOLVER_EXPERIMENT_COUNT, 75 }; 76 77 // The "Experiment" structure describes an individual test to run. 78 struct Experiment { ExperimentExperiment79 Experiment(const GURL& url, 80 ProxySettingsExperiment proxy_settings_experiment, 81 HostResolverExperiment host_resolver_experiment) 82 : url(url), 83 proxy_settings_experiment(proxy_settings_experiment), 84 host_resolver_experiment(host_resolver_experiment) { 85 } 86 87 // The URL to try and fetch. 88 GURL url; 89 90 // The proxy settings to use. 91 ProxySettingsExperiment proxy_settings_experiment; 92 93 // The host resolver settings to use. 94 HostResolverExperiment host_resolver_experiment; 95 }; 96 97 typedef std::vector<Experiment> ExperimentList; 98 99 // "Delegate" is an interface for receiving start and completion notification 100 // of individual tests that are run by the ConnectionTester. 101 // 102 // NOTE: do not delete the ConnectionTester when executing within one of the 103 // delegate methods. 104 class Delegate { 105 public: ~Delegate()106 virtual ~Delegate() {} 107 108 // Called once the test suite is about to start. 109 virtual void OnStartConnectionTestSuite() = 0; 110 111 // Called when an individual experiment is about to be started. 112 virtual void OnStartConnectionTestExperiment( 113 const Experiment& experiment) = 0; 114 115 // Called when an individual experiment has completed. 116 // |experiment| - the experiment that has completed. 117 // |result| - the net error that the experiment completed with 118 // (or net::OK if it was success). 119 virtual void OnCompletedConnectionTestExperiment( 120 const Experiment& experiment, 121 int result) = 0; 122 123 // Called once ALL tests have completed. 124 virtual void OnCompletedConnectionTestSuite() = 0; 125 }; 126 127 // Constructs a ConnectionTester that notifies test progress to |delegate|. 128 // |delegate| is owned by the caller, and must remain valid for the lifetime 129 // of ConnectionTester. 130 ConnectionTester(Delegate* delegate, 131 net::URLRequestContext* proxy_request_context); 132 133 // Note that destruction cancels any in-progress tests. 134 ~ConnectionTester(); 135 136 // Starts running the test suite on |url|. Notification of progress is sent to 137 // |delegate_|. 138 void RunAllTests(const GURL& url); 139 140 // Returns a text string explaining what |experiment| is testing. 141 static string16 ProxySettingsExperimentDescription( 142 ProxySettingsExperiment experiment); 143 static string16 HostResolverExperimentDescription( 144 HostResolverExperiment experiment); 145 146 private: 147 // Internally each experiment run by ConnectionTester is handled by a 148 // "TestRunner" instance. 149 class TestRunner; 150 friend class TestRunner; 151 152 // Fills |list| with the set of all possible experiments for |url|. 153 static void GetAllPossibleExperimentCombinations(const GURL& url, 154 ExperimentList* list); 155 156 // Starts the next experiment from |remaining_experiments_|. 157 void StartNextExperiment(); 158 159 // Callback for when |current_test_runner_| finishes. 160 void OnExperimentCompleted(int result); 161 162 // Returns the experiment at the front of our list. current_experiment()163 const Experiment& current_experiment() const { 164 return remaining_experiments_.front(); 165 } 166 167 // The object to notify test progress to. 168 Delegate* delegate_; 169 170 // The current in-progress test, or NULL if there is no active test. 171 scoped_ptr<TestRunner> current_test_runner_; 172 173 // The ordered list of experiments to try next. The experiment at the front 174 // of the list is the one currently in progress. 175 ExperimentList remaining_experiments_; 176 177 const scoped_refptr<net::URLRequestContext> proxy_request_context_; 178 179 DISALLOW_COPY_AND_ASSIGN(ConnectionTester); 180 }; 181 182 #endif // CHROME_BROWSER_NET_CONNECTION_TESTER_H_ 183