Home | History | Annotate | Download | only in net
      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:
     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:
     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 
     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