url_request_filter.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter* URLRequestFilter::shared_instance_ = NULL;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter::~URLRequestFilter() {}
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestJob* URLRequestFilter::Factory(URLRequest* request,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         NetworkDelegate* network_delegate,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::string& scheme) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returning null here just means that the built-in handler will be used.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetInstance()->FindRequestHandler(request, network_delegate, scheme);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter* URLRequestFilter::GetInstance() {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!shared_instance_)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shared_instance_ = new URLRequestFilter;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return shared_instance_;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::AddHostnameHandler(const std::string& scheme,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& hostname, URLRequest::ProtocolFactory* factory) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hostname_handler_map_[make_pair(scheme, hostname)] = factory;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register with the ProtocolFactory.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLRequest::Deprecated::RegisterProtocolFactory(
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scheme, &URLRequestFilter::Factory);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if we're masking URLs in the url_handler_map_.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (UrlHandlerMap::const_iterator i = url_handler_map_.begin();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != url_handler_map_.end(); ++i) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url = GURL(i->first);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostnameHandlerMap::iterator host_it =
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hostname_handler_map_.find(make_pair(url.scheme(), url.host()));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (host_it != hostname_handler_map_.end())
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !NDEBUG
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const std::string& hostname) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostnameHandlerMap::iterator iter =
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hostname_handler_map_.find(make_pair(scheme, hostname));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(iter != hostname_handler_map_.end());
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hostname_handler_map_.erase(iter);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we don't unregister from the URLRequest ProtocolFactory as
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this would left no protocol factory for the scheme.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URLRequestFilter::Factory will keep forwarding the requests to the
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URLRequestInetJob.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFilter::AddUrlHandler(
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLRequest::ProtocolFactory* factory) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url.is_valid())
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_handler_map_[url.spec()] = factory;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register with the ProtocolFactory.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLRequest::Deprecated::RegisterProtocolFactory(url.scheme(),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &URLRequestFilter::Factory);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if this URL is masked by a hostname handler.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostnameHandlerMap::iterator host_it =
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hostname_handler_map_.find(make_pair(url.scheme(), url.host()));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host_it != hostname_handler_map_.end())
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !NDEBUG
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UrlHandlerMap::iterator iter = url_handler_map_.find(url.spec());
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(iter != url_handler_map_.end());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_handler_map_.erase(iter);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we don't unregister from the URLRequest ProtocolFactory as
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this would left no protocol factory for the scheme.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URLRequestFilter::Factory will keep forwarding the requests to the
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URLRequestInetJob.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFilter::ClearHandlers() {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unregister with the ProtocolFactory.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> schemes;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (UrlHandlerMap::const_iterator i = url_handler_map_.begin();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != url_handler_map_.end(); ++i) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    schemes.insert(GURL(i->first).scheme());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (HostnameHandlerMap::const_iterator i = hostname_handler_map_.begin();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != hostname_handler_map_.end(); ++i) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    schemes.insert(i->first.first);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::const_iterator scheme = schemes.begin();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       scheme != schemes.end(); ++scheme) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLRequest::Deprecated::RegisterProtocolFactory(*scheme, NULL);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_handler_map_.clear();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hostname_handler_map_.clear();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hit_count_ = 0;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFilter::URLRequestFilter() : hit_count_(0) { }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestJob* URLRequestFilter::FindRequestHandler(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLRequest* request,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetworkDelegate* network_delegate,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& scheme) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLRequestJob* job = NULL;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->url().is_valid()) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check the hostname map first.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& hostname = request->url().host();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostnameHandlerMap::iterator i =
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hostname_handler_map_.find(make_pair(scheme, hostname));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != hostname_handler_map_.end())
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      job = i->second(request, network_delegate, scheme);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!job) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Not in the hostname map, check the url map.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& url = request->url().spec();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UrlHandlerMap::iterator i = url_handler_map_.find(url);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i != url_handler_map_.end())
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        job = i->second(request, network_delegate, scheme);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (job) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hit_count_++;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return job;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
151