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 
     11 namespace net {
     12 
     13 URLRequestFilter* URLRequestFilter::shared_instance_ = NULL;
     14 
     15 URLRequestFilter::~URLRequestFilter() {}
     16 
     17 // static
     18 URLRequestJob* URLRequestFilter::Factory(URLRequest* request,
     19                                          const std::string& scheme) {
     20   // Returning null here just means that the built-in handler will be used.
     21   return GetInstance()->FindRequestHandler(request, scheme);
     22 }
     23 
     24 // static
     25 URLRequestFilter* URLRequestFilter::GetInstance() {
     26   if (!shared_instance_)
     27     shared_instance_ = new URLRequestFilter;
     28   return shared_instance_;
     29 }
     30 
     31 void URLRequestFilter::AddHostnameHandler(const std::string& scheme,
     32     const std::string& hostname, URLRequest::ProtocolFactory* factory) {
     33   hostname_handler_map_[make_pair(scheme, hostname)] = factory;
     34 
     35   // Register with the ProtocolFactory.
     36   URLRequest::RegisterProtocolFactory(scheme, &URLRequestFilter::Factory);
     37 
     38 #ifndef NDEBUG
     39   // Check to see if we're masking URLs in the url_handler_map_.
     40   for (UrlHandlerMap::const_iterator i = url_handler_map_.begin();
     41        i != url_handler_map_.end(); ++i) {
     42     const GURL& url = GURL(i->first);
     43     HostnameHandlerMap::iterator host_it =
     44         hostname_handler_map_.find(make_pair(url.scheme(), url.host()));
     45     if (host_it != hostname_handler_map_.end())
     46       NOTREACHED();
     47   }
     48 #endif  // !NDEBUG
     49 }
     50 
     51 void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
     52                                              const std::string& hostname) {
     53   HostnameHandlerMap::iterator iter =
     54       hostname_handler_map_.find(make_pair(scheme, hostname));
     55   DCHECK(iter != hostname_handler_map_.end());
     56 
     57   hostname_handler_map_.erase(iter);
     58   // Note that we don't unregister from the URLRequest ProtocolFactory as
     59   // this would left no protocol factory for the scheme.
     60   // URLRequestFilter::Factory will keep forwarding the requests to the
     61   // URLRequestInetJob.
     62 }
     63 
     64 bool URLRequestFilter::AddUrlHandler(
     65     const GURL& url,
     66     URLRequest::ProtocolFactory* factory) {
     67   if (!url.is_valid())
     68     return false;
     69   url_handler_map_[url.spec()] = factory;
     70 
     71   // Register with the ProtocolFactory.
     72   URLRequest::RegisterProtocolFactory(url.scheme(),
     73                                            &URLRequestFilter::Factory);
     74 #ifndef NDEBUG
     75   // Check to see if this URL is masked by a hostname handler.
     76   HostnameHandlerMap::iterator host_it =
     77       hostname_handler_map_.find(make_pair(url.scheme(), url.host()));
     78   if (host_it != hostname_handler_map_.end())
     79     NOTREACHED();
     80 #endif  // !NDEBUG
     81 
     82   return true;
     83 }
     84 
     85 void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
     86   UrlHandlerMap::iterator iter = url_handler_map_.find(url.spec());
     87   DCHECK(iter != url_handler_map_.end());
     88 
     89   url_handler_map_.erase(iter);
     90   // Note that we don't unregister from the URLRequest ProtocolFactory as
     91   // this would left no protocol factory for the scheme.
     92   // URLRequestFilter::Factory will keep forwarding the requests to the
     93   // URLRequestInetJob.
     94 }
     95 
     96 void URLRequestFilter::ClearHandlers() {
     97   // Unregister with the ProtocolFactory.
     98   std::set<std::string> schemes;
     99   for (UrlHandlerMap::const_iterator i = url_handler_map_.begin();
    100        i != url_handler_map_.end(); ++i) {
    101     schemes.insert(GURL(i->first).scheme());
    102   }
    103   for (HostnameHandlerMap::const_iterator i = hostname_handler_map_.begin();
    104        i != hostname_handler_map_.end(); ++i) {
    105     schemes.insert(i->first.first);
    106   }
    107   for (std::set<std::string>::const_iterator scheme = schemes.begin();
    108        scheme != schemes.end(); ++scheme) {
    109     URLRequest::RegisterProtocolFactory(*scheme, NULL);
    110   }
    111 
    112   url_handler_map_.clear();
    113   hostname_handler_map_.clear();
    114   hit_count_ = 0;
    115 }
    116 
    117 URLRequestFilter::URLRequestFilter() : hit_count_(0) { }
    118 
    119 URLRequestJob* URLRequestFilter::FindRequestHandler(
    120     URLRequest* request,
    121     const std::string& scheme) {
    122   URLRequestJob* job = NULL;
    123   if (request->url().is_valid()) {
    124     // Check the hostname map first.
    125     const std::string& hostname = request->url().host();
    126 
    127     HostnameHandlerMap::iterator i =
    128         hostname_handler_map_.find(make_pair(scheme, hostname));
    129     if (i != hostname_handler_map_.end())
    130       job = i->second(request, scheme);
    131 
    132     if (!job) {
    133       // Not in the hostname map, check the url map.
    134       const std::string& url = request->url().spec();
    135       UrlHandlerMap::iterator i = url_handler_map_.find(url);
    136       if (i != url_handler_map_.end())
    137         job = i->second(request, scheme);
    138     }
    139   }
    140   if (job) {
    141     DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
    142     hit_count_++;
    143   }
    144   return job;
    145 }
    146 
    147 }  // namespace net
    148