blob: f249af6ccb505af80eacf86168bcb41f12c32b50 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_NET_HTTP_PIPELINING_COMPATIBILITY_CLIENT_H_
#define CHROME_BROWSER_NET_HTTP_PIPELINING_COMPATIBILITY_CLIENT_H_
#include <string>
#include <vector>
#include "base/memory/scoped_vector.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
class IOThread;
namespace chrome_browser_net {
struct RequestInfo {
std::string filename; // The path relative to the test server's base_url.
std::string expected_response; // The expected body of the response.
};
namespace internal {
class PipelineTestRequest {
public:
enum Status {
STATUS_SUCCESS,
STATUS_REDIRECTED, // Response was redirected. We won't follow.
STATUS_CERT_ERROR, // Any certificate problem.
STATUS_BAD_RESPONSE_CODE, // Any non-200 response.
STATUS_NETWORK_ERROR, // Any socket error reported by the network
// layer.
STATUS_TOO_LARGE, // The response matched, but had extra data on
// the end.
STATUS_TOO_SMALL, // The response was shorter than expected, but
// what we got matched.
STATUS_CONTENT_MISMATCH, // The response didn't match the expected value.
STATUS_BAD_HTTP_VERSION, // Any version older than HTTP/1.1.
STATUS_CORRUPT_STATS, // The stats.txt response was corrupt.
STATUS_MAX,
};
enum Type {
TYPE_PIPELINED, // Pipelined test requests.
TYPE_CANARY, // A non-pipelined request to verify basic HTTP
// connectivity.
TYPE_STATS, // Collects stats from the test server.
};
class Delegate {
public:
virtual ~Delegate() {}
// Called when the canary request completes.
virtual void OnCanaryFinished(Status status) = 0;
// Called when a Request determines its result. Reports to UMA.
virtual void OnRequestFinished(int request_id, Status status) = 0;
// Called when a Request encounters a network error. Reports to UMA.
virtual void ReportNetworkError(int request_id, int error_code) = 0;
// Called when a Request determines its HTTP response code. Reports to UMA.
virtual void ReportResponseCode(int request_id, int response_code) = 0;
};
class Factory {
public:
virtual ~Factory() {}
virtual PipelineTestRequest* NewRequest(
int request_id,
const std::string& base_url,
const RequestInfo& info,
Delegate* delegate,
net::URLRequestContext* url_request_context,
Type type) = 0;
};
virtual ~PipelineTestRequest() {}
virtual void Start() = 0;
};
PipelineTestRequest::Status ProcessStatsResponse(
const std::string& response);
} // namespace internal
// Class for performing a background test of users' Internet connections.
// Fetches a collection of resources on a test server and verifies all were
// received correctly. This will be used to determine whether or not proxies are
// interfering with a user's ability to use HTTP pipelining. Results are
// recorded with UMA.
class HttpPipeliningCompatibilityClient
: public internal::PipelineTestRequest::Delegate {
public:
enum Options {
PIPE_TEST_DEFAULTS, // Only run the |requests| passed to Start.
PIPE_TEST_RUN_CANARY_REQUEST, // Also perform a canary request before
// testing pipelining.
PIPE_TEST_COLLECT_SERVER_STATS, // Also request stats from the server after
// the pipeline test completes.
PIPE_TEST_CANARY_AND_STATS, // Both of the above.
};
HttpPipeliningCompatibilityClient(
internal::PipelineTestRequest::Factory* factory);
virtual ~HttpPipeliningCompatibilityClient();
// Launches the asynchronous URLRequests to fetch the URLs specified by
// |requests| combined with |base_url|. |base_url| should match the pattern
// "http://host/". |callback| is invoked once all the requests have completed.
// URLRequests are initiated in |url_request_context|. Results are recorded to
// UMA as they are received. If |collect_server_stats| is true, also collects
// pipelining information recorded by the server.
void Start(const std::string& base_url,
std::vector<RequestInfo>& requests,
Options options,
const net::CompletionCallback& callback,
net::URLRequestContext* url_request_context);
private:
// Sends the pipelining test requests.
void StartTestRequests();
// Returns the full UMA metric name based on |request_id| and |description|.
std::string GetMetricName(int request_id, const char* description);
// PipelineTestRequest::Delegate interface.
virtual void OnCanaryFinished(
internal::PipelineTestRequest::Status status) OVERRIDE;
virtual void OnRequestFinished(
int request_id,
internal::PipelineTestRequest::Status status) OVERRIDE;
virtual void ReportNetworkError(int request_id, int error_code) OVERRIDE;
virtual void ReportResponseCode(int request_id, int response_code) OVERRIDE;
scoped_ptr<net::HttpTransactionFactory> http_transaction_factory_;
scoped_ptr<net::URLRequestContext> url_request_context_;
scoped_ptr<internal::PipelineTestRequest::Factory> factory_;
ScopedVector<internal::PipelineTestRequest> requests_;
scoped_ptr<internal::PipelineTestRequest> canary_request_;
net::CompletionCallback finished_callback_;
size_t num_finished_;
size_t num_succeeded_;
};
void CollectPipeliningCapabilityStatsOnUIThread(
const std::string& pipeline_test_server, IOThread* io_thread);
} // namespace chrome_browser_net
#endif // CHROME_BROWSER_NET_HTTP_PIPELINING_COMPATIBILITY_CLIENT_H_