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

#include <stdint.h>

#include "base/macros.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/streams/stream.h"
#include "content/common/frame_messages.h"
#include "content/common/navigation_params.h"
#include "content/common/site_isolation_policy.h"
#include "content/public/browser/stream_handle.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_utils.h"
#include "content/test/browser_side_navigation_test_utils.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"

#if !defined(OS_ANDROID)
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#endif

namespace content {

class NavigatorTestWithBrowserSideNavigation
    : public RenderViewHostImplTestHarness {
 public:
  // Re-defines the private RenderFrameHostManager::SiteInstanceDescriptor here
  // to allow access to it from tests.
  typedef RenderFrameHostManager::SiteInstanceDescriptor SiteInstanceDescriptor;

  void SetUp() override {
#if !defined(OS_ANDROID)
    ImageTransportFactory::InitializeForUnitTests(
        scoped_ptr<ImageTransportFactory>(
            new NoTransportImageTransportFactory));
#endif
    EnableBrowserSideNavigation();
    RenderViewHostImplTestHarness::SetUp();
  }

  void TearDown() override {
    RenderViewHostImplTestHarness::TearDown();
#if !defined(OS_ANDROID)
    ImageTransportFactory::Terminate();
#endif
  }

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

  // Requests a navigation of the specified FrameTreeNode to the specified URL;
  // returns the unique ID of the pending NavigationEntry.
  int RequestNavigation(FrameTreeNode* node, const GURL& url) {
    return RequestNavigationWithParameters(node, url, Referrer(),
                                           ui::PAGE_TRANSITION_LINK);
  }

  // Requests a navigation of the specified FrameTreeNode to the specified URL,
  // using other specified parameters; returns the unique ID of the pending
  // NavigationEntry.
  int RequestNavigationWithParameters(
      FrameTreeNode* node,
      const GURL& url,
      const Referrer& referrer,
      ui::PageTransition transition_type) {
    NavigationController::LoadURLParams load_params(url);
    load_params.frame_tree_node_id = node->frame_tree_node_id();
    load_params.referrer = referrer;
    load_params.transition_type = transition_type;

    controller().LoadURLWithParams(load_params);
    return controller().GetPendingEntry()->GetUniqueID();
  }

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

  // Checks if this RenderFrameHost sent a single FrameMsg_CommitNavigation
  // since the last clearing of the sink.
  // Note: caller must invoke ClearMessages on the sink at some point before
  // the tracked commit happens to clear up commit messages from previous
  // navigations.
  bool DidRenderFrameHostRequestCommit(TestRenderFrameHost* rfh) {
    const IPC::Message* message =
        rfh->GetProcess()->sink().GetUniqueMessageMatching(
            FrameMsg_CommitNavigation::ID);
    return message && rfh->GetRoutingID() == message->routing_id();
  }

  SiteInstance* ConvertToSiteInstance(RenderFrameHostManager* rfhm,
                                      const SiteInstanceDescriptor& descriptor,
                                      SiteInstance* candidate_instance) {
    return rfhm->ConvertToSiteInstance(descriptor, candidate_instance);
  }
};

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

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

  // Start a browser-initiated navigation.
  int32_t site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  int entry_id = RequestNavigation(node, kUrl);
  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 ACK from the renderer and start right away.
  EXPECT_EQ(NavigationRequest::STARTED, request->state());
  ASSERT_TRUE(GetLoaderForNavigationRequest(request));
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  EXPECT_FALSE(node->render_manager()->pending_frame_host());

  // Have the current RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(request)
      ->CallOnResponseStarted(response, MakeEmptyStream());
  EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
  EXPECT_TRUE(main_test_rfh()->is_loading());
  EXPECT_FALSE(node->navigation_request());

  // Commit the navigation.
  main_test_rfh()->SendNavigate(0, entry_id, true, kUrl);
  EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
  EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
            main_test_rfh()->GetSiteInstance()->GetSiteURL());
  EXPECT_EQ(kUrl, contents()->GetLastCommittedURL());
  EXPECT_FALSE(node->render_manager()->pending_frame_host());

  // 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));

  // With PlzNavigate enabled a pending RenderFrameHost should never exist.
  EXPECT_FALSE(node->render_manager()->pending_frame_host());
}

// PlzNavigate: Test a complete renderer-initiated same-site navigation.
TEST_F(NavigatorTestWithBrowserSideNavigation,
       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());

  // Start a renderer-initiated non-user-initiated navigation.
  process()->sink().ClearMessages();
  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  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::STARTED, request->state());
  EXPECT_FALSE(request->begin_params().has_user_gesture);
  EXPECT_EQ(kUrl2, request->common_params().url);
  EXPECT_FALSE(request->browser_initiated());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // Have the current RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(request)
      ->CallOnResponseStarted(response, MakeEmptyStream());
  EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
  EXPECT_TRUE(main_test_rfh()->is_loading());
  EXPECT_FALSE(node->navigation_request());

  // Commit the navigation.
  main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
  EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
  EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2),
            main_test_rfh()->GetSiteInstance()->GetSiteURL());
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  EXPECT_FALSE(node->render_manager()->pending_frame_host());
}

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

  contents()->NavigateAndCommit(kUrl1);
  EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
  int32_t site_instance_id_1 = main_test_rfh()->GetSiteInstance()->GetId();

  // Start a renderer-initiated non-user-initiated navigation.
  process()->sink().ClearMessages();
  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  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::STARTED, request->state());
  EXPECT_FALSE(request->begin_params().has_user_gesture);
  EXPECT_EQ(kUrl2, request->common_params().url);
  EXPECT_FALSE(request->browser_initiated());
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

  // Have the current RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(request)
      ->CallOnResponseStarted(response, MakeEmptyStream());
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(
        DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
  } else {
    EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
  }
  EXPECT_TRUE(main_test_rfh()->is_loading());
  EXPECT_FALSE(node->navigation_request());

  // Commit the navigation.
  main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
  EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  EXPECT_FALSE(node->render_manager()->pending_frame_host());

  // The SiteInstance did not change.
  EXPECT_EQ(site_instance_id_1, main_test_rfh()->GetSiteInstance()->GetId());
}

// PlzNavigate: Test that a beforeUnload denial cancels the navigation.
TEST_F(NavigatorTestWithBrowserSideNavigation,
       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();
  RequestNavigation(node, kUrl2);
  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()->SendBeforeUnloadACK(false);
  EXPECT_FALSE(node->navigation_request());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  EXPECT_TRUE(rfh_deleted_observer.deleted());
}

// PlzNavigate: Test that a proper NavigationRequest is created by
// RequestNavigation.
TEST_F(NavigatorTestWithBrowserSideNavigation, 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()->GetFrameTree()->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();
  RequestNavigation(subframe_node, kUrl2);
  NavigationRequest* subframe_request = subframe_node->navigation_request();
  TestNavigationURLLoader* subframe_loader =
      GetLoaderForNavigationRequest(subframe_request);

  // Subframe navigations should start right away as they don't have to request
  // beforeUnload to run at the renderer.
  ASSERT_TRUE(subframe_request);
  ASSERT_TRUE(subframe_loader);
  EXPECT_EQ(NavigationRequest::STARTED, subframe_request->state());
  EXPECT_EQ(kUrl2, subframe_request->common_params().url);
  EXPECT_EQ(kUrl2, subframe_loader->request_info()->common_params.url);
  // First party for cookies url should be that of the main frame.
  EXPECT_EQ(kUrl1, subframe_loader->request_info()->first_party_for_cookies);
  EXPECT_FALSE(subframe_loader->request_info()->is_main_frame);
  EXPECT_TRUE(subframe_loader->request_info()->parent_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 is enabled. In that case, as the subframe
  // navigation is to a different site and is still ongoing, it should have one.
  if (AreAllSitesIsolatedForTesting()) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
  }

  // Now start a navigation at the root node.
  RequestNavigation(root_node, kUrl3);
  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));

  // Simulate a BeforeUnloadACK IPC on the main frame.
  main_test_rfh()->SendBeforeUnloadACK(true);
  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_EQ(kUrl3, main_loader->request_info()->first_party_for_cookies);
  EXPECT_TRUE(main_loader->request_info()->is_main_frame);
  EXPECT_FALSE(main_loader->request_info()->parent_is_main_frame);
  EXPECT_TRUE(main_request->browser_initiated());
  // BeforeUnloadACK was received from the renderer so the navigation should
  // have started.
  EXPECT_EQ(NavigationRequest::STARTED, 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 (AreAllSitesIsolatedForTesting()) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(subframe_node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(subframe_node));
  }
}

// PlzNavigate: Test that committing an HTTP 204 or HTTP 205 response cancels
// the navigation.
TEST_F(NavigatorTestWithBrowserSideNavigation, 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.
  process()->sink().ClearMessages();
  RequestNavigation(node, kUrl2);
  main_test_rfh()->SendBeforeUnloadACK(true);

  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.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  const char kNoContentHeaders[] = "HTTP/1.1 204 No Content\0\0";
  response->head.headers = new net::HttpResponseHeaders(
      std::string(kNoContentHeaders, arraysize(kNoContentHeaders)));
  GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
      response, MakeEmptyStream());

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

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

  // Navigate to a different site again.
  process()->sink().ClearMessages();
  RequestNavigation(node, kUrl2);
  main_test_rfh()->SendBeforeUnloadACK(true);

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

  // Commit an HTTP 205 response.
  response = new ResourceResponse;
  const char kResetContentHeaders[] = "HTTP/1.1 205 Reset Content\0\0";
  response->head.headers = new net::HttpResponseHeaders(
      std::string(kResetContentHeaders, arraysize(kResetContentHeaders)));
  GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
      response, MakeEmptyStream());

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

// PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
// site navigation.
TEST_F(NavigatorTestWithBrowserSideNavigation, 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.
  process()->sink().ClearMessages();
  int entry_id = RequestNavigation(node, kUrl2);
  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request);
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);

  // Receive the beforeUnload ACK.
  main_test_rfh()->SendBeforeUnloadACK(true);
  EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
  EXPECT_FALSE(contents()->CrossProcessNavigationPending());

  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
      response, MakeEmptyStream());
  EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
  EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
  EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
  EXPECT_TRUE(contents()->CrossProcessNavigationPending());

  speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);

  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));
}

// PlzNavigate: Test that redirects are followed and the speculative
// RenderFrameHost logic behaves as expected.
TEST_F(NavigatorTestWithBrowserSideNavigation, 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.
  process()->sink().ClearMessages();
  int entry_id = RequestNavigation(node, kUrl1);
  main_test_rfh()->SendBeforeUnloadACK(true);
  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request);
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // It then redirects to another site.
  GetLoaderForNavigationRequest(main_request)->SimulateServerRedirect(kUrl2);

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

  // Have the RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
      response, MakeEmptyStream());
  TestRenderFrameHost* final_speculative_rfh =
      GetSpeculativeRenderFrameHost(node);
  EXPECT_TRUE(final_speculative_rfh);
  EXPECT_TRUE(DidRenderFrameHostRequestCommit(final_speculative_rfh));

  // Commit the navigation.
  final_speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
  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));
}

// PlzNavigate: 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(NavigatorTestWithBrowserSideNavigation,
       BrowserInitiatedNavigationCancel) {
  const GURL kUrl0("http://www.wikipedia.org/");
  const GURL kUrl1("http://www.chromium.org/");
  const GURL kUrl1_site = SiteInstance::GetSiteForURL(browser_context(), kUrl1);
  const GURL kUrl2("http://www.google.com/");
  const GURL kUrl2_site = SiteInstance::GetSiteForURL(browser_context(), kUrl2);

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

  // Request navigation to the 1st URL.
  process()->sink().ClearMessages();
  RequestNavigation(node, kUrl1);
  main_test_rfh()->SendBeforeUnloadACK(true);
  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);
  int32_t site_instance_id_1 = speculative_rfh->GetSiteInstance()->GetId();
  EXPECT_EQ(kUrl1_site, speculative_rfh->GetSiteInstance()->GetSiteURL());

  // Request navigation to the 2nd URL; the NavigationRequest must have been
  // replaced by a new one with a different URL.
  int entry_id = RequestNavigation(node, kUrl2);
  main_test_rfh()->SendBeforeUnloadACK(true);
  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);
  int32_t site_instance_id_2 = speculative_rfh->GetSiteInstance()->GetId();
  EXPECT_NE(site_instance_id_1, site_instance_id_2);

  // Have the RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
      response, MakeEmptyStream());
  EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
  EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));

  // Commit the navigation.
  speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);

  // Confirm that the commit corresponds to the new request.
  ASSERT_TRUE(main_test_rfh());
  EXPECT_EQ(kUrl2_site, main_test_rfh()->GetSiteInstance()->GetSiteURL());
  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());
}

// PlzNavigate: Test that a browser-initiated navigation is canceled if a
// renderer-initiated user-initiated request has been issued in the meantime.
TEST_F(NavigatorTestWithBrowserSideNavigation,
       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();

  // Start a browser-initiated navigation to the 1st URL and receive its
  // beforeUnload ACK.
  process()->sink().ClearMessages();
  RequestNavigation(node, kUrl1);
  main_test_rfh()->SendBeforeUnloadACK(true);
  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.
  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, true);
  NavigationRequest* request2 = node->navigation_request();
  ASSERT_TRUE(request2);
  EXPECT_EQ(kUrl2, request2->common_params().url);
  EXPECT_FALSE(request2->browser_initiated());
  EXPECT_TRUE(request2->begin_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 (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

  // Have the RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(request2)
      ->CallOnResponseStarted(response, MakeEmptyStream());
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(
        DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
  } else {
    EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
  }

  // Commit the navigation.
  main_test_rfh()->SendNavigate(1, 0, true, kUrl2);

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

// PlzNavigate: Test that a renderer-initiated user-initiated navigation is NOT
// canceled if a renderer-initiated non-user-initiated request is issued in the
// meantime.
TEST_F(NavigatorTestWithBrowserSideNavigation,
       RendererNonUserInitiatedNavigationDoesntCancelRendererUserInitiated) {
  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 renderer-initiated user-initiated navigation to the 1st URL.
  process()->sink().ClearMessages();
  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, true);
  NavigationRequest* request1 = node->navigation_request();
  ASSERT_TRUE(request1);
  EXPECT_EQ(kUrl1, request1->common_params().url);
  EXPECT_FALSE(request1->browser_initiated());
  EXPECT_TRUE(request1->begin_params().has_user_gesture);
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

  // Now receive a renderer-initiated non-user-initiated request. Nothing should
  // change.
  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
  NavigationRequest* request2 = node->navigation_request();
  ASSERT_TRUE(request2);
  EXPECT_EQ(request1, request2);
  EXPECT_EQ(kUrl1, request2->common_params().url);
  EXPECT_FALSE(request2->browser_initiated());
  EXPECT_TRUE(request2->begin_params().has_user_gesture);
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

  // Have the RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(request2)
      ->CallOnResponseStarted(response, MakeEmptyStream());
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(
        DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
  } else {
    EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
  }

  // Commit the navigation.
  main_test_rfh()->SendNavigate(1, 0, true, kUrl1);
  EXPECT_EQ(kUrl1, 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(NavigatorTestWithBrowserSideNavigation,
       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.
  process()->sink().ClearMessages();
  int entry_id = RequestNavigation(node, kUrl1);
  NavigationRequest* request1 = node->navigation_request();
  ASSERT_TRUE(request1);
  EXPECT_EQ(kUrl1, request1->common_params().url);
  EXPECT_TRUE(request1->browser_initiated());
  EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));

  // Now receive a renderer-initiated non-user-initiated request. Nothing should
  // change.
  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
  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(GetSpeculativeRenderFrameHost(node));

  // Now receive the beforeUnload ACK from the still ongoing navigation.
  main_test_rfh()->SendBeforeUnloadACK(true);
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);

  // Have the RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(request2)
      ->CallOnResponseStarted(response, MakeEmptyStream());
  EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
  EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));

  // Commit the navigation.
  speculative_rfh->SendNavigate(0, entry_id, true, kUrl1);
  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(NavigatorTestWithBrowserSideNavigation,
       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();
  int32_t site_instance_id_0 = main_test_rfh()->GetSiteInstance()->GetId();

  // Start a renderer-initiated non-user-initiated navigation to the 1st URL.
  process()->sink().ClearMessages();
  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, false);
  NavigationRequest* request1 = node->navigation_request();
  ASSERT_TRUE(request1);
  EXPECT_EQ(kUrl1, request1->common_params().url);
  EXPECT_FALSE(request1->browser_initiated());
  EXPECT_FALSE(request1->begin_params().has_user_gesture);
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    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.
  main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, false);
  NavigationRequest* request2 = node->navigation_request();
  EXPECT_EQ(kUrl2, request2->common_params().url);
  EXPECT_FALSE(request2->browser_initiated());
  EXPECT_FALSE(request2->begin_params().has_user_gesture);
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
  } else {
    EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  }

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

  // Have the RenderFrameHost commit the navigation.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(request2)
      ->CallOnResponseStarted(response, MakeEmptyStream());
  if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
    EXPECT_TRUE(
        DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
  } else {
    EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
  }

  // Commit the navigation.
  main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
  EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());

  // The SiteInstance did not change.
  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(NavigatorTestWithBrowserSideNavigation, Reload) {
  const GURL kUrl("http://www.google.com/");
  contents()->NavigateAndCommit(kUrl);

  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  controller().Reload(false);
  int entry_id = controller().GetPendingEntry()->GetUniqueID();
  // A NavigationRequest should have been generated.
  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request != NULL);
  EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD,
            main_request->common_params().navigation_type);
  main_test_rfh()->PrepareForCommit();
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  main_test_rfh()->SendNavigate(0, entry_id, false, kUrl);
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));

  // Now do a shift+reload.
  controller().ReloadIgnoringCache(false);
  // A NavigationRequest should have been generated.
  main_request = node->navigation_request();
  ASSERT_TRUE(main_request != NULL);
  EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE,
            main_request->common_params().navigation_type);
  main_test_rfh()->PrepareForCommit();
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// PlzNavigate: Confirm that a speculative RenderFrameHost is used when
// navigating from one site to another.
TEST_F(NavigatorTestWithBrowserSideNavigation,
       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/");
  process()->sink().ClearMessages();
  int entry_id = RequestNavigation(node, kUrl);
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  EXPECT_NE(speculative_rfh, main_test_rfh());

  // Receive the beforeUnload ACK.
  main_test_rfh()->SendBeforeUnloadACK(true);
  EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
  EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
            speculative_rfh->GetSiteInstance()->GetSiteURL());
  EXPECT_FALSE(node->render_manager()->pending_frame_host());
  int32_t site_instance_id = speculative_rfh->GetSiteInstance()->GetId();

  // Ask Navigator to commit the navigation by simulating a call to
  // OnResponseStarted.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(node->navigation_request())
      ->CallOnResponseStarted(response, MakeEmptyStream());
  EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
  EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
  EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
  EXPECT_FALSE(node->render_manager()->pending_frame_host());

  // Invoke OnDidCommitProvisionalLoad.
  speculative_rfh->SendNavigate(0, entry_id, true, kUrl);
  EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
  EXPECT_FALSE(node->render_manager()->pending_frame_host());
}

// 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(NavigatorTestWithBrowserSideNavigation,
       SpeculativeRendererDiscardedAfterRedirectToAnotherSite) {
  // Navigate to an initial site.
  const GURL kUrlInit("http://wikipedia.org/");
  contents()->NavigateAndCommit(kUrlInit);
  FrameTreeNode* node = main_test_rfh()->frame_tree_node();
  int32_t init_site_instance_id = main_test_rfh()->GetSiteInstance()->GetId();

  // Begin navigating to another site.
  const GURL kUrl("http://google.com/");
  process()->sink().ClearMessages();
  int entry_id = RequestNavigation(node, kUrl);
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  int32_t 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());
  EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
            speculative_rfh->GetSiteInstance()->GetSiteURL());

  // Receive the beforeUnload ACK.
  main_test_rfh()->SendBeforeUnloadACK(true);
  EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));

  // It then redirects to yet another site.
  NavigationRequest* main_request = node->navigation_request();
  ASSERT_TRUE(main_request);
  const GURL kUrlRedirect("https://www.google.com/");
  GetLoaderForNavigationRequest(main_request)
      ->SimulateServerRedirect(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());

  // Commit the navigation with Navigator by simulating the call to
  // OnResponseStarted.
  scoped_refptr<ResourceResponse> response(new ResourceResponse);
  GetLoaderForNavigationRequest(main_request)
      ->CallOnResponseStarted(response, MakeEmptyStream());
  speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
  EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
  EXPECT_TRUE(rfh_deleted_observer.deleted());

  // Once commit happens the speculative RenderFrameHost is updated to match the
  // known final SiteInstance.
  EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrlRedirect),
            speculative_rfh->GetSiteInstance()->GetSiteURL());
  int32_t redirect_site_instance_id =
      speculative_rfh->GetSiteInstance()->GetId();
  EXPECT_NE(init_site_instance_id, redirect_site_instance_id);
  EXPECT_NE(site_instance_id, redirect_site_instance_id);

  // Invoke OnDidCommitProvisionalLoad.
  speculative_rfh->SendNavigate(0, entry_id, true, kUrlRedirect);

  // 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(NavigatorTestWithBrowserSideNavigation, DataUrls) {
  const GURL kUrl1("http://wikipedia.org/");
  const GURL kUrl2("data:text/html,test");

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

  // Navigate to a data url. The request should not have been sent to the IO
  // thread but committed immediately.
  int entry_id = RequestNavigation(node, kUrl2);
  TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
  ASSERT_TRUE(speculative_rfh);
  EXPECT_TRUE(speculative_rfh->is_loading());
  EXPECT_FALSE(node->navigation_request());
  speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
  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 not be
  // sent to the IO thread, nor committed.
  TestRenderFrameHost* main_rfh = main_test_rfh();
  main_rfh->SendRendererInitiatedNavigationRequest(kUrl2, true);
  EXPECT_TRUE(main_rfh->is_loading());
  EXPECT_FALSE(node->navigation_request());
  EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}

// 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(NavigatorTestWithBrowserSideNavigation,
       SiteInstanceDescriptionConversion) {
  // Navigate to set a current SiteInstance on the RenderFrameHost.
  GURL kUrl1("http://a.com");
  contents()->NavigateAndCommit(kUrl1);
  SiteInstance* 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);
    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());
    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(browser_context(), kUrlSameSiteAs1, true);
    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<SiteInstance> related_instance;
  {
    SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2, true);
    related_instance = ConvertToSiteInstance(rfhm, descriptor, nullptr);
    // Should return a new instance, related to the current, set to the new site
    // URL.
    EXPECT_TRUE(
        current_instance->IsRelatedSiteInstance(related_instance.get()));
    EXPECT_NE(current_instance, related_instance.get());
    EXPECT_NE(unrelated_instance.get(), related_instance.get());
    EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
              related_instance->GetSiteURL());
  }

  // 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(browser_context(), kUrlSameSiteAs1,
                                      false);
    scoped_refptr<SiteInstance> 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(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1),
              converted_instance_1->GetSiteURL());

    // Does the same but this time using unrelated_instance as a candidate,
    // which has a different site.
    scoped_refptr<SiteInstance> 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(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs1),
              converted_instance_2->GetSiteURL());

    // Converts once more but with |converted_instance_1| as a candidate.
    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(browser_context(), kUrlSameSiteAs2,
                                      false);
    scoped_refptr<SiteInstance> 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());
    EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
              converted_instance_1->GetSiteURL());

    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);
  }
}

namespace {
void SetWithinPage(const GURL& url,
                   FrameHostMsg_DidCommitProvisionalLoad_Params* params) {
  params->was_within_same_page = true;
  params->url = url;
  params->origin = url::Origin(url);
}
}

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

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

  // Navigate to a different site.
  int entry_id = RequestNavigation(node, kUrl2);
  main_test_rfh()->PrepareForCommit();

  // Claim that the navigation was within same page.
  int bad_msg_count = process()->bad_msg_count();
  GetSpeculativeRenderFrameHost(node)->SendNavigateWithModificationCallback(
      0, entry_id, true, kUrl2, base::Bind(SetWithinPage, kUrl1));
  EXPECT_EQ(process()->bad_msg_count(), bad_msg_count + 1);
}

}  // namespace content
