url_request_filter.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 12namespace net { 13 14namespace { 15 16class 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 37URLRequestFilter* URLRequestFilter::shared_instance_ = NULL; 38 39URLRequestFilter::~URLRequestFilter() {} 40 41// static 42URLRequestJob* 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 50URLRequestFilter* URLRequestFilter::GetInstance() { 51 if (!shared_instance_) 52 shared_instance_ = new URLRequestFilter; 53 return shared_instance_; 54} 55 56void 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 64void 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 89void 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 left no protocol factory for the scheme. 99 // URLRequestFilter::Factory will keep forwarding the requests to the 100 // URLRequestInetJob. 101} 102 103bool URLRequestFilter::AddUrlHandler( 104 const GURL& url, 105 URLRequest::ProtocolFactory* factory) { 106 return AddUrlProtocolHandler( 107 url, 108 scoped_ptr<URLRequestJobFactory::ProtocolHandler>( 109 new URLRequestFilterProtocolHandler(factory))); 110} 111 112 113bool URLRequestFilter::AddUrlProtocolHandler( 114 const GURL& url, 115 scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) { 116 if (!url.is_valid()) 117 return false; 118 DCHECK_EQ(0u, url_handler_map_.count(url.spec())); 119 url_handler_map_[url.spec()] = protocol_handler.release(); 120 121 // Register with the ProtocolFactory. 122 URLRequest::Deprecated::RegisterProtocolFactory(url.scheme(), 123 &URLRequestFilter::Factory); 124 // Check to see if this URL is masked by a hostname handler. 125 DCHECK_EQ(0u, hostname_handler_map_.count(make_pair(url.scheme(), 126 url.host()))); 127 128 return true; 129} 130 131void URLRequestFilter::RemoveUrlHandler(const GURL& url) { 132 UrlHandlerMap::iterator iter = url_handler_map_.find(url.spec()); 133 DCHECK(iter != url_handler_map_.end()); 134 135 delete iter->second; 136 url_handler_map_.erase(iter); 137 // Note that we don't unregister from the URLRequest ProtocolFactory as 138 // this would left no protocol factory for the scheme. 139 // URLRequestFilter::Factory will keep forwarding the requests to the 140 // URLRequestInetJob. 141} 142 143void URLRequestFilter::ClearHandlers() { 144 // Unregister with the ProtocolFactory. 145 std::set<std::string> schemes; 146 for (UrlHandlerMap::const_iterator i = url_handler_map_.begin(); 147 i != url_handler_map_.end(); ++i) { 148 schemes.insert(GURL(i->first).scheme()); 149 } 150 for (HostnameHandlerMap::const_iterator i = hostname_handler_map_.begin(); 151 i != hostname_handler_map_.end(); ++i) { 152 schemes.insert(i->first.first); 153 } 154 for (std::set<std::string>::const_iterator scheme = schemes.begin(); 155 scheme != schemes.end(); ++scheme) { 156 URLRequest::Deprecated::RegisterProtocolFactory(*scheme, NULL); 157 } 158 159 STLDeleteValues(&url_handler_map_); 160 STLDeleteValues(&hostname_handler_map_); 161 hit_count_ = 0; 162} 163 164URLRequestFilter::URLRequestFilter() : hit_count_(0) { } 165 166URLRequestJob* URLRequestFilter::FindRequestHandler( 167 URLRequest* request, 168 NetworkDelegate* network_delegate, 169 const std::string& scheme) { 170 URLRequestJob* job = NULL; 171 if (request->url().is_valid()) { 172 // Check the hostname map first. 173 const std::string& hostname = request->url().host(); 174 175 HostnameHandlerMap::iterator i = 176 hostname_handler_map_.find(make_pair(scheme, hostname)); 177 if (i != hostname_handler_map_.end()) 178 job = i->second->MaybeCreateJob(request, network_delegate); 179 180 if (!job) { 181 // Not in the hostname map, check the url map. 182 const std::string& url = request->url().spec(); 183 UrlHandlerMap::iterator i = url_handler_map_.find(url); 184 if (i != url_handler_map_.end()) 185 job = i->second->MaybeCreateJob(request, network_delegate); 186 } 187 } 188 if (job) { 189 DVLOG(1) << "URLRequestFilter hit for " << request->url().spec(); 190 hit_count_++; 191 } 192 return job; 193} 194 195} // namespace net 196