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