// Copyright 2014 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/navigator.h"

#include <stdint.h>

#include "base/feature_list.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigation_request_info.h"
#include "content/browser/renderer_host/render_frame_host_manager.h"
#include "content/browser/site_info.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/frame.mojom.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_navigation_throttle_inserter.h"
#include "content/public/test/test_utils.h"
#include "content/test/navigation_simulator_impl.h"
#include "content/test/task_runner_deferring_throttle.h"
#include "content/test/test_navigation_url_loader.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_web_contents.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/redirect_info.h"
#include "ui/base/page_transition_types.h"
#include "url/url_constants.h"

namespace content {

namespace {

// Helper function that determines if a test should expect a cross-site
// navigation to trigger a SiteInstance change based on the current process
// model.
bool ExpectSiteInstanceChange(SiteInstanceImpl* site_instance) {
  return AreAllSitesIsolatedForTesting() ||
         CanCrossSiteNavigationsProactivelySwapBrowsingInstances() ||
         !site_instance->IsDefaultSiteInstance();
}

// Same as above but does not return true if back/forward cache is the only
// trigger for SiteInstance change. This function is useful if, e.g. the test
// intends to disable back/forward cache.
bool ExpectSiteInstanceChangeWithoutBackForwardCache(
    SiteInstanceImpl* site_instance) {
  return AreAllSitesIsolatedForTesting() ||
         IsProactivelySwapBrowsingInstanceEnabled() ||
         !site_instance->IsDefaultSiteInstance();
}

}  // namespace

class NavigatorTest : public RenderViewHostImplTestHarness {
 public:
  using SiteInstanceDescriptor = RenderFrameHostManager::SiteInstanceDescriptor;
  using SiteInstanceRelation = RenderFrameHostManager::SiteInstanceRelation;

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

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

  TestNavigationURLLoader* GetLoaderForNavigationRequest(
      NavigationRequest* request) const {
    return static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
  }

  TestRenderFrameHost* GetSpeculativeRenderFrameHost(FrameTreeNode* node) {
    return static_cast<TestRenderFrameHost*>(
        node->render_manager()->speculative_render_frame_host_.get());
  }

  scoped_refptr<SiteInstanceImpl> ConvertToSiteInstance(
      RenderFrameHostManager* rfhm,
      const SiteInstanceDescriptor& descriptor,
      SiteInstance* candidate_instance) {
    return static_cast<SiteInstanceImpl*>(
        rfhm->ConvertToSiteInstance(
                descriptor, static_cast<SiteInstanceImpl*>(candidate_instance))
            .get());
  }

  SiteInfo CreateExpectedSiteInfo(const GURL& url) {
    return SiteInfo::CreateForTesting(IsolationContext(browser_context()), url);
  }
};

// Tests a complete browser-initiated navigation starting with a non-live
// renderer.
TEST_F(NavigatorTest, SimpleBrowserInitiatedNavigationFromNonLiveRenderer) {
  const GURL kUrl("http://chromium.org/");

  EXPECT_FALSE(main_test_rfh()->IsRenderFrameLive());

  // Start a browser-initiated navigation.
  auto navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
  auto site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  navigation->Start();
  NavigationRequest* request = node->navigation_request();
  ASSERT_TRUE(request);
  EXPECT_EQ(kUrl, request->common_params().url);
  EXPECT_TRUE(request->browser_initiated());

  // As there's no live renderer the navigation should not wait for a
  // beforeUnload completion callback being invoked by the renderer and
  // start right away.
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, request->state());
  ASSERT_TRUE(GetLoaderForNavigationRequest(request));
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  navigation->ReadyToCommit();
  EXPECT_TRUE(main_test_rfh()->is_loading());
  EXPECT_FALSE(node->navigation_request());

  // Commit the navigation.
  navigation->Commit();
  EXPECT_TRUE(main_test_rfh()->IsActive());
  EXPECT_EQ(main_test_rfh()->lifecycle_state(),
            RenderFrameHostImpl::LifecycleStateImpl::kActive);
  if (AreDefaultSiteInstancesEnabled()) {
    EXPECT_TRUE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
  } else {
    EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
              main_test_rfh()->GetSiteInstance()->GetSiteInfo());
  }
  EXPECT_EQ(kUrl, contents()->GetLastCommittedURL());

  // The main RenderFrameHost should not have been changed, and the renderer
  // should have been initialized.
  EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
  EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());

  // After a navigation is finished no speculative RenderFrameHost should
  // exist.
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// Tests a complete renderer-initiated same-site navigation.
TEST_F(NavigatorTest, SimpleRendererInitiatedSameSiteNavigation) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.chromium.org/Home");

  contents()->NavigateAndCommit(kUrl1);
  EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
  static_cast<mojom::FrameHost*>(main_test_rfh())->DidStopLoading();
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  // Start a renderer-initiated non-user-initiated navigation.
  EXPECT_FALSE(node->navigation_request());
  auto navigation =
      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
  navigation->SetTransition(ui::PageTransitionFromInt(
      ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
  navigation->SetHasUserGesture(false);
  navigation->Start();
  NavigationRequest* request = node->navigation_request();
  ASSERT_TRUE(request);

  // The navigation is immediately started as there's no need to wait for
  // beforeUnload to be executed.
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, request->state());
  EXPECT_FALSE(request->common_params().has_user_gesture);
  EXPECT_EQ(kUrl2, request->common_params().url);
  EXPECT_FALSE(request->browser_initiated());

  if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
    // If same-site ProactivelySwapBrowsingInstance or main-frame RenderDocument
    // is enabled, the RFH should change so we should have a speculative RFH.
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)->is_loading());
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }
  EXPECT_FALSE(main_test_rfh()->is_loading());

  // Have the current RenderFrameHost commit the navigation
  navigation->ReadyToCommit();
  if (CanSameSiteMainFrameNavigationsChangeRenderFrameHosts()) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->is_loading());
  } else {
    EXPECT_TRUE(main_test_rfh()->is_loading());
  }
  EXPECT_FALSE(node->navigation_request());

  // Commit the navigation.
  navigation->Commit();
  EXPECT_TRUE(main_test_rfh()->IsActive());
  if (AreDefaultSiteInstancesEnabled()) {
    EXPECT_TRUE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
  } else {
    EXPECT_EQ(CreateExpectedSiteInfo(kUrl2),
              main_test_rfh()->GetSiteInstance()->GetSiteInfo());
  }
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// Tests a complete renderer-initiated navigation that should be
// cross-site but does not result in a SiteInstance swap because its
// renderer-initiated.
TEST_F(NavigatorTest, SimpleRendererInitiatedCrossSiteNavigation) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com");

  contents()->NavigateAndCommit(kUrl1);
  EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
  scoped_refptr<SiteInstanceImpl> site_instance_1 =
      main_test_rfh()->GetSiteInstance();
  bool expect_site_instance_change =
      ExpectSiteInstanceChange(site_instance_1.get());
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  // Start a renderer-initiated navigation.
  EXPECT_FALSE(node->navigation_request());
  auto navigation =
      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
  navigation->Start();
  NavigationRequest* request = node->navigation_request();
  ASSERT_TRUE(request);

  // The navigation is immediately started as there's no need to wait for
  // beforeUnload to be executed.
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, request->state());
  EXPECT_EQ(kUrl2, request->common_params().url);
  EXPECT_FALSE(request->browser_initiated());
  if (expect_site_instance_change) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

  // Have the current RenderFrameHost commit the navigation.
  navigation->ReadyToCommit();
  if (expect_site_instance_change) {
    EXPECT_EQ(navigation->GetFinalRenderFrameHost(),
              GetSpeculativeRenderFrameHost(node));
  }
  EXPECT_FALSE(node->navigation_request());

  // Commit the navigation.
  navigation->Commit();
  EXPECT_TRUE(main_test_rfh()->IsActive());
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  if (expect_site_instance_change) {
    EXPECT_NE(site_instance_1->GetId(),
              main_test_rfh()->GetSiteInstance()->GetId());
    EXPECT_EQ(site_instance_1->IsDefaultSiteInstance(),
              main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
  } else {
    EXPECT_EQ(site_instance_1->GetId(),
              main_test_rfh()->GetSiteInstance()->GetId());
  }
}

// Tests that when a navigation to about:blank is renderer-aborted,
// after another cross-site navigation has been initiated, that the
// second navigation is undisturbed.
TEST_F(NavigatorTest, RendererAbortedAboutBlankNavigation) {
  const GURL kUrl0("http://www.google.com/");
  const GURL kUrl1("about:blank");
  const GURL kUrl2("http://www.chromium.org/Home");

  contents()->NavigateAndCommit(kUrl0);
  EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());

  // The test expects cross-site navigations to change SiteInstances, but not
  // same-site navigations. Return if SiteInstance change is not possible, and
  // disable same-site back/forward cache to ensure SiteInstance won't change
  // for same-site navigations.
  DisableBackForwardCacheForTesting(
      contents(), BackForwardCache::TEST_ASSUMES_NO_RENDER_FRAME_CHANGE);
  if (!ExpectSiteInstanceChangeWithoutBackForwardCache(
          main_test_rfh()->GetSiteInstance())) {
    return;
  }

  // Start a renderer-initiated navigation to about:blank.
  EXPECT_FALSE(main_test_rfh()->is_loading());
  auto navigation1 =
      NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
  navigation1->SetTransition(ui::PAGE_TRANSITION_LINK);
  navigation1->Start();
  navigation1->ReadyToCommit();

  // about:blank should load on the main rfhi, not a speculative one,
  // and automatically advance to READY_TO_COMMIT since it requires
  // no network resources.
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  ASSERT_FALSE(node->navigation_request());
  EXPECT_TRUE(main_test_rfh()->is_loading());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // Start a second, cross-origin navigation.
  auto navigation2 =
      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
  navigation2->SetTransition(ui::PAGE_TRANSITION_LINK);
  navigation2->Start();
  ASSERT_TRUE(node->navigation_request());
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));

  // Abort the initial navigation.
  navigation1->AbortFromRenderer();

  // But the speculative rfhi and second navigation request
  // should be unaffected.
  ASSERT_TRUE(node->navigation_request());
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
}

// Tests that when a navigation to about:blank is renderer-aborted,
// after another cross-site navigation has been initiated, that the
// second navigation is undisturbed. In this variation, the second
// navigation is initially same-site, then redirects cross-site,
// and a throttle DEFERs during WillProcessResponse(). The initial
// navigation gets aborted during this defer.
TEST_F(NavigatorTest,
       RedirectedRendererAbortedAboutBlankNavigationwithDeferredCommit) {
  const GURL kUrl0("http://www.google.com/");
  const GURL kUrl0SameSiteVariation("http://www.google.com/home");
  const GURL kUrl1("about:blank");
  const GURL kUrl2("http://www.chromium.org/Home");

  contents()->NavigateAndCommit(kUrl0);
  EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());

  // The test expects cross-site navigations to change SiteInstances, but not
  // same-site navigations. Return if SiteInstance change is not possible, and
  // disable same-site back/forward cache to ensure SiteInstance won't change
  // for same-site navigations.
  DisableBackForwardCacheForTesting(
      contents(), BackForwardCache::TEST_ASSUMES_NO_RENDER_FRAME_CHANGE);
  if (!ExpectSiteInstanceChangeWithoutBackForwardCache(
          main_test_rfh()->GetSiteInstance())) {
    return;
  }

  // Start a renderer-initiated navigation to about:blank.
  EXPECT_FALSE(main_test_rfh()->is_loading());
  auto navigation1 =
      NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
  navigation1->SetTransition(ui::PAGE_TRANSITION_LINK);
  navigation1->Start();
  navigation1->ReadyToCommit();

  // about:blank should load on the main rfhi, not a speculative one,
  // and automatically advance to READY_TO_COMMIT since it requires
  // no network resources.
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  ASSERT_FALSE(node->navigation_request());
  EXPECT_TRUE(main_test_rfh()->is_loading());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // Start a second, same-origin navigation.
  auto navigation2 = NavigationSimulator::CreateRendererInitiated(
      kUrl0SameSiteVariation, main_test_rfh());
  navigation2->SetTransition(ui::PAGE_TRANSITION_LINK);
  navigation2->SetAutoAdvance(false);

  // Insert a TaskRunnerDeferringThrottle that will defer
  // during WillProcessResponse() of navigation2.
  auto task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
  auto* raw_runner = task_runner.get();
  TestNavigationThrottleInserter throttle_inserter(
      web_contents(),
      base::BindRepeating(&TaskRunnerDeferringThrottle::Create,
                          std::move(task_runner), false /* defer_start */,
                          false /* defer-redirect */,
                          true /* defer_response */));

  navigation2->Start();
  ASSERT_TRUE(node->navigation_request());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // Redirect navigation2 cross-site, which, once ReadyCommit()
  // is called, will force a speculative RFHI to be created,
  // and update the associated site instance type of the
  // NavigationRequest for navigation2. This will prevent
  // the abort of navigation1 from destroying the speculative
  // RFHI that navigation2 depends on.
  navigation2->Redirect(kUrl2);
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  EXPECT_TRUE(node->navigation_request()->GetAssociatedRFHType() ==
              NavigationRequest::AssociatedRenderFrameHostType::CURRENT);

  navigation2->ReadyToCommit();
  EXPECT_EQ(1u, raw_runner->NumPendingTasks());
  EXPECT_TRUE(navigation2->IsDeferred());
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  EXPECT_EQ(node->navigation_request()->GetRenderFrameHost(),
            GetSpeculativeRenderFrameHost(node));

  // Abort the initial navigation.
  navigation1->AbortFromRenderer();

  // The speculative rfhi and second navigation request
  // should be unaffected.
  ASSERT_TRUE(node->navigation_request());
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
}

// Tests that a beforeUnload denial cancels the navigation.
TEST_F(NavigatorTest, BeforeUnloadDenialCancelNavigation) {
  const GURL kUrl1("http://www.google.com/");
  const GURL kUrl2("http://www.chromium.org/");

  contents()->NavigateAndCommit(kUrl1);

  // Start a new navigation.
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  auto navigation =
      NavigationSimulatorImpl::CreateBrowserInitiated(kUrl2, contents());
  navigation->BrowserInitiatedStartAndWaitBeforeUnload();
  NavigationRequest* request = node->navigation_request();
  ASSERT_TRUE(request);
  EXPECT_TRUE(request->browser_initiated());
  EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE, request->state());
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  RenderFrameDeletedObserver rfh_deleted_observer(
      GetSpeculativeRenderFrameHost(node));

  // Simulate a beforeUnload denial.
  main_test_rfh()->SimulateBeforeUnloadCompleted(false);
  EXPECT_FALSE(node->navigation_request());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  EXPECT_TRUE(rfh_deleted_observer.deleted());
}

// Test that a proper NavigationRequest is created at navigation start.
TEST_F(NavigatorTest, BeginNavigation) {
  const GURL kUrl1("http://www.google.com/");
  const GURL kUrl2("http://www.chromium.org/");
  const GURL kUrl3("http://www.gmail.com/");

  contents()->NavigateAndCommit(kUrl1);

  // Add a subframe.
  FrameTreeNode* root_node = contents()->GetPrimaryFrameTree().root();
  TestRenderFrameHost* subframe_rfh = main_test_rfh()->AppendChild("Child");
  ASSERT_TRUE(subframe_rfh);

  // Start a navigation at the subframe.
  FrameTreeNode* subframe_node = subframe_rfh->frame_tree_node();
  auto navigation =
      NavigationSimulatorImpl::CreateBrowserInitiated(kUrl2, contents());
  NavigationController::LoadURLParams load_url_params(kUrl2);
  load_url_params.frame_tree_node_id = subframe_node->frame_tree_node_id();
  navigation->SetLoadURLParams(&load_url_params);
  navigation->BrowserInitiatedStartAndWaitBeforeUnload();
  NavigationRequest* subframe_request = subframe_node->navigation_request();

  // We should be waiting for the BeforeUnload event to execute in the subframe.
  ASSERT_TRUE(subframe_request);
  EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE,
            subframe_request->state());
  EXPECT_TRUE(subframe_rfh->is_waiting_for_beforeunload_completion());

  // Start the navigation, which will internally simulate that the beforeUnload
  // completion callback has been invoked.
  navigation->Start();
  TestNavigationURLLoader* subframe_loader =
      GetLoaderForNavigationRequest(subframe_request);
  ASSERT_TRUE(subframe_loader);
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, subframe_request->state());
  EXPECT_EQ(kUrl2, subframe_request->common_params().url);
  EXPECT_EQ(kUrl2, subframe_loader->request_info()->common_params->url);
  EXPECT_TRUE(
      net::IsolationInfo::Create(
          net::IsolationInfo::RequestType::kSubFrame,
          url::Origin::Create(kUrl1), url::Origin::Create(kUrl2),
          net::SiteForCookies::FromUrl(kUrl1), std::set<net::SchemefulSite>())
          .IsEqualForTesting(subframe_loader->request_info()->isolation_info));

  EXPECT_FALSE(subframe_loader->request_info()->is_main_frame);
  EXPECT_TRUE(subframe_request->browser_initiated());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(root_node));

  // Subframe navigations should never create a speculative RenderFrameHost,
  // unless site-per-process or ProcessSharingWithStrictSiteInstances is
  // enabled. In that case, as the subframe navigation is to a different site
  // and is still ongoing, it should have one.
  bool expect_site_instance_change = AreStrictSiteInstancesEnabled();
  if (expect_site_instance_change) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
  }

  // Now start a navigation at the root node.
  auto navigation2 =
      NavigationSimulatorImpl::CreateBrowserInitiated(kUrl3, contents());
  navigation2->BrowserInitiatedStartAndWaitBeforeUnload();
  NavigationRequest* main_request = root_node->navigation_request();
  ASSERT_TRUE(main_request);
  EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE,
            main_request->state());

  // Main frame navigation to a different site should use a speculative
  // RenderFrameHost.
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node));

  // Start the navigation, which will internally simulate that the beforeUnload
  // completion callback has been invoked.
  navigation2->Start();
  TestNavigationURLLoader* main_loader =
      GetLoaderForNavigationRequest(main_request);
  EXPECT_EQ(kUrl3, main_request->common_params().url);
  EXPECT_EQ(kUrl3, main_loader->request_info()->common_params->url);
  EXPECT_TRUE(
      net::IsolationInfo::Create(
          net::IsolationInfo::RequestType::kMainFrame,
          url::Origin::Create(kUrl3), url::Origin::Create(kUrl3),
          net::SiteForCookies::FromUrl(kUrl3), std::set<net::SchemefulSite>())
          .IsEqualForTesting(main_loader->request_info()->isolation_info));
  EXPECT_TRUE(main_loader->request_info()->is_main_frame);
  EXPECT_TRUE(main_request->browser_initiated());
  // BeforeUnloadCompleted callback was invoked by the renderer so the
  // navigation should have started.
  EXPECT_EQ(NavigationRequest::WILL_START_REQUEST, main_request->state());
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(root_node));

  // As the main frame hasn't yet committed the subframe still exists. Thus, the
  // above situation regarding subframe navigations is valid here.
  if (expect_site_instance_change) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
  }
}

// Tests that committing an HTTP 204 or HTTP 205 response cancels
// the navigation.
TEST_F(NavigatorTest, NoContent) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com/");

  // Load a URL.
  contents()->NavigateAndCommit(kUrl1);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  // Navigate to a different site.
  EXPECT_FALSE(node->navigation_request());
  auto navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
  navigation->Start();

  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request);

  // Navigations to a different site do create a speculative RenderFrameHost.
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));

  // Commit an HTTP 204 response.
  auto response = network::mojom::URLResponseHead::New();
  const char kNoContentHeaders[] = "HTTP/1.1 204 No Content\0\0";
  response->headers = new net::HttpResponseHeaders(
      std::string(kNoContentHeaders, std::size(kNoContentHeaders)));
  GetLoaderForNavigationRequest(main_request)
      ->CallOnResponseStarted(std::move(response),
                              mojo::ScopedDataPipeConsumerHandle(),
                              absl::nullopt);

  // There should be no pending nor speculative RenderFrameHost; the navigation
  // was aborted.
  EXPECT_FALSE(node->navigation_request());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // Now, repeat the test with 205 Reset Content.

  // Navigate to a different site again.
  auto navigation2 =
      NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
  navigation2->Start();

  main_request = node->navigation_request();
  ASSERT_TRUE(main_request);
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));

  // Commit an HTTP 205 response.
  response = network::mojom::URLResponseHead::New();
  const char kResetContentHeaders[] = "HTTP/1.1 205 Reset Content\0\0";
  response->headers = new net::HttpResponseHeaders(
      std::string(kResetContentHeaders, std::size(kResetContentHeaders)));
  GetLoaderForNavigationRequest(main_request)
      ->CallOnResponseStarted(std::move(response),
                              mojo::ScopedDataPipeConsumerHandle(),
                              absl::nullopt);

  // There should be no pending nor speculative RenderFrameHost; the navigation
  // was aborted.
  EXPECT_FALSE(node->navigation_request());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// Test that a new RenderFrameHost is created when doing a cross site
// navigation.
TEST_F(NavigatorTest, CrossSiteNavigation) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com/");

  contents()->NavigateAndCommit(kUrl1);
  RenderFrameHostImpl* initial_rfh = main_test_rfh();
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  // Navigate to a different site.
  EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);
  auto navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
  navigation->Start();
  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request);
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));

  navigation->ReadyToCommit();
  EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
  EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
  EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);

  navigation->Commit();
  RenderFrameHostImpl* final_rfh = main_test_rfh();
  EXPECT_EQ(speculative_rfh, final_rfh);
  EXPECT_NE(initial_rfh, final_rfh);
  EXPECT_TRUE(final_rfh->IsRenderFrameLive());
  EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// Test that redirects are followed and the speculative RenderFrameHost logic
// behaves as expected.
TEST_F(NavigatorTest, RedirectCrossSite) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com/");

  contents()->NavigateAndCommit(kUrl1);
  RenderFrameHostImpl* rfh = main_test_rfh();
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  // Navigate to a URL on the same site.
  EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);
  auto navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
  navigation->Start();
  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request);
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // It then redirects to another site.
  navigation->Redirect(kUrl2);

  // The redirect should have been followed.
  EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request)->redirect_count());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  navigation->ReadyToCommit();
  TestRenderFrameHost* final_speculative_rfh =
      GetSpeculativeRenderFrameHost(node);
  EXPECT_TRUE(final_speculative_rfh);
  EXPECT_EQ(final_speculative_rfh->navigation_requests().size(), 1u);

  navigation->Commit();
  RenderFrameHostImpl* final_rfh = main_test_rfh();
  ASSERT_TRUE(final_rfh);
  EXPECT_NE(rfh, final_rfh);
  EXPECT_EQ(final_speculative_rfh, final_rfh);
  EXPECT_TRUE(final_rfh->IsRenderFrameLive());
  EXPECT_TRUE(final_rfh->render_view_host()->IsRenderViewLive());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// Test that a navigation is canceled if another browser-initiated request has
// been issued in the meantime. Also confirms that the speculative
// RenderFrameHost is correctly updated in the process.
TEST_F(NavigatorTest, BrowserInitiatedNavigationCancel) {
  const GURL kUrl0("http://www.wikipedia.org/");
  const GURL kUrl1("http://www.chromium.org/");
  const auto kUrl1SiteInfo = CreateExpectedSiteInfo(kUrl1);
  const GURL kUrl2("http://www.google.com/");
  const auto kUrl2SiteInfo = CreateExpectedSiteInfo(kUrl2);

  // Initialization.
  contents()->NavigateAndCommit(kUrl0);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  // Request navigation to the 1st URL.
  EXPECT_FALSE(node->navigation_request());
  auto navigation1 =
      NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
  navigation1->Start();
  NavigationRequest* request1 = node->navigation_request();
  ASSERT_TRUE(request1);
  EXPECT_EQ(kUrl1, request1->common_params().url);
  EXPECT_TRUE(request1->browser_initiated());
  base::WeakPtr<TestNavigationURLLoader> loader1 =
      GetLoaderForNavigationRequest(request1)->AsWeakPtr();
  EXPECT_TRUE(loader1);

  // Confirm a speculative RenderFrameHost was created.
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  auto site_instance_id_1 = speculative_rfh->GetSiteInstance()->GetId();
  if (AreDefaultSiteInstancesEnabled()) {
    EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
  } else {
    EXPECT_EQ(kUrl1SiteInfo, speculative_rfh->GetSiteInstance()->GetSiteInfo());
  }

  // Request navigation to the 2nd URL; the NavigationRequest must have been
  // replaced by a new one with a different URL.
  auto navigation2 =
      NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
  navigation2->Start();
  NavigationRequest* request2 = node->navigation_request();
  ASSERT_TRUE(request2);
  EXPECT_EQ(kUrl2, request2->common_params().url);
  EXPECT_TRUE(request2->browser_initiated());

  // Confirm that the first loader got destroyed.
  EXPECT_FALSE(loader1);

  // Confirm that a new speculative RenderFrameHost was created.
  speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  auto site_instance_id_2 = speculative_rfh->GetSiteInstance()->GetId();

  if (AreDefaultSiteInstancesEnabled()) {
    EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
    EXPECT_EQ(site_instance_id_1, site_instance_id_2);
  } else {
    EXPECT_NE(site_instance_id_1, site_instance_id_2);
  }

  navigation2->ReadyToCommit();
  EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
  EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);

  // Have the RenderFrameHost commit the navigation.
  navigation2->Commit();

  // Confirm that the commit corresponds to the new request.
  ASSERT_TRUE(main_test_rfh());
  if (AreDefaultSiteInstancesEnabled()) {
    EXPECT_TRUE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());
  } else {
    EXPECT_EQ(kUrl2SiteInfo, main_test_rfh()->GetSiteInstance()->GetSiteInfo());
  }
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());

  // Confirm that the committed RenderFrameHost is the latest speculative one.
  EXPECT_EQ(site_instance_id_2, main_test_rfh()->GetSiteInstance()->GetId());
}

// Test that a browser-initiated navigation is canceled if a renderer-initiated
// user-initiated request has been issued in the meantime.
TEST_F(NavigatorTest, RendererUserInitiatedNavigationCancel) {
  const GURL kUrl0("http://www.wikipedia.org/");
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com/");

  // Initialization.
  contents()->NavigateAndCommit(kUrl0);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  bool expect_site_instance_change =
      ExpectSiteInstanceChange(main_test_rfh()->GetSiteInstance());

  // Start a browser-initiated navigation to the 1st URL and invoke its
  // beforeUnload completion callback.
  EXPECT_FALSE(node->navigation_request());
  auto navigation2 =
      NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
  navigation2->Start();
  NavigationRequest* request1 = node->navigation_request();
  ASSERT_TRUE(request1);
  EXPECT_EQ(kUrl1, request1->common_params().url);
  EXPECT_TRUE(request1->browser_initiated());
  base::WeakPtr<TestNavigationURLLoader> loader1 =
      GetLoaderForNavigationRequest(request1)->AsWeakPtr();
  EXPECT_TRUE(loader1);

  // Confirm that a speculative RenderFrameHost was created.
  ASSERT_TRUE(GetSpeculativeRenderFrameHost(node));

  // Now receive a renderer-initiated user-initiated request. It should replace
  // the current NavigationRequest.
  auto navigation =
      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
  navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
  navigation->SetHasUserGesture(true);
  navigation->Start();
  NavigationRequest* request2 = node->navigation_request();
  ASSERT_TRUE(request2);
  EXPECT_EQ(kUrl2, request2->common_params().url);
  EXPECT_FALSE(request2->browser_initiated());
  EXPECT_TRUE(request2->common_params().has_user_gesture);

  // Confirm that the first loader got destroyed.
  EXPECT_FALSE(loader1);

  // Confirm that the speculative RenderFrameHost was destroyed in the non
  // SitePerProcess case.
  if (expect_site_instance_change) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

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

  // Confirm that the commit corresponds to the new request.
  ASSERT_TRUE(main_test_rfh());
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
}

// Tests that a renderer-initiated user-initiated navigation is
// canceled if a renderer-initiated non-user-initiated request is issued in the
// meantime.
TEST_F(NavigatorTest,
       RendererNonUserInitiatedNavigationCancelsRendererUserInitiated) {
  const GURL kUrl0("http://www.wikipedia.org/");
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com/");

  // Initialization.
  contents()->NavigateAndCommit(kUrl0);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  bool expect_site_instance_change =
      ExpectSiteInstanceChange(main_test_rfh()->GetSiteInstance());

  // Start a renderer-initiated user-initiated navigation to the 1st URL.
  EXPECT_FALSE(node->navigation_request());
  auto user_initiated_navigation =
      NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
  user_initiated_navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
  user_initiated_navigation->SetHasUserGesture(true);
  user_initiated_navigation->Start();
  NavigationRequest* request1 = node->navigation_request();
  ASSERT_TRUE(request1);
  EXPECT_EQ(kUrl1, request1->common_params().url);
  EXPECT_FALSE(request1->browser_initiated());
  EXPECT_TRUE(request1->common_params().has_user_gesture);
  if (expect_site_instance_change) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

  // Now receive a renderer-initiated non-user-initiated request. The previous
  // navigation should be replaced.
  auto non_user_initiated_navigation =
      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
  non_user_initiated_navigation->SetTransition(ui::PAGE_TRANSITION_LINK);
  non_user_initiated_navigation->SetHasUserGesture(false);
  non_user_initiated_navigation->Start();

  NavigationRequest* request2 = node->navigation_request();
  ASSERT_TRUE(request2);
  EXPECT_NE(request1, request2);
  EXPECT_EQ(kUrl2, request2->common_params().url);
  EXPECT_FALSE(request2->browser_initiated());
  EXPECT_FALSE(request2->common_params().has_user_gesture);
  if (expect_site_instance_change) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

  // Commit the navigation.
  non_user_initiated_navigation->Commit();
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
}

// PlzNavigate: Test that a browser-initiated navigation is NOT canceled if a
// renderer-initiated non-user-initiated request is issued in the meantime.
TEST_F(NavigatorTest,
       RendererNonUserInitiatedNavigationDoesntCancelBrowserInitiated) {
  const GURL kUrl0("http://www.wikipedia.org/");
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com/");

  // Initialization.
  contents()->NavigateAndCommit(kUrl0);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  // Start a browser-initiated navigation to the 1st URL.
  EXPECT_FALSE(node->navigation_request());
  auto navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
  navigation->Start();
  NavigationRequest* request1 = node->navigation_request();
  ASSERT_TRUE(request1);
  EXPECT_EQ(kUrl1, request1->common_params().url);
  EXPECT_TRUE(request1->browser_initiated());
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);

  // Now receive a renderer-initiated non-user-initiated request. Nothing should
  // change.
  main_test_rfh()->SendRendererInitiatedNavigationRequest(
      kUrl2, false /* has_user_gesture */);
  NavigationRequest* request2 = node->navigation_request();
  ASSERT_TRUE(request2);
  EXPECT_EQ(request1, request2);
  EXPECT_EQ(kUrl1, request2->common_params().url);
  EXPECT_TRUE(request2->browser_initiated());
  EXPECT_TRUE(speculative_rfh);

  navigation->ReadyToCommit();
  EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
  EXPECT_EQ(main_test_rfh()->navigation_requests().size(), 0u);

  navigation->Commit();
  EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL());
}

// PlzNavigate: Test that a renderer-initiated non-user-initiated navigation is
// canceled if a another similar request is issued in the meantime.
TEST_F(NavigatorTest,
       RendererNonUserInitiatedNavigationCancelSimilarNavigation) {
  const GURL kUrl0("http://www.wikipedia.org/");
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com/");

  // Initialization.
  contents()->NavigateAndCommit(kUrl0);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  auto site_instance_id_0 = main_test_rfh()->GetSiteInstance()->GetId();
  bool expect_site_instance_change =
      ExpectSiteInstanceChange(main_test_rfh()->GetSiteInstance());

  // Start a renderer-initiated non-user-initiated navigation to the 1st URL.
  EXPECT_FALSE(node->navigation_request());
  auto navigation1 =
      NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
  navigation1->SetTransition(ui::PageTransitionFromInt(
      ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
  navigation1->SetHasUserGesture(false);
  navigation1->Start();
  NavigationRequest* request1 = node->navigation_request();
  ASSERT_TRUE(request1);
  EXPECT_EQ(kUrl1, request1->common_params().url);
  EXPECT_FALSE(request1->browser_initiated());
  EXPECT_FALSE(request1->common_params().has_user_gesture);
  if (expect_site_instance_change) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }
  base::WeakPtr<TestNavigationURLLoader> loader1 =
      GetLoaderForNavigationRequest(request1)->AsWeakPtr();
  EXPECT_TRUE(loader1);

  // Now receive a 2nd similar request that should replace the current one.
  auto navigation2 =
      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
  navigation2->SetTransition(ui::PageTransitionFromInt(
      ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
  navigation2->SetHasUserGesture(false);
  navigation2->Start();
  NavigationRequest* request2 = node->navigation_request();
  EXPECT_EQ(kUrl2, request2->common_params().url);
  EXPECT_FALSE(request2->browser_initiated());
  EXPECT_FALSE(request2->common_params().has_user_gesture);
  if (expect_site_instance_change) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

  // Confirm that the first loader got destroyed.
  EXPECT_FALSE(loader1);

  // Commit the navigation.
  navigation2->Commit();
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());

  if (expect_site_instance_change) {
    EXPECT_NE(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
  } else {
    EXPECT_EQ(site_instance_id_0, main_test_rfh()->GetSiteInstance()->GetId());
  }
}

// PlzNavigate: Test that a reload navigation is properly signaled to the
// RenderFrame when the navigation can commit. A speculative RenderFrameHost
// should not be created at any step.
TEST_F(NavigatorTest, Reload) {
  const GURL kUrl("http://www.google.com/");
  contents()->NavigateAndCommit(kUrl);

  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  controller().Reload(ReloadType::NORMAL, false);
  auto reload1 =
      NavigationSimulator::CreateFromPending(contents()->GetController());
  // A NavigationRequest should have been generated.
  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request != nullptr);
  EXPECT_EQ(blink::mojom::NavigationType::RELOAD,
            main_request->common_params().navigation_type);
  reload1->ReadyToCommit();
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  reload1->Commit();
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // Now do a shift+reload.
  controller().Reload(ReloadType::BYPASSING_CACHE, false);
  auto reload2 =
      NavigationSimulator::CreateFromPending(contents()->GetController());
  // A NavigationRequest should have been generated.
  main_request = node->navigation_request();
  ASSERT_TRUE(main_request != nullptr);
  EXPECT_EQ(blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE,
            main_request->common_params().navigation_type);
  reload2->ReadyToCommit();
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// PlzNavigate: Confirm that a speculative RenderFrameHost is used when
// navigating from one site to another.
TEST_F(NavigatorTest, SpeculativeRendererWorksBaseCase) {
  // Navigate to an initial site.
  const GURL kUrlInit("http://wikipedia.org/");
  contents()->NavigateAndCommit(kUrlInit);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  // Begin navigating to another site.
  const GURL kUrl("http://google.com/");
  EXPECT_FALSE(node->navigation_request());
  auto navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
  navigation->Start();
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  auto site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
  ASSERT_TRUE(speculative_rfh);
  EXPECT_NE(speculative_rfh, main_test_rfh());
  if (AreDefaultSiteInstancesEnabled()) {
    EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
  } else {
    EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
              speculative_rfh->GetSiteInstance()->GetSiteInfo());
  }

  navigation->ReadyToCommit();
  EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);

  // Ask the navigation to commit.
  navigation->Commit();
  EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// PlzNavigate: Confirm that a speculative RenderFrameHost is thrown away when
// the final URL's site differs from the initial one due to redirects.
TEST_F(NavigatorTest, SpeculativeRendererDiscardedAfterRedirectToAnotherSite) {
  // Navigate to an initial site.
  const GURL kUrlInit("http://wikipedia.org/");
  contents()->NavigateAndCommit(kUrlInit);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  auto init_site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();

  // Begin navigating to another site.
  const GURL kUrl("http://google.com/");
  EXPECT_FALSE(node->navigation_request());
  auto navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl, contents());
  navigation->Start();

  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  auto site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
  RenderFrameDeletedObserver rfh_deleted_observer(speculative_rfh);
  EXPECT_NE(init_site_instance_id, site_instance_id);
  EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
  EXPECT_NE(speculative_rfh, main_test_rfh());

  if (AreDefaultSiteInstancesEnabled()) {
    EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
  } else {
    EXPECT_EQ(CreateExpectedSiteInfo(kUrl),
              speculative_rfh->GetSiteInstance()->GetSiteInfo());
  }

  // It then redirects to yet another site.
  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request);
  const GURL kUrlRedirect("https://www.google.com/");
  navigation->Redirect(kUrlRedirect);
  EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());

  // For now, ensure that the speculative RenderFrameHost does not change after
  // the redirect.
  // TODO(carlosk): once the speculative RenderFrameHost updates with redirects
  // this next check will be changed to verify that it actually happens.
  EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
  EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
  EXPECT_FALSE(rfh_deleted_observer.deleted());

  // Send the commit to the renderer.
  navigation->ReadyToCommit();

  // Once commit happens the speculative RenderFrameHost is updated to match the
  // known final SiteInstance.
  speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  EXPECT_EQ(speculative_rfh->navigation_requests().size(), 1u);
  EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());

  auto redirect_site_instance_id = speculative_rfh->GetSiteInstance()->GetId();

  // Expect the initial and redirect SiteInstances to be different because
  // they should be associated with different BrowsingInstances.
  EXPECT_NE(init_site_instance_id, redirect_site_instance_id);

  if (AreDefaultSiteInstancesEnabled()) {
    EXPECT_TRUE(speculative_rfh->GetSiteInstance()->IsDefaultSiteInstance());
    EXPECT_EQ(site_instance_id, redirect_site_instance_id);

    // Verify the old speculative RenderFrameHost was not deleted because
    // the SiteInstance stayed the same.
    EXPECT_FALSE(rfh_deleted_observer.deleted());
  } else {
    EXPECT_EQ(CreateExpectedSiteInfo(kUrlRedirect),
              speculative_rfh->GetSiteInstance()->GetSiteInfo());
    EXPECT_NE(site_instance_id, redirect_site_instance_id);

    // Verify the old speculative RenderFrameHost was deleted because
    // the SiteInstance changed.
    EXPECT_TRUE(rfh_deleted_observer.deleted());
  }

  // Invoke DidCommitProvisionalLoad.
  navigation->Commit();

  // Check that the speculative RenderFrameHost was swapped in.
  EXPECT_EQ(redirect_site_instance_id,
            main_test_rfh()->GetSiteInstance()->GetId());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// PlzNavigate: Verify that data urls are properly handled.
TEST_F(NavigatorTest, DataUrls) {
  const GURL kUrl1("http://wikipedia.org/");
  const GURL kUrl2("data:text/html,test");

  // Isolate kUrl1 so it can't be mapped into a default SiteInstance along with
  // kUrl2. This ensures that the speculative RenderFrameHost will always be
  // used because the URLs map to different SiteInstances.
  ChildProcessSecurityPolicy::GetInstance()->AddFutureIsolatedOrigins(
      {url::Origin::Create(kUrl1)},
      ChildProcessSecurityPolicy::IsolatedOriginSource::TEST,
      browser_context());

  // Navigate to an initial site.
  contents()->NavigateAndCommit(kUrl1);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();

  EXPECT_FALSE(main_test_rfh()->GetSiteInstance()->IsDefaultSiteInstance());

  // Navigate to a data url. The request should have been sent to the IO
  // thread and not committed immediately.
  auto navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
  navigation->Start();
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  EXPECT_FALSE(speculative_rfh->is_loading());
  EXPECT_TRUE(node->navigation_request());
  navigation->ReadyToCommit();
  EXPECT_TRUE(speculative_rfh->is_loading());
  EXPECT_FALSE(node->navigation_request());
  EXPECT_NE(main_test_rfh(), speculative_rfh);
  navigation->Commit();
  EXPECT_EQ(main_test_rfh(), speculative_rfh);

  // Go back to the initial site.
  contents()->NavigateAndCommit(kUrl1);

  // Do a renderer-initiated navigation to a data url. The request should be
  // sent to the IO thread.
  auto navigation_to_data_url =
      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
  navigation_to_data_url->Start();
  EXPECT_FALSE(main_test_rfh()->is_loading());
  EXPECT_TRUE(node->navigation_request());
}

// Tests several cases for converting SiteInstanceDescriptors into
// SiteInstances:
// 1) Pointer to the current SiteInstance.
// 2) Pointer to an unrelated SiteInstance.
// 3) Same-site URL, related.
// 4) Cross-site URL, related.
// 5) Same-site URL, unrelated (with and without candidate SiteInstances).
// 6) Cross-site URL, unrelated (with candidate SiteInstance).
TEST_F(NavigatorTest, SiteInstanceDescriptionConversion) {
  // Navigate to set a current SiteInstance on the RenderFrameHost.
  GURL kUrl1("http://a.com");
  // Isolate one of the sites so the both can't be mapped to the default
  // site instance.
  ChildProcessSecurityPolicy::GetInstance()->AddFutureIsolatedOrigins(
      {url::Origin::Create(kUrl1)},
      ChildProcessSecurityPolicy::IsolatedOriginSource::TEST,
      browser_context());
  contents()->NavigateAndCommit(kUrl1);
  SiteInstanceImpl* current_instance = main_test_rfh()->GetSiteInstance();
  ASSERT_TRUE(current_instance);

  // 1) Convert a descriptor pointing to the current instance.
  RenderFrameHostManager* rfhm =
      main_test_rfh()->frame_tree_node()->render_manager();
  {
    SiteInstanceDescriptor descriptor(current_instance);
    scoped_refptr<SiteInstance> converted_instance =
        ConvertToSiteInstance(rfhm, descriptor, nullptr);
    EXPECT_EQ(current_instance, converted_instance);
  }

  // 2) Convert a descriptor pointing an instance unrelated to the current one,
  // with a different site.
  GURL kUrl2("http://b.com");
  scoped_refptr<SiteInstance> unrelated_instance(
      SiteInstance::CreateForURL(browser_context(), kUrl2));
  EXPECT_FALSE(
      current_instance->IsRelatedSiteInstance(unrelated_instance.get()));
  {
    SiteInstanceDescriptor descriptor(unrelated_instance.get());
    scoped_refptr<SiteInstance> converted_instance =
        ConvertToSiteInstance(rfhm, descriptor, nullptr);
    EXPECT_EQ(unrelated_instance.get(), converted_instance);
  }

  // 3) Convert a descriptor of a related instance with the same site as the
  // current one.
  GURL kUrlSameSiteAs1("http://www.a.com/foo");
  {
    SiteInstanceDescriptor descriptor(
        UrlInfo::CreateForTesting(kUrlSameSiteAs1),
        SiteInstanceRelation::RELATED);
    scoped_refptr<SiteInstance> converted_instance =
        ConvertToSiteInstance(rfhm, descriptor, nullptr);
    EXPECT_EQ(current_instance, converted_instance);
  }

  // 4) Convert a descriptor of a related instance with a site different from
  // the current one.
  GURL kUrlSameSiteAs2("http://www.b.com/foo");
  scoped_refptr<SiteInstanceImpl> related_instance;
  {
    SiteInstanceDescriptor descriptor(
        UrlInfo::CreateForTesting(kUrlSameSiteAs2),
        SiteInstanceRelation::RELATED);
    related_instance = ConvertToSiteInstance(rfhm, descriptor, nullptr);
    // If kUrlSameSiteAs2 requires a dedicated process on this platform, this
    // should return a new instance, related to the current and set to the new
    // site URL.
    // Otherwise, this should return the default site instance
    EXPECT_TRUE(
        current_instance->IsRelatedSiteInstance(related_instance.get()));
    EXPECT_NE(current_instance, related_instance.get());
    EXPECT_NE(unrelated_instance.get(), related_instance.get());

    if (AreDefaultSiteInstancesEnabled()) {
      ASSERT_TRUE(related_instance->IsDefaultSiteInstance());
    } else {
      EXPECT_EQ(SiteInfo::CreateForTesting(
                    current_instance->GetIsolationContext(), kUrlSameSiteAs2),
                related_instance->GetSiteInfo());
    }
  }

  // 5) Convert a descriptor of an unrelated instance with the same site as the
  // current one, several times, with and without candidate sites.
  {
    SiteInstanceDescriptor descriptor(
        UrlInfo::CreateForTesting(kUrlSameSiteAs1),
        SiteInstanceRelation::UNRELATED);
    scoped_refptr<SiteInstanceImpl> converted_instance_1 =
        ConvertToSiteInstance(rfhm, descriptor, nullptr);
    // Should return a new instance, unrelated to the current one, set to the
    // provided site URL.
    EXPECT_FALSE(
        current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
    EXPECT_NE(current_instance, converted_instance_1.get());
    EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());
    EXPECT_EQ(CreateExpectedSiteInfo(kUrlSameSiteAs1),
              converted_instance_1->GetSiteInfo());

    // Does the same but this time using unrelated_instance as a candidate,
    // which has a different site.
    scoped_refptr<SiteInstanceImpl> converted_instance_2 =
        ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
    // Should return yet another new instance, unrelated to the current one, set
    // to the same site URL.
    EXPECT_FALSE(
        current_instance->IsRelatedSiteInstance(converted_instance_2.get()));
    EXPECT_NE(current_instance, converted_instance_2.get());
    EXPECT_NE(unrelated_instance.get(), converted_instance_2.get());
    EXPECT_NE(converted_instance_1.get(), converted_instance_2.get());
    EXPECT_EQ(CreateExpectedSiteInfo(kUrlSameSiteAs1),
              converted_instance_1->GetSiteInfo());

    // Converts once more but with |converted_instance_1| as a candidate.
    scoped_refptr<SiteInstance> converted_instance_3 =
        ConvertToSiteInstance(rfhm, descriptor, converted_instance_1.get());
    // Should return |converted_instance_1| because its site matches and it is
    // unrelated to the current SiteInstance.
    EXPECT_EQ(converted_instance_1.get(), converted_instance_3);
  }

  // 6) Convert a descriptor of an unrelated instance with the same site of
  // related_instance and using it as a candidate.
  {
    SiteInstanceDescriptor descriptor(
        UrlInfo::CreateForTesting(kUrlSameSiteAs2),
        SiteInstanceRelation::UNRELATED);
    scoped_refptr<SiteInstanceImpl> converted_instance_1 =
        ConvertToSiteInstance(rfhm, descriptor, related_instance.get());
    // Should return a new instance, unrelated to the current, set to the
    // provided site URL.
    EXPECT_FALSE(
        current_instance->IsRelatedSiteInstance(converted_instance_1.get()));
    EXPECT_NE(related_instance.get(), converted_instance_1.get());
    EXPECT_NE(unrelated_instance.get(), converted_instance_1.get());

    if (AreDefaultSiteInstancesEnabled()) {
      EXPECT_TRUE(converted_instance_1->IsDefaultSiteInstance());
    } else {
      EXPECT_EQ(CreateExpectedSiteInfo(kUrlSameSiteAs2),
                converted_instance_1->GetSiteInfo());
    }

    scoped_refptr<SiteInstance> converted_instance_2 =
        ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
    // Should return |unrelated_instance| because its site matches and it is
    // unrelated to the current SiteInstance.
    EXPECT_EQ(unrelated_instance.get(), converted_instance_2);
  }
}

// A renderer process might try and claim that a cross site navigation was
// within the same document by setting was_within_same_document = true in
// DidCommitProvisionalLoadParams. Such case should be detected on the browser
// side and the renderer process should be killed.
TEST_F(NavigatorTest, CrossSiteClaimWithinPage) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.google.com/");

  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl1);

  // Navigate to a different site and claim that the navigation was within same
  // page.
  int bad_msg_count = process()->bad_msg_count();
  auto simulator =
      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
  simulator->CommitSameDocument();
  EXPECT_EQ(process()->bad_msg_count(), bad_msg_count + 1);
}

// Permissions Policy: Test that the permissions policy is reset when navigating
// pages within a site.
TEST_F(NavigatorTest, PermissionsPolicySameSiteNavigation) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.chromium.org/Home");

  contents()->NavigateAndCommit(kUrl1);

  // Check the permissions policy before navigation.
  const blink::PermissionsPolicy* original_permissions_policy =
      main_test_rfh()->permissions_policy();
  ASSERT_TRUE(original_permissions_policy);

  // Navigate to the new URL.
  contents()->NavigateAndCommit(kUrl2);

  // Check the permissions policy after navigation.
  const blink::PermissionsPolicy* final_permissions_policy =
      main_test_rfh()->permissions_policy();
  ASSERT_TRUE(final_permissions_policy);
  ASSERT_NE(original_permissions_policy, final_permissions_policy);
}

// Permissions Policy: Test that the permissions policy is not reset when
// navigating within a page.
TEST_F(NavigatorTest, PermissionsPolicyFragmentNavigation) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.chromium.org/#Home");

  contents()->NavigateAndCommit(kUrl1);

  // Check the permissions policy before navigation.
  const blink::PermissionsPolicy* original_permissions_policy =
      main_test_rfh()->permissions_policy();
  ASSERT_TRUE(original_permissions_policy);

  // Navigate to the new URL.
  contents()->NavigateAndCommit(kUrl2);

  // Check the permissions policy after navigation.
  const blink::PermissionsPolicy* final_permissions_policy =
      main_test_rfh()->permissions_policy();
  ASSERT_EQ(original_permissions_policy, final_permissions_policy);
}

// Permissions Policy: Test that the permissions policy is set correctly when
// inserting a new child frame.
TEST_F(NavigatorTest, PermissionsPolicyNewChild) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.chromium.org/Home");

  contents()->NavigateAndCommit(kUrl1);

  // Simulate the navigation triggered by inserting a child frame into a page.
  TestRenderFrameHost* subframe_rfh =
      contents()->GetPrimaryMainFrame()->AppendChild("child");
  NavigationSimulator::NavigateAndCommitFromDocument(kUrl2, subframe_rfh);

  const blink::PermissionsPolicy* subframe_permissions_policy =
      subframe_rfh->permissions_policy();
  ASSERT_TRUE(subframe_permissions_policy);
  ASSERT_FALSE(subframe_permissions_policy->GetOriginForTest().opaque());
}

TEST_F(NavigatorTest, TwoNavigationsRacingCommit) {
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl2("http://www.chromium.org/Home");

  EXPECT_EQ(0u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());

  // Have the first navigation reach ReadyToCommit.
  auto first_navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
  first_navigation->ReadyToCommit();
  EXPECT_EQ(1u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());

  // A second navigation starts and reaches ReadyToCommit.
  auto second_navigation =
      NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
  second_navigation->ReadyToCommit();
  EXPECT_EQ(2u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());

  // The first navigation commits.
  first_navigation->Commit();
  EXPECT_EQ(1u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());

  // The second navigation commits.
  second_navigation->Commit();
  EXPECT_EQ(0u, contents()->GetPrimaryMainFrame()->navigation_requests_.size());
}

}  // namespace content
