// Copyright (c) 2012 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/test_url_request_interceptor.h"

#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {

namespace {

// This class is needed because URLRequestFileJob always returns a -1
// HTTP response status code.
class TestURLRequestJob : public URLRequestFileJob {
 public:
  TestURLRequestJob(URLRequest* request,
                    NetworkDelegate* network_delegate,
                    const base::FilePath& file_path,
                    const scoped_refptr<base::TaskRunner>& worker_task_runner)
      : URLRequestFileJob(request,
                          network_delegate,
                          file_path,
                          worker_task_runner) {}

  void GetResponseInfo(HttpResponseInfo* info) override {
    info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK");
  }

 private:
  ~TestURLRequestJob() override = default;

  DISALLOW_COPY_AND_ASSIGN(TestURLRequestJob);
};

}  // namespace

// This class handles the actual URL request interception. It may be constructed
// on any thread, but all other methods are called on the |network_task_runner|
// thread. It is destroyed by the URLRequestFilter singleton.
class TestURLRequestInterceptor::Delegate : public URLRequestInterceptor {
 public:
  Delegate(const std::string& scheme,
           const std::string& hostname,
           const scoped_refptr<base::TaskRunner>& network_task_runner,
           const scoped_refptr<base::TaskRunner>& worker_task_runner)
      : scheme_(scheme),
        hostname_(hostname),
        network_task_runner_(network_task_runner),
        worker_task_runner_(worker_task_runner),
        hit_count_(0) {}
  ~Delegate() override = default;

  void Register() {
    URLRequestFilter::GetInstance()->AddHostnameInterceptor(
        scheme_, hostname_, std::unique_ptr<URLRequestInterceptor>(this));
  }

  static void Unregister(const std::string& scheme,
                         const std::string& hostname) {
    URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme, hostname);
  }

  // When requests for |url| arrive, respond with the contents of |path|. The
  // hostname and scheme of |url| must match the corresponding parameters
  // passed as constructor arguments.
  void SetResponse(const GURL& url,
                   const base::FilePath& path,
                   bool ignore_query) {
    DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
    if (ignore_query) {
      ignore_query_responses_[url] = path;
    } else {
      responses_[url] = path;
    }
  }

  // Returns how many requests have been issued that have a stored reply.
  int GetHitCount() const {
    base::AutoLock auto_lock(hit_count_lock_);
    return hit_count_;
  }

 private:
  typedef std::map<GURL, base::FilePath> ResponseMap;

  // When computing matches, this ignores the query parameters of the url.
  URLRequestJob* MaybeInterceptRequest(
      URLRequest* request,
      NetworkDelegate* network_delegate) const override {
    DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
    if (request->url().scheme() != scheme_ ||
        request->url().host() != hostname_) {
      return NULL;
    }

    ResponseMap::const_iterator it = responses_.find(request->url());
    if (it == responses_.end()) {
      // Search for this request's url, ignoring any query parameters.
      GURL url = request->url();
      if (url.has_query()) {
        GURL::Replacements replacements;
        replacements.ClearQuery();
        url = url.ReplaceComponents(replacements);
      }
      it = ignore_query_responses_.find(url);
      if (it == ignore_query_responses_.end())
        return NULL;
    }
    {
      base::AutoLock auto_lock(hit_count_lock_);
      ++hit_count_;
    }

    return new TestURLRequestJob(
        request, network_delegate, it->second, worker_task_runner_);
  }

  const std::string scheme_;
  const std::string hostname_;

  const scoped_refptr<base::TaskRunner> network_task_runner_;
  const scoped_refptr<base::TaskRunner> worker_task_runner_;

  ResponseMap responses_;
  ResponseMap ignore_query_responses_;

  mutable base::Lock hit_count_lock_;
  mutable int hit_count_;

  DISALLOW_COPY_AND_ASSIGN(Delegate);
};

TestURLRequestInterceptor::TestURLRequestInterceptor(
    const std::string& scheme,
    const std::string& hostname,
    const scoped_refptr<base::TaskRunner>& network_task_runner,
    const scoped_refptr<base::TaskRunner>& worker_task_runner)
    : scheme_(scheme),
      hostname_(hostname),
      network_task_runner_(network_task_runner),
      delegate_(new Delegate(scheme,
                             hostname,
                             network_task_runner_,
                             worker_task_runner)) {
  network_task_runner_->PostTask(
      FROM_HERE, base::Bind(&Delegate::Register, base::Unretained(delegate_)));
}

TestURLRequestInterceptor::~TestURLRequestInterceptor() {
  network_task_runner_->PostTask(
      FROM_HERE, base::Bind(&Delegate::Unregister, scheme_, hostname_));
}

void TestURLRequestInterceptor::SetResponse(const GURL& url,
                                            const base::FilePath& path) {
  CHECK_EQ(scheme_, url.scheme());
  CHECK_EQ(hostname_, url.host());
  network_task_runner_->PostTask(FROM_HERE,
                                 base::Bind(&Delegate::SetResponse,
                                            base::Unretained(delegate_),
                                            url,
                                            path,
                                            false));
}

void TestURLRequestInterceptor::SetResponseIgnoreQuery(
    const GURL& url,
    const base::FilePath& path) {
  CHECK_EQ(scheme_, url.scheme());
  CHECK_EQ(hostname_, url.host());
  network_task_runner_->PostTask(FROM_HERE,
                                 base::Bind(&Delegate::SetResponse,
                                            base::Unretained(delegate_),
                                            url,
                                            path,
                                            true));
}

int TestURLRequestInterceptor::GetHitCount() {
  return delegate_->GetHitCount();
}

LocalHostTestURLRequestInterceptor::LocalHostTestURLRequestInterceptor(
    const scoped_refptr<base::TaskRunner>& network_task_runner,
    const scoped_refptr<base::TaskRunner>& worker_task_runner)
    : TestURLRequestInterceptor("http",
                                "localhost",
                                network_task_runner,
                                worker_task_runner) {
}

}  // namespace net
