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