blob: 01b6069107282999088a9e32ce6d4cfae62557f1 [file] [log] [blame]
// 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