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
11 namespace net {
12
13 URLRequestFilter* URLRequestFilter::shared_instance_ = NULL;
14
~URLRequestFilter()15 URLRequestFilter::~URLRequestFilter() {}
16
17 // static
Factory(URLRequest * request,const std::string & scheme)18 URLRequestJob* URLRequestFilter::Factory(URLRequest* request,
19 const std::string& scheme) {
20 // Returning null here just means that the built-in handler will be used.
21 return GetInstance()->FindRequestHandler(request, scheme);
22 }
23
24 // static
GetInstance()25 URLRequestFilter* URLRequestFilter::GetInstance() {
26 if (!shared_instance_)
27 shared_instance_ = new URLRequestFilter;
28 return shared_instance_;
29 }
30
AddHostnameHandler(const std::string & scheme,const std::string & hostname,URLRequest::ProtocolFactory * factory)31 void URLRequestFilter::AddHostnameHandler(const std::string& scheme,
32 const std::string& hostname, URLRequest::ProtocolFactory* factory) {
33 hostname_handler_map_[make_pair(scheme, hostname)] = factory;
34
35 // Register with the ProtocolFactory.
36 URLRequest::RegisterProtocolFactory(scheme, &URLRequestFilter::Factory);
37
38 #ifndef NDEBUG
39 // Check to see if we're masking URLs in the url_handler_map_.
40 for (UrlHandlerMap::const_iterator i = url_handler_map_.begin();
41 i != url_handler_map_.end(); ++i) {
42 const GURL& url = GURL(i->first);
43 HostnameHandlerMap::iterator host_it =
44 hostname_handler_map_.find(make_pair(url.scheme(), url.host()));
45 if (host_it != hostname_handler_map_.end())
46 NOTREACHED();
47 }
48 #endif // !NDEBUG
49 }
50
RemoveHostnameHandler(const std::string & scheme,const std::string & hostname)51 void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
52 const std::string& hostname) {
53 HostnameHandlerMap::iterator iter =
54 hostname_handler_map_.find(make_pair(scheme, hostname));
55 DCHECK(iter != hostname_handler_map_.end());
56
57 hostname_handler_map_.erase(iter);
58 // Note that we don't unregister from the URLRequest ProtocolFactory as
59 // this would left no protocol factory for the scheme.
60 // URLRequestFilter::Factory will keep forwarding the requests to the
61 // URLRequestInetJob.
62 }
63
AddUrlHandler(const GURL & url,URLRequest::ProtocolFactory * factory)64 bool URLRequestFilter::AddUrlHandler(
65 const GURL& url,
66 URLRequest::ProtocolFactory* factory) {
67 if (!url.is_valid())
68 return false;
69 url_handler_map_[url.spec()] = factory;
70
71 // Register with the ProtocolFactory.
72 URLRequest::RegisterProtocolFactory(url.scheme(),
73 &URLRequestFilter::Factory);
74 #ifndef NDEBUG
75 // Check to see if this URL is masked by a hostname handler.
76 HostnameHandlerMap::iterator host_it =
77 hostname_handler_map_.find(make_pair(url.scheme(), url.host()));
78 if (host_it != hostname_handler_map_.end())
79 NOTREACHED();
80 #endif // !NDEBUG
81
82 return true;
83 }
84
RemoveUrlHandler(const GURL & url)85 void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
86 UrlHandlerMap::iterator iter = url_handler_map_.find(url.spec());
87 DCHECK(iter != url_handler_map_.end());
88
89 url_handler_map_.erase(iter);
90 // Note that we don't unregister from the URLRequest ProtocolFactory as
91 // this would left no protocol factory for the scheme.
92 // URLRequestFilter::Factory will keep forwarding the requests to the
93 // URLRequestInetJob.
94 }
95
ClearHandlers()96 void URLRequestFilter::ClearHandlers() {
97 // Unregister with the ProtocolFactory.
98 std::set<std::string> schemes;
99 for (UrlHandlerMap::const_iterator i = url_handler_map_.begin();
100 i != url_handler_map_.end(); ++i) {
101 schemes.insert(GURL(i->first).scheme());
102 }
103 for (HostnameHandlerMap::const_iterator i = hostname_handler_map_.begin();
104 i != hostname_handler_map_.end(); ++i) {
105 schemes.insert(i->first.first);
106 }
107 for (std::set<std::string>::const_iterator scheme = schemes.begin();
108 scheme != schemes.end(); ++scheme) {
109 URLRequest::RegisterProtocolFactory(*scheme, NULL);
110 }
111
112 url_handler_map_.clear();
113 hostname_handler_map_.clear();
114 hit_count_ = 0;
115 }
116
URLRequestFilter()117 URLRequestFilter::URLRequestFilter() : hit_count_(0) { }
118
FindRequestHandler(URLRequest * request,const std::string & scheme)119 URLRequestJob* URLRequestFilter::FindRequestHandler(
120 URLRequest* request,
121 const std::string& scheme) {
122 URLRequestJob* job = NULL;
123 if (request->url().is_valid()) {
124 // Check the hostname map first.
125 const std::string& hostname = request->url().host();
126
127 HostnameHandlerMap::iterator i =
128 hostname_handler_map_.find(make_pair(scheme, hostname));
129 if (i != hostname_handler_map_.end())
130 job = i->second(request, scheme);
131
132 if (!job) {
133 // Not in the hostname map, check the url map.
134 const std::string& url = request->url().spec();
135 UrlHandlerMap::iterator i = url_handler_map_.find(url);
136 if (i != url_handler_map_.end())
137 job = i->second(request, scheme);
138 }
139 }
140 if (job) {
141 DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
142 hit_count_++;
143 }
144 return job;
145 }
146
147 } // namespace net
148