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