OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "net/url_request/test_url_request_interceptor.h" | |
6 | |
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" | |
15 | |
16 namespace net { | |
17 | |
18 namespace { | |
19 | |
20 // This class is needed because net::URLRequestFileJob always returns a -1 | |
21 // HTTP response status code. | |
22 class TestURLRequestJob : public net::URLRequestFileJob { | |
23 public: | |
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, | |
29 network_delegate, | |
30 file_path, | |
31 worker_task_runner) {} | |
32 | |
33 int GetResponseCode() const override { return 200; } | |
34 | |
35 private: | |
36 ~TestURLRequestJob() override {} | |
37 | |
38 DISALLOW_COPY_AND_ASSIGN(TestURLRequestJob); | |
39 }; | |
40 | |
41 } // namespace | |
42 | |
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 { | |
47 public: | |
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) | |
52 : scheme_(scheme), | |
53 hostname_(hostname), | |
54 network_task_runner_(network_task_runner), | |
55 worker_task_runner_(worker_task_runner), | |
56 hit_count_(0) {} | |
57 ~Delegate() override {} | |
58 | |
59 void Register() { | |
60 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( | |
61 scheme_, hostname_, scoped_ptr<net::URLRequestInterceptor>(this)); | |
62 } | |
63 | |
64 static void Unregister(const std::string& scheme, | |
65 const std::string& hostname) { | |
66 net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme, | |
67 hostname); | |
68 } | |
69 | |
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, | |
75 bool ignore_query) { | |
76 DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); | |
77 if (ignore_query) { | |
78 ignore_query_responses_[url] = path; | |
79 } else { | |
80 responses_[url] = path; | |
81 } | |
82 } | |
83 | |
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_); | |
87 return hit_count_; | |
88 } | |
89 | |
90 private: | |
91 typedef std::map<GURL, base::FilePath> ResponseMap; | |
92 | |
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_) { | |
100 return NULL; | |
101 } | |
102 | |
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); | |
111 } | |
112 it = ignore_query_responses_.find(url); | |
113 if (it == ignore_query_responses_.end()) | |
114 return NULL; | |
115 } | |
116 { | |
117 base::AutoLock auto_lock(hit_count_lock_); | |
118 ++hit_count_; | |
119 } | |
120 | |
121 return new TestURLRequestJob( | |
122 request, network_delegate, it->second, worker_task_runner_); | |
123 } | |
124 | |
125 const std::string scheme_; | |
126 const std::string hostname_; | |
127 | |
128 const scoped_refptr<base::TaskRunner> network_task_runner_; | |
129 const scoped_refptr<base::TaskRunner> worker_task_runner_; | |
130 | |
131 ResponseMap responses_; | |
132 ResponseMap ignore_query_responses_; | |
133 | |
134 mutable base::Lock hit_count_lock_; | |
135 mutable int hit_count_; | |
136 | |
137 DISALLOW_COPY_AND_ASSIGN(Delegate); | |
138 }; | |
139 | |
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) | |
145 : scheme_(scheme), | |
146 hostname_(hostname), | |
147 network_task_runner_(network_task_runner), | |
148 delegate_(new Delegate(scheme, | |
149 hostname, | |
150 network_task_runner_, | |
151 worker_task_runner)) { | |
152 network_task_runner_->PostTask( | |
153 FROM_HERE, base::Bind(&Delegate::Register, base::Unretained(delegate_))); | |
154 } | |
155 | |
156 TestURLRequestInterceptor::~TestURLRequestInterceptor() { | |
157 network_task_runner_->PostTask( | |
158 FROM_HERE, base::Bind(&Delegate::Unregister, scheme_, hostname_)); | |
159 } | |
160 | |
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_), | |
168 url, | |
169 path, | |
170 false)); | |
171 } | |
172 | |
173 void TestURLRequestInterceptor::SetResponseIgnoreQuery( | |
174 const GURL& url, | |
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_), | |
181 url, | |
182 path, | |
183 true)); | |
184 } | |
185 | |
186 int TestURLRequestInterceptor::GetHitCount() { | |
187 return delegate_->GetHitCount(); | |
188 } | |
189 | |
190 LocalHostTestURLRequestInterceptor::LocalHostTestURLRequestInterceptor( | |
191 const scoped_refptr<base::TaskRunner>& network_task_runner, | |
192 const scoped_refptr<base::TaskRunner>& worker_task_runner) | |
193 : TestURLRequestInterceptor("http", | |
194 "localhost", | |
195 network_task_runner, | |
196 worker_task_runner) { | |
197 } | |
198 | |
199 } // namespace net | |
OLD | NEW |