Home | History | Annotate | Download | only in url_request
      1 // Copyright (c) 2011 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/url_request_filter.h"
      6 
      7 #include <set>
      8 
      9 #include "base/logging.h"
     10 #include "base/stl_util.h"
     11 #include "net/url_request/url_request_job_factory_impl.h"
     12 
     13 namespace net {
     14 
     15 namespace {
     16 
     17 class URLRequestFilterInterceptor : public URLRequestInterceptor {
     18  public:
     19   explicit URLRequestFilterInterceptor(URLRequest::ProtocolFactory* factory)
     20       : factory_(factory) {}
     21   virtual ~URLRequestFilterInterceptor() {}
     22 
     23   // URLRequestInterceptor implementation.
     24   virtual URLRequestJob* MaybeInterceptRequest(
     25       URLRequest* request, NetworkDelegate* network_delegate) const OVERRIDE {
     26     return factory_(request, network_delegate, request->url().scheme());
     27   }
     28 
     29  private:
     30   URLRequest::ProtocolFactory* factory_;
     31 
     32   DISALLOW_COPY_AND_ASSIGN(URLRequestFilterInterceptor);
     33 };
     34 
     35 }  // namespace
     36 
     37 URLRequestFilter* URLRequestFilter::shared_instance_ = NULL;
     38 
     39 // static
     40 URLRequestFilter* URLRequestFilter::GetInstance() {
     41   if (!shared_instance_)
     42     shared_instance_ = new URLRequestFilter;
     43   return shared_instance_;
     44 }
     45 
     46 void URLRequestFilter::AddHostnameHandler(const std::string& scheme,
     47     const std::string& hostname, URLRequest::ProtocolFactory* factory) {
     48   AddHostnameInterceptor(
     49       scheme, hostname,
     50       scoped_ptr<URLRequestInterceptor>(
     51           new URLRequestFilterInterceptor(factory)));
     52 }
     53 
     54 void URLRequestFilter::AddHostnameInterceptor(
     55     const std::string& scheme,
     56     const std::string& hostname,
     57     scoped_ptr<URLRequestInterceptor> interceptor) {
     58   DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(scheme, hostname)));
     59   hostname_interceptor_map_[make_pair(scheme, hostname)] =
     60       interceptor.release();
     61 
     62 #ifndef NDEBUG
     63   // Check to see if we're masking URLs in the url_interceptor_map_.
     64   for (URLInterceptorMap::const_iterator it = url_interceptor_map_.begin();
     65        it != url_interceptor_map_.end(); ++it) {
     66     const GURL& url = GURL(it->first);
     67     HostnameInterceptorMap::const_iterator host_it =
     68         hostname_interceptor_map_.find(make_pair(url.scheme(), url.host()));
     69     if (host_it != hostname_interceptor_map_.end())
     70       NOTREACHED();
     71   }
     72 #endif  // !NDEBUG
     73 }
     74 
     75 void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
     76                                              const std::string& hostname) {
     77   HostnameInterceptorMap::iterator it =
     78       hostname_interceptor_map_.find(make_pair(scheme, hostname));
     79   DCHECK(it != hostname_interceptor_map_.end());
     80 
     81   delete it->second;
     82   hostname_interceptor_map_.erase(it);
     83   // Note that we don't unregister from the URLRequest ProtocolFactory as
     84   // this would leave no protocol factory for the remaining hostname and URL
     85   // handlers.
     86 }
     87 
     88 bool URLRequestFilter::AddUrlHandler(
     89     const GURL& url,
     90     URLRequest::ProtocolFactory* factory) {
     91   return AddUrlInterceptor(
     92       url,
     93       scoped_ptr<URLRequestInterceptor>(
     94           new URLRequestFilterInterceptor(factory)));
     95 }
     96 
     97 bool URLRequestFilter::AddUrlInterceptor(
     98     const GURL& url,
     99     scoped_ptr<URLRequestInterceptor> interceptor) {
    100   if (!url.is_valid())
    101     return false;
    102   DCHECK_EQ(0u, url_interceptor_map_.count(url.spec()));
    103   url_interceptor_map_[url.spec()] = interceptor.release();
    104 
    105   // Check to see if this URL is masked by a hostname handler.
    106   DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(url.scheme(),
    107                                                           url.host())));
    108 
    109   return true;
    110 }
    111 
    112 void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
    113   URLInterceptorMap::iterator it = url_interceptor_map_.find(url.spec());
    114   DCHECK(it != url_interceptor_map_.end());
    115 
    116   delete it->second;
    117   url_interceptor_map_.erase(it);
    118   // Note that we don't unregister from the URLRequest ProtocolFactory as
    119   // this would leave no protocol factory for the remaining hostname and URL
    120   // handlers.
    121 }
    122 
    123 void URLRequestFilter::ClearHandlers() {
    124   STLDeleteValues(&url_interceptor_map_);
    125   STLDeleteValues(&hostname_interceptor_map_);
    126   hit_count_ = 0;
    127 }
    128 
    129 URLRequestJob* URLRequestFilter::MaybeInterceptRequest(
    130     URLRequest* request,
    131     NetworkDelegate* network_delegate) const {
    132   URLRequestJob* job = NULL;
    133   if (!request->url().is_valid())
    134     return NULL;
    135 
    136   // Check the hostname map first.
    137   const std::string hostname = request->url().host();
    138   const std::string scheme = request->url().scheme();
    139 
    140   HostnameInterceptorMap::const_iterator it =
    141       hostname_interceptor_map_.find(make_pair(scheme, hostname));
    142   if (it != hostname_interceptor_map_.end())
    143     job = it->second->MaybeInterceptRequest(request, network_delegate);
    144 
    145   if (!job) {
    146     // Not in the hostname map, check the url map.
    147     const std::string& url = request->url().spec();
    148     URLInterceptorMap::const_iterator it = url_interceptor_map_.find(url);
    149     if (it != url_interceptor_map_.end())
    150       job = it->second->MaybeInterceptRequest(request, network_delegate);
    151   }
    152   if (job) {
    153     DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
    154     hit_count_++;
    155   }
    156   return job;
    157 }
    158 
    159 URLRequestFilter::URLRequestFilter() : hit_count_(0) {
    160   URLRequestJobFactoryImpl::SetInterceptorForTesting(this);
    161 }
    162 
    163 URLRequestFilter::~URLRequestFilter() {
    164   URLRequestJobFactoryImpl::SetInterceptorForTesting(NULL);
    165 }
    166 
    167 }  // namespace net
    168