url_request_filter.cc revision f2477e01787aa58f445919b809d89e252beef54f
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" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class URLRequestFilterProtocolHandler 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : public URLRequestJobFactory::ProtocolHandler { 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit URLRequestFilterProtocolHandler(URLRequest::ProtocolFactory* factory) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : factory_(factory) {} 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~URLRequestFilterProtocolHandler() {} 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // URLRequestJobFactory::ProtocolHandler implementation 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual URLRequestJob* MaybeCreateJob( 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) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(URLRequestFilterProtocolHandler); 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. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetInstance()->FindRequestHandler(request, network_delegate, scheme); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter* URLRequestFilter::GetInstance() { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shared_instance_) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_instance_ = new URLRequestFilter; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shared_instance_; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::AddHostnameHandler(const std::string& scheme, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname, URLRequest::ProtocolFactory* factory) { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddHostnameProtocolHandler( 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scheme, hostname, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<URLRequestJobFactory::ProtocolHandler>( 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new URLRequestFilterProtocolHandler(factory))); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFilter::AddHostnameProtocolHandler( 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& scheme, 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& hostname, 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0u, hostname_handler_map_.count(make_pair(scheme, hostname))); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hostname_handler_map_[make_pair(scheme, hostname)] = 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protocol_handler.release(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register with the ProtocolFactory. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest::Deprecated::RegisterProtocolFactory( 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme, &URLRequestFilter::Factory); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see if we're masking URLs in the url_handler_map_. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (UrlHandlerMap::const_iterator i = url_handler_map_.begin(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != url_handler_map_.end(); ++i) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url = GURL(i->first); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostnameHandlerMap::iterator host_it = 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostname_handler_map_.find(make_pair(url.scheme(), url.host())); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_it != hostname_handler_map_.end()) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !NDEBUG 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostnameHandlerMap::iterator iter = 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostname_handler_map_.find(make_pair(scheme, hostname)); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(iter != hostname_handler_map_.end()); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete iter->second; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostname_handler_map_.erase(iter); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we don't unregister from the URLRequest ProtocolFactory as 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // this would leave no protocol factory for the remaining hostname and URL 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // handlers. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFilter::AddUrlHandler( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest::ProtocolFactory* factory) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return AddUrlProtocolHandler( 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<URLRequestJobFactory::ProtocolHandler>( 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new URLRequestFilterProtocolHandler(factory))); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool URLRequestFilter::AddUrlProtocolHandler( 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url, 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.is_valid()) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0u, url_handler_map_.count(url.spec())); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_handler_map_[url.spec()] = protocol_handler.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. 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0u, hostname_handler_map_.count(make_pair(url.scheme(), 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlHandlerMap::iterator iter = url_handler_map_.find(url.spec()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(iter != url_handler_map_.end()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete iter->second; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_handler_map_.erase(iter); 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; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (UrlHandlerMap::const_iterator i = url_handler_map_.begin(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != url_handler_map_.end(); ++i) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) schemes.insert(GURL(i->first).scheme()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (HostnameHandlerMap::const_iterator i = hostname_handler_map_.begin(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != hostname_handler_map_.end(); ++i) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) schemes.insert(i->first.first); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<std::string>::const_iterator scheme = schemes.begin(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme != schemes.end(); ++scheme) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest::Deprecated::RegisterProtocolFactory(*scheme, NULL); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteValues(&url_handler_map_); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteValues(&hostname_handler_map_); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit_count_ = 0; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter::URLRequestFilter() : hit_count_(0) { } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestJob* URLRequestFilter::FindRequestHandler( 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequest* request, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetworkDelegate* network_delegate, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& scheme) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequestJob* job = NULL; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->url().is_valid()) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the hostname map first. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname = request->url().host(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostnameHandlerMap::iterator i = 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostname_handler_map_.find(make_pair(scheme, hostname)); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != hostname_handler_map_.end()) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) job = i->second->MaybeCreateJob(request, network_delegate); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!job) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not in the hostname map, check the url map. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& url = request->url().spec(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlHandlerMap::iterator i = url_handler_map_.find(url); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != url_handler_map_.end()) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) job = i->second->MaybeCreateJob(request, network_delegate); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (job) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "URLRequestFilter hit for " << request->url().spec(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit_count_++; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return job; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 194