root/net/url_request/url_request_filter.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. MaybeCreateJob
  2. Factory
  3. GetInstance
  4. AddHostnameHandler
  5. AddHostnameProtocolHandler
  6. RemoveHostnameHandler
  7. AddUrlHandler
  8. AddUrlProtocolHandler
  9. RemoveUrlHandler
  10. ClearHandlers
  11. FindRequestHandler

// 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"
#include "base/stl_util.h"

namespace net {

namespace {

class URLRequestFilterProtocolHandler
    : public URLRequestJobFactory::ProtocolHandler {
 public:
  explicit URLRequestFilterProtocolHandler(URLRequest::ProtocolFactory* factory)
      : factory_(factory) {}
  virtual ~URLRequestFilterProtocolHandler() {}

  // URLRequestJobFactory::ProtocolHandler implementation
  virtual URLRequestJob* MaybeCreateJob(
      URLRequest* request, NetworkDelegate* network_delegate) const OVERRIDE {
    return factory_(request, network_delegate, request->url().scheme());
  }

 private:
  URLRequest::ProtocolFactory* factory_;

  DISALLOW_COPY_AND_ASSIGN(URLRequestFilterProtocolHandler);
};

}  // namespace

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) {
  AddHostnameProtocolHandler(
      scheme, hostname,
      scoped_ptr<URLRequestJobFactory::ProtocolHandler>(
          new URLRequestFilterProtocolHandler(factory)));
}

void URLRequestFilter::AddHostnameProtocolHandler(
    const std::string& scheme,
    const std::string& hostname,
    scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) {
  DCHECK_EQ(0u, hostname_handler_map_.count(make_pair(scheme, hostname)));
  hostname_handler_map_[make_pair(scheme, hostname)] =
      protocol_handler.release();

  // 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());

  delete iter->second;
  hostname_handler_map_.erase(iter);
  // Note that we don't unregister from the URLRequest ProtocolFactory as
  // this would leave no protocol factory for the remaining hostname and URL
  // handlers.
}

bool URLRequestFilter::AddUrlHandler(
    const GURL& url,
    URLRequest::ProtocolFactory* factory) {
  return AddUrlProtocolHandler(
      url,
      scoped_ptr<URLRequestJobFactory::ProtocolHandler>(
          new URLRequestFilterProtocolHandler(factory)));
}


bool URLRequestFilter::AddUrlProtocolHandler(
    const GURL& url,
    scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) {
  if (!url.is_valid())
    return false;
  DCHECK_EQ(0u, url_handler_map_.count(url.spec()));
  url_handler_map_[url.spec()] = protocol_handler.release();

  // Register with the ProtocolFactory.
  URLRequest::Deprecated::RegisterProtocolFactory(url.scheme(),
                                                  &URLRequestFilter::Factory);
  // Check to see if this URL is masked by a hostname handler.
  DCHECK_EQ(0u, hostname_handler_map_.count(make_pair(url.scheme(),
                                                      url.host())));

  return true;
}

void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
  UrlHandlerMap::iterator iter = url_handler_map_.find(url.spec());
  DCHECK(iter != url_handler_map_.end());

  delete iter->second;
  url_handler_map_.erase(iter);
  // Note that we don't unregister from the URLRequest ProtocolFactory as
  // this would leave no protocol factory for the remaining hostname and URL
  // handlers.
}

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);
  }

  STLDeleteValues(&url_handler_map_);
  STLDeleteValues(&hostname_handler_map_);
  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->MaybeCreateJob(request, network_delegate);

    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->MaybeCreateJob(request, network_delegate);
    }
  }
  if (job) {
    DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
    hit_count_++;
  }
  return job;
}

}  // namespace net

/* [<][>][^][v][top][bottom][index][help] */