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 11URLRequestFilter* URLRequestFilter::shared_instance_ = NULL; 12 13/* static */ 14URLRequestFilter* URLRequestFilter::GetInstance() { 15 if (!shared_instance_) 16 shared_instance_ = new URLRequestFilter; 17 return shared_instance_; 18} 19 20/* static */ 21URLRequestJob* 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 27void 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 48void 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 60bool 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 80void 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 90void 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 111URLRequestJob* 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