- add sources.
[platform/framework/web/crosswalk.git] / src / content / test / net / url_request_prepackaged_interceptor.cc
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 "content/test/net/url_request_prepackaged_interceptor.h"
6
7 #include "base/file_util.h"
8 #include "base/threading/sequenced_worker_pool.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "net/url_request/url_request.h"
12 #include "net/url_request/url_request_file_job.h"
13 #include "net/url_request/url_request_filter.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 using content::BrowserThread;
17
18 namespace content {
19
20 namespace {
21
22 class URLRequestPrepackagedJob : public net::URLRequestFileJob {
23  public:
24   URLRequestPrepackagedJob(net::URLRequest* request,
25                            net::NetworkDelegate* network_delegate,
26                            const base::FilePath& file_path)
27       : net::URLRequestFileJob(
28             request, network_delegate, file_path,
29             content::BrowserThread::GetBlockingPool()->
30                 GetTaskRunnerWithShutdownBehavior(
31                     base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)) {}
32
33   virtual int GetResponseCode() const OVERRIDE { return 200; }
34
35  private:
36   virtual ~URLRequestPrepackagedJob() {}
37
38   DISALLOW_COPY_AND_ASSIGN(URLRequestPrepackagedJob);
39 };
40
41 }  // namespace
42
43 class URLRequestPrepackagedInterceptor::Delegate
44     : public net::URLRequestJobFactory::ProtocolHandler {
45  public:
46   Delegate(const std::string& scheme, const std::string& hostname)
47     : scheme_(scheme), hostname_(hostname), hit_count_(0) {}
48   virtual ~Delegate() {}
49
50   void Register() {
51     net::URLRequestFilter::GetInstance()->AddHostnameProtocolHandler(
52         scheme_, hostname_,
53         scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(this));
54   }
55
56   static void Unregister(
57       const std::string& scheme,
58       const std::string& hostname) {
59     net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme,
60                                                                 hostname);
61   }
62
63   // When requests for |url| arrive, respond with the contents of |path|. The
64   // hostname and scheme of |url| must match the corresponding parameters
65   // passed as constructor arguments.
66   void SetResponse(const GURL& url,
67                    const base::FilePath& path,
68                    bool ignore_query) {
69     CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
70     // It's ok to do a blocking disk access on this thread; this class
71     // is just used for tests.
72     base::ThreadRestrictions::ScopedAllowIO allow_io;
73     EXPECT_TRUE(base::PathExists(path));
74     if (ignore_query) {
75       ignore_query_responses_[url] = path;
76     } else {
77       responses_[url] = path;
78     }
79   }
80
81   // Returns how many requests have been issued that have a stored reply.
82   int GetHitCount() const {
83     base::AutoLock auto_lock(hit_count_lock_);
84     return hit_count_;
85   }
86
87  private:
88   typedef std::map<GURL, base::FilePath> ResponseMap;
89
90   // When computing matches, this ignores the query parameters of the url.
91   virtual net::URLRequestJob* MaybeCreateJob(
92       net::URLRequest* request,
93       net::NetworkDelegate* network_delegate) const OVERRIDE {
94     CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
95     if (request->url().scheme() != scheme_ ||
96         request->url().host() != hostname_) {
97       return NULL;
98     }
99
100     ResponseMap::const_iterator it = responses_.find(request->url());
101     if (it == responses_.end()) {
102       // Search for this request's url, ignoring any query parameters.
103       GURL url = request->url();
104       if (url.has_query()) {
105         GURL::Replacements replacements;
106         replacements.ClearQuery();
107         url = url.ReplaceComponents(replacements);
108       }
109       it = ignore_query_responses_.find(url);
110       if (it == ignore_query_responses_.end())
111         return NULL;
112     }
113     {
114       base::AutoLock auto_lock(hit_count_lock_);
115       ++hit_count_;
116     }
117
118     return new URLRequestPrepackagedJob(request,
119                                         network_delegate,
120                                         it->second);
121   }
122
123   const std::string scheme_;
124   const std::string hostname_;
125
126   ResponseMap responses_;
127   ResponseMap ignore_query_responses_;
128
129   mutable base::Lock hit_count_lock_;
130   mutable int hit_count_;
131
132   DISALLOW_COPY_AND_ASSIGN(Delegate);
133 };
134
135
136 URLRequestPrepackagedInterceptor::URLRequestPrepackagedInterceptor(
137     const std::string& scheme,
138     const std::string& hostname)
139     : scheme_(scheme),
140       hostname_(hostname),
141       delegate_(new Delegate(scheme, hostname)) {
142   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
143                           base::Bind(&Delegate::Register,
144                                      base::Unretained(delegate_)));
145 }
146
147 URLRequestPrepackagedInterceptor::~URLRequestPrepackagedInterceptor() {
148   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
149                           base::Bind(&Delegate::Unregister,
150                                      scheme_,
151                                      hostname_));
152 }
153
154 void URLRequestPrepackagedInterceptor::SetResponse(
155     const GURL& url,
156     const base::FilePath& path) {
157   CHECK_EQ(scheme_, url.scheme());
158   CHECK_EQ(hostname_, url.host());
159   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
160                           base::Bind(&Delegate::SetResponse,
161                                      base::Unretained(delegate_), url, path,
162                                      false));
163 }
164
165 void URLRequestPrepackagedInterceptor::SetResponseIgnoreQuery(
166     const GURL& url,
167     const base::FilePath& path) {
168   CHECK_EQ(scheme_, url.scheme());
169   CHECK_EQ(hostname_, url.host());
170   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
171                           base::Bind(&Delegate::SetResponse,
172                                      base::Unretained(delegate_), url, path,
173                                      true));
174 }
175
176 int URLRequestPrepackagedInterceptor::GetHitCount() {
177   return delegate_->GetHitCount();
178 }
179
180
181 URLLocalHostRequestPrepackagedInterceptor
182   ::URLLocalHostRequestPrepackagedInterceptor()
183     : URLRequestPrepackagedInterceptor("http", "localhost") {
184 }
185
186 }  // namespace content