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.
5 #include "net/url_request/test_url_request_interceptor.h"
7 #include "base/files/file_util.h"
8 #include "base/threading/sequenced_worker_pool.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "net/url_request/url_request.h"
11 #include "net/url_request/url_request_file_job.h"
12 #include "net/url_request/url_request_filter.h"
13 #include "net/url_request/url_request_interceptor.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 // This class is needed because net::URLRequestFileJob always returns a -1
21 // HTTP response status code.
22 class TestURLRequestJob
: public net::URLRequestFileJob
{
24 TestURLRequestJob(net::URLRequest
* request
,
25 net::NetworkDelegate
* network_delegate
,
26 const base::FilePath
& file_path
,
27 const scoped_refptr
<base::TaskRunner
>& worker_task_runner
)
28 : net::URLRequestFileJob(request
,
31 worker_task_runner
) {}
33 int GetResponseCode() const override
{ return 200; }
36 ~TestURLRequestJob() override
{}
38 DISALLOW_COPY_AND_ASSIGN(TestURLRequestJob
);
43 // This class handles the actual URL request interception. It may be constructed
44 // on any thread, but all other methods are called on the |network_task_runner|
45 // thread. It is destroyed by the net::URLRequestFilter singleton.
46 class TestURLRequestInterceptor::Delegate
: public net::URLRequestInterceptor
{
48 Delegate(const std::string
& scheme
,
49 const std::string
& hostname
,
50 const scoped_refptr
<base::TaskRunner
>& network_task_runner
,
51 const scoped_refptr
<base::TaskRunner
>& worker_task_runner
)
54 network_task_runner_(network_task_runner
),
55 worker_task_runner_(worker_task_runner
),
57 ~Delegate() override
{}
60 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
61 scheme_
, hostname_
, scoped_ptr
<net::URLRequestInterceptor
>(this));
64 static void Unregister(const std::string
& scheme
,
65 const std::string
& hostname
) {
66 net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme
,
70 // When requests for |url| arrive, respond with the contents of |path|. The
71 // hostname and scheme of |url| must match the corresponding parameters
72 // passed as constructor arguments.
73 void SetResponse(const GURL
& url
,
74 const base::FilePath
& path
,
76 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
78 ignore_query_responses_
[url
] = path
;
80 responses_
[url
] = path
;
84 // Returns how many requests have been issued that have a stored reply.
85 int GetHitCount() const {
86 base::AutoLock
auto_lock(hit_count_lock_
);
91 typedef std::map
<GURL
, base::FilePath
> ResponseMap
;
93 // When computing matches, this ignores the query parameters of the url.
94 net::URLRequestJob
* MaybeInterceptRequest(
95 net::URLRequest
* request
,
96 net::NetworkDelegate
* network_delegate
) const override
{
97 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
98 if (request
->url().scheme() != scheme_
||
99 request
->url().host() != hostname_
) {
103 ResponseMap::const_iterator it
= responses_
.find(request
->url());
104 if (it
== responses_
.end()) {
105 // Search for this request's url, ignoring any query parameters.
106 GURL url
= request
->url();
107 if (url
.has_query()) {
108 GURL::Replacements replacements
;
109 replacements
.ClearQuery();
110 url
= url
.ReplaceComponents(replacements
);
112 it
= ignore_query_responses_
.find(url
);
113 if (it
== ignore_query_responses_
.end())
117 base::AutoLock
auto_lock(hit_count_lock_
);
121 return new TestURLRequestJob(
122 request
, network_delegate
, it
->second
, worker_task_runner_
);
125 const std::string scheme_
;
126 const std::string hostname_
;
128 const scoped_refptr
<base::TaskRunner
> network_task_runner_
;
129 const scoped_refptr
<base::TaskRunner
> worker_task_runner_
;
131 ResponseMap responses_
;
132 ResponseMap ignore_query_responses_
;
134 mutable base::Lock hit_count_lock_
;
135 mutable int hit_count_
;
137 DISALLOW_COPY_AND_ASSIGN(Delegate
);
140 TestURLRequestInterceptor::TestURLRequestInterceptor(
141 const std::string
& scheme
,
142 const std::string
& hostname
,
143 const scoped_refptr
<base::TaskRunner
>& network_task_runner
,
144 const scoped_refptr
<base::TaskRunner
>& worker_task_runner
)
147 network_task_runner_(network_task_runner
),
148 delegate_(new Delegate(scheme
,
150 network_task_runner_
,
151 worker_task_runner
)) {
152 network_task_runner_
->PostTask(
153 FROM_HERE
, base::Bind(&Delegate::Register
, base::Unretained(delegate_
)));
156 TestURLRequestInterceptor::~TestURLRequestInterceptor() {
157 network_task_runner_
->PostTask(
158 FROM_HERE
, base::Bind(&Delegate::Unregister
, scheme_
, hostname_
));
161 void TestURLRequestInterceptor::SetResponse(const GURL
& url
,
162 const base::FilePath
& path
) {
163 CHECK_EQ(scheme_
, url
.scheme());
164 CHECK_EQ(hostname_
, url
.host());
165 network_task_runner_
->PostTask(FROM_HERE
,
166 base::Bind(&Delegate::SetResponse
,
167 base::Unretained(delegate_
),
173 void TestURLRequestInterceptor::SetResponseIgnoreQuery(
175 const base::FilePath
& path
) {
176 CHECK_EQ(scheme_
, url
.scheme());
177 CHECK_EQ(hostname_
, url
.host());
178 network_task_runner_
->PostTask(FROM_HERE
,
179 base::Bind(&Delegate::SetResponse
,
180 base::Unretained(delegate_
),
186 int TestURLRequestInterceptor::GetHitCount() {
187 return delegate_
->GetHitCount();
190 LocalHostTestURLRequestInterceptor::LocalHostTestURLRequestInterceptor(
191 const scoped_refptr
<base::TaskRunner
>& network_task_runner
,
192 const scoped_refptr
<base::TaskRunner
>& worker_task_runner
)
193 : TestURLRequestInterceptor("http",
196 worker_task_runner
) {