// 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 "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job_factory_impl.h"

namespace net {

namespace {

// When adding interceptors, DCHECK that this function returns true.
bool OnMessageLoopForInterceptorAddition() {
  base::MessageLoop* message_loop = base::MessageLoop::current();
  // Return true if called on a MessageLoopForIO or if there is no MessageLoop.
  // Checking for a MessageLoopForIO is a best effort at determining whether the
  // current thread is a networking thread.  Allowing cases without a
  // MessageLoop is required for some tests where there is no chance to insert
  // an interceptor between a networking thread being started and a resource
  // request being issued.
  return message_loop == nullptr ||
         message_loop->type() == base::MessageLoop::TYPE_IO;
}

// When removing interceptors, DCHECK that this function returns true.
bool OnMessageLoopForInterceptorRemoval() {
  // Checking for a MessageLoopForIO is a best effort at determining whether the
  // current thread is a networking thread.
  return base::MessageLoopForIO::IsCurrent();
}

}  // namespace

URLRequestFilter* URLRequestFilter::shared_instance_ = NULL;

// static
URLRequestFilter* URLRequestFilter::GetInstance() {
  DCHECK(OnMessageLoopForInterceptorAddition());
  if (!shared_instance_)
    shared_instance_ = new URLRequestFilter;
  return shared_instance_;
}

void URLRequestFilter::AddHostnameInterceptor(
    const std::string& scheme,
    const std::string& hostname,
    std::unique_ptr<URLRequestInterceptor> interceptor) {
  DCHECK(OnMessageLoopForInterceptorAddition());
  DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(scheme, hostname)));
  hostname_interceptor_map_[make_pair(scheme, hostname)] =
      std::move(interceptor);

#ifndef NDEBUG
  // Check to see if we're masking URLs in the url_interceptor_map_.
  for (const auto& pair : url_interceptor_map_) {
    const GURL& url = GURL(pair.first);
    HostnameInterceptorMap::const_iterator host_it =
        hostname_interceptor_map_.find(make_pair(url.scheme(), url.host()));
    if (host_it != hostname_interceptor_map_.end())
      NOTREACHED();
  }
#endif  // !NDEBUG
}

void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
                                             const std::string& hostname) {
  DCHECK(OnMessageLoopForInterceptorRemoval());
  int removed = hostname_interceptor_map_.erase(make_pair(scheme, hostname));
  DCHECK(removed);

  // 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::AddUrlInterceptor(
    const GURL& url,
    std::unique_ptr<URLRequestInterceptor> interceptor) {
  DCHECK(OnMessageLoopForInterceptorAddition());
  if (!url.is_valid())
    return false;
  DCHECK_EQ(0u, url_interceptor_map_.count(url.spec()));
  url_interceptor_map_[url.spec()] = std::move(interceptor);

  // Check to see if this URL is masked by a hostname handler.
  DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(url.scheme(),
                                                          url.host())));

  return true;
}

void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
  DCHECK(OnMessageLoopForInterceptorRemoval());
  size_t removed = url_interceptor_map_.erase(url.spec());
  DCHECK(removed);
  // 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() {
  DCHECK(OnMessageLoopForInterceptorRemoval());
  url_interceptor_map_.clear();
  hostname_interceptor_map_.clear();
  hit_count_ = 0;
}

URLRequestJob* URLRequestFilter::MaybeInterceptRequest(
    URLRequest* request,
    NetworkDelegate* network_delegate) const {
  DCHECK(base::MessageLoopForIO::current());
  URLRequestJob* job = NULL;
  if (!request->url().is_valid())
    return NULL;

  // Check the hostname map first.
  const std::string hostname = request->url().host();
  const std::string scheme = request->url().scheme();

  {
    HostnameInterceptorMap::const_iterator it =
        hostname_interceptor_map_.find(make_pair(scheme, hostname));
    if (it != hostname_interceptor_map_.end())
      job = it->second->MaybeInterceptRequest(request, network_delegate);
  }

  if (!job) {
    // Not in the hostname map, check the url map.
    const std::string& url = request->url().spec();
    URLInterceptorMap::const_iterator it = url_interceptor_map_.find(url);
    if (it != url_interceptor_map_.end())
      job = it->second->MaybeInterceptRequest(request, network_delegate);
  }
  if (job) {
    DVLOG(1) << "URLRequestFilter hit for " << request->url().spec();
    hit_count_++;
  }
  return job;
}

URLRequestFilter::URLRequestFilter() : hit_count_(0) {
  DCHECK(OnMessageLoopForInterceptorAddition());
  URLRequestJobFactoryImpl::SetInterceptorForTesting(this);
}

URLRequestFilter::~URLRequestFilter() {
  DCHECK(OnMessageLoopForInterceptorRemoval());
  URLRequestJobFactoryImpl::SetInterceptorForTesting(NULL);
}

}  // namespace net
