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 #include "net/url_request/url_request_job_factory_impl.h" 12 13 namespace net { 14 15 namespace { 16 17 class URLRequestFilterInterceptor : public URLRequestInterceptor { 18 public: 19 explicit URLRequestFilterInterceptor(URLRequest::ProtocolFactory* factory) 20 : factory_(factory) {} 21 virtual ~URLRequestFilterInterceptor() {} 22 23 // URLRequestInterceptor implementation. 24 virtual URLRequestJob* MaybeInterceptRequest( 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(URLRequestFilterInterceptor); 33 }; 34 35 } // namespace 36 37 URLRequestFilter* URLRequestFilter::shared_instance_ = NULL; 38 39 // static 40 URLRequestFilter* URLRequestFilter::GetInstance() { 41 if (!shared_instance_) 42 shared_instance_ = new URLRequestFilter; 43 return shared_instance_; 44 } 45 46 void URLRequestFilter::AddHostnameHandler(const std::string& scheme, 47 const std::string& hostname, URLRequest::ProtocolFactory* factory) { 48 AddHostnameInterceptor( 49 scheme, hostname, 50 scoped_ptr<URLRequestInterceptor>( 51 new URLRequestFilterInterceptor(factory))); 52 } 53 54 void URLRequestFilter::AddHostnameInterceptor( 55 const std::string& scheme, 56 const std::string& hostname, 57 scoped_ptr<URLRequestInterceptor> interceptor) { 58 DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(scheme, hostname))); 59 hostname_interceptor_map_[make_pair(scheme, hostname)] = 60 interceptor.release(); 61 62 #ifndef NDEBUG 63 // Check to see if we're masking URLs in the url_interceptor_map_. 64 for (URLInterceptorMap::const_iterator it = url_interceptor_map_.begin(); 65 it != url_interceptor_map_.end(); ++it) { 66 const GURL& url = GURL(it->first); 67 HostnameInterceptorMap::const_iterator host_it = 68 hostname_interceptor_map_.find(make_pair(url.scheme(), url.host())); 69 if (host_it != hostname_interceptor_map_.end()) 70 NOTREACHED(); 71 } 72 #endif // !NDEBUG 73 } 74 75 void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme, 76 const std::string& hostname) { 77 HostnameInterceptorMap::iterator it = 78 hostname_interceptor_map_.find(make_pair(scheme, hostname)); 79 DCHECK(it != hostname_interceptor_map_.end()); 80 81 delete it->second; 82 hostname_interceptor_map_.erase(it); 83 // Note that we don't unregister from the URLRequest ProtocolFactory as 84 // this would leave no protocol factory for the remaining hostname and URL 85 // handlers. 86 } 87 88 bool URLRequestFilter::AddUrlHandler( 89 const GURL& url, 90 URLRequest::ProtocolFactory* factory) { 91 return AddUrlInterceptor( 92 url, 93 scoped_ptr<URLRequestInterceptor>( 94 new URLRequestFilterInterceptor(factory))); 95 } 96 97 bool URLRequestFilter::AddUrlInterceptor( 98 const GURL& url, 99 scoped_ptr<URLRequestInterceptor> interceptor) { 100 if (!url.is_valid()) 101 return false; 102 DCHECK_EQ(0u, url_interceptor_map_.count(url.spec())); 103 url_interceptor_map_[url.spec()] = interceptor.release(); 104 105 // Check to see if this URL is masked by a hostname handler. 106 DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(url.scheme(), 107 url.host()))); 108 109 return true; 110 } 111 112 void URLRequestFilter::RemoveUrlHandler(const GURL& url) { 113 URLInterceptorMap::iterator it = url_interceptor_map_.find(url.spec()); 114 DCHECK(it != url_interceptor_map_.end()); 115 116 delete it->second; 117 url_interceptor_map_.erase(it); 118 // Note that we don't unregister from the URLRequest ProtocolFactory as 119 // this would leave no protocol factory for the remaining hostname and URL 120 // handlers. 121 } 122 123 void URLRequestFilter::ClearHandlers() { 124 STLDeleteValues(&url_interceptor_map_); 125 STLDeleteValues(&hostname_interceptor_map_); 126 hit_count_ = 0; 127 } 128 129 URLRequestJob* URLRequestFilter::MaybeInterceptRequest( 130 URLRequest* request, 131 NetworkDelegate* network_delegate) const { 132 URLRequestJob* job = NULL; 133 if (!request->url().is_valid()) 134 return NULL; 135 136 // Check the hostname map first. 137 const std::string hostname = request->url().host(); 138 const std::string scheme = request->url().scheme(); 139 140 HostnameInterceptorMap::const_iterator it = 141 hostname_interceptor_map_.find(make_pair(scheme, hostname)); 142 if (it != hostname_interceptor_map_.end()) 143 job = it->second->MaybeInterceptRequest(request, network_delegate); 144 145 if (!job) { 146 // Not in the hostname map, check the url map. 147 const std::string& url = request->url().spec(); 148 URLInterceptorMap::const_iterator it = url_interceptor_map_.find(url); 149 if (it != url_interceptor_map_.end()) 150 job = it->second->MaybeInterceptRequest(request, network_delegate); 151 } 152 if (job) { 153 DVLOG(1) << "URLRequestFilter hit for " << request->url().spec(); 154 hit_count_++; 155 } 156 return job; 157 } 158 159 URLRequestFilter::URLRequestFilter() : hit_count_(0) { 160 URLRequestJobFactoryImpl::SetInterceptorForTesting(this); 161 } 162 163 URLRequestFilter::~URLRequestFilter() { 164 URLRequestJobFactoryImpl::SetInterceptorForTesting(NULL); 165 } 166 167 } // namespace net 168