// 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_manager.h"

#include <deque>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory_handle.h"
#include "base/pickle.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader_delegate_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/resource_messages.h"
#include "content/common/resource_request.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/appcache_info.h"
#include "content/public/common/process_type.h"
#include "content/public/common/resource_type.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_param_traits.h"
#include "net/base/load_flags.h"
#include "net/base/network_delegate.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory.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"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
#include "url/url_constants.h"

namespace content {

namespace {

// This class is a variation on URLRequestTestJob that
// returns ERR_IO_PENDING before every read, not just the first one.
class URLRequestTestDelayedCompletionJob : public net::URLRequestTestJob {
 public:
  URLRequestTestDelayedCompletionJob(net::URLRequest* request,
                                     net::NetworkDelegate* network_delegate,
                                     const std::string& response_headers,
                                     const std::string& response_data)
      : net::URLRequestTestJob(request,
                               network_delegate,
                               response_headers,
                               response_data,
                               false) {}

 private:
  bool NextReadAsync() override { return true; }
};

// A URLRequestJob implementation which sets the |async_revalidation_required|
// flag on the HttpResponseInfo object to true if the request has the
// LOAD_SUPPORT_ASYNC_REVALIDATION flag.
class AsyncRevalidationRequiredURLRequestTestJob
    : public net::URLRequestTestJob {
 public:
  AsyncRevalidationRequiredURLRequestTestJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate)
      : URLRequestTestJob(request,
                          network_delegate,
                          net::URLRequestTestJob::test_headers(),
                          std::string(),
                          false) {}

  void GetResponseInfo(net::HttpResponseInfo* info) override {
    URLRequestTestJob::GetResponseInfo(info);
    if (request()->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION)
      info->async_revalidation_required = true;
  }
};

// A URLRequestJob implementation which serves a redirect and sets the
// |async_revalidation_required| flag on the HttpResponseInfo object to true if
// the request has the LOAD_SUPPORT_ASYNC_REVALIDATION flag.
class RedirectAndRevalidateURLRequestTestJob : public net::URLRequestTestJob {
 public:
  RedirectAndRevalidateURLRequestTestJob(net::URLRequest* request,
                                         net::NetworkDelegate* network_delegate)
      : URLRequestTestJob(request,
                          network_delegate,
                          CreateRedirectHeaders(),
                          std::string(),
                          false) {}

  void GetResponseInfo(net::HttpResponseInfo* info) override {
    URLRequestTestJob::GetResponseInfo(info);
    if (request()->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION)
      info->async_revalidation_required = true;
  }

 private:
  static std::string CreateRedirectHeaders() {
    static const char kRedirectHeaders[] =
        "HTTP/1.1 302 MOVED\n"
        "Location: http://example.com/async-revalidate/from-redirect\n"
        "\n";
    return std::string(kRedirectHeaders, arraysize(kRedirectHeaders) - 1);
  }
};

class TestURLRequestJobFactory : public net::URLRequestJobFactory {
 public:
  TestURLRequestJobFactory() = default;

  // Sets the contents of the response. |headers| should have "\n" as line
  // breaks and end in "\n\n".
  void SetResponse(const std::string& headers, const std::string& data) {
    response_headers_ = headers;
    response_data_ = data;
  }

  net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
      const std::string& scheme,
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate) const override {
    std::string path = request->url().path();
    if (base::StartsWith(path, "/async-revalidate",
                         base::CompareCase::SENSITIVE)) {
      return new AsyncRevalidationRequiredURLRequestTestJob(request,
                                                            network_delegate);
    }
    if (base::StartsWith(path, "/redirect", base::CompareCase::SENSITIVE)) {
      return new RedirectAndRevalidateURLRequestTestJob(request,
                                                        network_delegate);
    }
    return new URLRequestTestDelayedCompletionJob(
        request, network_delegate, response_headers_, response_data_);
  }

  net::URLRequestJob* MaybeInterceptRedirect(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate,
      const GURL& location) const override {
    return nullptr;
  }

  net::URLRequestJob* MaybeInterceptResponse(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate) const override {
    return nullptr;
  }

  bool IsHandledProtocol(const std::string& scheme) const override {
    // If non-standard schemes need to be tested in future it will be
    // necessary to call ChildProcessSecurityPolicyImpl::
    // RegisterWebSafeScheme() for them.
    return scheme == url::kHttpScheme || scheme == url::kHttpsScheme;
  }

  bool IsHandledURL(const GURL& url) const override {
    return IsHandledProtocol(url.scheme());
  }

  bool IsSafeRedirectTarget(const GURL& location) const override {
    return false;
  }

 private:
  std::string response_headers_;
  std::string response_data_;

  DISALLOW_COPY_AND_ASSIGN(TestURLRequestJobFactory);
};

// On Windows, ResourceMsg_SetDataBuffer supplies a HANDLE which is not
// automatically released.
//
// See ResourceDispatcher::ReleaseResourcesInDataMessage.
//
// TODO(ricea): Maybe share this implementation with
// resource_dispatcher_host_unittest.cc.
void ReleaseHandlesInMessage(const IPC::Message& message) {
  if (message.type() == ResourceMsg_SetDataBuffer::ID) {
    base::PickleIterator iter(message);
    int request_id;
    CHECK(iter.ReadInt(&request_id));
    base::SharedMemoryHandle shm_handle;
    if (IPC::ParamTraits<base::SharedMemoryHandle>::Read(&message, &iter,
                                                         &shm_handle)) {
      if (base::SharedMemory::IsHandleValid(shm_handle))
        base::SharedMemory::CloseHandle(shm_handle);
    }
  }
}

// This filter just deletes any messages that are sent through it.
class BlackholeFilter : public ResourceMessageFilter {
 public:
  explicit BlackholeFilter(ResourceContext* resource_context)
      : ResourceMessageFilter(
            ChildProcessHostImpl::GenerateChildProcessUniqueId(),
            PROCESS_TYPE_RENDERER,
            nullptr,
            nullptr,
            nullptr,
            nullptr,
            nullptr,
            base::Bind(&BlackholeFilter::GetContexts, base::Unretained(this))),
        resource_context_(resource_context) {
    ChildProcessSecurityPolicyImpl::GetInstance()->Add(child_id());
  }

  bool Send(IPC::Message* msg) override {
    std::unique_ptr<IPC::Message> take_ownership(msg);
    ReleaseHandlesInMessage(*msg);
    return true;
  }

 private:
  ~BlackholeFilter() override {
    ChildProcessSecurityPolicyImpl::GetInstance()->Remove(child_id());
  }

  void GetContexts(ResourceType resource_type,
                   ResourceContext** resource_context,
                   net::URLRequestContext** request_context) {
    *resource_context = resource_context_;
    *request_context = resource_context_->GetRequestContext();
  }

  ResourceContext* resource_context_;

  DISALLOW_COPY_AND_ASSIGN(BlackholeFilter);
};

ResourceRequest CreateResourceRequest(const char* method,
                                      ResourceType type,
                                      const GURL& url) {
  ResourceRequest request;
  request.method = std::string(method);
  request.url = url;
  request.first_party_for_cookies = url;  // Bypass third-party cookie blocking.
  request.referrer_policy = blink::WebReferrerPolicyDefault;
  request.load_flags = 0;
  request.origin_pid = 0;
  request.resource_type = type;
  request.request_context = 0;
  request.appcache_host_id = kAppCacheNoHostId;
  request.download_to_file = false;
  request.should_reset_appcache = false;
  request.is_main_frame = true;
  request.parent_is_main_frame = false;
  request.parent_render_frame_id = -1;
  request.transition_type = ui::PAGE_TRANSITION_LINK;
  request.allow_download = true;
  return request;
}

class AsyncRevalidationManagerTest : public ::testing::Test {
 protected:
  AsyncRevalidationManagerTest(
      std::unique_ptr<net::TestNetworkDelegate> network_delegate)
      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
        network_delegate_(std::move(network_delegate)) {
    host_.SetLoaderDelegate(&loader_delegate_);
    browser_context_.reset(new TestBrowserContext());
    BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
    base::RunLoop().RunUntilIdle();
    ResourceContext* resource_context = browser_context_->GetResourceContext();
    filter_ = new BlackholeFilter(resource_context);
    net::URLRequestContext* request_context =
        resource_context->GetRequestContext();
    job_factory_.reset(new TestURLRequestJobFactory);
    request_context->set_job_factory(job_factory_.get());
    request_context->set_network_delegate(network_delegate_.get());
    host_.EnableStaleWhileRevalidateForTesting();
  }

  AsyncRevalidationManagerTest()
      : AsyncRevalidationManagerTest(
            base::WrapUnique(new net::TestNetworkDelegate)) {}

  void TearDown() override {
    host_.CancelRequestsForProcess(filter_->child_id());
    host_.Shutdown();
    host_.CancelRequestsForContext(browser_context_->GetResourceContext());
    browser_context_.reset();
    base::RunLoop().RunUntilIdle();
  }

  void SetResponse(const std::string& headers, const std::string& data) {
    job_factory_->SetResponse(headers, data);
  }

  // Creates a request using the current test object as the filter and
  // SubResource as the resource type.
  void MakeTestRequest(int render_view_id, int request_id, const GURL& url) {
    ResourceRequest request =
        CreateResourceRequest("GET", RESOURCE_TYPE_SUB_RESOURCE, url);
    ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
    host_.OnMessageReceived(msg, filter_.get());
    base::RunLoop().RunUntilIdle();
  }

  void EnsureSchemeIsAllowed(const std::string& scheme) {
    ChildProcessSecurityPolicyImpl* policy =
        ChildProcessSecurityPolicyImpl::GetInstance();
    if (!policy->IsWebSafeScheme(scheme))
      policy->RegisterWebSafeScheme(scheme);
  }

  content::TestBrowserThreadBundle thread_bundle_;
  std::unique_ptr<TestBrowserContext> browser_context_;
  std::unique_ptr<TestURLRequestJobFactory> job_factory_;
  scoped_refptr<BlackholeFilter> filter_;
  std::unique_ptr<net::TestNetworkDelegate> network_delegate_;
  LoaderDelegateImpl loader_delegate_;
  ResourceDispatcherHostImpl host_;
};

TEST_F(AsyncRevalidationManagerTest, SupportsAsyncRevalidation) {
  SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
  MakeTestRequest(0, 1, GURL("http://example.com/baz"));

  net::URLRequest* url_request(
      host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
  ASSERT_TRUE(url_request);

  EXPECT_TRUE(url_request->load_flags() & net::LOAD_SUPPORT_ASYNC_REVALIDATION);
}

TEST_F(AsyncRevalidationManagerTest, AsyncRevalidationNotSupportedForPOST) {
  SetResponse(net::URLRequestTestJob::test_headers(), "delay complete");
  // Create POST request.
  ResourceRequest request = CreateResourceRequest(
      "POST", RESOURCE_TYPE_SUB_RESOURCE, GURL("http://example.com/baz.php"));
  ResourceHostMsg_RequestResource msg(0, 1, request);
  host_.OnMessageReceived(msg, filter_.get());
  base::RunLoop().RunUntilIdle();

  net::URLRequest* url_request(
      host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
  ASSERT_TRUE(url_request);

  EXPECT_FALSE(url_request->load_flags() &
               net::LOAD_SUPPORT_ASYNC_REVALIDATION);
}

TEST_F(AsyncRevalidationManagerTest,
       AsyncRevalidationNotSupportedAfterRedirect) {
  static const char kRedirectHeaders[] =
      "HTTP/1.1 302 MOVED\n"
      "Location: http://example.com/var\n"
      "\n";
  SetResponse(kRedirectHeaders, "");

  MakeTestRequest(0, 1, GURL("http://example.com/baz"));

  net::URLRequest* url_request(
      host_.GetURLRequest(GlobalRequestID(filter_->child_id(), 1)));
  ASSERT_TRUE(url_request);

  EXPECT_FALSE(url_request->load_flags() &
               net::LOAD_SUPPORT_ASYNC_REVALIDATION);
}

// A NetworkDelegate that records the URLRequests as they are created.
class URLRequestRecordingNetworkDelegate : public net::TestNetworkDelegate {
 public:
  URLRequestRecordingNetworkDelegate() : requests_() {}

  net::URLRequest* NextRequest() {
    EXPECT_FALSE(requests_.empty());
    if (requests_.empty())
      return nullptr;
    net::URLRequest* request = requests_.front();
    EXPECT_TRUE(request);
    requests_.pop_front();
    return request;
  }

  bool NextRequestWasDestroyed() {
    net::URLRequest* request = requests_.front();
    requests_.pop_front();
    return request == nullptr;
  }

  bool IsEmpty() const { return requests_.empty(); }

  int OnBeforeURLRequest(net::URLRequest* request,
                         const net::CompletionCallback& callback,
                         GURL* new_url) override {
    requests_.push_back(request);
    return TestNetworkDelegate::OnBeforeURLRequest(request, callback, new_url);
  }

  void OnURLRequestDestroyed(net::URLRequest* request) override {
    for (auto*& recorded_request : requests_) {
      if (recorded_request == request)
        recorded_request = nullptr;
    }
    net::TestNetworkDelegate::OnURLRequestDestroyed(request);
  }

 private:
  std::deque<net::URLRequest*> requests_;

  DISALLOW_COPY_AND_ASSIGN(URLRequestRecordingNetworkDelegate);
};

class AsyncRevalidationManagerRecordingTest
    : public AsyncRevalidationManagerTest {
 public:
  AsyncRevalidationManagerRecordingTest()
      : AsyncRevalidationManagerTest(
            base::WrapUnique(new URLRequestRecordingNetworkDelegate)) {}

  void TearDown() override {
    EXPECT_TRUE(IsEmpty());
    AsyncRevalidationManagerTest::TearDown();
  }

  URLRequestRecordingNetworkDelegate* recording_network_delegate() const {
    return static_cast<URLRequestRecordingNetworkDelegate*>(
        network_delegate_.get());
  }

  bool NextRequestWasDestroyed() {
    return recording_network_delegate()->NextRequestWasDestroyed();
  }

  net::URLRequest* NextRequest() {
    return recording_network_delegate()->NextRequest();
  }

  bool IsEmpty() const { return recording_network_delegate()->IsEmpty(); }
};

// Verify that an async revalidation is actually created when needed.
TEST_F(AsyncRevalidationManagerRecordingTest, Issued) {
  // Create the original request.
  MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate"));

  net::URLRequest* initial_request = NextRequest();
  ASSERT_TRUE(initial_request);
  EXPECT_TRUE(initial_request->load_flags() &
              net::LOAD_SUPPORT_ASYNC_REVALIDATION);

  net::URLRequest* async_request = NextRequest();
  ASSERT_TRUE(async_request);
}

// Verify the the URL of the async revalidation matches the original request.
TEST_F(AsyncRevalidationManagerRecordingTest, URLMatches) {
  // Create the original request.
  MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate/u"));

  // Discard the original request.
  NextRequest();

  net::URLRequest* async_request = NextRequest();
  ASSERT_TRUE(async_request);
  EXPECT_EQ(GURL("http://example.com/async-revalidate/u"),
            async_request->url());
}

TEST_F(AsyncRevalidationManagerRecordingTest,
       AsyncRevalidationsDoNotSupportAsyncRevalidation) {
  // Create the original request.
  MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate"));

  // Discard the original request.
  NextRequest();

  // Get the async revalidation request.
  net::URLRequest* async_request = NextRequest();
  ASSERT_TRUE(async_request);
  EXPECT_FALSE(async_request->load_flags() &
               net::LOAD_SUPPORT_ASYNC_REVALIDATION);
}

TEST_F(AsyncRevalidationManagerRecordingTest, AsyncRevalidationsNotDuplicated) {
  // Create the original request.
  MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate"));

  // Discard the original request.
  NextRequest();

  // Get the async revalidation request.
  net::URLRequest* async_request = NextRequest();
  EXPECT_TRUE(async_request);

  // Start a second request to the same URL.
  MakeTestRequest(0, 2, GURL("http://example.com/async-revalidate"));

  // Discard the second request.
  NextRequest();

  // There should not be another async revalidation request.
  EXPECT_TRUE(IsEmpty());
}

// Async revalidation to different URLs should not be treated as duplicates.
TEST_F(AsyncRevalidationManagerRecordingTest,
       AsyncRevalidationsToSeparateURLsAreSeparate) {
  // Create two requests to two URLs.
  MakeTestRequest(0, 1, GURL("http://example.com/async-revalidate"));
  MakeTestRequest(0, 2, GURL("http://example.com/async-revalidate2"));

  net::URLRequest* initial_request = NextRequest();
  ASSERT_TRUE(initial_request);
  net::URLRequest* initial_async_revalidation = NextRequest();
  ASSERT_TRUE(initial_async_revalidation);
  net::URLRequest* second_request = NextRequest();
  ASSERT_TRUE(second_request);
  net::URLRequest* second_async_revalidation = NextRequest();
  ASSERT_TRUE(second_async_revalidation);

  EXPECT_EQ("http://example.com/async-revalidate",
            initial_request->url().spec());
  EXPECT_EQ("http://example.com/async-revalidate",
            initial_async_revalidation->url().spec());
  EXPECT_EQ("http://example.com/async-revalidate2",
            second_request->url().spec());
  EXPECT_EQ("http://example.com/async-revalidate2",
            second_async_revalidation->url().spec());
}

// Nothing after the first redirect leg has stale-while-revalidate applied.
// TODO(ricea): s-w-r should work with redirects. Change this test when it does.
TEST_F(AsyncRevalidationManagerRecordingTest, NoSWRAfterFirstRedirectLeg) {
  MakeTestRequest(0, 1, GURL("http://example.com/redirect"));

  net::URLRequest* initial_request = NextRequest();
  EXPECT_TRUE(initial_request);

  EXPECT_FALSE(initial_request->load_flags() &
               net::LOAD_SUPPORT_ASYNC_REVALIDATION);

  // An async revalidation happens for the redirect. It has no body, so it has
  // already completed.
  EXPECT_TRUE(NextRequestWasDestroyed());

  // But no others.
  EXPECT_TRUE(IsEmpty());
}

}  // namespace

}  // namespace content
