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