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