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