• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
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:
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:
~Delegate()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.
current_experiment()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