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 
     12 namespace net {
     13 
     14 namespace {
     15 
     16 class URLRequestFilterProtocolHandler
     17     : public URLRequestJobFactory::ProtocolHandler {
     18  public:
     19   explicit URLRequestFilterProtocolHandler(URLRequest::ProtocolFactory* factory)
     20       : factory_(factory) {}
     21   virtual ~URLRequestFilterProtocolHandler() {}
     22 
     23   // URLRequestJobFactory::ProtocolHandler implementation
     24   virtual URLRequestJob* MaybeCreateJob(
     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(URLRequestFilterProtocolHandler);
     33 };
     34 
     35 }  // namespace
     36 
     37 URLRequestFilter* URLRequestFilter::shared_instance_ = NULL;
     38 
     39 URLRequestFilter::~URLRequestFilter() {}
     40 
     41 // static
     42 URLRequestJob* URLRequestFilter::Factory(URLRequest* request,
     43                                          NetworkDelegate* network_delegate,
     44                                          const std::string& scheme) {
     45   // Returning null here just means that the built-in handler will be used.
     46   return GetInstance()->FindRequestHandler(request, network_delegate, scheme);
     47 }
     48 
     49 // static
     50 URLRequestFilter* URLRequestFilter::GetInstance() {
     51   if (!shared_instance_)
     52     shared_instance_ = new URLRequestFilter;
     53   return shared_instance_;
     54 }
     55 
     56 void URLRequestFilter::AddHostnameHandler(const std::string& scheme,
     57     const std::string& hostname, URLRequest::ProtocolFactory* factory) {
     58   AddHostnameProtocolHandler(
     59       scheme, hostname,
     60       scoped_ptr<URLRequestJobFactory::ProtocolHandler>(
     61           new URLRequestFilterProtocolHandler(factory)));
     62 }
     63 
     64 void URLRequestFilter::AddHostnameProtocolHandler(
     65     const std::string& scheme,
     66     const std::string& hostname,
     67     scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) {
     68   DCHECK_EQ(0u, hostname_handler_map_.count(make_pair(scheme, hostname)));
     69   hostname_handler_map_[make_pair(scheme, hostname)] =
     70       protocol_handler.release();
     71 
     72   // Register with the ProtocolFactory.
     73   URLRequest::Deprecated::RegisterProtocolFactory(
     74       scheme, &URLRequestFilter::Factory);
     75 
     76 #ifndef NDEBUG
     77   // Check to see if we're masking URLs in the url_handler_map_.
     78   for (UrlHandlerMap::const_iterator i = url_handler_map_.begin();
     79        i != url_handler_map_.end(); ++i) {
     80     const GURL& url = GURL(i->first);
     81     HostnameHandlerMap::iterator host_it =
     82         hostname_handler_map_.find(make_pair(url.scheme(), url.host()));
     83     if (host_it != hostname_handler_map_.end())
     84       NOTREACHED();
     85   }
     86 #endif  // !NDEBUG
     87 }
     88 
     89 void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
     90                                              const std::string& hostname) {
     91   HostnameHandlerMap::iterator iter =
     92       hostname_handler_map_.find(make_pair(scheme, hostname));
     93   DCHECK(iter != hostname_handler_map_.end());
     94 
     95   delete iter->second;
     96   hostname_handler_map_.erase(iter);
     97   // Note that we don't unregister from the URLRequest ProtocolFactory as
     98   // this would leave no protocol factory for the remaining hostname and URL
     99   // handlers.
    100 }
    101 
    102 bool URLRequestFilter::AddUrlHandler(
    103     const GURL& url,
    104     URLRequest::ProtocolFactory* factory) {
    105   return AddUrlProtocolHandler(
    106       url,
    107       scoped_ptr<URLRequestJobFactory::ProtocolHandler>(
    108           new URLRequestFilterProtocolHandler(factory)));
    109 }
    110 
    111 
    112 bool URLRequestFilter::AddUrlProtocolHandler(
    113     const GURL& url,
    114     scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) {
    115   if (!url.is_valid())
    116     return false;
    117   DCHECK_EQ(0u, url_handler_map_.count(url.spec()));
    118   url_handler_map_[url.spec()] = protocol_handler.release();
    119 
    120   // Register with the ProtocolFactory.
    121   URLRequest::Deprecated::RegisterProtocolFactory(url.scheme(),
    122                                                   &URLRequestFilter::Factory);
    123   // Check to see if this URL is masked by a hostname handler.
    124   DCHECK_EQ(0u, hostname_handler_map_.count(make_pair(url.scheme(),
    125                                                       url.host())));
    126 
    127   return true;
    128 }
    129 
    130 void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
    131   UrlHandlerMap::iterator iter = url_handler_map_.find(url.spec());
    132   DCHECK(iter != url_handler_map_.end());
    133 
    134   delete iter->second;
    135   url_handler_map_.erase(iter);
    136   // Note that we don't unregister from the URLRequest ProtocolFactory as
    137   // this would leave no protocol factory for the remaining hostname and URL
    138   // handlers.
    139 }
    140 
    141 void URLRequestFilter::ClearHandlers() {
    142   // Unregister with the ProtocolFactory.
    143   std::set<std::string> schemes;
    144   for (UrlHandlerMap::const_iterator i = url_handler_map_.begin();
    145        i != url_handler_map_.end(); ++i) {
    146     schemes.insert(GURL(i->first).scheme());
    147   }
    148   for (HostnameHandlerMap::const_iterator i = hostname_handler_map_.begin();
    149        i != hostname_handler_map_.end(); ++i) {
    150     schemes.insert(i->first.first);
    151   }
    152   for (std::set<std::string>::const_iterator scheme = schemes.begin();
    153        scheme != schemes.end(); ++scheme) {
    154     URLRequest::Deprecated::RegisterProtocolFactory(*scheme, NULL);
    155   }
    156 
    157   STLDeleteValues(&url_handler_map_);
    158   STLDeleteValues(&hostname_handler_map_);
    159   hit_count_ = 0;
    160 }
    161 
    162 URLRequestFilter::URLRequestFilter() : hit_count_(0) { }
    163 
    164 URLRequestJob* URLRequestFilter::FindRequestHandler(
    165     URLRequest* request,
    166     NetworkDelegate* network_delegate,
    167     const std::string& scheme) {
    168   URLRequestJob* job = NULL;
    169   if (request->url().is_valid()) {
    170     // Check the hostname map first.
    171     const std::string& hostname = request->url().host();
    172 
    173     HostnameHandlerMap::iterator i =
    174         hostname_handler_map_.find(make_pair(scheme, hostname));
    175     if (i != hostname_handler_map_.end())
    176       job = i->second->MaybeCreateJob(request, network_delegate);
    177 
    178     if (!job) {
    179       // Not in the hostname map, check the url map.
    180       const std::string& url = request->url().spec();
    181       UrlHandlerMap::iterator i = url_handler_map_.find(url);
    182       if (i != url_handler_map_.end())
    183         job = i->second->MaybeCreateJob(request, network_delegate);
    184     }
    185   }
    186   if (job) {
    187     DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
    188     hit_count_++;
    189   }
    190   return job;
    191 }
    192 
    193 }  // namespace net
    194