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