| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/url_request/url_request_filter.h" |
| |
| #include <set> |
| |
| #include "base/logging.h" |
| |
| namespace net { |
| |
| URLRequestFilter* URLRequestFilter::shared_instance_ = NULL; |
| |
| URLRequestFilter::~URLRequestFilter() {} |
| |
| // static |
| URLRequestJob* URLRequestFilter::Factory(URLRequest* request, |
| NetworkDelegate* network_delegate, |
| const std::string& scheme) { |
| // Returning null here just means that the built-in handler will be used. |
| return GetInstance()->FindRequestHandler(request, network_delegate, scheme); |
| } |
| |
| // static |
| URLRequestFilter* URLRequestFilter::GetInstance() { |
| if (!shared_instance_) |
| shared_instance_ = new URLRequestFilter; |
| return shared_instance_; |
| } |
| |
| void URLRequestFilter::AddHostnameHandler(const std::string& scheme, |
| const std::string& hostname, URLRequest::ProtocolFactory* factory) { |
| hostname_handler_map_[make_pair(scheme, hostname)] = factory; |
| |
| // Register with the ProtocolFactory. |
| URLRequest::Deprecated::RegisterProtocolFactory( |
| scheme, &URLRequestFilter::Factory); |
| |
| #ifndef NDEBUG |
| // Check to see if we're masking URLs in the url_handler_map_. |
| for (UrlHandlerMap::const_iterator i = url_handler_map_.begin(); |
| i != url_handler_map_.end(); ++i) { |
| const GURL& url = GURL(i->first); |
| HostnameHandlerMap::iterator host_it = |
| hostname_handler_map_.find(make_pair(url.scheme(), url.host())); |
| if (host_it != hostname_handler_map_.end()) |
| NOTREACHED(); |
| } |
| #endif // !NDEBUG |
| } |
| |
| void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme, |
| const std::string& hostname) { |
| HostnameHandlerMap::iterator iter = |
| hostname_handler_map_.find(make_pair(scheme, hostname)); |
| DCHECK(iter != hostname_handler_map_.end()); |
| |
| hostname_handler_map_.erase(iter); |
| // Note that we don't unregister from the URLRequest ProtocolFactory as |
| // this would left no protocol factory for the scheme. |
| // URLRequestFilter::Factory will keep forwarding the requests to the |
| // URLRequestInetJob. |
| } |
| |
| bool URLRequestFilter::AddUrlHandler( |
| const GURL& url, |
| URLRequest::ProtocolFactory* factory) { |
| if (!url.is_valid()) |
| return false; |
| url_handler_map_[url.spec()] = factory; |
| |
| // Register with the ProtocolFactory. |
| URLRequest::Deprecated::RegisterProtocolFactory(url.scheme(), |
| &URLRequestFilter::Factory); |
| #ifndef NDEBUG |
| // Check to see if this URL is masked by a hostname handler. |
| HostnameHandlerMap::iterator host_it = |
| hostname_handler_map_.find(make_pair(url.scheme(), url.host())); |
| if (host_it != hostname_handler_map_.end()) |
| NOTREACHED(); |
| #endif // !NDEBUG |
| |
| return true; |
| } |
| |
| void URLRequestFilter::RemoveUrlHandler(const GURL& url) { |
| UrlHandlerMap::iterator iter = url_handler_map_.find(url.spec()); |
| DCHECK(iter != url_handler_map_.end()); |
| |
| url_handler_map_.erase(iter); |
| // Note that we don't unregister from the URLRequest ProtocolFactory as |
| // this would left no protocol factory for the scheme. |
| // URLRequestFilter::Factory will keep forwarding the requests to the |
| // URLRequestInetJob. |
| } |
| |
| void URLRequestFilter::ClearHandlers() { |
| // Unregister with the ProtocolFactory. |
| std::set<std::string> schemes; |
| for (UrlHandlerMap::const_iterator i = url_handler_map_.begin(); |
| i != url_handler_map_.end(); ++i) { |
| schemes.insert(GURL(i->first).scheme()); |
| } |
| for (HostnameHandlerMap::const_iterator i = hostname_handler_map_.begin(); |
| i != hostname_handler_map_.end(); ++i) { |
| schemes.insert(i->first.first); |
| } |
| for (std::set<std::string>::const_iterator scheme = schemes.begin(); |
| scheme != schemes.end(); ++scheme) { |
| URLRequest::Deprecated::RegisterProtocolFactory(*scheme, NULL); |
| } |
| |
| url_handler_map_.clear(); |
| hostname_handler_map_.clear(); |
| hit_count_ = 0; |
| } |
| |
| URLRequestFilter::URLRequestFilter() : hit_count_(0) { } |
| |
| URLRequestJob* URLRequestFilter::FindRequestHandler( |
| URLRequest* request, |
| NetworkDelegate* network_delegate, |
| const std::string& scheme) { |
| URLRequestJob* job = NULL; |
| if (request->url().is_valid()) { |
| // Check the hostname map first. |
| const std::string& hostname = request->url().host(); |
| |
| HostnameHandlerMap::iterator i = |
| hostname_handler_map_.find(make_pair(scheme, hostname)); |
| if (i != hostname_handler_map_.end()) |
| job = i->second(request, network_delegate, scheme); |
| |
| if (!job) { |
| // Not in the hostname map, check the url map. |
| const std::string& url = request->url().spec(); |
| UrlHandlerMap::iterator i = url_handler_map_.find(url); |
| if (i != url_handler_map_.end()) |
| job = i->second(request, network_delegate, scheme); |
| } |
| } |
| if (job) { |
| DVLOG(1) << "URLRequestFilter hit for " << request->url().spec(); |
| hit_count_++; |
| } |
| return job; |
| } |
| |
| } // namespace net |