url_request_filter.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_filter.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h" 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/url_request/url_request_interceptor.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class URLRequestFilterInterceptor : public URLRequestInterceptor { 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) explicit URLRequestFilterInterceptor(URLRequest::ProtocolFactory* factory) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : factory_(factory) {} 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual ~URLRequestFilterInterceptor() {} 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // URLRequestInterceptor implementation. 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual URLRequestJob* MaybeInterceptRequest( 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) URLRequest* request, NetworkDelegate* network_delegate) const OVERRIDE { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return factory_(request, network_delegate, request->url().scheme()); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) URLRequest::ProtocolFactory* factory_; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(URLRequestFilterInterceptor); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter* URLRequestFilter::shared_instance_ = NULL; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter::~URLRequestFilter() {} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestJob* URLRequestFilter::Factory(URLRequest* request, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetworkDelegate* network_delegate, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& scheme) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returning null here just means that the built-in handler will be used. 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return GetInstance()->MaybeInterceptRequest(request, network_delegate, 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scheme); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter* URLRequestFilter::GetInstance() { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shared_instance_) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_instance_ = new URLRequestFilter; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shared_instance_; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::AddHostnameHandler(const std::string& scheme, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname, URLRequest::ProtocolFactory* factory) { 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) AddHostnameInterceptor( 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scheme, hostname, 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<URLRequestInterceptor>( 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new URLRequestFilterInterceptor(factory))); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void URLRequestFilter::AddHostnameInterceptor( 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& scheme, 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& hostname, 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<URLRequestInterceptor> interceptor) { 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(scheme, hostname))); 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_[make_pair(scheme, hostname)] = 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) interceptor.release(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register with the ProtocolFactory. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest::Deprecated::RegisterProtocolFactory( 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme, &URLRequestFilter::Factory); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Check to see if we're masking URLs in the url_interceptor_map_. 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (URLInterceptorMap::const_iterator it = url_interceptor_map_.begin(); 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != url_interceptor_map_.end(); ++it) { 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const GURL& url = GURL(it->first); 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HostnameInterceptorMap::const_iterator host_it = 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_.find(make_pair(url.scheme(), url.host())); 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (host_it != hostname_interceptor_map_.end()) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !NDEBUG 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname) { 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HostnameInterceptorMap::iterator it = 9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_.find(make_pair(scheme, hostname)); 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(it != hostname_interceptor_map_.end()); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delete it->second; 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_.erase(it); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we don't unregister from the URLRequest ProtocolFactory as 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // this would leave no protocol factory for the remaining hostname and URL 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // handlers. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFilter::AddUrlHandler( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest::ProtocolFactory* factory) { 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return AddUrlInterceptor( 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<URLRequestInterceptor>( 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new URLRequestFilterInterceptor(factory))); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool URLRequestFilter::AddUrlInterceptor( 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url, 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<URLRequestInterceptor> interceptor) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.is_valid()) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(0u, url_interceptor_map_.count(url.spec())); 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url_interceptor_map_[url.spec()] = interceptor.release(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register with the ProtocolFactory. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest::Deprecated::RegisterProtocolFactory(url.scheme(), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &URLRequestFilter::Factory); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if this URL is masked by a hostname handler. 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(url.scheme(), 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url.host()))); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::RemoveUrlHandler(const GURL& url) { 13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLInterceptorMap::iterator it = url_interceptor_map_.find(url.spec()); 13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(it != url_interceptor_map_.end()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delete it->second; 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url_interceptor_map_.erase(it); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we don't unregister from the URLRequest ProtocolFactory as 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // this would leave no protocol factory for the remaining hostname and URL 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // handlers. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::ClearHandlers() { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unregister with the ProtocolFactory. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> schemes; 14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (URLInterceptorMap::const_iterator it= url_interceptor_map_.begin(); 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != url_interceptor_map_.end(); ++it) { 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) schemes.insert(GURL(it->first).scheme()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (HostnameInterceptorMap::const_iterator it = 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_.begin(); 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != hostname_interceptor_map_.end(); ++it) { 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) schemes.insert(it->first.first); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<std::string>::const_iterator scheme = schemes.begin(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme != schemes.end(); ++scheme) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest::Deprecated::RegisterProtocolFactory(*scheme, NULL); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) STLDeleteValues(&url_interceptor_map_); 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) STLDeleteValues(&hostname_interceptor_map_); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit_count_ = 0; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter::URLRequestFilter() : hit_count_(0) { } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)URLRequestJob* URLRequestFilter::MaybeInterceptRequest( 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest* request, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetworkDelegate* network_delegate, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& scheme) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequestJob* job = NULL; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->url().is_valid()) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the hostname map first. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname = request->url().host(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HostnameInterceptorMap::iterator i = 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_.find(make_pair(scheme, hostname)); 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (i != hostname_interceptor_map_.end()) 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) job = i->second->MaybeInterceptRequest(request, network_delegate); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!job) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not in the hostname map, check the url map. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url = request->url().spec(); 18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLInterceptorMap::iterator i = url_interceptor_map_.find(url); 18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (i != url_interceptor_map_.end()) 18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) job = i->second->MaybeInterceptRequest(request, network_delegate); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (job) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "URLRequestFilter hit for " << request->url().spec(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit_count_++; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return job; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 195