// Copyright 2013 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 <stddef.h>

#include <limits>
#include <memory>
#include <vector>

#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "content/common/frame_messages.h"
#include "content/common/frame_owner_properties.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/frame/frame_policy.h"

namespace content {

class RenderProcessHostUnitTest : public RenderViewHostImplTestHarness {};

// Tests that guest RenderProcessHosts are not considered suitable hosts when
// searching for RenderProcessHost.
TEST_F(RenderProcessHostUnitTest, GuestsAreNotSuitableHosts) {
  GURL test_url("http://foo.com");

  MockRenderProcessHost guest_host(browser_context());
  guest_host.set_is_for_guests_only(true);

  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), test_url);
  EXPECT_FALSE(RenderProcessHostImpl::IsSuitableHost(
      &guest_host, browser_context(), site_instance->GetSiteURL(),
      site_instance->lock_url()));
  EXPECT_TRUE(RenderProcessHostImpl::IsSuitableHost(
      process(), browser_context(), site_instance->GetSiteURL(),
      site_instance->lock_url()));
  EXPECT_EQ(process(),
            RenderProcessHostImpl::GetExistingProcessHost(site_instance.get()));
}

#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
TEST_F(RenderProcessHostUnitTest, RendererProcessLimit) {
  // This test shouldn't run with --site-per-process mode, which prohibits
  // the renderer process reuse this test explicitly exercises.
  if (AreAllSitesIsolatedForTesting())
    return;

  // Verify that the limit is between 1 and kMaxRendererProcessCount.
  EXPECT_GT(RenderProcessHostImpl::GetMaxRendererProcessCount(), 0u);
  EXPECT_LE(RenderProcessHostImpl::GetMaxRendererProcessCount(),
      kMaxRendererProcessCount);

  // Add dummy process hosts to saturate the limit.
  ASSERT_NE(0u, kMaxRendererProcessCount);
  std::vector<std::unique_ptr<MockRenderProcessHost>> hosts;
  for (size_t i = 0; i < kMaxRendererProcessCount; ++i) {
    hosts.push_back(std::make_unique<MockRenderProcessHost>(browser_context()));
  }

  // Verify that the renderer sharing will happen.
  GURL test_url("http://foo.com");
  EXPECT_TRUE(RenderProcessHostImpl::ShouldTryToUseExistingProcessHost(
        browser_context(), test_url));
}
#endif

#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
TEST_F(RenderProcessHostUnitTest, NoRendererProcessLimitOnAndroidOrChromeOS) {
  // Add a few dummy process hosts.
  ASSERT_NE(0u, kMaxRendererProcessCount);
  std::vector<std::unique_ptr<MockRenderProcessHost>> hosts;
  for (size_t i = 0; i < kMaxRendererProcessCount; ++i) {
    hosts.push_back(std::make_unique<MockRenderProcessHost>(browser_context()));
  }

  // Verify that the renderer sharing still won't happen.
  GURL test_url("http://foo.com");
  EXPECT_FALSE(RenderProcessHostImpl::ShouldTryToUseExistingProcessHost(
        browser_context(), test_url));
}
#endif

// Tests that RenderProcessHost reuse considers committed sites correctly.
TEST_F(RenderProcessHostUnitTest, ReuseCommittedSite) {
  const GURL kUrl1("http://foo.com");
  const GURL kUrl2("http://bar.com");

  // At first, trying to get a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Have the main frame navigate to the first url. Getting a RenderProcessHost
  // with the REUSE_PENDING_OR_COMMITTED_SITE policy should now return the
  // process of the main RFH.
  NavigateAndCommit(kUrl1);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Navigate away. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should again return a new process.
  NavigateAndCommit(kUrl2);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
  // Now add a subframe that navigates to kUrl1. Getting a RenderProcessHost
  // with the REUSE_PENDING_OR_COMMITTED_SITE policy for kUrl1 should now
  // return the process of the subframe RFH.
  std::string unique_name("uniqueName0");
  main_test_rfh()->OnCreateChildFrame(
      process()->GetNextRoutingID(),
      TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
      blink::WebTreeScopeType::kDocument, std::string(), unique_name, false,
      base::UnguessableToken::Create(), blink::FramePolicy(),
      FrameOwnerProperties(), blink::FrameOwnerElementType::kIframe);
  TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
      contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
  subframe = static_cast<TestRenderFrameHost*>(
      NavigationSimulator::NavigateAndCommitFromDocument(kUrl1, subframe));
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(subframe->GetProcess(), site_instance->GetProcess());
}

// Check that only new processes that haven't yet hosted any web content are
// allowed to be reused to host a site requiring a dedicated process.
TEST_F(RenderProcessHostUnitTest, IsUnused) {
  const GURL kUrl1("http://foo.com");

  // A process for a SiteInstance that has no site should be able to host any
  // site that requires a dedicated process.
  EXPECT_FALSE(main_test_rfh()->GetSiteInstance()->HasSite());
  EXPECT_TRUE(main_test_rfh()->GetProcess()->IsUnused());
  {
    scoped_refptr<SiteInstanceImpl> site_instance =
        SiteInstanceImpl::Create(browser_context());
    EXPECT_FALSE(site_instance->HasSite());
    EXPECT_TRUE(site_instance->GetProcess()->IsUnused());
  }

  // Navigation should mark the process as unable to become a dedicated process
  // for arbitrary sites.
  NavigateAndCommit(kUrl1);
  EXPECT_FALSE(main_test_rfh()->GetProcess()->IsUnused());

  // A process for a SiteInstance with a preassigned site should be considered
  // "used" from the point the process is created via GetProcess().
  {
    scoped_refptr<SiteInstanceImpl> site_instance =
        SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
    EXPECT_FALSE(site_instance->GetProcess()->IsUnused());
  }
}

TEST_F(RenderProcessHostUnitTest, ReuseUnmatchedServiceWorkerProcess) {
  const GURL kUrl("https://foo.com");

  // Gets a RenderProcessHost for an unmatched service worker.
  scoped_refptr<SiteInstanceImpl> sw_site_instance1 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance1->set_is_for_service_worker();
  RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess();

  // Getting a RenderProcessHost for a service worker with DEFAULT reuse policy
  // should not reuse the existing service worker's process. We create this
  // second service worker to test the "find the newest process" logic later.
  scoped_refptr<SiteInstanceImpl> sw_site_instance2 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance2->set_is_for_service_worker();
  RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess();
  EXPECT_NE(sw_host1, sw_host2);

  // Getting a RenderProcessHost for a navigation to the same site must reuse
  // the newest unmatched service worker's process (i.e., sw_host2).
  scoped_refptr<SiteInstanceImpl> site_instance1 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  EXPECT_EQ(sw_host2, site_instance1->GetProcess());

  // Getting a RenderProcessHost for a navigation to the same site must reuse
  // the newest unmatched service worker's process (i.e., sw_host1). sw_host2
  // is no longer unmatched, so sw_host1 is now the newest (and only) process
  // with a corresponding unmatched service worker.
  scoped_refptr<SiteInstanceImpl> site_instance2 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  EXPECT_EQ(sw_host1, site_instance2->GetProcess());

  // Getting a RenderProcessHost for a navigation should return a new process
  // because there is no unmatched service worker's process.
  scoped_refptr<SiteInstanceImpl> site_instance3 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  EXPECT_NE(sw_host1, site_instance3->GetProcess());
  EXPECT_NE(sw_host2, site_instance3->GetProcess());
}

class UnsuitableHostContentBrowserClient : public ContentBrowserClient {
 public:
  UnsuitableHostContentBrowserClient() {}
  ~UnsuitableHostContentBrowserClient() override {}

 private:
  bool IsSuitableHost(RenderProcessHost* process_host,
                      const GURL& site_url) override {
    return false;
  }
};

// Check that an unmatched ServiceWorker process is not reused when it's not a
// suitable host for the destination URL.  See https://crbug.com/782349.
TEST_F(RenderProcessHostUnitTest,
       DontReuseUnsuitableUnmatchedServiceWorkerProcess) {
  const GURL kUrl("https://foo.com");

  // Gets a RenderProcessHost for an unmatched service worker.
  scoped_refptr<SiteInstanceImpl> sw_site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance->set_is_for_service_worker();
  RenderProcessHost* sw_host = sw_site_instance->GetProcess();

  // Simulate a situation where |sw_host| won't be considered suitable for
  // future navigations to |kUrl|.  In https://crbug.com/782349, this happened
  // when |kUrl| corresponded to a nonexistent extension, but
  // chrome-extension:// URLs can't be tested inside content/.  Instead,
  // install a ContentBrowserClient which will return false when IsSuitableHost
  // is consulted.
  UnsuitableHostContentBrowserClient modified_client;
  ContentBrowserClient* regular_client =
      SetBrowserClientForTesting(&modified_client);

  // Discard the spare, so it cannot be considered by the GetProcess call below.
  RenderProcessHostImpl::DiscardSpareRenderProcessHostForTesting();

  // Now, getting a RenderProcessHost for a navigation to the same site should
  // not reuse the unmatched service worker's process (i.e., |sw_host|), as
  // it's unsuitable.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  EXPECT_NE(sw_host, site_instance->GetProcess());

  SetBrowserClientForTesting(regular_client);
}

TEST_F(RenderProcessHostUnitTest, ReuseServiceWorkerProcessForServiceWorker) {
  const GURL kUrl("https://foo.com");

  // Gets a RenderProcessHost for a service worker.
  scoped_refptr<SiteInstanceImpl> sw_site_instance1 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance1->set_is_for_service_worker();
  sw_site_instance1->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess();

  // Getting a RenderProcessHost for a service worker with DEFAULT reuse policy
  // should not reuse the existing service worker's process. This is because
  // we use DEFAULT reuse policy for a service worker when we have failed to
  // start the service worker and want to use a new process. We create this
  // second service worker to test the "find the newest process" logic later.
  scoped_refptr<SiteInstanceImpl> sw_site_instance2 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance2->set_is_for_service_worker();
  RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess();
  EXPECT_NE(sw_host1, sw_host2);

  // Getting a RenderProcessHost for a service worker of the same site with
  // REUSE_PENDING_OR_COMMITTED_SITE reuse policy should reuse the newest
  // unmatched service worker's process (i.e., sw_host2).
  scoped_refptr<SiteInstanceImpl> sw_site_instance3 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance3->set_is_for_service_worker();
  sw_site_instance3->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  RenderProcessHost* sw_host3 = sw_site_instance3->GetProcess();
  EXPECT_EQ(sw_host2, sw_host3);

  // Getting a RenderProcessHost for a service worker of the same site with
  // REUSE_PENDING_OR_COMMITTED_SITE reuse policy should reuse the newest
  // unmatched service worker's process (i.e., sw_host2). sw_host3 doesn't cause
  // sw_host2 to be considered matched, so we can keep putting more service
  // workers in that process.
  scoped_refptr<SiteInstanceImpl> sw_site_instance4 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance4->set_is_for_service_worker();
  sw_site_instance4->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  RenderProcessHost* sw_host4 = sw_site_instance4->GetProcess();
  EXPECT_EQ(sw_host2, sw_host4);

  // Getting a RenderProcessHost for a navigation to the same site must reuse
  // the newest unmatched service worker's process (i.e., sw_host2).
  scoped_refptr<SiteInstanceImpl> site_instance1 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  EXPECT_EQ(sw_host2, site_instance1->GetProcess());

  // Getting a RenderProcessHost for a navigation to the same site must reuse
  // the newest unmatched service worker's process (i.e., sw_host1). sw_host2
  // is no longer unmatched, so sw_host1 is now the newest (and only) process
  // with a corresponding unmatched service worker.
  scoped_refptr<SiteInstanceImpl> site_instance2 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  EXPECT_EQ(sw_host1, site_instance2->GetProcess());
}

TEST_F(RenderProcessHostUnitTest,
       ReuseServiceWorkerProcessInProcessPerSitePolicy) {
  base::CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kProcessPerSite);
  const GURL kUrl("http://foo.com");

  // Gets a RenderProcessHost for a service worker with process-per-site flag.
  scoped_refptr<SiteInstanceImpl> sw_site_instance1 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance1->set_is_for_service_worker();
  RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess();

  // Getting a RenderProcessHost for a service worker of the same site with
  // process-per-site flag should reuse the unmatched service worker's process.
  scoped_refptr<SiteInstanceImpl> sw_site_instance2 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance2->set_is_for_service_worker();
  RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess();
  EXPECT_EQ(sw_host1, sw_host2);

  // Getting a RenderProcessHost for a navigation to the same site with
  // process-per-site flag should reuse the unmatched service worker's process.
  scoped_refptr<SiteInstanceImpl> sw_site_instance3 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  RenderProcessHost* sw_host3 = sw_site_instance3->GetProcess();
  EXPECT_EQ(sw_host1, sw_host3);

  // Getting a RenderProcessHost for a navigation to the same site again with
  // process-per-site flag should reuse the unmatched service worker's process.
  scoped_refptr<SiteInstanceImpl> sw_site_instance4 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  RenderProcessHost* sw_host4 = sw_site_instance4->GetProcess();
  EXPECT_EQ(sw_host1, sw_host4);
}

TEST_F(RenderProcessHostUnitTest, DoNotReuseOtherSiteServiceWorkerProcess) {
  const GURL kUrl1("https://foo.com");
  const GURL kUrl2("https://bar.com");

  // Gets a RenderProcessHost for a service worker.
  scoped_refptr<SiteInstanceImpl> sw_site_instance1 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  sw_site_instance1->set_is_for_service_worker();
  RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess();

  // Getting a RenderProcessHost for a service worker of a different site should
  // return a new process because there is no reusable process.
  scoped_refptr<SiteInstanceImpl> sw_site_instance2 =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl2);
  EXPECT_NE(sw_host1, sw_site_instance2->GetProcess());
}

// Tests that RenderProcessHost will not consider reusing a process that has
// committed an error page.
TEST_F(RenderProcessHostUnitTest, DoNotReuseError) {
  const GURL kUrl1("http://foo.com");
  const GURL kUrl2("http://bar.com");

  // At first, trying to get a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Have the main frame navigate to the first url. Getting a RenderProcessHost
  // with the REUSE_PENDING_OR_COMMITTED_SITE policy should now return the
  // process of the main RFH.
  NavigateAndCommit(kUrl1);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Navigate away. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should again return a new process.
  NavigateAndCommit(kUrl2);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Navigate back and simulate an error. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
  NavigationSimulator::GoBackAndFail(contents(), net::ERR_TIMED_OUT);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
}

// Tests that RenderProcessHost will not consider reusing a process that is
// marked as never suitable for reuse, according to MayReuseHost().
TEST_F(RenderProcessHostUnitTest, DoNotReuseHostThatIsNeverSuitableForReuse) {
  const GURL kUrl("http://foo.com");
  NavigateAndCommit(kUrl);
  main_test_rfh()->GetProcess()->SetIsNeverSuitableForReuse();
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
}

// Tests that RenderProcessHost reuse considers navigations correctly.
// Disabled for flakiness: see https://crbug.com/826595
TEST_F(RenderProcessHostUnitTest, DISABLED_ReuseNavigationProcess) {
  const GURL kUrl1("http://foo.com");
  const GURL kUrl2("http://bar.com");

  // At first, trying to get a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Start a navigation. Now Getting RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return the current process.
  auto navigation =
      NavigationSimulator::CreateRendererInitiated(kUrl1, main_test_rfh());
  navigation->Start();
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl1);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Finish the navigation and start a new cross-site one. Getting
  // RenderProcessHost with the REUSE_PENDING_OR_COMMITTED_SITE policy should
  // return the process of the speculative RenderFrameHost.
  navigation->Commit();
  navigation = NavigationSimulator::CreateBrowserInitiated(kUrl2, contents());
  navigation->Start();
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl2);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(contents()->GetPendingMainFrame()->GetProcess(),
            site_instance->GetProcess());

  // Remember the process id and cancel the navigation. Getting
  // RenderProcessHost with the REUSE_PENDING_OR_COMMITTED_SITE policy should
  // no longer return the process of the speculative RenderFrameHost.
  int speculative_process_host_id =
      contents()->GetPendingMainFrame()->GetProcess()->GetID();
  navigation->Fail(net::ERR_ABORTED);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl2);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(speculative_process_host_id, site_instance->GetProcess()->GetID());
}

// Tests that RenderProcessHost reuse considers navigations correctly during
// redirects in a renderer-initiated navigation.    Also ensures that with
// --site-per-process, there's no mismatch in origin locks for
// https://crbug.com/773809.
TEST_F(RenderProcessHostUnitTest,
       ReuseNavigationProcessRedirectsRendererInitiated) {
  const GURL kUrl("http://foo.com");
  const GURL kRedirectUrl1("http://foo.com/redirect");
  const GURL kRedirectUrl2("http://bar.com");

  // At first, trying to get a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Start a navigation. Now getting RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return the current process.
  auto simulator =
      NavigationSimulator::CreateRendererInitiated(kUrl, main_test_rfh());
  simulator->Start();

  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  // Note that with --site-per-process, the GetProcess() call on
  // |site_instance| will also lock the current process to http://foo.com.
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Simulate a same-site redirect. Getting RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return the current process.
  simulator->Redirect(kRedirectUrl1);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Simulate a cross-site redirect.  Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy for the initial foo.com site should
  // no longer return the original process.  Getting a RenderProcessHost with
  // the REUSE_PENDING_OR_COMMITTED_SITE policy for the new bar.com site should
  // return the the original process, unless we're in --site-per-process mode.
  simulator->Redirect(kRedirectUrl2);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
  site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kRedirectUrl2);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  if (AreAllSitesIsolatedForTesting()) {
    // In --site-per-process, we should've recognized that we will need to swap
    // to a new process; however, the new process won't be created until
    // ready-to-commit time, when the final response comes from bar.com.  Thus,
    // we should have neither foo.com nor bar.com in the original process's
    // list of pending sites, and |site_instance| should create a brand new
    // process that does not match any existing one.  In
    // https://crbug.com/773809, the site_instance->GetProcess() call tried to
    // reuse the original process (already locked to foo.com), leading to
    // origin lock mismatch.
    EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
  } else {
    EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
  }

  // Once the navigation is ready to commit, getting RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return the current
  // process for the final site, but not the initial one.
  simulator->ReadyToCommit();
  RenderProcessHost* post_redirect_process =
      simulator->GetFinalRenderFrameHost()->GetProcess();
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
  EXPECT_NE(post_redirect_process, site_instance->GetProcess());
  site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kRedirectUrl2);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(post_redirect_process, site_instance->GetProcess());
}

// Tests that RenderProcessHost reuse considers navigations correctly during
// redirects in a browser-initiated navigation.
TEST_F(RenderProcessHostUnitTest,
       ReuseNavigationProcessRedirectsBrowserInitiated) {
  const GURL kInitialUrl("http://google.com");
  const GURL kUrl("http://foo.com");
  const GURL kRedirectUrl1("http://foo.com/redirect");
  const GURL kRedirectUrl2("http://bar.com");

  NavigateAndCommit(kInitialUrl);

  // At first, trying to get a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Start a navigation. Now getting RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return the speculative
  // process.
  contents()->GetController().LoadURL(kUrl, Referrer(),
                                      ui::PAGE_TRANSITION_TYPED, std::string());
  main_test_rfh()->SendBeforeUnloadACK(true);
  int speculative_process_host_id =
      contents()->GetPendingMainFrame()->GetProcess()->GetID();
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(speculative_process_host_id, site_instance->GetProcess()->GetID());

  // Simulate a same-site redirect. Getting RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return the speculative
  // process.
  main_test_rfh()->SimulateRedirect(kRedirectUrl1);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(speculative_process_host_id, site_instance->GetProcess()->GetID());

  // Simulate a cross-site redirect. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should no longer return the
  // speculative process: neither for the new site nor for the initial site we
  // were trying to navigate to. It shouldn't return the current process either.
  main_test_rfh()->SimulateRedirect(kRedirectUrl2);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
  EXPECT_NE(speculative_process_host_id, site_instance->GetProcess()->GetID());
  site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kRedirectUrl2);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
  EXPECT_NE(speculative_process_host_id, site_instance->GetProcess()->GetID());

  // Once the navigation is ready to commit, Getting RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return the new speculative
  // process for the final site, but not the initial one. The current process
  // shouldn't be returned either.
  main_test_rfh()->PrepareForCommit();
  speculative_process_host_id =
      contents()->GetPendingMainFrame()->GetProcess()->GetID();
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());
  EXPECT_NE(speculative_process_host_id, site_instance->GetProcess()->GetID());
  site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kRedirectUrl2);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(speculative_process_host_id, site_instance->GetProcess()->GetID());
}

// Tests that RenderProcessHost reuse works correctly even if the site URL of a
// URL changes.
TEST_F(RenderProcessHostUnitTest, ReuseSiteURLChanges) {
  const GURL kUrl("http://foo.com");
  const GURL kModifiedSiteUrl("custom-scheme://custom");

  // At first, trying to get a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Have the main frame navigate to the first url. Getting a RenderProcessHost
  // with the REUSE_PENDING_OR_COMMITTED_SITE policy should now return the
  // process of the main RFH.
  NavigateAndCommit(kUrl);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Install the custom ContentBrowserClient. Site URLs are now modified.
  // Getting a RenderProcessHost with the REUSE_PENDING_OR_COMMITTED_SITE policy
  // should no longer return the process of the main RFH, as the RFH is
  // registered with the normal site URL.
  EffectiveURLContentBrowserClient modified_client(kUrl, kModifiedSiteUrl);
  ContentBrowserClient* regular_client =
      SetBrowserClientForTesting(&modified_client);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Reload. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
  // main RFH, as it is now registered with the modified site URL.
  contents()->GetController().Reload(ReloadType::NORMAL, false);
  TestRenderFrameHost* rfh = main_test_rfh();
  // In --site-per-process, the reload will use the pending/speculative RFH
  // instead of the current one.
  if (contents()->GetPendingMainFrame())
    rfh = contents()->GetPendingMainFrame();
  rfh->PrepareForCommit();
  rfh->SendNavigate(0, true, kUrl);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(rfh->GetProcess(), site_instance->GetProcess());

  // Remove the custom ContentBrowserClient. Site URLs are back to normal.
  // Getting a RenderProcessHost with the REUSE_PENDING_OR_COMMITTED_SITE policy
  // should no longer return the process of the main RFH, as it is registered
  // with the modified site URL.
  SetBrowserClientForTesting(regular_client);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(rfh->GetProcess(), site_instance->GetProcess());

  // Reload. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
  // main RFH, as it is now registered with the regular site URL.
  contents()->GetController().Reload(ReloadType::NORMAL, false);
  rfh = contents()->GetPendingMainFrame() ? contents()->GetPendingMainFrame()
                                          : main_test_rfh();
  rfh->PrepareForCommit();
  rfh->SendNavigate(0, true, kUrl);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(rfh->GetProcess(), site_instance->GetProcess());
}

// Tests that RenderProcessHost reuse works correctly even if the site URL of a
// URL we're navigating to changes.
TEST_F(RenderProcessHostUnitTest, ReuseExpectedSiteURLChanges) {
  if (AreAllSitesIsolatedForTesting())
    return;

  const GURL kUrl("http://foo.com");
  const GURL kModifiedSiteUrl("custom-scheme://custom");

  // At first, trying to get a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return a new process.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Start a navigation. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
  // main RFH.
  auto navigation =
      NavigationSimulator::CreateRendererInitiated(kUrl, main_test_rfh());
  navigation->Start();
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Install the custom ContentBrowserClient. Site URLs are now modified.
  // Getting a RenderProcessHost with the REUSE_PENDING_OR_COMMITTED_SITE policy
  // should no longer return the process of the main RFH, as the RFH is
  // registered with the normal site URL.
  EffectiveURLContentBrowserClient modified_client(kUrl, kModifiedSiteUrl);
  ContentBrowserClient* regular_client =
      SetBrowserClientForTesting(&modified_client);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Have the navigation commit. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
  // main RFH, as it was registered with the modified site URL at commit time.
  navigation->Commit();
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Start a reload. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should return the process of the
  // main RFH.
  contents()->GetController().Reload(ReloadType::NORMAL, false);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Remove the custom ContentBrowserClient. Site URLs are back to normal.
  // Getting a RenderProcessHost with the REUSE_PENDING_OR_COMMITTED_SITE policy
  // should no longer return the process of the main RFH, as it is registered
  // with the modified site URL.
  SetBrowserClientForTesting(regular_client);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess());

  // Finish the reload. Getting a RenderProcessHost with the
  // REUSE_PENDING_OR_COMMITTED_SITE policy should now return the process of the
  // main RFH, as it was registered with the regular site URL when it committed.
  main_test_rfh()->PrepareForCommit();
  main_test_rfh()->SendNavigate(0, true, kUrl);
  site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess());
}

// Helper test class to modify the StoragePartition returned for a particular
// site URL.
class StoragePartitionContentBrowserClient : public ContentBrowserClient {
 public:
  StoragePartitionContentBrowserClient(const GURL& site,
                                       const std::string& partition_domain,
                                       const std::string& partition_name)
      : site_(site),
        partition_domain_(partition_domain),
        partition_name_(partition_name) {}
  ~StoragePartitionContentBrowserClient() override {}

 private:
  void GetStoragePartitionConfigForSite(BrowserContext* browser_context,
                                        const GURL& site,
                                        bool can_be_default,
                                        std::string* partition_domain,
                                        std::string* partition_name,
                                        bool* in_memory) override {
    partition_domain->clear();
    partition_name->clear();
    *in_memory = false;

    if (site == site_) {
      *partition_domain = partition_domain_;
      *partition_name = partition_name_;
    }
  }

  GURL site_;
  std::string partition_domain_;
  std::string partition_name_;
};

// Check that a SiteInstance cannot reuse a RenderProcessHost in a different
// StoragePartition.
TEST_F(RenderProcessHostUnitTest,
       DoNotReuseProcessInDifferentStoragePartition) {
  const GURL kUrl("https://foo.com");
  NavigateAndCommit(kUrl);

  // Change foo.com SiteInstances to use a different StoragePartition.
  StoragePartitionContentBrowserClient modified_client(kUrl, "foo_domain",
                                                       "foo_name");
  ContentBrowserClient* regular_client =
      SetBrowserClientForTesting(&modified_client);

  // Create a foo.com SiteInstance and check that its process does not
  // reuse the foo process from the first navigation, since it's now in a
  // different StoragePartition.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  RenderProcessHost* process = site_instance->GetProcess();
  EXPECT_NE(main_test_rfh()->GetProcess(), process);

  SetBrowserClientForTesting(regular_client);
}

// Check that a SiteInstance cannot reuse a ServiceWorker process in a
// different StoragePartition.
TEST_F(RenderProcessHostUnitTest,
       DoNotReuseServiceWorkerProcessInDifferentStoragePartition) {
  const GURL kUrl("https://foo.com");

  // Create a RenderProcessHost for a service worker.
  scoped_refptr<SiteInstanceImpl> sw_site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  sw_site_instance->set_is_for_service_worker();
  RenderProcessHost* sw_process = sw_site_instance->GetProcess();

  // Change foo.com SiteInstances to use a different StoragePartition.
  StoragePartitionContentBrowserClient modified_client(kUrl, "foo_domain",
                                                       "foo_name");
  ContentBrowserClient* regular_client =
      SetBrowserClientForTesting(&modified_client);

  // Create a foo.com SiteInstance and check that its process does not reuse
  // the ServiceWorker foo.com process, since it's now in a different
  // StoragePartition.
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), kUrl);
  site_instance->set_process_reuse_policy(
      SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
  RenderProcessHost* process = site_instance->GetProcess();
  EXPECT_NE(sw_process, process);

  SetBrowserClientForTesting(regular_client);
}

// Check whether we notify the renderer that it has been locked to a site or
// not. This should depend on the URL from the SiteInstance.
TEST_F(RenderProcessHostUnitTest, RendererLockedToSite) {
  struct TestData {
    GURL test_url;
    bool should_lock_renderer;
  } tests[] = {{GURL("http://"), false},
               {GURL("http://foo.com"), true},
               {GURL("http://bar.foo.com"), true},
               {GURL(""), false},
               {GURL("google.com"), false},
               {GURL("http:"), false},
               {GURL("http://user:pass@google.com:99/foo;bar?q=a#ref"), true}};
  for (const auto& test : tests) {
    scoped_refptr<SiteInstanceImpl> site_instance =
        SiteInstanceImpl::CreateForURL(browser_context(), test.test_url);
    auto* host =
        static_cast<MockRenderProcessHost*>(site_instance->GetProcess());
    if (AreAllSitesIsolatedForTesting())
      EXPECT_EQ(test.should_lock_renderer, host->is_renderer_locked_to_site());
    else
      EXPECT_EQ(false, host->is_renderer_locked_to_site());
  }
}

class SpareRenderProcessHostUnitTest : public RenderViewHostImplTestHarness {
 public:
  SpareRenderProcessHostUnitTest() {}
  ~SpareRenderProcessHostUnitTest() override = default;

 protected:
  void SetUp() override {
    SetRenderProcessHostFactory(&rph_factory_);
    RenderViewHostImplTestHarness::SetUp();
    SetContents(nullptr);  // Start with no renderers.
    RenderProcessHostImpl::DiscardSpareRenderProcessHostForTesting();
    while (!rph_factory_.GetProcesses()->empty()) {
      rph_factory_.Remove(rph_factory_.GetProcesses()->back().get());
    }
  }

  void TearDown() override {
    // Important: Reset the max renderer count to leave this process in a
    // pristine state.
    RenderProcessHost::SetMaxRendererProcessCount(0);
    RenderViewHostImplTestHarness::TearDown();
  }

  MockRenderProcessHostFactory rph_factory_;

 private:
  DISALLOW_COPY_AND_ASSIGN(SpareRenderProcessHostUnitTest);
};

using SpareProcessMaybeTakeAction =
    RenderProcessHostImpl::SpareProcessMaybeTakeAction;
void ExpectSpareProcessMaybeTakeActionBucket(
    const base::HistogramTester& histograms,
    SpareProcessMaybeTakeAction expected_action) {
  EXPECT_THAT(
      histograms.GetAllSamples(
          "BrowserRenderProcessHost.SpareProcessMaybeTakeAction"),
      testing::ElementsAre(base::Bucket(static_cast<int>(expected_action), 1)));
}

TEST_F(SpareRenderProcessHostUnitTest, TestRendererTaken) {
  RenderProcessHost::WarmupSpareRenderProcessHost(browser_context());
  ASSERT_EQ(1U, rph_factory_.GetProcesses()->size());
  RenderProcessHost* spare_rph =
      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
  EXPECT_EQ(spare_rph, rph_factory_.GetProcesses()->at(0).get());

  const GURL kUrl1("http://foo.com");
  base::HistogramTester histograms;
  SetContents(CreateTestWebContents());
  NavigateAndCommit(kUrl1);
  EXPECT_EQ(spare_rph, main_test_rfh()->GetProcess());
  ExpectSpareProcessMaybeTakeActionBucket(
      histograms, SpareProcessMaybeTakeAction::kSpareTaken);

  EXPECT_NE(spare_rph,
            RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
  if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
    EXPECT_NE(nullptr,
              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
    EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());
  } else {
    EXPECT_EQ(nullptr,
              RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
    EXPECT_EQ(1U, rph_factory_.GetProcesses()->size());
  }
}

TEST_F(SpareRenderProcessHostUnitTest, TestRendererNotTaken) {
  std::unique_ptr<BrowserContext> alternate_context(new TestBrowserContext());
  RenderProcessHost::WarmupSpareRenderProcessHost(alternate_context.get());
  ASSERT_EQ(1U, rph_factory_.GetProcesses()->size());
  RenderProcessHost* old_spare =
      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
  EXPECT_EQ(alternate_context.get(), old_spare->GetBrowserContext());
  EXPECT_EQ(old_spare, rph_factory_.GetProcesses()->at(0).get());

  const GURL kUrl1("http://foo.com");
  base::HistogramTester histograms;
  SetContents(CreateTestWebContents());
  NavigateAndCommit(kUrl1);
  EXPECT_NE(old_spare, main_test_rfh()->GetProcess());
  ExpectSpareProcessMaybeTakeActionBucket(
      histograms, SpareProcessMaybeTakeAction::kMismatchedBrowserContext);

  // Pumping the message loop here accounts for the delay between calling
  // RPH::Cleanup on the spare and the time when the posted delete actually
  // happens.  Without pumping, the spare would still be present in
  // rph_factory_.GetProcesses().
  base::RunLoop().RunUntilIdle();

  RenderProcessHost* new_spare =
      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
  EXPECT_NE(old_spare, new_spare);
  if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
    EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());
    ASSERT_NE(nullptr, new_spare);
    EXPECT_EQ(GetBrowserContext(), new_spare->GetBrowserContext());
  } else {
    EXPECT_EQ(1U, rph_factory_.GetProcesses()->size());
    EXPECT_EQ(nullptr, new_spare);
  }
}

TEST_F(SpareRenderProcessHostUnitTest, SpareMissing) {
  RenderProcessHostImpl::DiscardSpareRenderProcessHostForTesting();
  ASSERT_EQ(0U, rph_factory_.GetProcesses()->size());
  RenderProcessHost* spare_rph =
      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
  EXPECT_FALSE(spare_rph);

  const GURL kUrl1("http://foo.com");
  base::HistogramTester histograms;
  SetContents(CreateTestWebContents());
  NavigateAndCommit(kUrl1);
  EXPECT_TRUE(main_test_rfh()->GetProcess());
  ExpectSpareProcessMaybeTakeActionBucket(
      histograms, SpareProcessMaybeTakeAction::kNoSparePresent);

  spare_rph = RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
  if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
    EXPECT_TRUE(spare_rph);
    EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());
  } else {
    EXPECT_FALSE(spare_rph);
    EXPECT_EQ(1U, rph_factory_.GetProcesses()->size());
  }
}

TEST_F(SpareRenderProcessHostUnitTest,
       SpareShouldNotLaunchInParallelWithOtherProcess) {
  std::unique_ptr<BrowserContext> alternate_context(new TestBrowserContext());
  RenderProcessHost::WarmupSpareRenderProcessHost(alternate_context.get());
  ASSERT_EQ(1U, rph_factory_.GetProcesses()->size());
  RenderProcessHost* old_spare =
      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
  EXPECT_EQ(alternate_context.get(), old_spare->GetBrowserContext());
  EXPECT_EQ(old_spare, rph_factory_.GetProcesses()->at(0).get());

  // When we try to get a process for foo.com, we won't be able to use the spare
  // (because it is associated with the alternate, mismatched BrowserContext)
  // and therefore we will have to spawn a new process.  This test verifies that
  // we don't at the same time try to warm-up a new spare (leading to
  // unnecessary resource contention when 2 processes try to launch at the same
  // time).
  scoped_refptr<SiteInstanceImpl> site_instance =
      SiteInstanceImpl::CreateForURL(browser_context(), GURL("http://foo.com"));
  RenderProcessHost* site_instance_process = site_instance->GetProcess();
  // We need to ensure the MockRenderProcessHost gets destroyed at the end of
  // the test.
  std::unique_ptr<MockRenderProcessHost> owned_mock_process(
      static_cast<MockRenderProcessHost*>(site_instance_process));

  // The SiteInstance shouldn't get the old spare, because of BrowserContext
  // mismatch.  The SiteInstance will get a new process instead.
  EXPECT_NE(old_spare, site_instance_process);
  EXPECT_FALSE(site_instance_process->IsReady());

  // There should be no new spare at this point to avoid launching 2 processes
  // at the same time.  Note that the spare might still be created later during
  // a navigation (e.g. after cross-site redirects or when committing).
  RenderProcessHost* new_spare =
      RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
  if (new_spare != old_spare)
    EXPECT_FALSE(new_spare);
}

// This unit test looks at the simplified equivalent of what
// CtrlClickShouldEndUpInSameProcessTest.BlankTarget test would have
// encountered.  The test verifies that the spare RPH is not launched if 1) we
// need to create another renderer process anyway (e.g. because the spare is
// missing when MaybeTakeSpareRenderProcessHost is called) and 2) creating the
// other renderer process will put as at the process limit.  Launching the spare
// in this scenario would put us over the process limit and is therefore
// undesirable.
TEST_F(SpareRenderProcessHostUnitTest, JustBelowProcessLimit) {
  // Override a global. TearDown() will call SetMaxRendererProcessCount() again
  // to clean up.
  RenderProcessHost::SetMaxRendererProcessCount(1);

  // No spare or any other renderer process at the start of the test.
  EXPECT_FALSE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
  EXPECT_EQ(0U, rph_factory_.GetProcesses()->size());

  // Navigation can't take a spare (none present) and needs to launch a new
  // renderer process.
  const GURL kUrl1("http://foo.com");
  SetContents(CreateTestWebContents());
  NavigateAndCommit(kUrl1);

  // We should still be below the process limit.
  EXPECT_EQ(1U, rph_factory_.GetProcesses()->size());

  // There should be no spare - having one would put us over the process limit.
  EXPECT_FALSE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
}

// This unit test verifies that a mismatched spare RenderProcessHost is dropped
// before considering process reuse due to the process limit.
TEST_F(SpareRenderProcessHostUnitTest, AtProcessLimit) {
  // Override a global. TearDown() will call SetMaxRendererProcessCount() again
  // to clean up.
  RenderProcessHost::SetMaxRendererProcessCount(2);

  // Create and navigate the 1st WebContents.
  const GURL kUrl1("http://foo.com");
  std::unique_ptr<WebContents> contents1(CreateTestWebContents());
  static_cast<TestWebContents*>(contents1.get())->NavigateAndCommit(kUrl1);
  EXPECT_NE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting(),
            contents1->GetMainFrame()->GetProcess());

  // Warm up a mismatched spare.
  std::unique_ptr<BrowserContext> alternate_context(new TestBrowserContext());
  RenderProcessHost::WarmupSpareRenderProcessHost(alternate_context.get());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());

  // Create and navigate the 2nd WebContents.
  const GURL kUrl2("http://bar.com");
  std::unique_ptr<WebContents> contents2(CreateTestWebContents());
  static_cast<TestWebContents*>(contents2.get())->NavigateAndCommit(kUrl2);
  base::RunLoop().RunUntilIdle();

  // Creating a 2nd WebContents shouldn't share a renderer process with the 1st
  // one - instead the spare should be dropped to stay under the process limit.
  EXPECT_EQ(2U, rph_factory_.GetProcesses()->size());
  EXPECT_FALSE(RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
  EXPECT_NE(contents1->GetMainFrame()->GetProcess(),
            contents2->GetMainFrame()->GetProcess());
}

}  // namespace content
