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