1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
// Copyright 2013 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 COMPONENTS_UPDATE_CLIENT_URL_REQUEST_POST_INTERCEPTOR_H_
#define COMPONENTS_UPDATE_CLIENT_URL_REQUEST_POST_INTERCEPTOR_H_
#include <stdint.h>
#include <map>
#include <queue>
#include <string>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "url/gurl.h"
namespace base {
class FilePath;
class SequencedTaskRunner;
}
namespace update_client {
// Intercepts requests to a file path, counts them, and captures the body of
// the requests. Optionally, for each request, it can return a canned response
// from a given file. The class maintains a queue of expectations, and returns
// one and only one response for each request that matches and it is
// intercepted.
class URLRequestPostInterceptor {
public:
// Allows a generic string maching interface when setting up expectations.
class RequestMatcher {
public:
virtual bool Match(const std::string& actual) const = 0;
virtual ~RequestMatcher() {}
};
// Returns the url that is intercepted.
GURL GetUrl() const;
// Sets an expection for the body of the POST request and optionally,
// provides a canned response identified by a |file_path| to be returned when
// the expectation is met. If no |file_path| is provided, then an empty
// response body is served. If |response_code| is provided, then an empty
// response body with that response code is returned.
// Returns |true| if the expectation was set. This class takes ownership of
// the |request_matcher| object.
bool ExpectRequest(class RequestMatcher* request_matcher);
bool ExpectRequest(class RequestMatcher* request_matcher, int response_code);
bool ExpectRequest(class RequestMatcher* request_matcher,
const base::FilePath& filepath);
// Returns how many requests have been intercepted and matched by
// an expectation. One expectation can only be matched by one request.
int GetHitCount() const;
// Returns how many requests in total have been captured by the interceptor.
int GetCount() const;
// Returns all requests that have been intercepted, matched or not.
std::vector<std::string> GetRequests() const;
// Returns all requests as a string for debugging purposes.
std::string GetRequestsAsString() const;
// Resets the state of the interceptor so that new expectations can be set.
void Reset();
class Delegate;
private:
friend class URLRequestPostInterceptorFactory;
static const int kResponseCode200 = 200;
struct ExpectationResponse {
ExpectationResponse(int code, const std::string& body)
: response_code(code), response_body(body) {}
const int response_code;
const std::string response_body;
};
typedef std::pair<const RequestMatcher*, ExpectationResponse> Expectation;
URLRequestPostInterceptor(
const GURL& url,
const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
~URLRequestPostInterceptor();
void ClearExpectations();
const GURL url_;
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
mutable base::Lock interceptor_lock_;
mutable int hit_count_;
mutable std::vector<std::string> requests_;
mutable std::queue<Expectation> expectations_;
DISALLOW_COPY_AND_ASSIGN(URLRequestPostInterceptor);
};
class URLRequestPostInterceptorFactory {
public:
URLRequestPostInterceptorFactory(
const std::string& scheme,
const std::string& hostname,
const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
~URLRequestPostInterceptorFactory();
// Creates an interceptor object for the specified url path. Returns NULL
// in case of errors or a valid interceptor object otherwise. The caller
// does not own the returned object.
URLRequestPostInterceptor* CreateInterceptor(const base::FilePath& filepath);
private:
const std::string scheme_;
const std::string hostname_;
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
// After creation, |delegate_| lives on the IO thread and it is owned by
// a URLRequestFilter after registration. A task to unregister it and
// implicitly destroy it is posted from ~URLRequestPostInterceptorFactory().
URLRequestPostInterceptor::Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(URLRequestPostInterceptorFactory);
};
// Intercepts HTTP POST requests sent to "localhost2".
class InterceptorFactory : public URLRequestPostInterceptorFactory {
public:
explicit InterceptorFactory(
const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
~InterceptorFactory();
// Creates an interceptor for the url path defined by POST_INTERCEPT_PATH.
URLRequestPostInterceptor* CreateInterceptor();
// Creates an interceptor for the given url path.
URLRequestPostInterceptor* CreateInterceptorForPath(const char* url_path);
private:
DISALLOW_COPY_AND_ASSIGN(InterceptorFactory);
};
class PartialMatch : public URLRequestPostInterceptor::RequestMatcher {
public:
explicit PartialMatch(const std::string& expected) : expected_(expected) {}
bool Match(const std::string& actual) const override;
private:
const std::string expected_;
DISALLOW_COPY_AND_ASSIGN(PartialMatch);
};
} // namespace update_client
#endif // COMPONENTS_UPDATE_CLIENT_URL_REQUEST_POST_INTERCEPTOR_H_
|