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" 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/url_request/url_request_job_factory_impl.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)// static 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter* URLRequestFilter::GetInstance() { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shared_instance_) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_instance_ = new URLRequestFilter; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shared_instance_; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::AddHostnameHandler(const std::string& scheme, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname, URLRequest::ProtocolFactory* factory) { 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) AddHostnameInterceptor( 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scheme, hostname, 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<URLRequestInterceptor>( 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new URLRequestFilterInterceptor(factory))); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void URLRequestFilter::AddHostnameInterceptor( 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& scheme, 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& hostname, 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<URLRequestInterceptor> interceptor) { 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(scheme, hostname))); 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_[make_pair(scheme, hostname)] = 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) interceptor.release(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Check to see if we're masking URLs in the url_interceptor_map_. 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (URLInterceptorMap::const_iterator it = url_interceptor_map_.begin(); 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != url_interceptor_map_.end(); ++it) { 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const GURL& url = GURL(it->first); 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HostnameInterceptorMap::const_iterator host_it = 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_.find(make_pair(url.scheme(), url.host())); 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (host_it != hostname_interceptor_map_.end()) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !NDEBUG 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname) { 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HostnameInterceptorMap::iterator it = 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_.find(make_pair(scheme, hostname)); 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(it != hostname_interceptor_map_.end()); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delete it->second; 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hostname_interceptor_map_.erase(it); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we don't unregister from the URLRequest ProtocolFactory as 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // this would leave no protocol factory for the remaining hostname and URL 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // handlers. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFilter::AddUrlHandler( 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest::ProtocolFactory* factory) { 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return AddUrlInterceptor( 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, 9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<URLRequestInterceptor>( 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new URLRequestFilterInterceptor(factory))); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool URLRequestFilter::AddUrlInterceptor( 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url, 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<URLRequestInterceptor> interceptor) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.is_valid()) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(0u, url_interceptor_map_.count(url.spec())); 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url_interceptor_map_[url.spec()] = interceptor.release(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if this URL is masked by a hostname handler. 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(url.scheme(), 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url.host()))); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::RemoveUrlHandler(const GURL& url) { 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLInterceptorMap::iterator it = url_interceptor_map_.find(url.spec()); 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(it != url_interceptor_map_.end()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delete it->second; 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url_interceptor_map_.erase(it); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we don't unregister from the URLRequest ProtocolFactory as 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // this would leave no protocol factory for the remaining hostname and URL 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // handlers. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::ClearHandlers() { 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) STLDeleteValues(&url_interceptor_map_); 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) STLDeleteValues(&hostname_interceptor_map_); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit_count_ = 0; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)URLRequestJob* URLRequestFilter::MaybeInterceptRequest( 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest* request, 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NetworkDelegate* network_delegate) const { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequestJob* job = NULL; 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!request->url().is_valid()) 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return NULL; 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Check the hostname map first. 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string hostname = request->url().host(); 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string scheme = request->url().scheme(); 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) HostnameInterceptorMap::const_iterator it = 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) hostname_interceptor_map_.find(make_pair(scheme, hostname)); 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it != hostname_interceptor_map_.end()) 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) job = it->second->MaybeInterceptRequest(request, network_delegate); 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!job) { 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Not in the hostname map, check the url map. 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& url = request->url().spec(); 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) URLInterceptorMap::const_iterator it = url_interceptor_map_.find(url); 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (it != url_interceptor_map_.end()) 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) job = it->second->MaybeInterceptRequest(request, network_delegate); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (job) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "URLRequestFilter hit for " << request->url().spec(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit_count_++; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return job; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)URLRequestFilter::URLRequestFilter() : hit_count_(0) { 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) URLRequestJobFactoryImpl::SetInterceptorForTesting(this); 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)URLRequestFilter::~URLRequestFilter() { 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) URLRequestJobFactoryImpl::SetInterceptorForTesting(NULL); 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 168