• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
URLRequestFilterInterceptor(URLRequest::ProtocolFactory * factory)19   explicit URLRequestFilterInterceptor(URLRequest::ProtocolFactory* factory)
20       : factory_(factory) {}
~URLRequestFilterInterceptor()21   virtual ~URLRequestFilterInterceptor() {}
22 
23   // URLRequestInterceptor implementation.
MaybeInterceptRequest(URLRequest * request,NetworkDelegate * network_delegate) const24   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
GetInstance()40 URLRequestFilter* URLRequestFilter::GetInstance() {
41   if (!shared_instance_)
42     shared_instance_ = new URLRequestFilter;
43   return shared_instance_;
44 }
45 
AddHostnameHandler(const std::string & scheme,const std::string & hostname,URLRequest::ProtocolFactory * factory)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 
AddHostnameInterceptor(const std::string & scheme,const std::string & hostname,scoped_ptr<URLRequestInterceptor> interceptor)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 
RemoveHostnameHandler(const std::string & scheme,const std::string & hostname)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 
AddUrlHandler(const GURL & url,URLRequest::ProtocolFactory * factory)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 
AddUrlInterceptor(const GURL & url,scoped_ptr<URLRequestInterceptor> interceptor)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 
RemoveUrlHandler(const GURL & url)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 
ClearHandlers()123 void URLRequestFilter::ClearHandlers() {
124   STLDeleteValues(&url_interceptor_map_);
125   STLDeleteValues(&hostname_interceptor_map_);
126   hit_count_ = 0;
127 }
128 
MaybeInterceptRequest(URLRequest * request,NetworkDelegate * network_delegate) const129 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 
URLRequestFilter()159 URLRequestFilter::URLRequestFilter() : hit_count_(0) {
160   URLRequestJobFactoryImpl::SetInterceptorForTesting(this);
161 }
162 
~URLRequestFilter()163 URLRequestFilter::~URLRequestFilter() {
164   URLRequestJobFactoryImpl::SetInterceptorForTesting(NULL);
165 }
166 
167 }  // namespace net
168