Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / component_updater / test / url_request_post_interceptor.cc
1 // Copyright 2013 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 "components/component_updater/test/url_request_post_interceptor.h"
6
7 #include "base/files/file_util.h"
8 #include "base/macros.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/stringprintf.h"
11 #include "components/component_updater/test/test_configurator.h"
12 #include "net/base/upload_bytes_element_reader.h"
13 #include "net/url_request/url_request.h"
14 #include "net/url_request/url_request_filter.h"
15 #include "net/url_request/url_request_interceptor.h"
16 #include "net/url_request/url_request_simple_job.h"
17 #include "net/url_request/url_request_test_util.h"
18
19 namespace component_updater {
20
21 // Returns a canned response.
22 class URLRequestMockJob : public net::URLRequestSimpleJob {
23  public:
24   URLRequestMockJob(net::URLRequest* request,
25                     net::NetworkDelegate* network_delegate,
26                     int response_code,
27                     const std::string& response_body)
28       : net::URLRequestSimpleJob(request, network_delegate),
29         response_code_(response_code),
30         response_body_(response_body) {}
31
32  protected:
33   virtual int GetResponseCode() const OVERRIDE { return response_code_; }
34
35   virtual int GetData(std::string* mime_type,
36                       std::string* charset,
37                       std::string* data,
38                       const net::CompletionCallback& callback) const OVERRIDE {
39     mime_type->assign("text/plain");
40     charset->assign("US-ASCII");
41     data->assign(response_body_);
42     return net::OK;
43   }
44
45  private:
46   virtual ~URLRequestMockJob() {}
47
48   int response_code_;
49   std::string response_body_;
50   DISALLOW_COPY_AND_ASSIGN(URLRequestMockJob);
51 };
52
53 URLRequestPostInterceptor::URLRequestPostInterceptor(
54     const GURL& url,
55     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
56     : url_(url), io_task_runner_(io_task_runner), hit_count_(0) {
57 }
58
59 URLRequestPostInterceptor::~URLRequestPostInterceptor() {
60   DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
61   ClearExpectations();
62 }
63
64 void URLRequestPostInterceptor::ClearExpectations() {
65   while (!expectations_.empty()) {
66     Expectation expectation(expectations_.front());
67     delete expectation.first;
68     expectations_.pop();
69   }
70 }
71
72 GURL URLRequestPostInterceptor::GetUrl() const {
73   return url_;
74 }
75
76 bool URLRequestPostInterceptor::ExpectRequest(
77     class RequestMatcher* request_matcher) {
78   expectations_.push(std::make_pair(request_matcher,
79                                     ExpectationResponse(kResponseCode200, "")));
80   return true;
81 }
82
83 bool URLRequestPostInterceptor::ExpectRequest(
84     class RequestMatcher* request_matcher,
85     int response_code) {
86   expectations_.push(
87       std::make_pair(request_matcher, ExpectationResponse(response_code, "")));
88   return true;
89 }
90
91 bool URLRequestPostInterceptor::ExpectRequest(
92     class RequestMatcher* request_matcher,
93     const base::FilePath& filepath) {
94   std::string response;
95   if (filepath.empty() || !base::ReadFileToString(filepath, &response))
96     return false;
97
98   expectations_.push(std::make_pair(
99       request_matcher, ExpectationResponse(kResponseCode200, response)));
100   return true;
101 }
102
103 int URLRequestPostInterceptor::GetHitCount() const {
104   base::AutoLock auto_lock(interceptor_lock_);
105   return hit_count_;
106 }
107
108 int URLRequestPostInterceptor::GetCount() const {
109   base::AutoLock auto_lock(interceptor_lock_);
110   return static_cast<int>(requests_.size());
111 }
112
113 std::vector<std::string> URLRequestPostInterceptor::GetRequests() const {
114   base::AutoLock auto_lock(interceptor_lock_);
115   return requests_;
116 }
117
118 std::string URLRequestPostInterceptor::GetRequestsAsString() const {
119   std::vector<std::string> requests(GetRequests());
120
121   std::string s = "Requests are:";
122
123   int i = 0;
124   for (std::vector<std::string>::const_iterator it = requests.begin();
125        it != requests.end();
126        ++it) {
127     s.append(base::StringPrintf("\n  (%d): %s", ++i, it->c_str()));
128   }
129
130   return s;
131 }
132
133 void URLRequestPostInterceptor::Reset() {
134   base::AutoLock auto_lock(interceptor_lock_);
135   hit_count_ = 0;
136   requests_.clear();
137   ClearExpectations();
138 }
139
140 class URLRequestPostInterceptor::Delegate : public net::URLRequestInterceptor {
141  public:
142   Delegate(const std::string& scheme,
143            const std::string& hostname,
144            const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
145       : scheme_(scheme), hostname_(hostname), io_task_runner_(io_task_runner) {}
146
147   void Register() {
148     DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
149     net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
150         scheme_, hostname_, scoped_ptr<net::URLRequestInterceptor>(this));
151   }
152
153   void Unregister() {
154     DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
155     for (InterceptorMap::iterator it = interceptors_.begin();
156          it != interceptors_.end();
157          ++it)
158       delete (*it).second;
159     net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme_,
160                                                                 hostname_);
161   }
162
163   void OnCreateInterceptor(URLRequestPostInterceptor* interceptor) {
164     DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
165     DCHECK(interceptors_.find(interceptor->GetUrl()) == interceptors_.end());
166
167     interceptors_.insert(std::make_pair(interceptor->GetUrl(), interceptor));
168   }
169
170  private:
171   virtual ~Delegate() {}
172
173   virtual net::URLRequestJob* MaybeInterceptRequest(
174       net::URLRequest* request,
175       net::NetworkDelegate* network_delegate) const OVERRIDE {
176     DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
177
178     // Only intercepts POST.
179     if (!request->has_upload())
180       return NULL;
181
182     GURL url = request->url();
183     if (url.has_query()) {
184       GURL::Replacements replacements;
185       replacements.ClearQuery();
186       url = url.ReplaceComponents(replacements);
187     }
188
189     InterceptorMap::const_iterator it(interceptors_.find(url));
190     if (it == interceptors_.end())
191       return NULL;
192
193     // There is an interceptor hooked up for this url. Read the request body,
194     // check the existing expectations, and handle the matching case by
195     // popping the expectation off the queue, counting the match, and
196     // returning a mock object to serve the canned response.
197     URLRequestPostInterceptor* interceptor(it->second);
198
199     const net::UploadDataStream* stream = request->get_upload();
200     const net::UploadBytesElementReader* reader =
201         stream->element_readers()[0]->AsBytesReader();
202     const int size = reader->length();
203     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size));
204     const std::string request_body(reader->bytes());
205
206     {
207       base::AutoLock auto_lock(interceptor->interceptor_lock_);
208       interceptor->requests_.push_back(request_body);
209       if (interceptor->expectations_.empty())
210         return NULL;
211       const URLRequestPostInterceptor::Expectation& expectation(
212           interceptor->expectations_.front());
213       if (expectation.first->Match(request_body)) {
214         const int response_code(expectation.second.response_code);
215         const std::string response_body(expectation.second.response_body);
216         delete expectation.first;
217         interceptor->expectations_.pop();
218         ++interceptor->hit_count_;
219
220         return new URLRequestMockJob(
221             request, network_delegate, response_code, response_body);
222       }
223     }
224
225     return NULL;
226   }
227
228   typedef std::map<GURL, URLRequestPostInterceptor*> InterceptorMap;
229   InterceptorMap interceptors_;
230
231   const std::string scheme_;
232   const std::string hostname_;
233   scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
234
235   DISALLOW_COPY_AND_ASSIGN(Delegate);
236 };
237
238 URLRequestPostInterceptorFactory::URLRequestPostInterceptorFactory(
239     const std::string& scheme,
240     const std::string& hostname,
241     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
242     : scheme_(scheme),
243       hostname_(hostname),
244       io_task_runner_(io_task_runner),
245       delegate_(new URLRequestPostInterceptor::Delegate(scheme,
246                                                         hostname,
247                                                         io_task_runner)) {
248   io_task_runner_->PostTask(
249       FROM_HERE,
250       base::Bind(&URLRequestPostInterceptor::Delegate::Register,
251                  base::Unretained(delegate_)));
252 }
253
254 URLRequestPostInterceptorFactory::~URLRequestPostInterceptorFactory() {
255   io_task_runner_->PostTask(
256       FROM_HERE,
257       base::Bind(&URLRequestPostInterceptor::Delegate::Unregister,
258                  base::Unretained(delegate_)));
259 }
260
261 URLRequestPostInterceptor* URLRequestPostInterceptorFactory::CreateInterceptor(
262     const base::FilePath& filepath) {
263   const GURL base_url(
264       base::StringPrintf("%s://%s", scheme_.c_str(), hostname_.c_str()));
265   GURL absolute_url(base_url.Resolve(filepath.MaybeAsASCII()));
266   URLRequestPostInterceptor* interceptor(
267       new URLRequestPostInterceptor(absolute_url, io_task_runner_));
268   bool res = io_task_runner_->PostTask(
269       FROM_HERE,
270       base::Bind(&URLRequestPostInterceptor::Delegate::OnCreateInterceptor,
271                  base::Unretained(delegate_),
272                  base::Unretained(interceptor)));
273   if (!res) {
274     delete interceptor;
275     return NULL;
276   }
277
278   return interceptor;
279 }
280
281 bool PartialMatch::Match(const std::string& actual) const {
282   return actual.find(expected_) != std::string::npos;
283 }
284
285 InterceptorFactory::InterceptorFactory(
286     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner)
287     : URLRequestPostInterceptorFactory(POST_INTERCEPT_SCHEME,
288                                        POST_INTERCEPT_HOSTNAME,
289                                        io_task_runner) {
290 }
291
292 InterceptorFactory::~InterceptorFactory() {
293 }
294
295 URLRequestPostInterceptor* InterceptorFactory::CreateInterceptor() {
296   return CreateInterceptorForPath(POST_INTERCEPT_PATH);
297 }
298
299 URLRequestPostInterceptor* InterceptorFactory::CreateInterceptorForPath(
300     const char* url_path) {
301   return URLRequestPostInterceptorFactory::CreateInterceptor(
302       base::FilePath::FromUTF8Unsafe(url_path));
303 }
304
305 }  // namespace component_updater