// Copyright (c) 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 <stdint.h>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/renderer_host/navigator.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/file_chooser_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame.mojom.h"
#include "content/common/frame_messages.mojom.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/did_commit_navigation_interceptor.h"
#include "content/test/frame_host_interceptor.h"
#include "content/test/test_content_browser_client.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_security_test_util.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/base/filename_util.h"
#include "net/base/network_isolation_key.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/test/test_url_loader_client.h"
#include "storage/browser/blob/blob_registry_impl.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/navigation/navigation_policy.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-test-utils.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-test-utils.h"
#include "third_party/blink/public/mojom/frame/frame.mojom.h"
#include "third_party/blink/public/mojom/loader/mixed_content.mojom.h"

using IPC::IpcSecurityTestUtil;
using ::testing::HasSubstr;
using ::testing::Optional;

namespace content {

namespace {

// This is a helper function for the tests which attempt to create a
// duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects
// with the same process and routing ids, which causes a collision.
// It creates a couple of windows in process 1, which causes a few routing ids
// to be allocated. Then a cross-process navigation is initiated, which causes a
// new process 2 to be created and have a pending RenderViewHost for it. The
// routing id of the RenderViewHost which is target for a duplicate is set
// into |target_routing_id| and the pending RenderFrameHost which is used for
// the attempt is the return value.
RenderFrameHostImpl* PrepareToDuplicateHosts(Shell* shell,
                                             net::EmbeddedTestServer* server,
                                             int* target_routing_id) {
  GURL foo("http://foo.com/simple_page.html");

  if (IsIsolatedOriginRequiredToGuaranteeDedicatedProcess()) {
    // Isolate "bar.com" so we are guaranteed to get a different process
    // for navigations to this origin.
    IsolateOriginsForTesting(server, shell->web_contents(), {"bar.com"});
  }

  // Start off with initial navigation, so we get the first process allocated.
  EXPECT_TRUE(NavigateToURL(shell, foo));
  EXPECT_EQ(u"OK", shell->web_contents()->GetTitle());

  // Open another window, so we generate some more routing ids.
  ShellAddedObserver shell2_observer;
  EXPECT_TRUE(ExecJs(shell, "window.open(document.URL + '#2');"));
  Shell* shell2 = shell2_observer.GetShell();

  // The new window must be in the same process, but have a new routing id.
  EXPECT_EQ(shell->web_contents()->GetMainFrame()->GetProcess()->GetID(),
            shell2->web_contents()->GetMainFrame()->GetProcess()->GetID());
  *target_routing_id = shell2->web_contents()
                           ->GetMainFrame()
                           ->GetRenderViewHost()
                           ->GetRoutingID();
  EXPECT_NE(*target_routing_id, shell->web_contents()
                                    ->GetMainFrame()
                                    ->GetRenderViewHost()
                                    ->GetRoutingID());

  // Now, simulate a link click coming from the renderer.
  GURL extension_url("http://bar.com/simple_page.html");
  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents());
  wc->GetFrameTree()->root()->navigator().RequestOpenURL(
      wc->GetFrameTree()->root()->current_frame_host(), extension_url,
      nullptr /* initiator_frame_token */,
      ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
      url::Origin::Create(foo), nullptr, std::string(), Referrer(),
      WindowOpenDisposition::CURRENT_TAB, false, true,
      blink::mojom::TriggeringEventInfo::kFromTrustedEvent, std::string(),
      nullptr /* blob_url_loader_factory */, absl::nullopt /* impression */);

  // Since the navigation above requires a cross-process swap, there will be a
  // speculative/pending RenderFrameHost. Ensure it exists and is in a different
  // process than the initial page.
  RenderFrameHostImpl* next_rfh =
      wc->GetRenderManagerForTesting()->speculative_frame_host();

  EXPECT_TRUE(next_rfh);
  EXPECT_NE(shell->web_contents()->GetMainFrame()->GetProcess()->GetID(),
            next_rfh->GetProcess()->GetID());

  return next_rfh;
}

blink::mojom::OpenURLParamsPtr CreateOpenURLParams(const GURL& url) {
  auto params = blink::mojom::OpenURLParams::New();
  params->url = url;
  params->disposition = WindowOpenDisposition::CURRENT_TAB;
  params->should_replace_current_entry = false;
  params->user_gesture = true;
  return params;
}

std::unique_ptr<content::BlobHandle> CreateMemoryBackedBlob(
    BrowserContext* browser_context,
    const std::string& contents,
    const std::string& content_type) {
  std::unique_ptr<content::BlobHandle> result;
  base::RunLoop loop;
  browser_context->CreateMemoryBackedBlob(
      base::as_bytes(base::make_span(contents)), content_type,
      base::BindOnce(
          [](std::unique_ptr<content::BlobHandle>* out_blob,
             base::OnceClosure done,
             std::unique_ptr<content::BlobHandle> blob) {
            *out_blob = std::move(blob);
            std::move(done).Run();
          },
          &result, loop.QuitClosure()));
  loop.Run();
  EXPECT_TRUE(result);
  return result;
}

// Helper class to interpose on Blob URL registrations, replacing the URL
// contained in incoming registration requests with the specified URL.
class BlobURLStoreInterceptor
    : public blink::mojom::BlobURLStoreInterceptorForTesting {
 public:
  static void Intercept(
      GURL target_url,
      mojo::SelfOwnedAssociatedReceiverRef<blink::mojom::BlobURLStore>
          receiver) {
    auto interceptor =
        base::WrapUnique(new BlobURLStoreInterceptor(target_url));
    auto* raw_interceptor = interceptor.get();
    auto impl = receiver->SwapImplForTesting(std::move(interceptor));
    raw_interceptor->url_store_ = std::move(impl);
  }

  blink::mojom::BlobURLStore* GetForwardingInterface() override {
    return url_store_.get();
  }

  void Register(
      mojo::PendingRemote<blink::mojom::Blob> blob,
      const GURL& url,
      // TODO(https://crbug.com/1224926): Remove this once experiment is over.
      const base::UnguessableToken& unsafe_agent_cluster_id,
      RegisterCallback callback) override {
    GetForwardingInterface()->Register(std::move(blob), target_url_,
                                       unsafe_agent_cluster_id,
                                       std::move(callback));
  }

 private:
  explicit BlobURLStoreInterceptor(GURL target_url) : target_url_(target_url) {}

  std::unique_ptr<blink::mojom::BlobURLStore> url_store_;
  GURL target_url_;
};

// Constructs a WebContentsDelegate that mocks a file dialog.
// Unlike content::FileChooserDelegate, this class doesn't make a response in
// RunFileChooser(), and a user needs to call Choose().
class DelayedFileChooserDelegate : public WebContentsDelegate {
 public:
  void Choose(const base::FilePath& file) {
    auto file_info = blink::mojom::FileChooserFileInfo::NewNativeFile(
        blink::mojom::NativeFileInfo::New(file, std::u16string()));
    std::vector<blink::mojom::FileChooserFileInfoPtr> files;
    files.push_back(std::move(file_info));
    listener_->FileSelected(std::move(files), base::FilePath(),
                            blink::mojom::FileChooserParams::Mode::kOpen);
    listener_.reset();
  }

  // WebContentsDelegate overrides
  void RunFileChooser(RenderFrameHost* render_frame_host,
                      scoped_refptr<FileSelectListener> listener,
                      const blink::mojom::FileChooserParams& params) override {
    listener_ = std::move(listener);
  }

  void EnumerateDirectory(WebContents* web_contents,
                          scoped_refptr<FileSelectListener> listener,
                          const base::FilePath& directory_path) override {
    listener->FileSelectionCanceled();
  }

 private:
  scoped_refptr<FileSelectListener> listener_;
};

void FileChooserCallback(base::RunLoop* run_loop,
                         blink::mojom::FileChooserResultPtr result) {
  run_loop->Quit();
}

}  // namespace

// The goal of these tests will be to "simulate" exploited renderer processes,
// which can send arbitrary IPC messages and confuse browser process internal
// state, leading to security bugs. We are trying to verify that the browser
// doesn't perform any dangerous operations in such cases.
class SecurityExploitBrowserTest : public ContentBrowserTest {
 public:
  SecurityExploitBrowserTest() {}

  void SetUpCommandLine(base::CommandLine* command_line) override {
    // EmbeddedTestServer::InitializeAndListen() initializes its |base_url_|
    // which is required below. This cannot invoke Start() however as that kicks
    // off the "EmbeddedTestServer IO Thread" which then races with
    // initialization in ContentBrowserTest::SetUp(), http://crbug.com/674545.
    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());

    // Add a host resolver rule to map all outgoing requests to the test server.
    // This allows us to use "real" hostnames in URLs, which we can use to
    // create arbitrary SiteInstances.
    command_line->AppendSwitchASCII(
        network::switches::kHostResolverRules,
        "MAP * " +
            net::HostPortPair::FromURL(embedded_test_server()->base_url())
                .ToString() +
            ",EXCLUDE localhost");
  }

  void SetUpOnMainThread() override {
    // Complete the manual Start() after ContentBrowserTest's own
    // initialization, ref. comment on InitializeAndListen() above.
    embedded_test_server()->StartAcceptingConnections();
  }

 protected:
  // Tests that a given file path sent in a FrameHostMsg_RunFileChooser will
  // cause renderer to be killed.
  void TestFileChooserWithPath(const base::FilePath& path);

  void IsolateOrigin(const std::string& hostname) {
    IsolateOriginsForTesting(embedded_test_server(), shell()->web_contents(),
                             {hostname});
  }
};

void SecurityExploitBrowserTest::TestFileChooserWithPath(
    const base::FilePath& path) {
  GURL foo("http://foo.com/simple_page.html");
  EXPECT_TRUE(NavigateToURL(shell(), foo));
  EXPECT_EQ(u"OK", shell()->web_contents()->GetTitle());

  RenderFrameHost* compromised_renderer =
      shell()->web_contents()->GetMainFrame();
  blink::mojom::FileChooserParamsPtr params =
      blink::mojom::FileChooserParams::New();
  params->default_file_name = path;

  mojo::test::BadMessageObserver bad_message_observer;
  mojo::Remote<blink::mojom::FileChooser> chooser =
      FileChooserImpl::CreateBoundForTesting(
          static_cast<RenderFrameHostImpl*>(compromised_renderer));
  chooser->OpenFileChooser(
      std::move(params), blink::mojom::FileChooser::OpenFileChooserCallback());
  chooser.FlushForTesting();
  EXPECT_THAT(bad_message_observer.WaitForBadMessage(),
              ::testing::StartsWith("FileChooser: The default file name"));
}

// Ensure that we kill the renderer process if we try to give it WebUI
// properties and it doesn't have enabled WebUI bindings.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, SetWebUIProperty) {
  GURL foo("http://foo.com/simple_page.html");

  EXPECT_TRUE(NavigateToURL(shell(), foo));
  EXPECT_EQ(u"OK", shell()->web_contents()->GetTitle());
  EXPECT_EQ(0, shell()->web_contents()->GetMainFrame()->GetEnabledBindings());

  RenderFrameHost* compromised_renderer =
      shell()->web_contents()->GetMainFrame();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      compromised_renderer->GetProcess());
  compromised_renderer->SetWebUIProperty("toolkit", "views");
  EXPECT_EQ(bad_message::RVH_WEB_UI_BINDINGS_MISMATCH, kill_waiter.Wait());
}

// This is a test for crbug.com/312016 attempting to create duplicate
// RenderViewHosts. SetupForDuplicateHosts sets up this test case and leaves
// it in a state with pending RenderViewHost. Before the commit of the new
// pending RenderViewHost, this test case creates a new window through the new
// process.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       AttemptDuplicateRenderViewHost) {
  int32_t duplicate_routing_id = MSG_ROUTING_NONE;
  RenderFrameHostImpl* pending_rfh = PrepareToDuplicateHosts(
      shell(), embedded_test_server(), &duplicate_routing_id);
  EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);

  mojom::CreateNewWindowParamsPtr params = mojom::CreateNewWindowParams::New();
  params->target_url = GURL("about:blank");
  pending_rfh->CreateNewWindow(
      std::move(params), base::BindOnce([](mojom::CreateNewWindowStatus,
                                           mojom::CreateNewWindowReplyPtr) {}));
  // If the above operation doesn't cause a crash, the test has succeeded!
}

// This is a test for crbug.com/444198. It tries to send a
// FrameHostMsg_RunFileChooser containing an invalid path. The browser should
// correctly terminate the renderer in these cases.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, AttemptRunFileChoosers) {
  TestFileChooserWithPath(base::FilePath(FILE_PATH_LITERAL("../../*.txt")));
  TestFileChooserWithPath(base::FilePath(FILE_PATH_LITERAL("/etc/*.conf")));
#if defined(OS_WIN)
  TestFileChooserWithPath(
      base::FilePath(FILE_PATH_LITERAL("\\\\evilserver\\evilshare\\*.txt")));
  TestFileChooserWithPath(base::FilePath(FILE_PATH_LITERAL("c:\\*.txt")));
  TestFileChooserWithPath(base::FilePath(FILE_PATH_LITERAL("..\\..\\*.txt")));
#endif
}

// A test for crbug.com/941008.
// Calling OpenFileChooser() and EnumerateChosenDirectory() for a single
// FileChooser instance had a problem.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, UnexpectedMethodsSequence) {
  EXPECT_TRUE(NavigateToURL(shell(), GURL("http://foo.com/simple_page.html")));
  RenderFrameHost* compromised_renderer =
      shell()->web_contents()->GetMainFrame();
  auto delegate = std::make_unique<DelayedFileChooserDelegate>();
  shell()->web_contents()->SetDelegate(delegate.get());

  mojo::Remote<blink::mojom::FileChooser> chooser =
      FileChooserImpl::CreateBoundForTesting(
          static_cast<RenderFrameHostImpl*>(compromised_renderer));
  base::RunLoop run_loop1;
  base::RunLoop run_loop2;
  chooser->OpenFileChooser(blink::mojom::FileChooserParams::New(),
                           base::BindOnce(FileChooserCallback, &run_loop2));
  // The following EnumerateChosenDirectory() runs the specified callback
  // immediately regardless of the content of the first argument FilePath.
  chooser->EnumerateChosenDirectory(
      base::FilePath(FILE_PATH_LITERAL(":*?\"<>|")),
      base::BindOnce(FileChooserCallback, &run_loop1));
  run_loop1.Run();

  delegate->Choose(base::FilePath(FILE_PATH_LITERAL("foo.txt")));
  run_loop2.Run();

  // The test passes if it doesn't crash.
}

class CorsExploitBrowserTest : public ContentBrowserTest {
 public:
  CorsExploitBrowserTest() = default;

  void SetUpOnMainThread() override {
    host_resolver()->AddRule("*", "127.0.0.1");
    SetupCrossSiteRedirector(embedded_test_server());
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(CorsExploitBrowserTest);
};

// Test that receiving a commit with incorrect origin properly terminates the
// renderer process.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, MismatchedOriginOnCommit) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetFrameTree()
                            ->root();

  // Navigate to a new URL, with an interceptor that replaces the origin with
  // one that does not match params.url.
  GURL url(embedded_test_server()->GetURL("/title2.html"));
  PwnCommitIPC(shell()->web_contents(), url, url,
               url::Origin::Create(GURL("http://bar.com/")));

  // Use LoadURL, as the test shouldn't wait for navigation commit.
  NavigationController& controller = shell()->web_contents()->GetController();
  controller.LoadURL(url, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
  EXPECT_NE(nullptr, controller.GetPendingEntry());
  EXPECT_EQ(url, controller.GetPendingEntry()->GetURL());

  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      root->current_frame_host()->GetProcess());

  // When the IPC message is received and validation fails, the process is
  // terminated. However, the notification for that should be processed in a
  // separate task of the message loop, so ensure that the process is still
  // considered alive.
  EXPECT_TRUE(
      root->current_frame_host()->GetProcess()->IsInitializedAndNotDead());

  EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
}

// Test that receiving a document.open() URL update with incorrect origin
// properly terminates the renderer process.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       MismatchedOriginOnDocumentOpenURLUpdate) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetMainFrame());

  // Simulate a document.open() URL update with incorrect origin.
  RenderProcessHostBadIpcMessageWaiter kill_waiter(rfh->GetProcess());
  static_cast<mojom::FrameHost*>(rfh)->DidOpenDocumentInputStream(
      embedded_test_server()->GetURL("evil.com", "/title1.html"));

  // Ensure that the renderer process gets killed.
  EXPECT_EQ(AreAllSitesIsolatedForTesting()
                ? bad_message::RFH_CAN_COMMIT_URL_BLOCKED
                : bad_message::RFH_INVALID_ORIGIN_ON_COMMIT,
            kill_waiter.Wait());
}

// Test that same-document navigations cannot go cross-origin (even within the
// same site).
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       CrossOriginSameDocumentCommit) {
  GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  // Do a same-document navigation to a cross-origin URL/Origin (which match
  // each other, unlike the MismatchedOriginOnCommit), using an interceptor that
  // replaces the origin and URL. This intentionally uses a cross-origin but
  // same-site destination, to avoid failing Site Isolation checks.
  GURL dest_url(embedded_test_server()->GetURL("bar.foo.com", "/title2.html"));
  PwnCommitIPC(shell()->web_contents(), start_url, dest_url,
               url::Origin::Create(dest_url));
  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      shell()->web_contents()->GetMainFrame()->GetProcess());
  // ExecJs will sometimes finish before the renderer gets killed, so we must
  // ignore the result.
  ignore_result(ExecJs(shell()->web_contents()->GetMainFrame(),
                       "history.pushState({}, '', location.href);"));
  EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
}

// Test that same-document navigations cannot go cross-origin from about:blank
// (even within the same site). Uses a subframe to inherit an existing origin.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       CrossOriginSameDocumentCommitFromAboutBlank) {
  GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  // Create an about:blank iframe that inherits the origin.
  RenderFrameHost* subframe =
      CreateSubframe(static_cast<WebContentsImpl*>(shell()->web_contents()),
                     "child1", GURL(), false /* wait_for_navigation */);
  EXPECT_EQ(url::Origin::Create(start_url), subframe->GetLastCommittedOrigin());

  // Do a same-document navigation to another about:blank URL, but using a
  // different origin. This intentionally uses a cross-origin but same-site
  // origin to avoid triggering Site Isolation checks.
  GURL blank_url("about:blank#foo");
  GURL fake_url(embedded_test_server()->GetURL("bar.foo.com", "/"));
  PwnCommitIPC(shell()->web_contents(), blank_url, blank_url,
               url::Origin::Create(fake_url));
  RenderProcessHostBadIpcMessageWaiter kill_waiter(subframe->GetProcess());
  // ExecJs will sometimes finish before the renderer gets killed, so we must
  // ignore the result.
  ignore_result(ExecJs(subframe, "location.hash='foo';"));
  EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
}

// Test that same-document navigations cannot go cross-origin (even within the
// same site), in the case that allow_universal_access_from_file_urls is enabled
// but the last committed origin is not a file URL.  See also
// RenderFrameHostManagerTest.EnsureUniversalAccessFromFileSchemeSucceeds for
// the intended case that file URLs are allowed to go cross-origin.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       CrossOriginSameDocumentCommitUniversalAccessNonFile) {
  auto prefs = shell()->web_contents()->GetOrCreateWebPreferences();
  prefs.allow_universal_access_from_file_urls = true;
  shell()->web_contents()->SetWebPreferences(prefs);

  GURL start_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  // Do a same-document navigation to a cross-origin URL, using an interceptor
  // that replaces the URL but not the origin (to simulate the universal access
  // case, but for a non-file committed origin). This intentionally uses a
  // cross-origin but same-site destination, to avoid failing Site Isolation
  // checks.
  GURL dest_url(embedded_test_server()->GetURL("bar.foo.com", "/title2.html"));
  PwnCommitIPC(shell()->web_contents(), start_url, dest_url,
               url::Origin::Create(start_url));
  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      shell()->web_contents()->GetMainFrame()->GetProcess());
  // ExecJs will sometimes finish before the renderer gets killed, so we must
  // ignore the result.
  ignore_result(ExecJs(shell()->web_contents()->GetMainFrame(),
                       "history.pushState({}, '', location.href);"));
  EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
}

namespace {

// Interceptor that replaces |interface_params| with the specified
// value for the first DidCommitProvisionalLoad message it observes in the given
// |web_contents| while in scope.
class ScopedInterfaceParamsReplacer : public DidCommitNavigationInterceptor {
 public:
  ScopedInterfaceParamsReplacer(
      WebContents* web_contents,
      mojom::DidCommitProvisionalLoadInterfaceParamsPtr params_override)
      : DidCommitNavigationInterceptor(web_contents),
        params_override_(std::move(params_override)) {}

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

  ~ScopedInterfaceParamsReplacer() override = default;

 protected:
  bool WillProcessDidCommitNavigation(
      RenderFrameHost* render_frame_host,
      NavigationRequest* navigation_request,
      mojom::DidCommitProvisionalLoadParamsPtr*,
      mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params)
      override {
    interface_params->Swap(&params_override_);

    return true;
  }

 private:
  mojom::DidCommitProvisionalLoadInterfaceParamsPtr params_override_;
};

}  // namespace

// Test that, as a general rule, not receiving new
// DidCommitProvisionalLoadInterfaceParamsPtr for a cross-document navigation
// properly terminates the renderer process. There is one exception to this
// rule, see: RenderFrameHostImplBrowserTest.
// InterfaceProviderRequestIsOptionalForFirstCommit.
// TODO(crbug.com/718652): when all clients are converted to use
// BrowserInterfaceBroker, PendingReceiver<InterfaceProvider>-related code will
// be removed.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       MissingInterfaceProviderOnNonSameDocumentCommit) {
  const GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  const GURL non_same_document_url(
      embedded_test_server()->GetURL("/title2.html"));

  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  RenderFrameHostImpl* frame = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetMainFrame());
  RenderProcessHostBadIpcMessageWaiter kill_waiter(frame->GetProcess());

  NavigationHandleObserver navigation_observer(shell()->web_contents(),
                                               non_same_document_url);
  ScopedInterfaceParamsReplacer replacer(shell()->web_contents(), nullptr);
  EXPECT_TRUE(NavigateToURLAndExpectNoCommit(shell(), non_same_document_url));
  EXPECT_EQ(bad_message::RFH_INTERFACE_PROVIDER_MISSING, kill_waiter.Wait());

  // Verify that the death of the renderer process doesn't leave behind and
  // leak NavigationRequests - see https://crbug.com/869193.
  EXPECT_FALSE(frame->HasPendingCommitNavigation());
  EXPECT_FALSE(navigation_observer.has_committed());
  EXPECT_TRUE(navigation_observer.is_error());
  EXPECT_TRUE(navigation_observer.last_committed_url().is_empty());
  EXPECT_EQ(net::OK, navigation_observer.net_error_code());
}

// Test that a compromised renderer cannot ask to upload an arbitrary file in
// OpenURL.  This is a regression test for https://crbug.com/726067.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       OpenUrl_ResourceRequestBody) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  GURL target_url(embedded_test_server()->GetURL("/echoall"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetFrameTree()
                            ->root();

  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      root->current_frame_host()->GetProcess());

  // Prepare a file to upload.
  base::ScopedAllowBlockingForTesting allow_blocking;
  base::ScopedTempDir temp_dir;
  base::FilePath file_path;
  std::string file_content("test-file-content");
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &file_path));
  ASSERT_TRUE(base::WriteFile(file_path, file_content));

  // Simulate an OpenURL Mojo method asking to POST a file that the renderer
  // shouldn't have access to.
  auto params = CreateOpenURLParams(target_url);
  params->post_body = new network::ResourceRequestBody;
  params->post_body->AppendFileRange(file_path, 0, file_content.size(),
                                     base::Time());
  params->should_replace_current_entry = true;

  static_cast<mojom::FrameHost*>(root->current_frame_host())
      ->OpenURL(std::move(params));

  // Verify that the malicious navigation did not commit the navigation to
  // |target_url|.
  EXPECT_EQ(start_url, root->current_frame_host()->GetLastCommittedURL());

  // Verify that the malicious renderer got killed.
  EXPECT_EQ(bad_message::ILLEGAL_UPLOAD_PARAMS, kill_waiter.Wait());
}

// Forging a navigation commit after the initial empty document will result in a
// renderer kill, even if the URL used is about:blank.
// See https://crbug.com/766262 for an example advanced case that involves
// forging a frame's unique name.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       NonInitialAboutBlankRendererKill) {
  // Navigate normally.
  GURL url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), url));
  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetMainFrame());

  // Simulate an about:blank commit without a NavigationRequest. It will fail
  // because only initial commits are allowed to do this.
  auto params = mojom::DidCommitProvisionalLoadParams::New();
  params->did_create_new_entry = false;
  params->url = GURL("about:blank");
  params->referrer = blink::mojom::Referrer::New();
  params->transition = ui::PAGE_TRANSITION_LINK;
  params->should_update_history = false;
  params->method = "GET";
  params->page_state = blink::PageState::CreateFromURL(GURL("about:blank"));
  params->origin = url::Origin::Create(GURL("about:blank"));
  params->embedding_token = base::UnguessableToken::Create();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(rfh->GetProcess());
  static_cast<mojom::FrameHost*>(rfh)->DidCommitProvisionalLoad(
      std::move(params),
      mojom::DidCommitProvisionalLoadInterfaceParams::New(
          mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
              .InitWithNewPipeAndPassReceiver()));

  // Verify that the malicious renderer got killed.
  EXPECT_EQ(bad_message::RFH_NO_MATCHING_NAVIGATION_REQUEST_ON_COMMIT,
            kill_waiter.Wait());
}

class SecurityExploitBrowserTestMojoBlobURLs
    : public SecurityExploitBrowserTest {
 public:
  SecurityExploitBrowserTestMojoBlobURLs() = default;

  void TearDown() override {
    storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(nullptr);
  }
};

// Check that when site isolation is enabled, an origin can't create a blob URL
// for a different origin.  Similar to the test above, but checks the
// mojo-based Blob URL implementation.  See https://crbug.com/886976.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestMojoBlobURLs,
                       CreateMojoBlobURLInDifferentOrigin) {
  IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());

  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));
  RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();

  // Intercept future blob URL registrations and overwrite the blob URL origin
  // with b.com.
  std::string target_origin = "http://b.com";
  std::string blob_path = "5881f76e-10d2-410d-8c61-ef210502acfd";
  auto intercept_hook =
      base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
                          GURL("blob:" + target_origin + "/" + blob_path));
  storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(&intercept_hook);

  // Register a blob URL from the a.com main frame, which will go through the
  // interceptor above and be rewritten to register the blob URL with the b.com
  // origin. This should result in a kill because a.com should not be allowed
  // to create blob URLs outside of its own origin.
  content::RenderProcessHostBadMojoMessageWaiter crash_observer(
      rfh->GetProcess());

  // The renderer should always get killed, but sometimes ExecuteScript returns
  // true anyway, so just ignore the result.
  ignore_result(ExecJs(rfh, "URL.createObjectURL(new Blob(['foo']))"));

  // If the process is killed, this test passes.
  EXPECT_EQ(
      "Received bad user message: "
      "Non committable URL passed to BlobURLStore::Register",
      crash_observer.Wait());
}

// Check that with site isolation enabled, an origin can't create a filesystem
// URL for a different origin.  See https://crbug.com/888001.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       CreateFilesystemURLInDifferentOrigin) {
  IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());

  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(b)"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));
  RenderFrameHost* rfh = shell()->web_contents()->GetMainFrame();

  // Block the renderer on operation that never completes, to shield it from
  // receiving unexpected browser->renderer IPCs that might CHECK.
  rfh->ExecuteJavaScriptWithUserGestureForTests(
      u"var r = new XMLHttpRequest();"
      u"r.open('GET', '/slow?99999', false);"
      u"r.send(null);"
      u"while (1);");

  // Set up a blob ID and populate it with attacker-controlled value. This
  // is just using the blob APIs directly since creating arbitrary blobs is not
  // what is prohibited; this data is not in any origin.
  std::string payload = "<html><body>pwned.</body></html>";
  std::string payload_type = "text/html";
  std::unique_ptr<content::BlobHandle> blob = CreateMemoryBackedBlob(
      rfh->GetSiteInstance()->GetBrowserContext(), payload, payload_type);
  std::string blob_id = blob->GetUUID();

  // Target a different origin.
  std::string target_origin = "http://b.com";
  GURL target_url =
      GURL("filesystem:" + target_origin + "/temporary/exploit.html");

  // Note: a well-behaved renderer would always call Open first before calling
  // Create and Write, but it's actually not necessary for the original attack
  // to succeed, so we omit it. As a result there are some log warnings from the
  // quota observer.

  PwnMessageHelper::FileSystemCreate(rfh->GetProcess(), 23, target_url, false,
                                     false, false);

  // Write the blob into the file. If successful, this places an
  // attacker-controlled value in a resource on the target origin.
  PwnMessageHelper::FileSystemWrite(rfh->GetProcess(), 24, target_url, blob_id,
                                    0);

  // Now navigate to |target_url| in a subframe. It should not succeed, and the
  // subframe should not contain |payload|.
  TestNavigationObserver observer(shell()->web_contents());
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetFrameTree()
                            ->root();
  NavigateFrameToURL(root->child_at(0), target_url);
  EXPECT_FALSE(observer.last_navigation_succeeded());
  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, observer.last_net_error_code());

  RenderFrameHost* attacked_rfh = root->child_at(0)->current_frame_host();
  std::string body =
      EvalJs(attacked_rfh, "document.body.innerText").ExtractString();
  EXPECT_TRUE(base::StartsWith(body, "Could not load the requested resource",
                               base::CompareCase::INSENSITIVE_ASCII))
      << " body=" << body;
}

// Verify that when a compromised renderer tries to navigate a remote frame to
// a disallowed URL (e.g., file URL), that navigation is blocked.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       BlockIllegalOpenURLFromRemoteFrame) {
  // Explicitly isolating a.com helps ensure that this test is applicable on
  // platforms without site-per-process.
  IsolateOrigin("a.com");

  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(b)"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));
  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetFrameTree()
                            ->root();
  FrameTreeNode* child = root->child_at(0);

  // Simulate an IPC message where the top frame asks the remote subframe to
  // navigate to a file: URL.
  SiteInstance* a_com_instance = root->current_frame_host()->GetSiteInstance();
  RenderFrameProxyHost* proxy =
      child->render_manager()->GetRenderFrameProxyHost(a_com_instance);
  EXPECT_TRUE(proxy);

  TestNavigationObserver observer(shell()->web_contents());
  static_cast<mojom::FrameHost*>(proxy->frame_tree_node()->current_frame_host())
      ->OpenURL(CreateOpenURLParams(GURL("file:///")));
  observer.Wait();

  // Verify that the malicious navigation was blocked.  Currently, this happens
  // by rewriting the target URL to about:blank#blocked.
  //
  // TODO(alexmos): Consider killing the renderer process in this case, since
  // this security check is already enforced in the renderer process.
  EXPECT_EQ(GURL(kBlockedURL),
            child->current_frame_host()->GetLastCommittedURL());

  // Navigate to the starting page again to recreate the proxy, then try the
  // same malicious navigation with a chrome:// URL.
  EXPECT_TRUE(NavigateToURL(shell(), main_url));
  child = root->child_at(0);
  proxy = child->render_manager()->GetRenderFrameProxyHost(a_com_instance);
  EXPECT_TRUE(proxy);

  TestNavigationObserver observer_2(shell()->web_contents());
  GURL chrome_url(std::string(kChromeUIScheme) + "://" +
                  std::string(kChromeUIGpuHost));
  static_cast<mojom::FrameHost*>(proxy->frame_tree_node()->current_frame_host())
      ->OpenURL(CreateOpenURLParams(chrome_url));
  observer_2.Wait();
  EXPECT_EQ(GURL(kBlockedURL),
            child->current_frame_host()->GetLastCommittedURL());
}

class RemoteFrameHostInterceptor
    : public blink::mojom::RemoteFrameHostInterceptorForTesting {
 public:
  explicit RemoteFrameHostInterceptor(
      RenderFrameProxyHost* render_frame_proxy_host,
      const std::u16string& evil_origin)
      : render_frame_proxy_host_(render_frame_proxy_host),
        evil_origin_(evil_origin) {
    render_frame_proxy_host_->frame_host_receiver_for_testing()
        .SwapImplForTesting(this);
  }

  RemoteFrameHost* GetForwardingInterface() override {
    return render_frame_proxy_host_;
  }

  void RouteMessageEvent(
      const absl::optional<blink::LocalFrameToken>& source_frame_token,
      const std::u16string& source_origin,
      const std::u16string& target_origin,
      blink::TransferableMessage message) override {
    // Forward the message to the actual RFPH replacing |source_origin| with the
    // "evil origin" as especified in SetEvilSourceOriginAndWaitForMessage().
    GetForwardingInterface()->RouteMessageEvent(
        std::move(source_frame_token), std::move(evil_origin_),
        std::move(target_origin), std::move(message));
  }

  void OpenURL(blink::mojom::OpenURLParamsPtr params) override {
    intercepted_params_ = std::move(params);
  }

  blink::mojom::OpenURLParamsPtr GetInterceptedParams() {
    return std::move(intercepted_params_);
  }

 private:
  RenderFrameProxyHost* render_frame_proxy_host_;

  std::u16string evil_origin_;
  blink::mojom::OpenURLParamsPtr intercepted_params_;
};

// Test verifying that a compromised renderer can't lie about the source_origin
// passed along with the RouteMessageEvent() mojo message.  See also
// https://crbug.com/915721.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, PostMessageSourceOrigin) {
  // Explicitly isolating a.com helps ensure that this test is applicable on
  // platforms without site-per-process.
  IsolateOrigin("b.com");

  // Navigate to a page with an OOPIF.
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(b)"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));

  // Sanity check of test setup: main frame and subframe should be isolated.
  WebContents* web_contents = shell()->web_contents();
  RenderFrameHost* main_frame = web_contents->GetMainFrame();
  RenderFrameHost* subframe = ChildFrameAt(main_frame, 0);
  EXPECT_NE(main_frame->GetProcess(), subframe->GetProcess());

  // We need to get ahold of the RenderFrameProxyHost representing the main
  // frame for the subframe's process, to install the mojo interceptor.
  FrameTreeNode* main_frame_node =
      static_cast<WebContentsImpl*>(shell()->web_contents())
          ->GetFrameTree()
          ->root();
  FrameTreeNode* subframe_node = main_frame_node->child_at(0);
  SiteInstance* b_com_instance =
      subframe_node->current_frame_host()->GetSiteInstance();
  RenderFrameProxyHost* main_frame_proxy_host =
      main_frame_node->render_manager()->GetRenderFrameProxyHost(
          b_com_instance);

  // Prepare to intercept the RouteMessageEvent IPC message that will come
  // from the subframe process.
  url::Origin invalid_origin =
      web_contents->GetMainFrame()->GetLastCommittedOrigin();
  std::u16string evil_source_origin =
      base::UTF8ToUTF16(invalid_origin.Serialize());
  RemoteFrameHostInterceptor mojo_interceptor(main_frame_proxy_host,
                                              evil_source_origin);

  // Post a message from the subframe to the cross-site parent and intercept the
  // associated IPC message, changing it to simulate a compromised subframe
  // renderer lying that the |source_origin| of the postMessage is the origin of
  // the parent (not of the subframe).
  RenderProcessHostBadIpcMessageWaiter kill_waiter(subframe->GetProcess());
  EXPECT_TRUE(ExecJs(subframe, "parent.postMessage('blah', '*')"));
  EXPECT_EQ(bad_message::RFPH_POST_MESSAGE_INVALID_SOURCE_ORIGIN,
            kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       InvalidRemoteNavigationInitiator) {
  // Explicitly isolating a.com helps ensure that this test is applicable on
  // platforms without site-per-process.
  IsolateOrigin("a.com");

  // Navigate to a test page where the subframe is cross-site (and because of
  // IsolateOrigin call above in a separate process) from the main frame.
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(b)"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));
  RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetMainFrame());
  RenderProcessHost* main_process = main_frame->GetProcess();
  RenderFrameHost* subframe = ChildFrameAt(main_frame, 0);
  ASSERT_TRUE(subframe);
  RenderProcessHost* subframe_process = subframe->GetProcess();
  EXPECT_NE(main_process->GetID(), subframe_process->GetID());

  // Prepare to intercept OpenURL Mojo message that will come from
  // the main frame.
  FrameTreeNode* main_frame_node =
      static_cast<WebContentsImpl*>(shell()->web_contents())
          ->GetFrameTree()
          ->root();
  FrameTreeNode* child_node = main_frame_node->child_at(0);
  SiteInstance* a_com_instance =
      main_frame_node->current_frame_host()->GetSiteInstance();
  RenderFrameProxyHost* proxy =
      child_node->render_manager()->GetRenderFrameProxyHost(a_com_instance);

  RemoteFrameHostInterceptor interceptor(proxy, std::u16string());

  // Have the main frame request navigation in the "remote" subframe.  This will
  // result in OpenURL Mojo message being sent to the RenderFrameProxyHost.
  EXPECT_TRUE(ExecJs(shell()->web_contents()->GetMainFrame(),
                     "window.frames[0].location = '/title1.html';"));

  // Change the intercepted message to simulate a compromised subframe renderer
  // lying that the |initiator_origin| is the origin of the |subframe|.
  auto evil_params = interceptor.GetInterceptedParams();
  evil_params->initiator_origin = subframe->GetLastCommittedOrigin();

  // Inject the invalid IPC and verify that the renderer gets terminated.
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_process);
  static_cast<mojom::FrameHost*>(main_frame)->OpenURL(std::move(evil_params));
  EXPECT_EQ(bad_message::INVALID_INITIATOR_ORIGIN, kill_waiter.Wait());
}

class BeginNavigationInitiatorReplacer : public FrameHostInterceptor {
 public:
  BeginNavigationInitiatorReplacer(
      WebContents* web_contents,
      absl::optional<url::Origin> initiator_to_inject)
      : FrameHostInterceptor(web_contents),
        initiator_to_inject_(initiator_to_inject) {}

  bool WillDispatchBeginNavigation(
      RenderFrameHost* render_frame_host,
      blink::mojom::CommonNavigationParamsPtr* common_params,
      blink::mojom::BeginNavigationParamsPtr* begin_params,
      mojo::PendingRemote<blink::mojom::BlobURLToken>* blob_url_token,
      mojo::PendingAssociatedRemote<mojom::NavigationClient>* navigation_client)
      override {
    if (is_activated_) {
      (*common_params)->initiator_origin = initiator_to_inject_;
      is_activated_ = false;
    }

    return true;
  }

  void Activate() { is_activated_ = true; }

 private:
  absl::optional<url::Origin> initiator_to_inject_;
  bool is_activated_ = false;

  DISALLOW_COPY_AND_ASSIGN(BeginNavigationInitiatorReplacer);
};

IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       InvalidBeginNavigationInitiator) {
  WebContentsImpl* web_contents =
      static_cast<WebContentsImpl*>(shell()->web_contents());

  // Prepare to intercept BeginNavigation mojo IPC. This has to be done before
  // the test creates the RenderFrameHostImpl that is the target of the IPC.
  BeginNavigationInitiatorReplacer injector(
      web_contents, url::Origin::Create(GURL("http://b.com")));

  // Explicitly isolating a.com helps ensure that this test is applicable on
  // platforms without site-per-process.
  IsolateOrigin("a.com");

  // Navigate to a test page that will be locked to a.com.
  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURL(web_contents, main_url));

  // Start monitoring for renderer kills.
  RenderProcessHost* main_process = web_contents->GetMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_process);

  // Have the main frame navigate and lie that the initiator origin is b.com.
  injector.Activate();
  // Don't expect a response for the script, as the process may be killed
  // before the script sends its completion message.
  ExecuteScriptAsync(web_contents, "window.location = '/title2.html';");

  // Verify that the renderer was terminated.
  EXPECT_EQ(bad_message::INVALID_INITIATOR_ORIGIN, kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       MissingBeginNavigationInitiator) {
  // Prepare to intercept BeginNavigation mojo IPC.  This has to be done before
  // the test creates the RenderFrameHostImpl that is the target of the IPC.
  WebContents* web_contents = shell()->web_contents();
  BeginNavigationInitiatorReplacer injector(web_contents, absl::nullopt);

  // Navigate to a test page.
  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURL(web_contents, main_url));

  // Start monitoring for renderer kills.
  RenderProcessHost* main_process = web_contents->GetMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_process);

  // Have the main frame submit a BeginNavigation IPC with a missing initiator.
  injector.Activate();
  // Don't expect a response for the script, as the process may be killed
  // before the script sends its completion message.
  ExecuteScriptAsync(web_contents, "window.location = '/title2.html';");

  // Verify that the renderer was terminated.
  EXPECT_EQ(bad_message::RFHI_BEGIN_NAVIGATION_MISSING_INITIATOR_ORIGIN,
            kill_waiter.Wait());
}

namespace {

// An interceptor class that allows replacing the URL of the commit IPC from
// the renderer process to the browser process.
class DidCommitUrlReplacer : public DidCommitNavigationInterceptor {
 public:
  DidCommitUrlReplacer(WebContents* web_contents, const GURL& replacement_url)
      : DidCommitNavigationInterceptor(web_contents),
        replacement_url_(replacement_url) {}

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

  ~DidCommitUrlReplacer() override = default;

 protected:
  bool WillProcessDidCommitNavigation(
      RenderFrameHost* render_frame_host,
      NavigationRequest* navigation_request,
      mojom::DidCommitProvisionalLoadParamsPtr* params,
      mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params)
      override {
    (**params).url = replacement_url_;
    return true;
  }

 private:
  GURL replacement_url_;
};

}  // namespace

// Test which verifies that when an exploited renderer process sends a commit
// message with URL that the process is not allowed to commit.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, DidCommitInvalidURL) {
  // Explicitly isolating foo.com helps ensure that this test is applicable on
  // platforms without site-per-process.
  IsolateOrigin("foo.com");

  RenderFrameDeletedObserver initial_frame_deleted_observer(
      shell()->web_contents()->GetMainFrame());

  // Test assumes the initial RenderFrameHost to be deleted. Disable
  // back-forward cache to ensure that it doesn't get preserved in the cache.
  DisableBackForwardCacheForTesting(shell()->web_contents(),
                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);

  // Navigate to foo.com initially.
  GURL foo_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), foo_url));

  // Wait for the RenderFrameHost which was current before the navigation to
  // foo.com to be deleted. This is necessary, since on a slow system the
  // UnloadACK event can arrive after the DidCommitUrlReplacer instance below
  // is created. The replacer code has checks to ensure that all frames being
  // deleted it has seen being created, which with delayed UnloadACK is
  // violated.
  initial_frame_deleted_observer.WaitUntilDeleted();

  // Create the interceptor object which will replace the URL of the subsequent
  // navigation with bar.com based URL.
  GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title3.html"));
  DidCommitUrlReplacer url_replacer(shell()->web_contents(), bar_url);

  // Navigate to another URL within foo.com, which would usually be committed
  // successfully, but when the URL is modified it should result in the
  // termination of the renderer process.
  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      shell()->web_contents()->GetMainFrame()->GetProcess());
  EXPECT_FALSE(NavigateToURL(
      shell(), embedded_test_server()->GetURL("foo.com", "/title2.html")));
  EXPECT_EQ(bad_message::RFH_CAN_COMMIT_URL_BLOCKED, kill_waiter.Wait());
}

// Test which verifies that when an exploited renderer process sends a commit
// message with URL that the process is not allowed to commit.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       DidCommitInvalidURLWithOpaqueOrigin) {
  // Explicitly isolating foo.com helps ensure that this test is applicable on
  // platforms without site-per-process.
  IsolateOrigin("foo.com");

  RenderFrameDeletedObserver initial_frame_deleted_observer(
      shell()->web_contents()->GetMainFrame());

  // Test assumes the initial RenderFrameHost to be deleted. Disable
  // back-forward cache to ensure that it doesn't get preserved in the cache.
  DisableBackForwardCacheForTesting(shell()->web_contents(),
                                    BackForwardCache::TEST_ASSUMES_NO_CACHING);

  // Navigate to foo.com initially.
  GURL foo_url(embedded_test_server()->GetURL("foo.com",
                                              "/page_with_blank_iframe.html"));
  EXPECT_TRUE(NavigateToURL(shell(), foo_url));

  // Wait for the RenderFrameHost which was current before the navigation to
  // foo.com to be deleted. This is necessary, since on a slow system the
  // UnloadACK event can arrive after the DidCommitUrlReplacer instance below
  // is created. The replacer code has checks to ensure that all frames being
  // deleted it has seen being created, which with delayed UnloadACK is
  // violated.
  initial_frame_deleted_observer.WaitUntilDeleted();

  // Create the interceptor object which will replace the URL of the subsequent
  // navigation with bar.com based URL.
  GURL bar_url(embedded_test_server()->GetURL("bar.com", "/title3.html"));
  DidCommitUrlReplacer url_replacer(shell()->web_contents(), bar_url);

  // Navigate the subframe to a data URL, which would usually be committed
  // successfully in the same process as foo.com, but when the URL is modified
  // it should result in the termination of the renderer process.
  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      shell()->web_contents()->GetMainFrame()->GetProcess());
  GURL data_url(R"(data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E)");
  EXPECT_TRUE(
      NavigateIframeToURL(shell()->web_contents(), "test_iframe", data_url));
  EXPECT_EQ(bad_message::RFH_CAN_COMMIT_URL_BLOCKED, kill_waiter.Wait());
}

// Test which verifies that a WebUI process cannot send a commit message with
// URL for a web document.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       WebUIProcessDidCommitWebURL) {
  // Navigate to a WebUI document.
  GURL webui_url(GetWebUIURL(kChromeUIGpuHost));
  EXPECT_TRUE(NavigateToURL(shell(), webui_url));

  // Create the interceptor object which will replace the URL of the subsequent
  // navigation with |web_url|.
  GURL web_url(embedded_test_server()->GetURL("foo.com", "/title3.html"));
  DidCommitUrlReplacer url_replacer(shell()->web_contents(), web_url);

  // Navigate to another URL within the WebUI, which would usually be committed
  // successfully, but when the URL is modified it should result in the
  // termination of the renderer process.
  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      shell()->web_contents()->GetMainFrame()->GetProcess());
  GURL second_webui_url(webui_url.Resolve("/foo"));
  EXPECT_FALSE(NavigateToURL(shell(), second_webui_url));
  EXPECT_EQ(bad_message::RFH_CAN_COMMIT_URL_BLOCKED, kill_waiter.Wait());
}

// Test that verifies that if a RenderFrameHost is incorrectly given WebUI
// bindings, committing a non-WebUI URL in it is detected and the process is
// correctly terminated.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       DidCommitNonWebUIURLInProcessWithBindings) {
  // Navigate to a web URL.
  GURL initial_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), initial_url));

  // Start a second navigation.
  GURL web_url(embedded_test_server()->GetURL("foo.com", "/title2.html"));
  TestNavigationManager navigation(shell()->web_contents(), web_url);
  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      shell()->web_contents()->GetMainFrame()->GetProcess());

  shell()->LoadURL(web_url);
  EXPECT_TRUE(navigation.WaitForResponse());

  // Grant WebUI bindings to the navigated frame to simulate a bug in the code
  // that incorrectly does it for a navigation that does not require it.
  navigation.GetNavigationHandle()->GetRenderFrameHost()->AllowBindings(
      BINDINGS_POLICY_WEB_UI);

  // Resume the navigation and upon receiving the commit message the renderer
  // process will be terminated.
  navigation.ResumeNavigation();
  EXPECT_EQ(bad_message::RFH_CAN_COMMIT_URL_BLOCKED, kill_waiter.Wait());
}

// Tests that a web page cannot bind to a WebUI interface if a WebUI page is the
// currently committed RenderFrameHost in the tab (https://crbug.com/1225929).
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, BindToWebUIFromWebViaMojo) {
  // Navigate to a non-privileged web page, and simulate a renderer compromise
  // by granting MojoJS.
  GURL web_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
  TestNavigationManager navigation(shell()->web_contents(), web_url);
  shell()->LoadURL(web_url);
  EXPECT_TRUE(navigation.WaitForResponse());
  RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetMainFrame());
  main_frame->GetFrameBindingsControl()->EnableMojoJsBindings();
  navigation.WaitForNavigationFinished();

  // Open a popup so that the process won't exit on its own when leaving.
  OpenBlankWindow(static_cast<WebContentsImpl*>(shell()->web_contents()));

  // When the page unloads (after the cross-process navigation to an actual
  // WebUI page below), try to bind to a WebUI interface from the web
  // RenderFrameHost. Ensure the unload timer and bfcache are disabled so that
  // the handler has a chance to run.
  main_frame->DisableUnloadTimerForTesting();
  DisableBackForwardCacheForTesting(shell()->web_contents(),
                                    BackForwardCache::TEST_USES_UNLOAD_EVENT);
  ASSERT_TRUE(ExecJs(main_frame, R"(
        // Intentionally leak pipe as a global so it doesn't get GCed.
        newMessagePipe = Mojo.createMessagePipe();
        onunload = function () {
          Mojo.bindInterface('mojom.ProcessInternalsHandler',
                             newMessagePipe.handle0);
        };
      )"));

  // Now navigate to a WebUI page and expect the previous renderer process to be
  // killed when asking to bind to the WebUI interface.
  GURL webui_url(
      GetWebUIURL(kChromeUIProcessInternalsHost).Resolve("#general"));
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame->GetProcess());
  EXPECT_TRUE(NavigateToURL(shell(), webui_url));

  // Verify that the previous renderer was terminated.
  EXPECT_EQ(bad_message::RFH_INVALID_WEB_UI_CONTROLLER, kill_waiter.Wait());
}

class BeginNavigationTransitionReplacer : public FrameHostInterceptor {
 public:
  BeginNavigationTransitionReplacer(WebContents* web_contents,
                                    ui::PageTransition transition_to_inject)
      : FrameHostInterceptor(web_contents),
        transition_to_inject_(transition_to_inject) {}

  bool WillDispatchBeginNavigation(
      RenderFrameHost* render_frame_host,
      blink::mojom::CommonNavigationParamsPtr* common_params,
      blink::mojom::BeginNavigationParamsPtr* begin_params,
      mojo::PendingRemote<blink::mojom::BlobURLToken>* blob_url_token,
      mojo::PendingAssociatedRemote<mojom::NavigationClient>* navigation_client)
      override {
    if (is_activated_) {
      (*common_params)->transition = transition_to_inject_;
      is_activated_ = false;
    }

    return true;
  }

  void Activate() { is_activated_ = true; }

 private:
  ui::PageTransition transition_to_inject_;
  bool is_activated_ = false;

  DISALLOW_COPY_AND_ASSIGN(BeginNavigationTransitionReplacer);
};

IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, NonWebbyTransition) {
  const ui::PageTransition test_cases[] = {
      ui::PAGE_TRANSITION_TYPED,
      ui::PAGE_TRANSITION_AUTO_BOOKMARK,
      ui::PAGE_TRANSITION_GENERATED,
      ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
      ui::PAGE_TRANSITION_RELOAD,
      ui::PAGE_TRANSITION_KEYWORD,
      ui::PAGE_TRANSITION_KEYWORD_GENERATED};

  for (ui::PageTransition transition : test_cases) {
    // Prepare to intercept BeginNavigation mojo IPC.  This has to be done
    // before the test creates the RenderFrameHostImpl that is the target of the
    // IPC.
    WebContents* web_contents = shell()->web_contents();
    BeginNavigationTransitionReplacer injector(web_contents, transition);

    // Navigate to a test page.
    GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
    EXPECT_TRUE(NavigateToURL(web_contents, main_url));

    // Start monitoring for renderer kills.
    RenderProcessHost* main_process =
        web_contents->GetMainFrame()->GetProcess();
    RenderProcessHostBadIpcMessageWaiter kill_waiter(main_process);

    // Have the main frame submit a BeginNavigation IPC with a missing
    // initiator.
    injector.Activate();
    // Don't expect a response for the script, as the process may be killed
    // before the script sends its completion message.
    ExecuteScriptAsync(web_contents, "window.location = '/title2.html';");

    // Verify that the renderer was terminated.
    EXPECT_EQ(bad_message::RFHI_BEGIN_NAVIGATION_NON_WEBBY_TRANSITION,
              kill_waiter.Wait());
  }
}

class SecurityExploitViaDisabledWebSecurityTest
    : public SecurityExploitBrowserTest {
 public:
  SecurityExploitViaDisabledWebSecurityTest() {
    // To get around BlockedSchemeNavigationThrottle. Other attempts at getting
    // around it don't work, i.e.:
    // -if the request is made in a child frame then the frame is torn down
    // immediately on process killing so the navigation doesn't complete
    // -if it's classified as same document, then a DCHECK in
    // NavigationRequest::CreateRendererInitiated fires
    feature_list_.InitAndEnableFeature(
        features::kAllowContentInitiatedDataUrlNavigations);
  }

 protected:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    // Simulate a compromised renderer, otherwise the cross-origin request to
    // file: is blocked.
    command_line->AppendSwitch(switches::kDisableWebSecurity);
    SecurityExploitBrowserTest::SetUpCommandLine(command_line);
  }

 private:
  base::test::ScopedFeatureList feature_list_;
};

// Test to verify that an exploited renderer process trying to specify a
// non-empty URL for base_url_for_data_url on navigation is correctly
// terminated.
IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest,
                       ValidateBaseUrlForDataUrl) {
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetMainFrame());

  GURL data_url("data:text/html,foo");
  base::FilePath file_path = GetTestFilePath("", "simple_page.html");
  GURL file_url = net::FilePathToFileURL(file_path);

  // Setup a BeginNavigate IPC with non-empty base_url_for_data_url.
  blink::mojom::CommonNavigationParamsPtr common_params =
      blink::mojom::CommonNavigationParams::New(
          data_url, url::Origin::Create(data_url),
          blink::mojom::Referrer::New(), ui::PAGE_TRANSITION_LINK,
          blink::mojom::NavigationType::DIFFERENT_DOCUMENT,
          blink::NavigationDownloadPolicy(),
          false /* should_replace_current_entry */,
          file_url, /* base_url_for_data_url */
          blink::PreviewsTypes::PREVIEWS_UNSPECIFIED,
          base::TimeTicks::Now() /* navigation_start */, "GET",
          nullptr /* post_data */, network::mojom::SourceLocation::New(),
          false /* started_from_context_menu */, false /* has_user_gesture */,
          false /* text_fragment_token */,
          network::mojom::CSPDisposition::CHECK,
          std::vector<int>() /* initiator_origin_trial_features */,
          std::string() /* href_translate */,
          false /* is_history_navigation_in_new_child_frame */,
          base::TimeTicks() /* input_start */,
          network::mojom::RequestDestination::kDocument);
  blink::mojom::BeginNavigationParamsPtr begin_params =
      blink::mojom::BeginNavigationParams::New(
          absl::nullopt /* initiator_frame_token */,
          std::string() /* headers */, net::LOAD_NORMAL,
          false /* skip_service_worker */,
          blink::mojom::RequestContextType::LOCATION,
          blink::mojom::MixedContentContextType::kBlockable,
          false /* is_form_submission */,
          false /* was_initiated_by_link_click */,
          GURL() /* searchable_form_url */,
          std::string() /* searchable_form_encoding */,
          GURL() /* client_side_redirect_url */,
          absl::nullopt /* devtools_initiator_info */,
          nullptr /* trust_token_params */, absl::nullopt /* impression */,
          base::TimeTicks() /* renderer_before_unload_start */,
          base::TimeTicks() /* renderer_before_unload_end */,
          absl::nullopt /* web_bundle_token */);

  // Receiving the invalid IPC message should lead to renderer process
  // termination.
  RenderProcessHostBadIpcMessageWaiter process_kill_waiter(rfh->GetProcess());

  mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client;
  auto navigation_client_receiver =
      navigation_client.InitWithNewEndpointAndPassReceiver();
  rfh->frame_host_receiver_for_testing().impl()->BeginNavigation(
      std::move(common_params), std::move(begin_params), mojo::NullRemote(),
      std::move(navigation_client), mojo::NullRemote());
  EXPECT_EQ(bad_message::RFH_BASE_URL_FOR_DATA_URL_SPECIFIED,
            process_kill_waiter.Wait());

  EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
      rfh->GetProcess()->GetID(), file_path));

  // Reload the page to create another renderer process.
  TestNavigationObserver tab_observer(shell()->web_contents(), 1);
  shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false);
  tab_observer.Wait();

  // Make an XHR request to check if the page has access.
  std::string script = base::StringPrintf(
      "var xhr = new XMLHttpRequest()\n"
      "xhr.open('GET', '%s', false);\n"
      "try { xhr.send(); } catch (e) {}\n"
      "xhr.responseText;",
      file_url.spec().c_str());
  std::string result = EvalJs(shell()->web_contents(), script).ExtractString();
  EXPECT_TRUE(result.empty());
}

// Tests what happens when a web renderer asks to begin navigating to a file
// url.
IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest,
                       WebToFileNavigation) {
  // Navigate to a web page.
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  // Have the webpage attempt to open a window with a file URL.
  //
  // Note that such attempt would normally be blocked in the renderer ("Not
  // allowed to load local resource: file:///..."), but the test here simulates
  // a compromised renderer by using --disable-web-security cmdline flag.
  GURL file_url = GetTestUrl("", "simple_page.html");
  WebContentsAddedObserver new_window_observer;
  TestNavigationObserver nav_observer(nullptr);
  nav_observer.StartWatchingNewWebContents();
  ASSERT_TRUE(ExecJs(shell()->web_contents(),
                     JsReplace("window.open($1, '_blank')", file_url)));
  WebContents* new_window = new_window_observer.GetWebContents();
  nav_observer.WaitForNavigationFinished();

  // Verify that the navigation got blocked.
  EXPECT_TRUE(nav_observer.last_navigation_succeeded());
  EXPECT_EQ(GURL(kBlockedURL), nav_observer.last_navigation_url());
  EXPECT_EQ(GURL(kBlockedURL),
            new_window->GetMainFrame()->GetLastCommittedURL());
  EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetLastCommittedOrigin(),
            new_window->GetMainFrame()->GetLastCommittedOrigin());
  EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(),
            new_window->GetMainFrame()->GetProcess());

  // Even though the navigation is blocked, we expect the opener relationship to
  // be established between the 2 windows.
  EXPECT_EQ(true, ExecJs(new_window, "!!window.opener"));
}

// Tests what happens when a web renderer asks to begin navigating to a
// view-source url.
IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest,
                       WebToViewSourceNavigation) {
  // Navigate to a web page.
  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  // Have the webpage attempt to open a window with a view-source URL.
  //
  // Note that such attempt would normally be blocked in the renderer ("Not
  // allowed to load local resource: view-source:///..."), but the test here
  // simulates a compromised renderer by using --disable-web-security flag.
  base::FilePath file_path = GetTestFilePath("", "simple_page.html");
  GURL view_source_url =
      GURL(std::string(kViewSourceScheme) + ":" + start_url.spec());
  WebContentsAddedObserver new_window_observer;
  TestNavigationObserver nav_observer(nullptr);
  nav_observer.StartWatchingNewWebContents();
  ASSERT_TRUE(ExecJs(shell()->web_contents(),
                     JsReplace("window.open($1, '_blank')", view_source_url)));
  WebContents* new_window = new_window_observer.GetWebContents();
  nav_observer.WaitForNavigationFinished();

  // Verify that the navigation got blocked.
  EXPECT_TRUE(nav_observer.last_navigation_succeeded());
  EXPECT_EQ(GURL(kBlockedURL), nav_observer.last_navigation_url());
  EXPECT_EQ(GURL(kBlockedURL),
            new_window->GetMainFrame()->GetLastCommittedURL());
  EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetLastCommittedOrigin(),
            new_window->GetMainFrame()->GetLastCommittedOrigin());
  EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(),
            new_window->GetMainFrame()->GetProcess());

  // Even though the navigation is blocked, we expect the opener relationship to
  // be established between the 2 windows.
  EXPECT_EQ(true, ExecJs(new_window, "!!window.opener"));
}

class BeginNavigationTrustTokenParamsReplacer : public FrameHostInterceptor {
 public:
  BeginNavigationTrustTokenParamsReplacer(
      WebContents* web_contents,
      network::mojom::TrustTokenParamsPtr params_to_inject)
      : FrameHostInterceptor(web_contents),
        params_to_inject_(std::move(params_to_inject)) {}

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

  bool WillDispatchBeginNavigation(
      RenderFrameHost* render_frame_host,
      blink::mojom::CommonNavigationParamsPtr* common_params,
      blink::mojom::BeginNavigationParamsPtr* begin_params,
      mojo::PendingRemote<blink::mojom::BlobURLToken>* blob_url_token,
      mojo::PendingAssociatedRemote<mojom::NavigationClient>* navigation_client)
      override {
    if (is_activated_) {
      (*begin_params)->trust_token_params = params_to_inject_.Clone();
      is_activated_ = false;
    }

    return true;
  }

  void Activate() { is_activated_ = true; }

 private:
  network::mojom::TrustTokenParamsPtr params_to_inject_;
  bool is_activated_ = false;
};

class SecurityExploitBrowserTestWithTrustTokensEnabled
    : public SecurityExploitBrowserTest {
 public:
  SecurityExploitBrowserTestWithTrustTokensEnabled() {
    feature_list_.InitAndEnableFeature(network::features::kTrustTokens);
  }

 private:
  base::test::ScopedFeatureList feature_list_;
};

// Test that the browser correctly reports a bad message when a child frame
// attempts to navigate with a Trust Tokens redemption operation associated with
// the navigation, but its parent lacks the trust-token-redemption Permissions
// Policy feature.
IN_PROC_BROWSER_TEST_F(
    SecurityExploitBrowserTestWithTrustTokensEnabled,
    BrowserForbidsTrustTokenRedemptionWithoutPermissionsPolicy) {
  WebContents* web_contents = shell()->web_contents();

  // Prepare to intercept BeginNavigation mojo IPC. This has to be done before
  // the test creates the RenderFrameHostImpl that is the target of the IPC.
  auto params = network::mojom::TrustTokenParams::New();
  params->type = network::mojom::TrustTokenOperationType::kRedemption;
  BeginNavigationTrustTokenParamsReplacer replacer(web_contents,
                                                   std::move(params));

  GURL start_url(embedded_test_server()->GetURL(
      "/page-with-trust-token-permissions-policy-disabled.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  RenderFrameHost* parent = web_contents->GetMainFrame();
  ASSERT_FALSE(parent->IsFeatureEnabled(
      blink::mojom::PermissionsPolicyFeature::kTrustTokenRedemption));

  RenderFrameHost* child = static_cast<WebContentsImpl*>(web_contents)
                               ->GetFrameTree()
                               ->root()
                               ->child_at(0)
                               ->current_frame_host();
  RenderProcessHostBadMojoMessageWaiter kill_waiter(child->GetProcess());

  replacer.Activate();

  // Note: this can't use NavigateFrameToURL, because that method doesn't
  // route through RFHI::BeginNavigation. It also can't use NavigateIframeToURL,
  // because that navigation will hang.
  //
  // It also can't EXPECT_TRUE or EXPECT_FALSE: sometimes the ExecJs call will
  // finish before the renderer gets killed, and sometimes it won't.
  ignore_result(
      ExecJs(child, JsReplace("location.href=$1;", GURL("/title2.html"))));

  EXPECT_THAT(kill_waiter.Wait(),
              Optional(HasSubstr("Permissions Policy feature is absent")));
}

// Test that the browser correctly reports a bad message when a child frame
// attempts to navigate with a Trust Tokens signing operation associated with
// the navigation, but its parent lacks the trust-token-redemption (sic)
// Permissions Policy feature.
IN_PROC_BROWSER_TEST_F(
    SecurityExploitBrowserTestWithTrustTokensEnabled,
    BrowserForbidsTrustTokenSigningWithoutPermissionsPolicy) {
  WebContents* web_contents = shell()->web_contents();

  // Prepare to intercept BeginNavigation mojo IPC. This has to be done before
  // the test creates the RenderFrameHostImpl that is the target of the IPC.
  auto params = network::mojom::TrustTokenParams::New();
  params->type = network::mojom::TrustTokenOperationType::kSigning;
  BeginNavigationTrustTokenParamsReplacer replacer(web_contents,
                                                   std::move(params));

  GURL start_url(embedded_test_server()->GetURL(
      "/page-with-trust-token-permissions-policy-disabled.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  RenderFrameHost* parent = web_contents->GetMainFrame();
  ASSERT_FALSE(parent->IsFeatureEnabled(
      blink::mojom::PermissionsPolicyFeature::kTrustTokenRedemption));

  RenderFrameHost* child = static_cast<WebContentsImpl*>(web_contents)
                               ->GetFrameTree()
                               ->root()
                               ->child_at(0)
                               ->current_frame_host();
  RenderProcessHostBadMojoMessageWaiter kill_waiter(child->GetProcess());

  replacer.Activate();

  // Note: this can't use NavigateFrameToURL, because that method doesn't
  // route through RFHI::BeginNavigation. It also can't use NavigateIframeToURL,
  // because that navigation will hang.
  //
  // It also can't EXPECT_TRUE or EXPECT_FALSE: sometimes the ExecJs call will
  // finish before the renderer gets killed, and sometimes it won't.
  ignore_result(
      ExecJs(child, JsReplace("location.href=$1;", GURL("/title2.html"))));

  EXPECT_THAT(kill_waiter.Wait(),
              Optional(HasSubstr("Permissions Policy feature is absent")));
}

IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestWithTrustTokensEnabled,
                       BrowserForbidsTrustTokenParamsOnMainFrameNav) {
  WebContents* web_contents = shell()->web_contents();

  // Prepare to intercept BeginNavigation mojo IPC. This has to be done before
  // the test creates the RenderFrameHostImpl that is the target of the IPC.
  BeginNavigationTrustTokenParamsReplacer replacer(
      web_contents, network::mojom::TrustTokenParams::New());

  GURL start_url(embedded_test_server()->GetURL("/title1.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  RenderFrameHost* compromised_renderer = web_contents->GetMainFrame();
  RenderProcessHostBadMojoMessageWaiter kill_waiter(
      compromised_renderer->GetProcess());

  replacer.Activate();

  // Can't use NavigateToURL here because it would hang. Additionally, we can't
  // EXPECT_TRUE or EXPECT_FALSE: sometimes the ExecJs call will finish
  // before the renderer gets killed, and sometimes it won't.
  ignore_result(ExecJs(compromised_renderer,
                       JsReplace("location.href=$1", GURL("/title2.html"))));

  EXPECT_THAT(kill_waiter.Wait(),
              Optional(HasSubstr("Trust Token params in main frame nav")));
}

}  // namespace content
