// Copyright 2015 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 "content/browser/loader/async_revalidation_driver.h"

#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/common/content_client.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_browser_client.h"
#include "ipc/ipc_message.h"
#include "net/base/net_errors.h"
#include "net/base/network_delegate_impl.h"
#include "net/base/request_priority.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/url_request/url_request_job_factory.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_status.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {
namespace {

// Dummy implementation of ResourceThrottle, an instance of which is needed to
// initialize AsyncRevalidationDriver.
class ResourceThrottleStub : public ResourceThrottle {
 public:
  ResourceThrottleStub() {}

  // If true, defers the request in WillStartRequest.
  void set_defer_request_on_will_start_request(
      bool defer_request_on_will_start_request) {
    defer_request_on_will_start_request_ = defer_request_on_will_start_request;
  }

  // ResourceThrottler implementation:
  void WillStartRequest(bool* defer) override {
    *defer = defer_request_on_will_start_request_;
  }

  const char* GetNameForLogging() const override {
    return "ResourceThrottleStub";
  }

 private:
  bool defer_request_on_will_start_request_ = false;

  DISALLOW_COPY_AND_ASSIGN(ResourceThrottleStub);
};

// There are multiple layers of boilerplate needed to use a URLRequestTestJob
// subclass.  Subclasses of AsyncRevalidationDriverTest can use
// BindCreateProtocolHandlerCallback() to bypass most of that boilerplate.
using CreateProtocolHandlerCallback = base::Callback<
    std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>()>;

template <typename T>
CreateProtocolHandlerCallback BindCreateProtocolHandlerCallback() {
  static_assert(std::is_base_of<net::URLRequestJob, T>::value,
                "Template argument to BindCreateProtocolHandlerCallback() must "
                "be a subclass of URLRequestJob.");

  class TemplatedProtocolHandler
      : public net::URLRequestJobFactory::ProtocolHandler {
   public:
    static std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
    Create() {
      return base::MakeUnique<TemplatedProtocolHandler>();
    }

    // URLRequestJobFactory::ProtocolHandler implementation:
    net::URLRequestJob* MaybeCreateJob(
        net::URLRequest* request,
        net::NetworkDelegate* network_delegate) const override {
      return new T(request, network_delegate);
    }
  };

  return base::Bind(&TemplatedProtocolHandler::Create);
}

// An implementation of NetworkDelegate that captures the status of the last
// URLRequest to be destroyed.
class StatusCapturingNetworkDelegate : public net::NetworkDelegateImpl {
 public:
  const net::URLRequestStatus& last_status() { return last_status_; }

 private:
  // net::NetworkDelegate implementation.
  void OnURLRequestDestroyed(net::URLRequest* request) override {
    last_status_ = request->status();
  }

  net::URLRequestStatus last_status_;
};

class AsyncRevalidationDriverTest : public testing::Test {
 protected:
  // Constructor for test fixtures that subclass this one.
  AsyncRevalidationDriverTest(
      const CreateProtocolHandlerCallback& create_protocol_handler_callback)
      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
        create_protocol_handler_callback_(create_protocol_handler_callback),
        raw_ptr_resource_throttle_(nullptr),
        raw_ptr_request_(nullptr) {
    test_url_request_context_.set_job_factory(&job_factory_);
    test_url_request_context_.set_network_delegate(&network_delegate_);
  }

  // Constructor for tests that use this fixture directly.
  AsyncRevalidationDriverTest()
      : AsyncRevalidationDriverTest(
            base::Bind(net::URLRequestTestJob::CreateProtocolHandler)) {}

  bool async_revalidation_complete_called() const {
    return async_revalidation_complete_called_;
  }

  const net::URLRequestStatus& last_status() {
    return network_delegate_.last_status();
  }

  void SetUpAsyncRevalidationDriverWithRequestToUrl(const GURL& url) {
    std::unique_ptr<net::URLRequest> request(
        test_url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY,
                                                nullptr /* delegate */));
    raw_ptr_request_ = request.get();
    raw_ptr_resource_throttle_ = new ResourceThrottleStub();
    // This use of base::Unretained() is safe because |driver_|, and the closure
    // passed to it, will be destroyed before this object is.
    driver_.reset(new AsyncRevalidationDriver(
        std::move(request), base::WrapUnique(raw_ptr_resource_throttle_),
        base::Bind(&AsyncRevalidationDriverTest::OnAsyncRevalidationComplete,
                   base::Unretained(this))));
  }

  void SetUpAsyncRevalidationDriverWithDefaultRequest() {
    SetUpAsyncRevalidationDriverWithRequestToUrl(
        net::URLRequestTestJob::test_url_1());
  }

  void SetUp() override {
    job_factory_.SetProtocolHandler("test",
                                    create_protocol_handler_callback_.Run());
    SetUpAsyncRevalidationDriverWithDefaultRequest();
  }

  void OnAsyncRevalidationComplete() {
    EXPECT_FALSE(async_revalidation_complete_called_);
    async_revalidation_complete_called_ = true;
    driver_.reset();
  }

  TestBrowserThreadBundle thread_bundle_;
  net::URLRequestJobFactoryImpl job_factory_;
  net::TestURLRequestContext test_url_request_context_;
  StatusCapturingNetworkDelegate network_delegate_;
  CreateProtocolHandlerCallback create_protocol_handler_callback_;

  // The AsyncRevalidationDriver owns the URLRequest and the ResourceThrottle.
  ResourceThrottleStub* raw_ptr_resource_throttle_;
  net::URLRequest* raw_ptr_request_;
  std::unique_ptr<AsyncRevalidationDriver> driver_;
  bool async_revalidation_complete_called_ = false;
};

TEST_F(AsyncRevalidationDriverTest, NormalRequestCompletes) {
  driver_->StartRequest();
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(async_revalidation_complete_called());
}

// Verifies that request that should be deferred at start is deferred.
TEST_F(AsyncRevalidationDriverTest, DeferOnStart) {
  raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);

  driver_->StartRequest();
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(raw_ptr_request_->is_pending());
  EXPECT_FALSE(async_revalidation_complete_called());
}

// Verifies that resuming a deferred request works. Assumes that DeferOnStart
// passes.
TEST_F(AsyncRevalidationDriverTest, ResumeDeferredRequestWorks) {
  raw_ptr_resource_throttle_->set_defer_request_on_will_start_request(true);

  driver_->StartRequest();
  base::RunLoop().RunUntilIdle();

  ResourceController* driver_as_resource_controller = driver_.get();
  driver_as_resource_controller->Resume();
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(async_revalidation_complete_called());
}

// Verifies that redirects are not followed.
TEST_F(AsyncRevalidationDriverTest, RedirectsAreNotFollowed) {
  SetUpAsyncRevalidationDriverWithRequestToUrl(
      net::URLRequestTestJob::test_url_redirect_to_url_2());

  driver_->StartRequest();
  while (net::URLRequestTestJob::ProcessOnePendingMessage())
    base::RunLoop().RunUntilIdle();
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(last_status().is_success());
  EXPECT_EQ(net::ERR_ABORTED, last_status().error());
  EXPECT_TRUE(async_revalidation_complete_called());
}

// A mock URLRequestJob which simulates an SSL client auth request.
class MockClientCertURLRequestJob : public net::URLRequestTestJob {
 public:
  MockClientCertURLRequestJob(net::URLRequest* request,
                              net::NetworkDelegate* network_delegate)
      : net::URLRequestTestJob(request, network_delegate, true),
        weak_factory_(this) {}

  // net::URLRequestTestJob implementation:
  void Start() override {
    scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
        new net::SSLCertRequestInfo);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
                   weak_factory_.GetWeakPtr(),
                   base::RetainedRef(cert_request_info)));
  }

  void ContinueWithCertificate(
      net::X509Certificate* cert,
      net::SSLPrivateKey* client_private_key) override {
    ADD_FAILURE() << "Certificate supplied.";
  }

  void Kill() override {
    weak_factory_.InvalidateWeakPtrs();
    URLRequestJob::Kill();
  }

 private:
  base::WeakPtrFactory<MockClientCertURLRequestJob> weak_factory_;
};

class AsyncRevalidationDriverClientCertTest
    : public AsyncRevalidationDriverTest {
 protected:
  AsyncRevalidationDriverClientCertTest()
      : AsyncRevalidationDriverTest(
            BindCreateProtocolHandlerCallback<MockClientCertURLRequestJob>()) {}
};

// Test browser client that causes the test to fail if SelectClientCertificate()
// is called. Automatically sets itself as the browser client when constructed
// and restores the old browser client in the destructor.
class ScopedDontSelectCertificateBrowserClient
    : public TestContentBrowserClient {
 public:
  ScopedDontSelectCertificateBrowserClient() {
    old_client_ = SetBrowserClientForTesting(this);
  }

  ~ScopedDontSelectCertificateBrowserClient() override {
    SetBrowserClientForTesting(old_client_);
  }

  void SelectClientCertificate(
      WebContents* web_contents,
      net::SSLCertRequestInfo* cert_request_info,
      std::unique_ptr<ClientCertificateDelegate> delegate) override {
    ADD_FAILURE() << "SelectClientCertificate was called.";
  }

 private:
  ContentBrowserClient* old_client_;

  DISALLOW_COPY_AND_ASSIGN(ScopedDontSelectCertificateBrowserClient);
};

// Verifies that async revalidation requests do not attempt to provide client
// certificates.
TEST_F(AsyncRevalidationDriverClientCertTest, RequestRejected) {
  // Ensure that SelectClientCertificate is not called during this test.
  ScopedDontSelectCertificateBrowserClient test_client;

  // Start the request and wait for it to pause.
  driver_->StartRequest();

  // Because TestBrowserThreadBundle only uses one real thread, this is
  // sufficient to ensure that tasks posted to the "UI thread" have run.
  base::RunLoop().RunUntilIdle();

  // Check that the request aborted.
  EXPECT_FALSE(last_status().is_success());
  EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, last_status().error());
  EXPECT_TRUE(async_revalidation_complete_called());
}

// A mock URLRequestJob which simulates an SSL certificate error.
class MockSSLErrorURLRequestJob : public net::URLRequestTestJob {
 public:
  MockSSLErrorURLRequestJob(net::URLRequest* request,
                            net::NetworkDelegate* network_delegate)
      : net::URLRequestTestJob(request, network_delegate, true),
        weak_factory_(this) {}

  // net::URLRequestTestJob implementation:
  void Start() override {
    // This SSLInfo isn't really valid, but it is good enough for testing.
    net::SSLInfo ssl_info;
    ssl_info.SetCertError(net::ERR_CERT_DATE_INVALID);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::Bind(&MockSSLErrorURLRequestJob::NotifySSLCertificateError,
                   weak_factory_.GetWeakPtr(), ssl_info, false));
  }

  void ContinueDespiteLastError() override {
    ADD_FAILURE() << "ContinueDespiteLastError called.";
  }

 private:
  base::WeakPtrFactory<MockSSLErrorURLRequestJob> weak_factory_;
};

class AsyncRevalidationDriverSSLErrorTest : public AsyncRevalidationDriverTest {
 protected:
  AsyncRevalidationDriverSSLErrorTest()
      : AsyncRevalidationDriverTest(
            BindCreateProtocolHandlerCallback<MockSSLErrorURLRequestJob>()) {}
};

// Verifies that async revalidation requests do not attempt to recover from SSL
// certificate errors.
TEST_F(AsyncRevalidationDriverSSLErrorTest, RequestWithSSLErrorRejected) {
  // Start the request and wait for it to pause.
  driver_->StartRequest();
  base::RunLoop().RunUntilIdle();

  // Check that the request has been aborted.
  EXPECT_FALSE(last_status().is_success());
  EXPECT_EQ(net::ERR_ABORTED, last_status().error());
  EXPECT_TRUE(async_revalidation_complete_called());
}

// A URLRequestTestJob that sets |request_time| and |was_cached| on their
// response_info, and causes the test to fail if Read() is called.
class FromCacheURLRequestJob : public net::URLRequestTestJob {
 public:
  FromCacheURLRequestJob(net::URLRequest* request,
                         net::NetworkDelegate* network_delegate)
      : net::URLRequestTestJob(request, network_delegate, true) {}

  void GetResponseInfo(net::HttpResponseInfo* info) override {
    URLRequestTestJob::GetResponseInfo(info);
    info->request_time = base::Time::Now();
    info->was_cached = true;
  }

  int ReadRawData(net::IOBuffer* buf, int buf_size) override {
    ADD_FAILURE() << "ReadRawData() was called.";
    return URLRequestTestJob::ReadRawData(buf, buf_size);
  }

 private:
  ~FromCacheURLRequestJob() override {}

  DISALLOW_COPY_AND_ASSIGN(FromCacheURLRequestJob);
};

class AsyncRevalidationDriverFromCacheTest
    : public AsyncRevalidationDriverTest {
 protected:
  AsyncRevalidationDriverFromCacheTest()
      : AsyncRevalidationDriverTest(
            BindCreateProtocolHandlerCallback<FromCacheURLRequestJob>()) {}
};

TEST_F(AsyncRevalidationDriverFromCacheTest,
       CacheNotReadOnSuccessfulRevalidation) {
  driver_->StartRequest();
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(async_revalidation_complete_called());
}

}  // namespace
}  // namespace content
