blob: d99196a1128535930662cb5487b11327d53c370a [file] [log] [blame]
// Copyright 2016 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.
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "content/browser/loader/resource_handler.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"
namespace net {
class URLRequestStatus;
namespace network {
struct ResourceResponse;
namespace content {
class ResourceController;
class ResourceHandler;
// A test version of a ResourceHandler. It returns a configurable buffer in
// response to OnWillStart. It records what ResourceHandler methods are called,
// and verifies that they are called in the correct order. It can optionally
// defer or fail the request at any stage, and record the response body and
// final status it sees. Redirects currently not supported.
class TestResourceHandler : public ResourceHandler {
// If non-null, |request_status| will be updated when the response is complete
// with the final status of the request received by the handler and |body|
// will be updated on each OnReadCompleted call.
TestResourceHandler(net::URLRequestStatus* request_status, std::string* body);
~TestResourceHandler() override;
// ResourceHandler implementation:
void OnRequestRedirected(
const net::RedirectInfo& redirect_info,
network::ResourceResponse* response,
std::unique_ptr<ResourceController> controller) override;
void OnResponseStarted(
network::ResourceResponse* response,
std::unique_ptr<ResourceController> controller) override;
void OnWillStart(const GURL& url,
std::unique_ptr<ResourceController> controller) override;
void OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
std::unique_ptr<ResourceController> controller) override;
void OnReadCompleted(int bytes_read,
std::unique_ptr<ResourceController> controller) override;
void OnResponseCompleted(
const net::URLRequestStatus& status,
std::unique_ptr<ResourceController> controller) override;
void Resume();
void CancelWithError(net::Error error_code);
// Sets the size of the read buffer returned by OnWillRead. Releases reference
// to previous read buffer. Default size is 2048 bytes.
void SetBufferSize(int buffer_size);
scoped_refptr<net::IOBuffer> buffer() const { return buffer_; }
// Sets the result returned by each method. All default to returning true.
void set_on_will_start_result(bool on_will_start_result) {
on_will_start_result_ = on_will_start_result;
void set_on_request_redirected_result(bool on_request_redirected_result) {
on_request_redirected_result_ = on_request_redirected_result;
void set_on_response_started_result(bool on_response_started_result) {
on_response_started_result_ = on_response_started_result;
void set_on_will_read_result(bool on_will_read_result) {
on_will_read_result_ = on_will_read_result;
void set_on_read_completed_result(bool on_read_completed_result) {
on_read_completed_result_ = on_read_completed_result;
void set_on_read_eof_result(bool on_read_eof_result) {
on_read_eof_result_ = on_read_eof_result;
// Cause |defer| to be set to true when the specified method is invoked. The
// test itself is responsible for resuming the request after deferral.
void set_defer_on_will_start(bool defer_on_will_start) {
defer_on_will_start_ = defer_on_will_start;
void set_defer_on_request_redirected(bool defer_on_request_redirected) {
defer_on_request_redirected_ = defer_on_request_redirected;
void set_defer_on_response_started(bool defer_on_response_started) {
defer_on_response_started_ = defer_on_response_started;
// Only the next OnWillRead call will set |defer| to true.
void set_defer_on_will_read(bool defer_on_will_read) {
defer_on_will_read_ = defer_on_will_read;
// Only the next OnReadCompleted call will set |defer| to true.
void set_defer_on_read_completed(bool defer_on_read_completed) {
defer_on_read_completed_ = defer_on_read_completed;
// The final-byte read will set |defer| to true.
void set_defer_on_read_eof(bool defer_on_read_eof) {
defer_on_read_eof_ = defer_on_read_eof;
void set_defer_on_response_completed(bool defer_on_response_completed) {
defer_on_response_completed_ = defer_on_response_completed;
// Sets whether to expect a final 0-byte read on success. Defaults to true.
void set_expect_eof_read(bool expect_eof_read) {
expect_eof_read_ = expect_eof_read;
// Return the number of times the corresponding method was invoked.
int on_will_start_called() const { return on_will_start_called_; }
int on_request_redirected_called() const {
return on_request_redirected_called_;
int on_response_started_called() const { return on_response_started_called_; }
int on_will_read_called() const { return on_will_read_called_; }
int on_read_completed_called() const { return on_read_completed_called_; }
int on_read_eof_called() const { return on_read_eof_called_; }
int on_response_completed_called() const {
return on_response_completed_called_;
// URL passed to OnResponseStarted, if it was called.
const GURL& start_url() const { return start_url_; }
network::ResourceResponse* resource_response() {
return resource_response_.get();
const std::string& body() const { return body_; }
net::URLRequestStatus final_status() const { return final_status_; }
// Returns the current number of |this|'s methods on the callstack.
int call_depth() const { return call_depth_; }
// Spins the message loop until the request is deferred. Using this is
// optional, but if used, must use it exclusively to wait for the request. If
// the request was deferred and then resumed/canceled without calling this
// method, behavior is undefined.
void WaitUntilDeferred();
void WaitUntilResponseStarted();
void WaitUntilResponseComplete();
// Returns a weak pointer to |this|. Allows testing object lifetime.
base::WeakPtr<TestResourceHandler> GetWeakPtr();
// TODO(mmenke): Remove these, in favor of final_status_ and body_.
net::URLRequestStatus* request_status_ptr_;
std::string* body_ptr_;
scoped_refptr<net::IOBuffer> buffer_;
size_t buffer_size_;
bool on_will_start_result_ = true;
bool on_request_redirected_result_ = true;
bool on_response_started_result_ = true;
bool on_will_read_result_ = true;
bool on_read_completed_result_ = true;
bool on_read_eof_result_ = true;
bool defer_on_will_start_ = false;
bool defer_on_request_redirected_ = false;
bool defer_on_response_started_ = false;
bool defer_on_will_read_ = false;
bool defer_on_read_completed_ = false;
bool defer_on_read_eof_ = false;
bool defer_on_response_completed_ = false;
bool expect_eof_read_ = true;
int on_will_start_called_ = 0;
int on_request_redirected_called_ = 0;
int on_response_started_called_ = 0;
int on_will_read_called_ = 0;
int on_read_completed_called_ = 0;
int on_read_eof_called_ = 0;
int on_response_completed_called_ = 0;
GURL start_url_;
scoped_refptr<network::ResourceResponse> resource_response_;
std::string body_;
net::URLRequestStatus final_status_ =
bool canceled_ = false;
// Pointers to the parent's read buffer and size. Only non-NULL during
// OnWillRead call, until cancellation or resumption.
scoped_refptr<net::IOBuffer>* parent_read_buffer_ = nullptr;
int* parent_read_buffer_size_ = nullptr;
// Tracks recursive calls, which aren't allowed.
int call_depth_ = 0;
std::unique_ptr<base::RunLoop> deferred_run_loop_;
base::RunLoop response_started_run_loop_;
base::RunLoop response_complete_run_loop_;
base::WeakPtrFactory<TestResourceHandler> weak_ptr_factory_;
} // namespace content