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.
5 #include "net/url_request/url_request_filter.h"
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11 #include "net/url_request/url_request_job_factory_impl.h"
17 class URLRequestFilterInterceptor : public URLRequestInterceptor {
19 explicit URLRequestFilterInterceptor(URLRequest::ProtocolFactory* factory)
20 : factory_(factory) {}
21 ~URLRequestFilterInterceptor() override {}
23 // URLRequestInterceptor implementation.
24 URLRequestJob* MaybeInterceptRequest(
26 NetworkDelegate* network_delegate) const override {
27 return factory_(request, network_delegate, request->url().scheme());
31 URLRequest::ProtocolFactory* factory_;
33 DISALLOW_COPY_AND_ASSIGN(URLRequestFilterInterceptor);
38 URLRequestFilter* URLRequestFilter::shared_instance_ = NULL;
41 URLRequestFilter* URLRequestFilter::GetInstance() {
42 if (!shared_instance_)
43 shared_instance_ = new URLRequestFilter;
44 return shared_instance_;
47 void URLRequestFilter::AddHostnameHandler(const std::string& scheme,
48 const std::string& hostname, URLRequest::ProtocolFactory* factory) {
49 AddHostnameInterceptor(
51 scoped_ptr<URLRequestInterceptor>(
52 new URLRequestFilterInterceptor(factory)));
55 void URLRequestFilter::AddHostnameInterceptor(
56 const std::string& scheme,
57 const std::string& hostname,
58 scoped_ptr<URLRequestInterceptor> interceptor) {
59 DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(scheme, hostname)));
60 hostname_interceptor_map_[make_pair(scheme, hostname)] =
61 interceptor.release();
64 // Check to see if we're masking URLs in the url_interceptor_map_.
65 for (URLInterceptorMap::const_iterator it = url_interceptor_map_.begin();
66 it != url_interceptor_map_.end(); ++it) {
67 const GURL& url = GURL(it->first);
68 HostnameInterceptorMap::const_iterator host_it =
69 hostname_interceptor_map_.find(make_pair(url.scheme(), url.host()));
70 if (host_it != hostname_interceptor_map_.end())
76 void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
77 const std::string& hostname) {
78 HostnameInterceptorMap::iterator it =
79 hostname_interceptor_map_.find(make_pair(scheme, hostname));
80 DCHECK(it != hostname_interceptor_map_.end());
83 hostname_interceptor_map_.erase(it);
84 // Note that we don't unregister from the URLRequest ProtocolFactory as
85 // this would leave no protocol factory for the remaining hostname and URL
89 bool URLRequestFilter::AddUrlHandler(
91 URLRequest::ProtocolFactory* factory) {
92 return AddUrlInterceptor(
94 scoped_ptr<URLRequestInterceptor>(
95 new URLRequestFilterInterceptor(factory)));
98 bool URLRequestFilter::AddUrlInterceptor(
100 scoped_ptr<URLRequestInterceptor> interceptor) {
103 DCHECK_EQ(0u, url_interceptor_map_.count(url.spec()));
104 url_interceptor_map_[url.spec()] = interceptor.release();
106 // Check to see if this URL is masked by a hostname handler.
107 DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(url.scheme(),
113 void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
114 URLInterceptorMap::iterator it = url_interceptor_map_.find(url.spec());
115 DCHECK(it != url_interceptor_map_.end());
118 url_interceptor_map_.erase(it);
119 // Note that we don't unregister from the URLRequest ProtocolFactory as
120 // this would leave no protocol factory for the remaining hostname and URL
124 void URLRequestFilter::ClearHandlers() {
125 STLDeleteValues(&url_interceptor_map_);
126 STLDeleteValues(&hostname_interceptor_map_);
130 URLRequestJob* URLRequestFilter::MaybeInterceptRequest(
132 NetworkDelegate* network_delegate) const {
133 URLRequestJob* job = NULL;
134 if (!request->url().is_valid())
137 // Check the hostname map first.
138 const std::string hostname = request->url().host();
139 const std::string scheme = request->url().scheme();
141 HostnameInterceptorMap::const_iterator it =
142 hostname_interceptor_map_.find(make_pair(scheme, hostname));
143 if (it != hostname_interceptor_map_.end())
144 job = it->second->MaybeInterceptRequest(request, network_delegate);
147 // Not in the hostname map, check the url map.
148 const std::string& url = request->url().spec();
149 URLInterceptorMap::const_iterator it = url_interceptor_map_.find(url);
150 if (it != url_interceptor_map_.end())
151 job = it->second->MaybeInterceptRequest(request, network_delegate);
154 DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
160 URLRequestFilter::URLRequestFilter() : hit_count_(0) {
161 URLRequestJobFactoryImpl::SetInterceptorForTesting(this);
164 URLRequestFilter::~URLRequestFilter() {
165 URLRequestJobFactoryImpl::SetInterceptorForTesting(NULL);