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 URLRequestFileJob always returns a -1
21 // HTTP response status code.
22 class TestURLRequestJob
: public URLRequestFileJob
{
24 TestURLRequestJob(URLRequest
* request
,
25 NetworkDelegate
* network_delegate
,
26 const base::FilePath
& file_path
,
27 const scoped_refptr
<base::TaskRunner
>& worker_task_runner
)
28 : 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 URLRequestFilter singleton.
46 class TestURLRequestInterceptor::Delegate
: public 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 URLRequestFilter::GetInstance()->AddHostnameInterceptor(
61 scheme_
, hostname_
, scoped_ptr
<URLRequestInterceptor
>(this));
64 static void Unregister(const std::string
& scheme
,
65 const std::string
& hostname
) {
66 URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme
, hostname
);
69 // When requests for |url| arrive, respond with the contents of |path|. The
70 // hostname and scheme of |url| must match the corresponding parameters
71 // passed as constructor arguments.
72 void SetResponse(const GURL
& url
,
73 const base::FilePath
& path
,
75 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
77 ignore_query_responses_
[url
] = path
;
79 responses_
[url
] = path
;
83 // Returns how many requests have been issued that have a stored reply.
84 int GetHitCount() const {
85 base::AutoLock
auto_lock(hit_count_lock_
);
90 typedef std::map
<GURL
, base::FilePath
> ResponseMap
;
92 // When computing matches, this ignores the query parameters of the url.
93 URLRequestJob
* MaybeInterceptRequest(
95 NetworkDelegate
* network_delegate
) const override
{
96 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
97 if (request
->url().scheme() != scheme_
||
98 request
->url().host() != hostname_
) {
102 ResponseMap::const_iterator it
= responses_
.find(request
->url());
103 if (it
== responses_
.end()) {
104 // Search for this request's url, ignoring any query parameters.
105 GURL url
= request
->url();
106 if (url
.has_query()) {
107 GURL::Replacements replacements
;
108 replacements
.ClearQuery();
109 url
= url
.ReplaceComponents(replacements
);
111 it
= ignore_query_responses_
.find(url
);
112 if (it
== ignore_query_responses_
.end())
116 base::AutoLock
auto_lock(hit_count_lock_
);
120 return new TestURLRequestJob(
121 request
, network_delegate
, it
->second
, worker_task_runner_
);
124 const std::string scheme_
;
125 const std::string hostname_
;
127 const scoped_refptr
<base::TaskRunner
> network_task_runner_
;
128 const scoped_refptr
<base::TaskRunner
> worker_task_runner_
;
130 ResponseMap responses_
;
131 ResponseMap ignore_query_responses_
;
133 mutable base::Lock hit_count_lock_
;
134 mutable int hit_count_
;
136 DISALLOW_COPY_AND_ASSIGN(Delegate
);
139 TestURLRequestInterceptor::TestURLRequestInterceptor(
140 const std::string
& scheme
,
141 const std::string
& hostname
,
142 const scoped_refptr
<base::TaskRunner
>& network_task_runner
,
143 const scoped_refptr
<base::TaskRunner
>& worker_task_runner
)
146 network_task_runner_(network_task_runner
),
147 delegate_(new Delegate(scheme
,
149 network_task_runner_
,
150 worker_task_runner
)) {
151 network_task_runner_
->PostTask(
152 FROM_HERE
, base::Bind(&Delegate::Register
, base::Unretained(delegate_
)));
155 TestURLRequestInterceptor::~TestURLRequestInterceptor() {
156 network_task_runner_
->PostTask(
157 FROM_HERE
, base::Bind(&Delegate::Unregister
, scheme_
, hostname_
));
160 void TestURLRequestInterceptor::SetResponse(const GURL
& url
,
161 const base::FilePath
& path
) {
162 CHECK_EQ(scheme_
, url
.scheme());
163 CHECK_EQ(hostname_
, url
.host());
164 network_task_runner_
->PostTask(FROM_HERE
,
165 base::Bind(&Delegate::SetResponse
,
166 base::Unretained(delegate_
),
172 void TestURLRequestInterceptor::SetResponseIgnoreQuery(
174 const base::FilePath
& path
) {
175 CHECK_EQ(scheme_
, url
.scheme());
176 CHECK_EQ(hostname_
, url
.host());
177 network_task_runner_
->PostTask(FROM_HERE
,
178 base::Bind(&Delegate::SetResponse
,
179 base::Unretained(delegate_
),
185 int TestURLRequestInterceptor::GetHitCount() {
186 return delegate_
->GetHitCount();
189 LocalHostTestURLRequestInterceptor::LocalHostTestURLRequestInterceptor(
190 const scoped_refptr
<base::TaskRunner
>& network_task_runner
,
191 const scoped_refptr
<base::TaskRunner
>& worker_task_runner
)
192 : TestURLRequestInterceptor("http",
195 worker_task_runner
) {