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 13namespace net { 14 15namespace { 16 17class 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 37URLRequestFilter* URLRequestFilter::shared_instance_ = NULL; 38 39// static 40URLRequestFilter* URLRequestFilter::GetInstance() { 41 if (!shared_instance_) 42 shared_instance_ = new URLRequestFilter; 43 return shared_instance_; 44} 45 46void 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 54void 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 75void 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 88bool 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 97bool 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 112void 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 123void URLRequestFilter::ClearHandlers() { 124 STLDeleteValues(&url_interceptor_map_); 125 STLDeleteValues(&hostname_interceptor_map_); 126 hit_count_ = 0; 127} 128 129URLRequestJob* 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 159URLRequestFilter::URLRequestFilter() : hit_count_(0) { 160 URLRequestJobFactoryImpl::SetInterceptorForTesting(this); 161} 162 163URLRequestFilter::~URLRequestFilter() { 164 URLRequestJobFactoryImpl::SetInterceptorForTesting(NULL); 165} 166 167} // namespace net 168