// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/renderer_host/navigation_request.h"

#include <optional>
#include <string>
#include <vector>

#include "base/containers/flat_map.h"
#include "base/functional/bind.h"
#include "base/i18n/number_formatting.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/origin_trials_controller_delegate.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_navigation_throttle.h"
#include "content/test/fenced_frame_test_utils.h"
#include "content/test/navigation_simulator_impl.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_web_contents.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/navigation/navigation_params.h"
#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h"
#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_context.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"

namespace content {

class NavigationRequestTest : public RenderViewHostImplTestHarness {
 public:
  NavigationRequestTest() : callback_result_(NavigationThrottle::DEFER) {}

  void SetUp() override {
    RenderViewHostImplTestHarness::SetUp();
    CreateNavigationHandle();
    contents()->GetPrimaryMainFrame()->InitializeRenderFrameIfNeeded();
  }

  void TearDown() override { RenderViewHostImplTestHarness::TearDown(); }

  void CancelDeferredNavigation(
      NavigationThrottle::ThrottleCheckResult result) {
    GetNavigationRequest()->CancelDeferredNavigationInternal(result);
  }

  // Helper function to call WillStartRequest on |handle|. If this function
  // returns DEFER, |callback_result_| will be set to the actual result of
  // the throttle checks when they are finished.
  void SimulateWillStartRequest() {
    was_callback_called_ = false;
    callback_result_ = NavigationThrottle::DEFER;

    // It's safe to use base::Unretained since the NavigationRequest is owned by
    // the NavigationRequestTest.
    GetNavigationRequest()->set_complete_callback_for_testing(
        base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
                       base::Unretained(this)));

    GetNavigationRequest()->WillStartRequest();
  }

  // Helper function to call WillRedirectRequest on |handle|. If this function
  // returns DEFER, |callback_result_| will be set to the actual result of the
  // throttle checks when they are finished.
  // TODO(clamy): this should also simulate that WillStartRequest was called if
  // it has not been called before.
  void SimulateWillRedirectRequest() {
    was_callback_called_ = false;
    callback_result_ = NavigationThrottle::DEFER;

    // It's safe to use base::Unretained since the NavigationRequest is owned by
    // the NavigationRequestTest.
    GetNavigationRequest()->set_complete_callback_for_testing(
        base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
                       base::Unretained(this)));

    GetNavigationRequest()->WillRedirectRequest(
        GURL(), nullptr /* post_redirect_process */);
  }

  // Helper function to call WillFailRequest on |handle|. If this function
  // returns DEFER, |callback_result_| will be set to the actual result of the
  // throttle checks when they are finished.
  void SimulateWillFailRequest(
      net::Error net_error_code,
      const std::optional<net::SSLInfo> ssl_info = std::nullopt) {
    was_callback_called_ = false;
    callback_result_ = NavigationThrottle::DEFER;
    GetNavigationRequest()->set_net_error(net_error_code);

    // It's safe to use base::Unretained since the NavigationRequest is owned by
    // the NavigationRequestTest.
    GetNavigationRequest()->set_complete_callback_for_testing(
        base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
                       base::Unretained(this)));

    GetNavigationRequest()->WillFailRequest();
  }

  // Helper function to call WillCommitWithoutUrlLoader on |handle|. If this
  // function returns DEFER, |callback_result_| will be set to the actual result
  // of the throttle checks when they are finished.
  void SimulateWillCommitWithoutUrlLoader() {
    was_callback_called_ = false;
    callback_result_ = NavigationThrottle::DEFER;

    // It's safe to use base::Unretained since the NavigationRequest is owned by
    // the NavigationRequestTest.
    GetNavigationRequest()->set_complete_callback_for_testing(
        base::BindOnce(&NavigationRequestTest::UpdateThrottleCheckResult,
                       base::Unretained(this)));

    GetNavigationRequest()->WillCommitWithoutUrlLoader();
  }

  // Whether the callback was called.
  bool was_callback_called() const { return was_callback_called_; }

  // Returns the callback_result.
  NavigationThrottle::ThrottleCheckResult callback_result() const {
    return callback_result_;
  }

  NavigationRequest::NavigationState state() {
    return GetNavigationRequest()->state();
  }

  bool call_counts_match(TestNavigationThrottle* throttle,
                         int start,
                         int redirect,
                         int failure,
                         int process,
                         int withoutUrlLoader) {
    return start == throttle->GetCallCount(
                        TestNavigationThrottle::WILL_START_REQUEST) &&
           redirect == throttle->GetCallCount(
                           TestNavigationThrottle::WILL_REDIRECT_REQUEST) &&
           failure == throttle->GetCallCount(
                          TestNavigationThrottle::WILL_FAIL_REQUEST) &&
           process == throttle->GetCallCount(
                          TestNavigationThrottle::WILL_PROCESS_RESPONSE) &&
           withoutUrlLoader ==
               throttle->GetCallCount(
                   TestNavigationThrottle::WILL_COMMIT_WITHOUT_URL_LOADER);
  }

  // Creates, register and returns a TestNavigationThrottle that will
  // synchronously return |result| on checks by default.
  TestNavigationThrottle* CreateTestNavigationThrottle(
      NavigationThrottle::ThrottleCheckResult result) {
    TestNavigationThrottle* test_throttle =
        new TestNavigationThrottle(GetNavigationRequest());
    test_throttle->SetResponseForAllMethods(TestNavigationThrottle::SYNCHRONOUS,
                                            result);
    GetNavigationRequest()->RegisterThrottleForTesting(
        std::unique_ptr<TestNavigationThrottle>(test_throttle));
    return test_throttle;
  }

  // Creates, register and returns a TestNavigationThrottle that will
  // synchronously return |result| on check for the given |method|, and
  // NavigationThrottle::PROCEED otherwise.
  TestNavigationThrottle* CreateTestNavigationThrottle(
      TestNavigationThrottle::ThrottleMethod method,
      NavigationThrottle::ThrottleCheckResult result) {
    TestNavigationThrottle* test_throttle =
        CreateTestNavigationThrottle(NavigationThrottle::PROCEED);
    test_throttle->SetResponse(method, TestNavigationThrottle::SYNCHRONOUS,
                               result);
    return test_throttle;
  }

  // TODO(zetamoo): Use NavigationSimulator instead of creating
  // NavigationRequest and NavigationHandleImpl.
  void CreateNavigationHandle() {
    auto common_params = blink::CreateCommonNavigationParams();
    common_params->initiator_origin =
        url::Origin::Create(GURL("https://initiator.example.com"));
    auto commit_params = blink::CreateCommitNavigationParams();
    commit_params->frame_policy =
        main_test_rfh()->frame_tree_node()->pending_frame_policy();
    auto request = NavigationRequest::CreateBrowserInitiated(
        main_test_rfh()->frame_tree_node(), std::move(common_params),
        std::move(commit_params), false /* was_opener_suppressed */,
        std::string() /* extra_headers */, nullptr /* frame_entry */,
        nullptr /* entry */, false /* is_form_submission */,
        nullptr /* navigation_ui_data */, std::nullopt /* impression */,
        false /* is_pdf */);
    main_test_rfh()->frame_tree_node()->TakeNavigationRequest(
        std::move(request));
    GetNavigationRequest()->StartNavigation();
  }

  FrameTreeNode* AddFrame(FrameTree& frame_tree,
                          RenderFrameHostImpl* parent,
                          int process_id,
                          int new_routing_id,
                          const blink::FramePolicy& frame_policy,
                          blink::FrameOwnerElementType owner_type) {
    return frame_tree.AddFrame(
        parent, process_id, new_routing_id,
        TestRenderFrameHost::CreateStubFrameRemote(),
        TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
        TestRenderFrameHost::CreateStubPolicyContainerBindParams(),
        TestRenderFrameHost::CreateStubAssociatedInterfaceProviderReceiver(),
        blink::mojom::TreeScopeType::kDocument, std::string(), "uniqueName0",
        false, blink::LocalFrameToken(), base::UnguessableToken::Create(),
        blink::DocumentToken(), frame_policy,
        blink::mojom::FrameOwnerProperties(), false, owner_type,
        /*is_dummy_frame_for_inner_tree=*/false);
  }

 private:
  // The callback provided to NavigationRequest::WillStartRequest,
  // NavigationRequest::WillRedirectRequest, and
  // NavigationRequest::WillFailRequest during the tests.
  bool UpdateThrottleCheckResult(
      NavigationThrottle::ThrottleCheckResult result) {
    callback_result_ = result;
    was_callback_called_ = true;
    return true;
  }

  // This must be called after CreateNavigationHandle().
  NavigationRequest* GetNavigationRequest() {
    return main_test_rfh()->frame_tree_node()->navigation_request();
  }

  bool was_callback_called_ = false;
  NavigationThrottle::ThrottleCheckResult callback_result_;
};

// Checks that the request_context_type is properly set.
// Note: can be extended to cover more internal members.
TEST_F(NavigationRequestTest, SimpleDataChecksRedirectAndProcess) {
  const GURL kUrl1 = GURL("http://chromium.org");
  const GURL kUrl2 = GURL("http://google.com");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
  navigation->Start();
  EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
            NavigationRequest::From(navigation->GetNavigationHandle())
                ->request_context_type());
  EXPECT_EQ(net::HttpConnectionInfo::kUNKNOWN,
            navigation->GetNavigationHandle()->GetConnectionInfo());

  navigation->set_http_connection_info(net::HttpConnectionInfo::kHTTP1_1);
  navigation->Redirect(kUrl2);
  EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
            NavigationRequest::From(navigation->GetNavigationHandle())
                ->request_context_type());
  EXPECT_EQ(net::HttpConnectionInfo::kHTTP1_1,
            navigation->GetNavigationHandle()->GetConnectionInfo());

  navigation->set_http_connection_info(net::HttpConnectionInfo::kQUIC_35);
  navigation->ReadyToCommit();
  EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
            NavigationRequest::From(navigation->GetNavigationHandle())
                ->request_context_type());
  EXPECT_EQ(net::HttpConnectionInfo::kQUIC_35,
            navigation->GetNavigationHandle()->GetConnectionInfo());
}

TEST_F(NavigationRequestTest, SimpleDataCheckNoRedirect) {
  const GURL kUrl = GURL("http://chromium.org");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
  navigation->Start();
  EXPECT_EQ(net::HttpConnectionInfo::kUNKNOWN,
            navigation->GetNavigationHandle()->GetConnectionInfo());

  navigation->set_http_connection_info(net::HttpConnectionInfo::kQUIC_35);
  navigation->ReadyToCommit();
  EXPECT_EQ(net::HttpConnectionInfo::kQUIC_35,
            navigation->GetNavigationHandle()->GetConnectionInfo());
}

TEST_F(NavigationRequestTest, SimpleDataChecksFailure) {
  const GURL kUrl = GURL("http://chromium.org");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
  navigation->Start();
  EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
            NavigationRequest::From(navigation->GetNavigationHandle())
                ->request_context_type());
  EXPECT_EQ(net::HttpConnectionInfo::kUNKNOWN,
            navigation->GetNavigationHandle()->GetConnectionInfo());

  navigation->Fail(net::ERR_CERT_DATE_INVALID);
  EXPECT_EQ(blink::mojom::RequestContextType::LOCATION,
            NavigationRequest::From(navigation->GetNavigationHandle())
                ->request_context_type());
  EXPECT_EQ(net::ERR_CERT_DATE_INVALID,
            navigation->GetNavigationHandle()->GetNetErrorCode());
}

// Checks that a navigation deferred during WillStartRequest can be properly
// cancelled.
TEST_F(NavigationRequestTest, CancelDeferredWillStart) {
  TestNavigationThrottle* test_throttle =
      CreateTestNavigationThrottle(NavigationThrottle::DEFER);
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0, 0));

  // Simulate WillStartRequest. The request should be deferred. The callback
  // should not have been called.
  SimulateWillStartRequest();
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
  EXPECT_FALSE(was_callback_called());
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0, 0));

  // Cancel the request. The callback should have been called.
  CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
  EXPECT_EQ(NavigationRequest::CANCELING, state());
  EXPECT_TRUE(was_callback_called());
  EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0, 0));
}

// Checks that a navigation deferred during WillRedirectRequest can be properly
// cancelled.
TEST_F(NavigationRequestTest, CancelDeferredWillRedirect) {
  TestNavigationThrottle* test_throttle =
      CreateTestNavigationThrottle(NavigationThrottle::DEFER);
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0, 0));

  // Simulate WillRedirectRequest. The request should be deferred. The callback
  // should not have been called.
  SimulateWillRedirectRequest();
  EXPECT_EQ(NavigationRequest::WILL_REDIRECT_REQUEST, state());
  EXPECT_FALSE(was_callback_called());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0, 0));

  // Cancel the request. The callback should have been called.
  CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
  EXPECT_EQ(NavigationRequest::CANCELING, state());
  EXPECT_TRUE(was_callback_called());
  EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 1, 0, 0, 0));
}

// Checks that a navigation deferred during WillFailRequest can be properly
// cancelled.
TEST_F(NavigationRequestTest, CancelDeferredWillFail) {
  TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
      TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0, 0));

  // Simulate WillStartRequest.
  SimulateWillStartRequest();
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0, 0));

  // Simulate WillFailRequest. The request should be deferred. The callback
  // should not have been called.
  SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
  EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
  EXPECT_FALSE(was_callback_called());
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0, 0));

  // Cancel the request. The callback should have been called.
  CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
  EXPECT_EQ(NavigationRequest::CANCELING, state());
  EXPECT_TRUE(was_callback_called());
  EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0, 0));
}

// Checks that a navigation deferred can be canceled and not ignored.
TEST_F(NavigationRequestTest, CancelDeferredWillRedirectNoIgnore) {
  TestNavigationThrottle* test_throttle =
      CreateTestNavigationThrottle(NavigationThrottle::DEFER);
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0, 0));

  // Simulate WillStartRequest. The request should be deferred. The callback
  // should not have been called.
  SimulateWillStartRequest();
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0, 0));

  // Cancel the request. The callback should have been called with CANCEL, and
  // not CANCEL_AND_IGNORE.
  CancelDeferredNavigation(NavigationThrottle::CANCEL);
  EXPECT_EQ(NavigationRequest::CANCELING, state());
  EXPECT_TRUE(was_callback_called());
  EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0, 0));
}

// Checks that a navigation deferred by WillFailRequest can be canceled and not
// ignored.
TEST_F(NavigationRequestTest, CancelDeferredWillFailNoIgnore) {
  TestNavigationThrottle* test_throttle = CreateTestNavigationThrottle(
      TestNavigationThrottle::WILL_FAIL_REQUEST, NavigationThrottle::DEFER);
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0, 0));

  // Simulate WillStartRequest.
  SimulateWillStartRequest();
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 0, 0, 0));

  // Simulate WillFailRequest. The request should be deferred. The callback
  // should not have been called.
  SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID);
  EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state());
  EXPECT_FALSE(was_callback_called());
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0, 0));

  // Cancel the request. The callback should have been called with CANCEL, and
  // not CANCEL_AND_IGNORE.
  CancelDeferredNavigation(NavigationThrottle::CANCEL);
  EXPECT_EQ(NavigationRequest::CANCELING, state());
  EXPECT_TRUE(was_callback_called());
  EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
  EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0, 0));
}

// Checks that a navigation deferred during WillCommitWithoutUrlLoader can be
// properly cancelled.
TEST_F(NavigationRequestTest, CancelDeferredWillCommitWithoutUrlLoader) {
  TestNavigationThrottle* test_throttle =
      CreateTestNavigationThrottle(NavigationThrottle::DEFER);
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, state());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0, 0));

  // Simulate WillCommitWithoutUrlLoader. The request should be deferred. The
  // callback should not have been called.
  SimulateWillCommitWithoutUrlLoader();
  EXPECT_EQ(NavigationRequest::WILL_COMMIT_WITHOUT_URL_LOADER, state());
  EXPECT_FALSE(was_callback_called());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0, 1));

  // Cancel the request. The callback should have been called.
  CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
  EXPECT_EQ(NavigationRequest::CANCELING, state());
  EXPECT_TRUE(was_callback_called());
  EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
  EXPECT_TRUE(call_counts_match(test_throttle, 0, 0, 0, 0, 1));
}

// Checks that data from the SSLInfo passed into SimulateWillStartRequest() is
// stored on the handle.
TEST_F(NavigationRequestTest, WillFailRequestSetsSSLInfo) {
  uint16_t cipher_suite = 0xc02f;  // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  int connection_status = 0;
  net::SSLConnectionStatusSetCipherSuite(cipher_suite, &connection_status);

  // Set some test values.
  net::SSLInfo ssl_info;
  ssl_info.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
  ssl_info.connection_status = connection_status;

  const GURL kUrl = GURL("https://chromium.org");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
  navigation->SetSSLInfo(ssl_info);
  navigation->Fail(net::ERR_CERT_DATE_INVALID);

  EXPECT_EQ(net::CERT_STATUS_AUTHORITY_INVALID,
            navigation->GetNavigationHandle()->GetSSLInfo()->cert_status);
  EXPECT_EQ(connection_status,
            navigation->GetNavigationHandle()->GetSSLInfo()->connection_status);
}

TEST_F(NavigationRequestTest, SharedStorageWritable) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitWithFeatures(
      /*enabled_features=*/{blink::features::kSharedStorageAPI,
                            blink::features::kSharedStorageAPIM118,
                            blink::features::kFencedFrames},
      /*disabled_features=*/{});

  // Create and start a simulated `NavigationRequest` for the main frame.
  GURL main_url = GURL("https://main.com");
  auto main_navigation =
      NavigationSimulatorImpl::CreateBrowserInitiated(main_url, contents());
  main_navigation->Start();
  main_navigation->ReadyToCommit();

  // Verify that the main frame's `NavigationRequest` will not be
  // SharedStorageWritable.
  ASSERT_TRUE(main_navigation->GetNavigationHandle());
  EXPECT_FALSE(main_navigation->GetNavigationHandle()
                   ->shared_storage_writable_eligible());

  // Commit the navigation.
  main_navigation->Commit();

  // Append a child frame and set its `shared_storage_writable` attribute to
  // true.
  TestRenderFrameHost* child_frame = static_cast<TestRenderFrameHost*>(
      content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"));
  blink::mojom::IframeAttributesPtr child_attributes =
      blink::mojom::IframeAttributes::New();
  child_attributes->shared_storage_writable_opted_in = true;
  child_frame->frame_tree_node()->SetAttributes(std::move(child_attributes));

  // Create and start a simulated `NavigationRequest` for the child frame.
  GURL a_url = GURL("https://a.com");
  auto child_navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(a_url, child_frame);
  child_navigation->Start();

  // Verify that the `NavigationRequest` will be SharedStorageWritable.
  ASSERT_TRUE(child_navigation->GetNavigationHandle());
  EXPECT_TRUE(child_navigation->GetNavigationHandle()
                  ->shared_storage_writable_eligible());

  // Commit the navigation.
  child_navigation->Commit();

  // Append a fenced frame and give it permission to access Shared Storage.
  TestRenderFrameHost* fenced_frame_root = static_cast<TestRenderFrameHost*>(
      content::RenderFrameHostTester::For(main_rfh())->AppendFencedFrame());
  FrameTreeNode* fenced_frame_node =
      static_cast<RenderFrameHostImpl*>(fenced_frame_root)->frame_tree_node();
  FencedFrameConfig new_config = FencedFrameConfig(GURL("about:blank"));
  new_config.AddEffectiveEnabledPermissionForTesting(
      blink::mojom::PermissionsPolicyFeature::kSharedStorage);
  FencedFrameProperties new_props = FencedFrameProperties(new_config);
  fenced_frame_node->set_fenced_frame_properties(new_props);
  fenced_frame_root->ResetPermissionsPolicy();

  // Append a child frame to the fenced frame root and set its
  // `shared_storage_writable` attribute to true.
  TestRenderFrameHost* child_of_fenced_frame =
      static_cast<TestRenderFrameHost*>(
          fenced_frame_root->AppendChild("child_of_fenced"));
  blink::mojom::IframeAttributesPtr child_of_fenced_frame_attributes =
      blink::mojom::IframeAttributes::New();
  child_of_fenced_frame_attributes->shared_storage_writable_opted_in = true;
  child_of_fenced_frame->frame_tree_node()->SetAttributes(
      std::move(child_of_fenced_frame_attributes));

  // Create and start a simulated `NavigationRequest` for the child frame.
  GURL b_url = GURL("https://b.com");
  auto child_of_fenced_frame_navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(b_url,
                                                       child_of_fenced_frame);
  child_of_fenced_frame_navigation->Start();

  // Verify that the `NavigationRequest` will be SharedStorageWritable.
  ASSERT_TRUE(child_of_fenced_frame_navigation->GetNavigationHandle());
  EXPECT_TRUE(child_of_fenced_frame_navigation->GetNavigationHandle()
                  ->shared_storage_writable_eligible());

  // Commit the navigation.
  child_of_fenced_frame_navigation->Commit();
}

namespace {

// Helper throttle which checks that it can access NavigationHandle's
// RenderFrameHost in WillFailRequest() and then defers the failure.
class GetRenderFrameHostOnFailureNavigationThrottle
    : public NavigationThrottle {
 public:
  explicit GetRenderFrameHostOnFailureNavigationThrottle(
      NavigationHandle* handle)
      : NavigationThrottle(handle) {}

  GetRenderFrameHostOnFailureNavigationThrottle(
      const GetRenderFrameHostOnFailureNavigationThrottle&) = delete;
  GetRenderFrameHostOnFailureNavigationThrottle& operator=(
      const GetRenderFrameHostOnFailureNavigationThrottle&) = delete;

  ~GetRenderFrameHostOnFailureNavigationThrottle() override = default;

  NavigationThrottle::ThrottleCheckResult WillFailRequest() override {
    EXPECT_TRUE(navigation_handle()->GetRenderFrameHost());
    return NavigationThrottle::DEFER;
  }

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

class ThrottleTestContentBrowserClient : public ContentBrowserClient {
  std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation(
      NavigationHandle* navigation_handle) override {
    std::vector<std::unique_ptr<NavigationThrottle>> throttle;
    throttle.push_back(
        std::make_unique<GetRenderFrameHostOnFailureNavigationThrottle>(
            navigation_handle));
    return throttle;
  }
};

}  // namespace

// Verify that the NavigationHandle::GetRenderFrameHost() can be retrieved by a
// throttle in WillFailRequest(), as well as after deferring the failure.  This
// is allowed, since at that point the final RenderFrameHost will have already
// been chosen. See https://crbug.com/817881.
TEST_F(NavigationRequestTest, WillFailRequestCanAccessRenderFrameHost) {
  std::unique_ptr<ContentBrowserClient> client(
      new ThrottleTestContentBrowserClient);
  ContentBrowserClient* old_browser_client =
      SetBrowserClientForTesting(client.get());

  const GURL kUrl = GURL("http://chromium.org");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
  navigation->SetAutoAdvance(false);
  navigation->Start();
  navigation->Fail(net::ERR_CERT_DATE_INVALID);
  EXPECT_EQ(
      NavigationRequest::WILL_FAIL_REQUEST,
      NavigationRequest::From(navigation->GetNavigationHandle())->state());
  EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());
  NavigationRequest::From(navigation->GetNavigationHandle())
      ->GetNavigationThrottleRunnerForTesting()
      ->CallResumeForTesting();
  EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost());

  SetBrowserClientForTesting(old_browser_client);
}

TEST_F(NavigationRequestTest, PolicyContainerInheritance) {
  struct TestCase {
    const char* url;
    bool expect_inherit;
  } cases[]{{"about:blank", true},
            {"data:text/plain,hello", true},
            {"file://local", false},
            {"http://chromium.org", false}};

  const GURL kUrl1 = GURL("http://chromium.org");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl1, main_rfh());
  navigation->Commit();

  for (auto test : cases) {
    // We navigate child frames because the BlockedSchemeNavigationThrottle
    // restricts navigations in the main frame.
    auto* child_frame = static_cast<TestRenderFrameHost*>(
        content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"));

    // We set the referrer policy of the frame to "always". We then create a new
    // navigation, set as initiator the frame itself, start the navigation, and
    // change the referrer policy of the frame to "never". After we commit the
    // navigation:
    // - If navigating to a local scheme, the target frame should have inherited
    //   the referrer policy of the initiator ("always").
    // - If navigating to a non-local scheme, the target frame should have a new
    //   policy container (hence referrer policy set to "default").
    const GURL kUrl = GURL(test.url);
    navigation =
        NavigationSimulatorImpl::CreateRendererInitiated(kUrl, child_frame);
    static_cast<blink::mojom::PolicyContainerHost*>(
        child_frame->policy_container_host())
        ->SetReferrerPolicy(network::mojom::ReferrerPolicy::kAlways);
    navigation->SetInitiatorFrame(child_frame);
    navigation->Start();
    static_cast<blink::mojom::PolicyContainerHost*>(
        child_frame->policy_container_host())
        ->SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
    navigation->Commit();
    EXPECT_EQ(
        test.expect_inherit ? network::mojom::ReferrerPolicy::kAlways
                            : network::mojom::ReferrerPolicy::kDefault,
        static_cast<RenderFrameHostImpl*>(navigation->GetFinalRenderFrameHost())
            ->policy_container_host()
            ->referrer_policy());
  }
}

TEST_F(NavigationRequestTest, DnsAliasesCanBeAccessed) {
  // Create simulated NavigationRequest for the URL, which has aliases.
  const GURL kUrl = GURL("http://chromium.org");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
  std::vector<std::string> dns_aliases({"alias1", "alias2"});
  navigation->SetResponseDnsAliases(std::move(dns_aliases));

  // Start the navigation.
  navigation->Start();
  EXPECT_EQ(net::HttpConnectionInfo::kUNKNOWN,
            navigation->GetNavigationHandle()->GetConnectionInfo());

  // Commit the navigation.
  navigation->set_http_connection_info(net::HttpConnectionInfo::kQUIC_35);
  navigation->ReadyToCommit();
  EXPECT_EQ(net::HttpConnectionInfo::kQUIC_35,
            navigation->GetNavigationHandle()->GetConnectionInfo());

  // Verify that the aliases are accessible from the NavigationRequest.
  EXPECT_THAT(navigation->GetNavigationHandle()->GetDnsAliases(),
              testing::ElementsAre("alias1", "alias2"));
}

TEST_F(NavigationRequestTest, NoDnsAliases) {
  // Create simulated NavigationRequest for the URL, which does not
  // have aliases. (Note the empty alias list.)
  const GURL kUrl = GURL("http://chromium.org");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
  std::vector<std::string> dns_aliases;
  navigation->SetResponseDnsAliases(std::move(dns_aliases));

  // Start the navigation.
  navigation->Start();
  EXPECT_EQ(net::HttpConnectionInfo::kUNKNOWN,
            navigation->GetNavigationHandle()->GetConnectionInfo());

  // Commit the navigation.
  navigation->set_http_connection_info(net::HttpConnectionInfo::kQUIC_35);
  navigation->ReadyToCommit();
  EXPECT_EQ(net::HttpConnectionInfo::kQUIC_35,
            navigation->GetNavigationHandle()->GetConnectionInfo());

  // Verify that there are no aliases in the NavigationRequest.
  EXPECT_TRUE(navigation->GetNavigationHandle()->GetDnsAliases().empty());
}

TEST_F(NavigationRequestTest, StorageKeyToCommit) {
  TestRenderFrameHost* child_document = static_cast<TestRenderFrameHost*>(
      content::RenderFrameHostTester::For(main_rfh())->AppendChild(""));
  auto attributes = child_document->frame_tree_node()->attributes_->Clone();
  attributes->credentialless = true;
  child_document->frame_tree_node()->SetAttributes(std::move(attributes));

  const GURL kUrl = GURL("http://chromium.org");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, child_document);
  navigation->ReadyToCommit();
  NavigationRequest* request =
      NavigationRequest::From(navigation->GetNavigationHandle());
  EXPECT_TRUE(request->commit_params().storage_key.nonce().has_value());
  EXPECT_EQ(child_document->GetPage().credentialless_iframes_nonce(),
            request->commit_params().storage_key.nonce().value());

  navigation->Commit();
  child_document =
      static_cast<TestRenderFrameHost*>(navigation->GetFinalRenderFrameHost());
  EXPECT_TRUE(child_document->IsCredentialless());
  EXPECT_EQ(blink::StorageKey::CreateWithNonce(
                url::Origin::Create(kUrl),
                child_document->GetPage().credentialless_iframes_nonce()),
            child_document->GetStorageKey());
}

// Test that the StorageKey's value is correctly affected by the
// RuntimeFeatureStateContext.
TEST_F(NavigationRequestTest, RuntimeFeatureStateStorageKey) {
  base::test::ScopedFeatureList scoped_feature_list;
  // Because the StorageKey's (and Storage Partitioning's) usage of
  // RuntimeFeatureState is only meant to disable partitioning (i.e.:
  // first-party only), we need the make sure the net::features is always
  // enabled.
  scoped_feature_list.InitAndEnableFeature(
      net::features::kThirdPartyStoragePartitioning);

  // This lambda performs the navigation and compares the commit_params'
  // StorageKey against the passed in one. If `disable_sp` is true then it will
  // also enable the deprecation trial feature in the RFSC. It returns
  // the new TestRenderFrameHost* to the navigated frame.
  auto NavigateAndCompareKeys =
      [](NavigationSimulator* navigation, const blink::StorageKey& key,
         bool disable_sp = false) -> TestRenderFrameHost* {
    navigation->Start();

    NavigationRequest* request =
        NavigationRequest::From(navigation->GetNavigationHandle());

    if (disable_sp) {
      request->GetMutableRuntimeFeatureStateContext()
          .SetDisableThirdPartyStoragePartitioningEnabled(true);
    }

    navigation->ReadyToCommit();

    EXPECT_EQ(key, request->commit_params().storage_key);

    navigation->Commit();
    return static_cast<TestRenderFrameHost*>(
        navigation->GetFinalRenderFrameHost());
  };

  // Throughout the test we'll be creating a frame tree with a main frame, a
  // child frame, and a grandchild frame.
  GURL main_url("https://main.com");
  GURL b_url("https://b.com");
  GURL c_url("https://c.com");

  url::Origin main_origin = url::Origin::Create(main_url);
  url::Origin b_origin = url::Origin::Create(b_url);
  url::Origin c_origin = url::Origin::Create(c_url);

  // Begin by testing with Storage Partitioning enabled.

  auto main_navigation =
      NavigationSimulatorImpl::CreateBrowserInitiated(main_url, contents());

  // By definition the main frame's StorageKey will always be first party
  blink::StorageKey main_frame_key =
      blink::StorageKey::CreateFirstParty(main_origin);

  NavigateAndCompareKeys(main_navigation.get(), main_frame_key);

  TestRenderFrameHost* child_frame = static_cast<TestRenderFrameHost*>(
      content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"));

  auto child_navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame);

  // The child and grandchild should both be third-party keys.
  blink::StorageKey child_frame_key =
      blink::StorageKey::Create(b_origin, net::SchemefulSite(main_origin),
                                blink::mojom::AncestorChainBit::kCrossSite);

  child_frame = NavigateAndCompareKeys(child_navigation.get(), child_frame_key);

  TestRenderFrameHost* grandchild_frame =
      child_frame->AppendChild("grandchild");

  auto grandchild_navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame);

  blink::StorageKey grandchild_frame_key =
      blink::StorageKey::Create(c_origin, net::SchemefulSite(main_origin),
                                blink::mojom::AncestorChainBit::kCrossSite);
  grandchild_frame =
      NavigateAndCompareKeys(grandchild_navigation.get(), grandchild_frame_key);

  // Only the RuntimeFeatureStateContext in the main frame's matters. So
  // disabling Storage Partitioning in the child_frame shouldn't affect the
  // child's or the grandchild's StorageKey.
  child_navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame);

  child_frame = NavigateAndCompareKeys(child_navigation.get(), child_frame_key,
                                       /*disable_sp=*/true);

  grandchild_frame = child_frame->AppendChild("grandchild");

  grandchild_navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame);

  grandchild_frame =
      NavigateAndCompareKeys(grandchild_navigation.get(), grandchild_frame_key);

  // Disabling Storage Partitioning on the main frame should cause the child's
  // and grandchild's StorageKey to be first-party.
  main_navigation =
      NavigationSimulatorImpl::CreateBrowserInitiated(main_url, contents());

  NavigateAndCompareKeys(main_navigation.get(), main_frame_key,
                         /*disable_sp=*/true);

  child_frame = static_cast<TestRenderFrameHost*>(
      content::RenderFrameHostTester::For(main_rfh())->AppendChild("child"));

  child_navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame);

  // The child and grandchild should both be first-party keys.
  blink::StorageKey child_frame_key_1p =
      blink::StorageKey::CreateFirstParty(b_origin);

  child_frame =
      NavigateAndCompareKeys(child_navigation.get(), child_frame_key_1p);

  grandchild_frame = child_frame->AppendChild("grandchild");

  blink::StorageKey grandchild_frame_key_1p =
      blink::StorageKey::CreateFirstParty(c_origin);

  grandchild_navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame);

  grandchild_frame = NavigateAndCompareKeys(grandchild_navigation.get(),
                                            grandchild_frame_key_1p);
}

TEST_F(NavigationRequestTest,
       NavigationToCredentiallessDocumentNetworkIsolationInfo) {
  auto* child_frame = static_cast<TestRenderFrameHost*>(
      content::RenderFrameHostTester::For(main_test_rfh())
          ->AppendChild("child"));
  auto attributes = child_frame->frame_tree_node()->attributes_->Clone();
  attributes->credentialless = true;
  child_frame->frame_tree_node()->SetAttributes(std::move(attributes));

  std::unique_ptr<NavigationSimulator> navigation =
      NavigationSimulator::CreateRendererInitiated(
          GURL("https://example.com/navigation.html"), child_frame);
  navigation->ReadyToCommit();

  EXPECT_EQ(main_test_rfh()->GetPage().credentialless_iframes_nonce(),
            static_cast<NavigationRequest*>(navigation->GetNavigationHandle())
                ->isolation_info_for_subresources()
                .network_isolation_key()
                .GetNonce());
  EXPECT_EQ(main_test_rfh()->GetPage().credentialless_iframes_nonce(),
            static_cast<NavigationRequest*>(navigation->GetNavigationHandle())
                ->GetIsolationInfo()
                .network_isolation_key()
                .GetNonce());
}

class ScopedIsolatedAppBrowserClient : public ContentBrowserClient {
 public:
  explicit ScopedIsolatedAppBrowserClient(const GURL& isolated_url)
      : isolated_host_(isolated_url.host()),
        old_client_(SetBrowserClientForTesting(this)) {}

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

  bool ShouldUrlUseApplicationIsolationLevel(BrowserContext* browser_context,
                                             const GURL& url) override {
    return url.host() == isolated_host_;
  }

 private:
  std::string isolated_host_;
  raw_ptr<ContentBrowserClient> old_client_;
};

TEST_F(NavigationRequestTest, IsolatedAppPolicyInjection) {
  const GURL kUrl = GURL("https://chromium.org");
  ScopedIsolatedAppBrowserClient client(kUrl);

  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());
  navigation->ReadyToCommit();

  // Validate the COOP/COEP headers.
  const PolicyContainerPolicies& policies =
      navigation->GetNavigationHandle()->GetPolicyContainerPolicies();
  EXPECT_EQ(network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep,
            policies.cross_origin_opener_policy.value);
  EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp,
            policies.cross_origin_embedder_policy.value);

  // Validate CSP.
  EXPECT_EQ(1UL, policies.content_security_policies.size());
  const auto& csp = policies.content_security_policies[0];
  EXPECT_EQ(11UL, csp->raw_directives.size());
  using Directive = network::mojom::CSPDirectiveName;
  EXPECT_EQ("'none'", csp->raw_directives[Directive::BaseURI]);
  EXPECT_EQ("'none'", csp->raw_directives[Directive::ObjectSrc]);
  EXPECT_EQ("'self'", csp->raw_directives[Directive::DefaultSrc]);
  EXPECT_EQ("'self' https: blob: data:",
            csp->raw_directives[Directive::FrameSrc]);
  EXPECT_EQ("'self' https: wss: blob: data:",
            csp->raw_directives[Directive::ConnectSrc]);
  EXPECT_EQ("'self' 'wasm-unsafe-eval'",
            csp->raw_directives[Directive::ScriptSrc]);
  EXPECT_EQ("'self' https: blob: data:",
            csp->raw_directives[Directive::ImgSrc]);
  EXPECT_EQ("'self' https: blob: data:",
            csp->raw_directives[Directive::MediaSrc]);
  EXPECT_EQ("'self' blob: data:", csp->raw_directives[Directive::FontSrc]);
  EXPECT_EQ("'self' 'unsafe-inline'", csp->raw_directives[Directive::StyleSrc]);
  EXPECT_EQ("'script'", csp->raw_directives[Directive::RequireTrustedTypesFor]);
}

TEST_F(NavigationRequestTest, UpdatePrivateNetworkRequestPolicy) {
  std::unique_ptr<NavigationSimulator> navigation =
      NavigationSimulator::CreateRendererInitiated(GURL("https://example.com/"),
                                                   main_test_rfh());
  navigation->SetSocketAddress(net::IPEndPoint());

  navigation->ReadyToCommit();
  NavigationRequest* request =
      NavigationRequest::From(navigation->GetNavigationHandle());
  EXPECT_FALSE(request->GetSocketAddress().address().IsValid());
  navigation->Commit();
}

// Test that the required CSP of every frame is computed/inherited correctly and
// that the Sec-Required-CSP header is set.
class CSPEmbeddedEnforcementUnitTest : public NavigationRequestTest {
 protected:
  TestRenderFrameHost* main_rfh() {
    return static_cast<TestRenderFrameHost*>(NavigationRequestTest::main_rfh());
  }

  // Simulate the |csp| attribute being set in |rfh|'s frame. Then navigate it.
  // Returns the request's Sec-Required-CSP header.
  std::string NavigateWithRequiredCSP(TestRenderFrameHost** rfh,
                                      std::string required_csp) {
    TestRenderFrameHost* document = *rfh;

    if (!required_csp.empty()) {
      auto headers =
          base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
      headers->SetHeader("Content-Security-Policy", required_csp);
      std::vector<network::mojom::ContentSecurityPolicyPtr> policies;
      network::AddContentSecurityPolicyFromHeaders(
          *headers, GURL("https://example.com/"), &policies);
      auto attributes = document->frame_tree_node()->attributes_->Clone();
      // Set csp value.
      attributes->parsed_csp_attribute = std::move(policies[0]);
      document->frame_tree_node()->SetAttributes(std::move(attributes));
    }

    // Chrome blocks a document navigating to a URL if more than one of its
    // ancestors have the same URL. Use a different URL every time, to
    // avoid blocking navigation of the grandchild frame.
    static int nonce = 0;
    GURL url("https://www.example.com" + base::NumberToString(nonce++));

    auto navigation =
        content::NavigationSimulator::CreateRendererInitiated(url, *rfh);
    navigation->Start();
    NavigationRequest* request =
        NavigationRequest::From(navigation->GetNavigationHandle());
    std::string sec_required_csp;
    request->GetRequestHeaders().GetHeader("sec-required-csp",
                                           &sec_required_csp);

    // Complete the navigation so that the required csp is stored in the
    // RenderFrameHost, so that when we will add children to this document they
    // will be able to get the parent's required csp (and hence also test that
    // the whole logic works).
    auto response_headers =
        base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
    response_headers->SetHeader("Allow-CSP-From", "*");
    navigation->SetResponseHeaders(response_headers);
    navigation->Commit();

    *rfh = static_cast<TestRenderFrameHost*>(
        navigation->GetFinalRenderFrameHost());

    return sec_required_csp;
  }

  TestRenderFrameHost* AddChild(TestRenderFrameHost* parent) {
    return static_cast<TestRenderFrameHost*>(
        content::RenderFrameHostTester::For(parent)->AppendChild(""));
  }
};

TEST_F(CSPEmbeddedEnforcementUnitTest, TopLevel) {
  TestRenderFrameHost* top_document = main_rfh();
  std::string sec_required_csp = NavigateWithRequiredCSP(&top_document, "");
  EXPECT_EQ("", sec_required_csp);
  EXPECT_FALSE(top_document->required_csp());
}

TEST_F(CSPEmbeddedEnforcementUnitTest, ChildNoCSP) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  std::string sec_required_csp = NavigateWithRequiredCSP(&child_document, "");
  EXPECT_EQ("", sec_required_csp);
  EXPECT_FALSE(child_document->required_csp());
}

TEST_F(CSPEmbeddedEnforcementUnitTest, ChildWithCSP) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  std::string sec_required_csp =
      NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  EXPECT_EQ("script-src 'none'", sec_required_csp);
  EXPECT_TRUE(child_document->required_csp());
  EXPECT_EQ("script-src 'none'",
            child_document->required_csp()->header->header_value);
}

TEST_F(CSPEmbeddedEnforcementUnitTest, ChildSiblingNoCSP) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  TestRenderFrameHost* sibling_document = AddChild(top_document);
  std::string sec_required_csp = NavigateWithRequiredCSP(&sibling_document, "");
  EXPECT_FALSE(sibling_document->required_csp());
}

TEST_F(CSPEmbeddedEnforcementUnitTest, ChildSiblingCSP) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  TestRenderFrameHost* sibling_document = AddChild(top_document);
  std::string sec_required_csp =
      NavigateWithRequiredCSP(&sibling_document, "script-src 'none'");
  EXPECT_EQ("script-src 'none'", sec_required_csp);
  EXPECT_TRUE(sibling_document->required_csp());
  EXPECT_EQ("script-src 'none'",
            sibling_document->required_csp()->header->header_value);
}

TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildNoCSP) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  TestRenderFrameHost* grand_child_document = AddChild(child_document);
  std::string sec_required_csp =
      NavigateWithRequiredCSP(&grand_child_document, "");
  EXPECT_EQ("script-src 'none'", sec_required_csp);
  EXPECT_TRUE(grand_child_document->required_csp());
  EXPECT_EQ("script-src 'none'",
            grand_child_document->required_csp()->header->header_value);
}

TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildSameCSP) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  TestRenderFrameHost* grand_child_document = AddChild(child_document);
  std::string sec_required_csp =
      NavigateWithRequiredCSP(&grand_child_document, "script-src 'none'");
  EXPECT_EQ("script-src 'none'", sec_required_csp);
  EXPECT_TRUE(grand_child_document->required_csp());
  EXPECT_EQ("script-src 'none'",
            grand_child_document->required_csp()->header->header_value);
}

TEST_F(CSPEmbeddedEnforcementUnitTest, GrandChildDifferentCSP) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  TestRenderFrameHost* grand_child_document = AddChild(child_document);
  std::string sec_required_csp =
      NavigateWithRequiredCSP(&grand_child_document, "img-src 'none'");

  // This seems weird, but it is the intended behaviour according to the spec.
  // The problem is that "script-src 'none'" does not subsume "img-src 'none'",
  // so "img-src 'none'" on the grandchild is an invalid csp attribute, and we
  // just discard it in favour of the parent's csp attribute.
  //
  // This should probably be fixed in the specification:
  // https://github.com/w3c/webappsec-cspee/pull/11
  EXPECT_EQ("script-src 'none'", sec_required_csp);
  EXPECT_TRUE(grand_child_document->required_csp());
  EXPECT_EQ("script-src 'none'",
            grand_child_document->required_csp()->header->header_value);
}

TEST_F(CSPEmbeddedEnforcementUnitTest, InvalidCSP) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  std::string sec_required_csp =
      NavigateWithRequiredCSP(&child_document, "report-to group");
  EXPECT_EQ("", sec_required_csp);
  EXPECT_FALSE(child_document->required_csp());
}

TEST_F(CSPEmbeddedEnforcementUnitTest, InvalidCspAndInheritFromParent) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  TestRenderFrameHost* grand_child_document = AddChild(child_document);
  std::string sec_required_csp =
      NavigateWithRequiredCSP(&grand_child_document, "report-to group");
  EXPECT_EQ("script-src 'none'", sec_required_csp);
  EXPECT_TRUE(grand_child_document->required_csp());
  EXPECT_EQ("script-src 'none'",
            grand_child_document->required_csp()->header->header_value);
}

TEST_F(CSPEmbeddedEnforcementUnitTest,
       SemiInvalidCspAndInheritSameCspFromParent) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  TestRenderFrameHost* grand_child_document = AddChild(child_document);
  std::string sec_required_csp = NavigateWithRequiredCSP(
      &grand_child_document, "script-src 'none'; report-to group");
  EXPECT_EQ("script-src 'none'", sec_required_csp);
  EXPECT_TRUE(grand_child_document->required_csp());
  EXPECT_EQ("script-src 'none'",
            grand_child_document->required_csp()->header->header_value);
}

TEST_F(CSPEmbeddedEnforcementUnitTest,
       SemiInvalidCspAndInheritDifferentCspFromParent) {
  TestRenderFrameHost* top_document = main_rfh();
  TestRenderFrameHost* child_document = AddChild(top_document);
  NavigateWithRequiredCSP(&child_document, "script-src 'none'");
  TestRenderFrameHost* grand_child_document = AddChild(child_document);
  std::string sec_required_csp = NavigateWithRequiredCSP(
      &grand_child_document, "sandbox; report-to group");
  EXPECT_EQ("script-src 'none'", sec_required_csp);
  EXPECT_TRUE(grand_child_document->required_csp());
  EXPECT_EQ("script-src 'none'",
            grand_child_document->required_csp()->header->header_value);
}

namespace {

// Mock that allows us to avoid depending on the origin_trials component.
class OriginTrialsControllerDelegateMock
    : public OriginTrialsControllerDelegate {
 public:
  ~OriginTrialsControllerDelegateMock() override = default;

  void PersistTrialsFromTokens(
      const url::Origin& origin,
      const url::Origin& partition_origin,
      const base::span<const std::string> header_tokens,
      const base::Time current_time) override {
    persisted_tokens_[origin] =
        std::vector<std::string>(header_tokens.begin(), header_tokens.end());
  }
  void PersistAdditionalTrialsFromTokens(
      const url::Origin& origin,
      const url::Origin& partition_origin,
      const base::span<const url::Origin> script_origins,
      const base::span<const std::string> header_tokens,
      const base::Time current_time) override {
    NOTREACHED() << "not used by test";
  }
  bool IsFeaturePersistedForOrigin(const url::Origin& origin,
                                   const url::Origin& partition_origin,
                                   blink::mojom::OriginTrialFeature feature,
                                   const base::Time current_time) override {
    DCHECK(false) << "Method not implemented for test.";
    return false;
  }

  base::flat_set<std::string> GetPersistedTrialsForOrigin(
      const url::Origin& origin,
      const url::Origin& partition_origin,
      base::Time current_time) override {
    DCHECK(false) << "Method not implemented for test.";
    return base::flat_set<std::string>();
  }

  void ClearPersistedTokens() override { persisted_tokens_.clear(); }

  base::flat_map<url::Origin, std::vector<std::string>> persisted_tokens_;
};

}  // namespace

class PersistentOriginTrialNavigationRequestTest
    : public NavigationRequestTest {
 public:
  PersistentOriginTrialNavigationRequestTest()
      : delegate_mock_(std::make_unique<OriginTrialsControllerDelegateMock>()) {

  }
  ~PersistentOriginTrialNavigationRequestTest() override = default;

  std::vector<std::string> GetPersistedTokens(const url::Origin& origin) {
    return delegate_mock_->persisted_tokens_[origin];
  }

 protected:
  std::unique_ptr<BrowserContext> CreateBrowserContext() override {
    std::unique_ptr<TestBrowserContext> context =
        std::make_unique<TestBrowserContext>();
    context->SetOriginTrialsControllerDelegate(delegate_mock_.get());
    return context;
  }

 private:
  std::unique_ptr<OriginTrialsControllerDelegateMock> delegate_mock_;
};

// Ensure that navigations with a valid Origin-Trial header with a persistent
// origin trial token results in the trial being marked as enabled.
// Then check that subsequent navigations without headers trigger an update
// that clears out stored trials.
TEST_F(PersistentOriginTrialNavigationRequestTest,
       NavigationCommitsPersistentOriginTrials) {
  // Generated with:
  // tools/origin_trials/generate_token.py https://example.com
  // FrobulatePersistent
  // --expire-timestamp=2000000000
  const char kPersistentOriginTrialToken[] =
      "AzZfd1vKZ0SSGRGk/"
      "8nIszQSlHYjbuYVE3jwaNZG3X4t11zRhzPWWJwTZ+JJDS3JJsyEZcpz+y20pAP6/"
      "6upOQ4AAABdeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZ"
      "SI"
      "6ICJGcm9idWxhdGVQZXJzaXN0ZW50IiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9";

  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeature(features::kPersistentOriginTrials);
  blink::ScopedTestOriginTrialPolicy origin_trial_policy_;

  const GURL kUrl = GURL("https://example.com");
  auto navigation =
      NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh());

  auto response_headers =
      base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
  response_headers->SetHeader("Origin-Trial", kPersistentOriginTrialToken);
  navigation->SetResponseHeaders(response_headers);

  navigation->Commit();

  url::Origin origin = url::Origin::Create(kUrl);
  EXPECT_EQ(std::vector<std::string>{kPersistentOriginTrialToken},
            GetPersistedTokens(origin));

  // Navigate again without response headers to assert the trial information is
  // still updated and cleared.
  NavigationSimulatorImpl::CreateRendererInitiated(kUrl, main_rfh())->Commit();
  EXPECT_EQ(std::vector<std::string>(), GetPersistedTokens(origin));
}

namespace {

// Test version of a NavigationThrottle that requests the response body.
class ResponseBodyNavigationThrottle : public NavigationThrottle {
 public:
  using ResponseBodyCallback = base::OnceCallback<void(const std::string&)>;

  ResponseBodyNavigationThrottle(NavigationHandle* handle,
                                 ResponseBodyCallback callback)
      : NavigationThrottle(handle), callback_(std::move(callback)) {}
  ResponseBodyNavigationThrottle(const ResponseBodyNavigationThrottle&) =
      delete;
  ResponseBodyNavigationThrottle& operator=(
      const ResponseBodyNavigationThrottle&) = delete;
  ~ResponseBodyNavigationThrottle() override = default;

  NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
    navigation_handle()->GetResponseBody(
        base::BindOnce(&ResponseBodyNavigationThrottle::OnResponseBodyReady,
                       base::Unretained(this)));
    return NavigationThrottle::DEFER;
  }

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

 private:
  void OnResponseBodyReady(const std::string& response_body) {
    std::move(callback_).Run(response_body);
    NavigationRequest::From(navigation_handle())
        ->GetNavigationThrottleRunnerForTesting()
        ->CallResumeForTesting();
  }

  ResponseBodyCallback callback_;
};

}  // namespace

// Tests response body.
class NavigationRequestResponseBodyTest : public NavigationRequestTest {
 public:
  std::unique_ptr<NavigationSimulator> CreateNavigationSimulator() {
    auto navigation = NavigationSimulatorImpl::CreateRendererInitiated(
        GURL("http://example.test"), main_rfh());
    navigation->SetAutoAdvance(false);
    navigation->Start();
    // It is safe to use base::Unretained as the NavigationThrottle will not be
    // destroyed before the callback is called.
    auto throttle = std::make_unique<ResponseBodyNavigationThrottle>(
        navigation->GetNavigationHandle(),
        base::BindOnce(&NavigationRequestResponseBodyTest::UpdateResponseBody,
                       base::Unretained(this)));
    navigation->GetNavigationHandle()->RegisterThrottleForTesting(
        std::move(throttle));
    return navigation;
  }

  void UpdateResponseBody(const std::string& response_body) {
    response_body_ = response_body;
    was_callback_called_ = true;
  }

  bool was_callback_called() const { return was_callback_called_; }

  const std::string& response_body() const { return response_body_; }

 protected:
  mojo::ScopedDataPipeProducerHandle producer_handle_;
  mojo::ScopedDataPipeConsumerHandle consumer_handle_;

 private:
  bool was_callback_called_ = false;
  std::string response_body_;
};

TEST_F(NavigationRequestResponseBodyTest, Received) {
  auto navigation = CreateNavigationSimulator();
  std::string response = "response-body-content";
  uint32_t write_size = response.size();
  ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(write_size, producer_handle_,
                                                 consumer_handle_));
  navigation->SetResponseBody(std::move(consumer_handle_));

  navigation->ReadyToCommit();
  EXPECT_EQ(
      NavigationRequest::WILL_PROCESS_RESPONSE,
      NavigationRequest::From(navigation->GetNavigationHandle())->state());
  EXPECT_FALSE(was_callback_called());
  EXPECT_EQ(std::string(), response_body());

  ASSERT_EQ(MOJO_RESULT_OK,
            producer_handle_->WriteData(response.c_str(), &write_size,
                                        MOJO_WRITE_DATA_FLAG_NONE));
  EXPECT_EQ(write_size, response.size());

  navigation->Wait();
  EXPECT_EQ(
      NavigationRequest::READY_TO_COMMIT,
      NavigationRequest::From(navigation->GetNavigationHandle())->state());
  EXPECT_TRUE(was_callback_called());
  EXPECT_EQ(response, response_body());
}

TEST_F(NavigationRequestResponseBodyTest, PartiallyReceived) {
  auto navigation = CreateNavigationSimulator();

  // The data pipe size is smaller than the response body size.
  uint32_t pipe_size = 8u;
  ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(pipe_size, producer_handle_,
                                                 consumer_handle_));
  navigation->SetResponseBody(std::move(consumer_handle_));

  navigation->ReadyToCommit();
  EXPECT_EQ(
      NavigationRequest::WILL_PROCESS_RESPONSE,
      NavigationRequest::From(navigation->GetNavigationHandle())->state());
  EXPECT_FALSE(was_callback_called());
  EXPECT_EQ(std::string(), response_body());

  std::string response = "response-body-content";
  uint32_t write_size = response.size();
  ASSERT_EQ(MOJO_RESULT_OK,
            producer_handle_->WriteData(response.c_str(), &write_size,
                                        MOJO_WRITE_DATA_FLAG_NONE));
  EXPECT_EQ(write_size, pipe_size);

  navigation->Wait();
  EXPECT_EQ(
      NavigationRequest::READY_TO_COMMIT,
      NavigationRequest::From(navigation->GetNavigationHandle())->state());
  EXPECT_TRUE(was_callback_called());
  // Only the first part of the response body that fits in the pipe is received.
  EXPECT_EQ("response", response_body());
}

TEST_F(NavigationRequestResponseBodyTest, PipeClosed) {
  auto navigation = CreateNavigationSimulator();
  ASSERT_EQ(MOJO_RESULT_OK,
            mojo::CreateDataPipe(10u, producer_handle_, consumer_handle_));
  navigation->SetResponseBody(std::move(consumer_handle_));
  navigation->ReadyToCommit();
  EXPECT_EQ(
      NavigationRequest::WILL_PROCESS_RESPONSE,
      NavigationRequest::From(navigation->GetNavigationHandle())->state());
  EXPECT_FALSE(was_callback_called());
  EXPECT_EQ(std::string(), response_body());

  // Close the pipe before any data is sent.
  producer_handle_.reset();
  navigation->Wait();
  EXPECT_EQ(
      NavigationRequest::READY_TO_COMMIT,
      NavigationRequest::From(navigation->GetNavigationHandle())->state());
  EXPECT_TRUE(was_callback_called());
  EXPECT_EQ(std::string(), response_body());
}

TEST_F(NavigationRequestTest, ViewTransitionForceEnablesPageSwap) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitWithFeatures({blink::features::kViewTransitionOnNavigation},
                                {});

  GURL main_url = GURL("https://main.com");
  auto main_navigation =
      NavigationSimulatorImpl::CreateBrowserInitiated(main_url, contents());
  main_navigation->Start();
  ASSERT_TRUE(
      main_navigation->GetNavigationHandle()->ShouldDispatchPageSwapEvent());
}

}  // namespace content
