1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_NET_CONNECTION_TESTER_H_ 6 #define CHROME_BROWSER_NET_CONNECTION_TESTER_H_ 7 8 #include <vector> 9 10 #include "base/basictypes.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "net/base/completion_callback.h" 13 #include "url/gurl.h" 14 15 namespace net { 16 class NetLog; 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 { 79 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: 106 // Called once the test suite is about to start. 107 virtual void OnStartConnectionTestSuite() = 0; 108 109 // Called when an individual experiment is about to be started. 110 virtual void OnStartConnectionTestExperiment( 111 const Experiment& experiment) = 0; 112 113 // Called when an individual experiment has completed. 114 // |experiment| - the experiment that has completed. 115 // |result| - the net error that the experiment completed with 116 // (or net::OK if it was success). 117 virtual void OnCompletedConnectionTestExperiment( 118 const Experiment& experiment, 119 int result) = 0; 120 121 // Called once ALL tests have completed. 122 virtual void OnCompletedConnectionTestSuite() = 0; 123 124 protected: 125 virtual ~Delegate() {} 126 }; 127 128 // Constructs a ConnectionTester that notifies test progress to |delegate|. 129 // |delegate| is owned by the caller, and must remain valid for the lifetime 130 // of ConnectionTester. 131 ConnectionTester(Delegate* delegate, 132 net::URLRequestContext* proxy_request_context, 133 net::NetLog* net_log); 134 135 // Note that destruction cancels any in-progress tests. 136 ~ConnectionTester(); 137 138 // Starts running the test suite on |url|. Notification of progress is sent to 139 // |delegate_|. 140 void RunAllTests(const GURL& url); 141 142 // Returns a text string explaining what |experiment| is testing. 143 static base::string16 ProxySettingsExperimentDescription( 144 ProxySettingsExperiment experiment); 145 static base::string16 HostResolverExperimentDescription( 146 HostResolverExperiment experiment); 147 148 private: 149 // Internally each experiment run by ConnectionTester is handled by a 150 // "TestRunner" instance. 151 class TestRunner; 152 friend class TestRunner; 153 154 // Fills |list| with the set of all possible experiments for |url|. 155 static void GetAllPossibleExperimentCombinations(const GURL& url, 156 ExperimentList* list); 157 158 // Starts the next experiment from |remaining_experiments_|. 159 void StartNextExperiment(); 160 161 // Callback for when |current_test_runner_| finishes. 162 void OnExperimentCompleted(int result); 163 164 // Returns the experiment at the front of our list. 165 const Experiment& current_experiment() const { 166 return remaining_experiments_.front(); 167 } 168 169 // The object to notify test progress to. 170 Delegate* delegate_; 171 172 // The current in-progress test, or NULL if there is no active test. 173 scoped_ptr<TestRunner> current_test_runner_; 174 175 // The ordered list of experiments to try next. The experiment at the front 176 // of the list is the one currently in progress. 177 ExperimentList remaining_experiments_; 178 179 net::URLRequestContext* const proxy_request_context_; 180 181 net::NetLog* net_log_; 182 183 DISALLOW_COPY_AND_ASSIGN(ConnectionTester); 184 }; 185 186 #endif // CHROME_BROWSER_NET_CONNECTION_TESTER_H_ 187