• 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_HTTP_PIPELINING_COMPATIBILITY_CLIENT_H_
6 #define CHROME_BROWSER_NET_HTTP_PIPELINING_COMPATIBILITY_CLIENT_H_
7 
8 #include <string>
9 #include <vector>
10 
11 #include "base/memory/scoped_vector.h"
12 #include "net/base/completion_callback.h"
13 #include "net/base/io_buffer.h"
14 #include "net/url_request/url_request.h"
15 #include "net/url_request/url_request_context.h"
16 
17 class IOThread;
18 
19 namespace chrome_browser_net {
20 
21 struct RequestInfo {
22   std::string filename;  // The path relative to the test server's base_url.
23   std::string expected_response;  // The expected body of the response.
24 };
25 
26 namespace internal {
27 
28 class PipelineTestRequest {
29  public:
30   enum Status {
31     STATUS_SUCCESS,
32     STATUS_REDIRECTED,         // Response was redirected. We won't follow.
33     STATUS_CERT_ERROR,         // Any certificate problem.
34     STATUS_BAD_RESPONSE_CODE,  // Any non-200 response.
35     STATUS_NETWORK_ERROR,      // Any socket error reported by the network
36                                // layer.
37     STATUS_TOO_LARGE,          // The response matched, but had extra data on
38                                // the end.
39     STATUS_TOO_SMALL,          // The response was shorter than expected, but
40                                // what we got matched.
41     STATUS_CONTENT_MISMATCH,   // The response didn't match the expected value.
42     STATUS_BAD_HTTP_VERSION,   // Any version older than HTTP/1.1.
43     STATUS_CORRUPT_STATS,      // The stats.txt response was corrupt.
44     STATUS_MAX,
45   };
46 
47   enum Type {
48     TYPE_PIPELINED,  // Pipelined test requests.
49     TYPE_CANARY,     // A non-pipelined request to verify basic HTTP
50                      // connectivity.
51     TYPE_STATS,      // Collects stats from the test server.
52   };
53 
54   class Delegate {
55    public:
~Delegate()56     virtual ~Delegate() {}
57 
58     // Called when the canary request completes.
59     virtual void OnCanaryFinished(Status status) = 0;
60 
61     // Called when a Request determines its result. Reports to UMA.
62     virtual void OnRequestFinished(int request_id, Status status) = 0;
63 
64     // Called when a Request encounters a network error. Reports to UMA.
65     virtual void ReportNetworkError(int request_id, int error_code) = 0;
66 
67     // Called when a Request determines its HTTP response code. Reports to UMA.
68     virtual void ReportResponseCode(int request_id, int response_code) = 0;
69   };
70 
71   class Factory {
72    public:
~Factory()73     virtual ~Factory() {}
74 
75     virtual PipelineTestRequest* NewRequest(
76         int request_id,
77         const std::string& base_url,
78         const RequestInfo& info,
79         Delegate* delegate,
80         net::URLRequestContext* url_request_context,
81         Type type) = 0;
82   };
83 
~PipelineTestRequest()84   virtual ~PipelineTestRequest() {}
85 
86   virtual void Start() = 0;
87 };
88 
89 PipelineTestRequest::Status ProcessStatsResponse(
90     const std::string& response);
91 
92 }  // namespace internal
93 
94 // Class for performing a background test of users' Internet connections.
95 // Fetches a collection of resources on a test server and verifies all were
96 // received correctly. This will be used to determine whether or not proxies are
97 // interfering with a user's ability to use HTTP pipelining. Results are
98 // recorded with UMA.
99 class HttpPipeliningCompatibilityClient
100     : public internal::PipelineTestRequest::Delegate {
101  public:
102   enum Options {
103     PIPE_TEST_DEFAULTS,              // Only run the |requests| passed to Start.
104     PIPE_TEST_RUN_CANARY_REQUEST,    // Also perform a canary request before
105                                      // testing pipelining.
106     PIPE_TEST_COLLECT_SERVER_STATS,  // Also request stats from the server after
107                                      // the pipeline test completes.
108     PIPE_TEST_CANARY_AND_STATS,      // Both of the above.
109   };
110 
111   HttpPipeliningCompatibilityClient(
112       internal::PipelineTestRequest::Factory* factory);
113   virtual ~HttpPipeliningCompatibilityClient();
114 
115   // Launches the asynchronous URLRequests to fetch the URLs specified by
116   // |requests| combined with |base_url|. |base_url| should match the pattern
117   // "http://host/". |callback| is invoked once all the requests have completed.
118   // URLRequests are initiated in |url_request_context|. Results are recorded to
119   // UMA as they are received. If |collect_server_stats| is true, also collects
120   // pipelining information recorded by the server.
121   void Start(const std::string& base_url,
122              std::vector<RequestInfo>& requests,
123              Options options,
124              const net::CompletionCallback& callback,
125              net::URLRequestContext* url_request_context);
126 
127  private:
128   // Sends the pipelining test requests.
129   void StartTestRequests();
130 
131   // Returns the full UMA metric name based on |request_id| and |description|.
132   std::string GetMetricName(int request_id, const char* description);
133 
134   // PipelineTestRequest::Delegate interface.
135   virtual void OnCanaryFinished(
136       internal::PipelineTestRequest::Status status) OVERRIDE;
137   virtual void OnRequestFinished(
138       int request_id,
139       internal::PipelineTestRequest::Status status) OVERRIDE;
140   virtual void ReportNetworkError(int request_id, int error_code) OVERRIDE;
141   virtual void ReportResponseCode(int request_id, int response_code) OVERRIDE;
142 
143   scoped_ptr<net::HttpTransactionFactory> http_transaction_factory_;
144   scoped_ptr<net::URLRequestContext> url_request_context_;
145   scoped_ptr<internal::PipelineTestRequest::Factory> factory_;
146   ScopedVector<internal::PipelineTestRequest> requests_;
147   scoped_ptr<internal::PipelineTestRequest> canary_request_;
148   net::CompletionCallback finished_callback_;
149   size_t num_finished_;
150   size_t num_succeeded_;
151 };
152 
153 void CollectPipeliningCapabilityStatsOnUIThread(
154     const std::string& pipeline_test_server, IOThread* io_thread);
155 
156 }  // namespace chrome_browser_net
157 
158 #endif  // CHROME_BROWSER_NET_HTTP_PIPELINING_COMPATIBILITY_CLIENT_H_
159