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

#include <stdint.h>

#include <tuple>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.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/fenced_frame/fenced_frame.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/fenced_frame_test_util.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_frame_navigation_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/test_support/test_utils.h"
#include "net/base/features.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/fenced_frame/fenced_frame_utils.h"
#include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h"
#include "third_party/blink/public/common/navigation/navigation_policy.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/blink/public/mojom/fenced_frame/fenced_frame.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()->GetPrimaryMainFrame()->GetProcess()->GetID(),
      shell2->web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID());
  *target_routing_id = shell2->web_contents()
                           ->GetPrimaryMainFrame()
                           ->GetRenderViewHost()
                           ->GetRoutingID();
  EXPECT_NE(*target_routing_id, shell->web_contents()
                                    ->GetPrimaryMainFrame()
                                    ->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->GetPrimaryFrameTree().root()->navigator().RequestOpenURL(
      wc->GetPrimaryFrameTree().root()->current_frame_host(), extension_url,
      nullptr /* initiator_frame_token */,
      ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
      url::Origin::Create(foo), /* initiator_base_url= */ absl::nullopt,
      nullptr, std::string(), Referrer(), WindowOpenDisposition::CURRENT_TAB,
      false /* should_replace_current_entry */, true /* user_gesture */,
      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->GetPrimaryFrameTree()
                                      .root()
                                      ->render_manager()
                                      ->speculative_frame_host();

  EXPECT_TRUE(next_rfh);
  EXPECT_NE(shell->web_contents()->GetPrimaryMainFrame()->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;
}

// 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()->GetPrimaryMainFrame();
  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()->GetPrimaryMainFrame()->GetEnabledBindings());

  RenderFrameHost* compromised_renderer =
      shell()->web_contents()->GetPrimaryMainFrame();
  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 BUILDFLAG(IS_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()->GetPrimaryMainFrame();
  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;

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

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

// 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())
                            ->GetPrimaryFrameTree()
                            .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()->GetPrimaryMainFrame());

  // 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()->GetPrimaryMainFrame()->GetProcess());
  // ExecJs will sometimes finish before the renderer gets killed, so we must
  // ignore the result.
  std::ignore = ExecJs(shell()->web_contents()->GetPrimaryMainFrame(),
                       "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.
  std::ignore = 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()->GetPrimaryMainFrame()->GetProcess());
  // ExecJs will sometimes finish before the renderer gets killed, so we must
  // ignore the result.
  std::ignore = ExecJs(shell()->web_contents()->GetPrimaryMainFrame(),
                       "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()->GetPrimaryMainFrame());
  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())
                            ->GetPrimaryFrameTree()
                            .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()->GetPrimaryMainFrame());

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

enum class SecurityExploitBrowserTestMojoBlobURLsTestCase {
  kSupportPartitionedBlobUrlDisabled,
  kSupportPartitionedBlobUrlEnabled,
};

class SecurityExploitBrowserTestMojoBlobURLsP
    : public SecurityExploitBrowserTest,
      public testing::WithParamInterface<
          SecurityExploitBrowserTestMojoBlobURLsTestCase> {
 public:
  SecurityExploitBrowserTestMojoBlobURLsP() = default;

  void SetUp() override {
    test_case_ = GetParam();
    scoped_feature_list_.InitWithFeatureState(
        net::features::kSupportPartitionedBlobUrl,
        test_case_ == SecurityExploitBrowserTestMojoBlobURLsTestCase::
                          kSupportPartitionedBlobUrlEnabled);

    SecurityExploitBrowserTest::SetUp();
  }

  void TearDown() override {
    if (base::FeatureList::IsEnabled(
            net::features::kSupportPartitionedBlobUrl)) {
      storage::BlobUrlRegistry::SetURLStoreCreationHookForTesting(nullptr);
    } else {
      storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(nullptr);
    }
  }

 private:
  SecurityExploitBrowserTestMojoBlobURLsTestCase test_case_;
  base::test::ScopedFeatureList scoped_feature_list_;
};

// 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_P(SecurityExploitBrowserTestMojoBlobURLsP,
                       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()->GetPrimaryMainFrame();

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

  base::RepeatingCallback<void(storage::BlobUrlRegistry*, mojo::ReceiverId)>
      blob_url_registry_intercept_hook;
  base::RepeatingCallback<void(
      mojo::SelfOwnedAssociatedReceiverRef<blink::mojom::BlobURLStore>)>
      blob_registry_impl_intercept_hook;

  if (base::FeatureList::IsEnabled(net::features::kSupportPartitionedBlobUrl)) {
    blob_url_registry_intercept_hook =
        base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
                            GURL("blob:" + target_origin + "/" + blob_path));
    storage::BlobUrlRegistry::SetURLStoreCreationHookForTesting(
        &blob_url_registry_intercept_hook);
  } else {
    blob_registry_impl_intercept_hook =
        base::BindRepeating(&BlobURLStoreInterceptor::InterceptDeprecated,
                            GURL("blob:" + target_origin + "/" + blob_path));
    storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(
        &blob_registry_impl_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.
  std::ignore = ExecJs(rfh, "URL.createObjectURL(new Blob(['foo']))");

  // If the process is killed, this test passes.
  EXPECT_EQ(
      "Received bad user message: "
      "URL with invalid origin 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));
  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetPrimaryMainFrame());

  // 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);",
      base::NullCallback());

  // 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, rfh->storage_key());

  // 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, rfh->storage_key());

  // 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())
                            ->GetPrimaryFrameTree()
                            .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())
                            ->GetPrimaryFrameTree()
                            .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.
  SiteInstanceImpl* a_com_instance =
      root->current_frame_host()->GetSiteInstance();
  RenderFrameProxyHost* proxy =
      child->current_frame_host()
          ->browsing_context_state()
          ->GetRenderFrameProxyHost(a_com_instance->group());
  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->current_frame_host()
              ->browsing_context_state()
              ->GetRenderFrameProxyHost(a_com_instance->group());
  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),
        swapped_impl_(
            render_frame_proxy_host_->frame_host_receiver_for_testing(),
            this) {}

  ~RemoteFrameHostInterceptor() override = default;

  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:
  raw_ptr<RenderFrameProxyHost> render_frame_proxy_host_;

  std::u16string evil_origin_;
  blink::mojom::OpenURLParamsPtr intercepted_params_;
  mojo::test::ScopedSwapImplForTesting<
      mojo::AssociatedReceiver<blink::mojom::RemoteFrameHost>>
      swapped_impl_;
};

// 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->GetPrimaryMainFrame();
  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())
          ->GetPrimaryFrameTree()
          .root();
  FrameTreeNode* subframe_node = main_frame_node->child_at(0);
  SiteInstanceImpl* b_com_instance =
      subframe_node->current_frame_host()->GetSiteInstance();
  RenderFrameProxyHost* main_frame_proxy_host =
      main_frame_node->current_frame_host()
          ->browsing_context_state()
          ->GetRenderFrameProxyHost(b_com_instance->group());

  // Prepare to intercept the RouteMessageEvent IPC message that will come
  // from the subframe process.
  url::Origin invalid_origin =
      web_contents->GetPrimaryMainFrame()->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()->GetPrimaryMainFrame());
  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())
          ->GetPrimaryFrameTree()
          .root();
  FrameTreeNode* child_node = main_frame_node->child_at(0);
  SiteInstanceImpl* a_com_instance =
      main_frame_node->current_frame_host()->GetSiteInstance();
  RenderFrameProxyHost* proxy =
      child_node->current_frame_host()
          ->browsing_context_state()
          ->GetRenderFrameProxyHost(a_com_instance->group());
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_process);
  {
    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()->GetPrimaryMainFrame(),
                       "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.
    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) {}

  BeginNavigationInitiatorReplacer(const BeginNavigationInitiatorReplacer&) =
      delete;
  BeginNavigationInitiatorReplacer& operator=(
      const BeginNavigationInitiatorReplacer&) = 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_) {
      (*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;
};

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->GetPrimaryMainFrame()->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->GetPrimaryMainFrame()->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()->GetPrimaryMainFrame());

  // 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_REQUIRES_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()->GetPrimaryMainFrame()->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()->GetPrimaryMainFrame());

  // 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_REQUIRES_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()->GetPrimaryMainFrame()->GetProcess());

  // Using BeginNavigateIframeToURL is necessary here, since the process
  // termination will result in DidFinishNavigation notification with the
  // navigation not in "committed" state. NavigateIframeToURL waits for the
  // navigation to complete and ignores non-committed navigations, therefore
  // it will wait indefinitely.
  GURL data_url(R"(data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E)");
  EXPECT_TRUE(BeginNavigateIframeToURL(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()->GetPrimaryMainFrame()->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()->GetPrimaryMainFrame()->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()->GetPrimaryMainFrame());
  main_frame->GetFrameBindingsControl()->EnableMojoJsBindings(nullptr);
  ASSERT_TRUE(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) {}

  BeginNavigationTransitionReplacer(const BeginNavigationTransitionReplacer&) =
      delete;
  BeginNavigationTransitionReplacer& operator=(
      const BeginNavigationTransitionReplacer&) = 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_) {
      (*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;
};

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->GetPrimaryMainFrame()->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()->GetPrimaryMainFrame());

  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),
          /* initiator_base_url= */ absl::nullopt,
          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 */
          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 */,
          blink::mojom::ForceHistoryPush::kNo, 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 */,
          blink::mojom::NavigationInitiatorActivationAndAdStatus::
              kDidNotStartWithTransientActivation);

  // 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(), mojo::NullReceiver());
  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->GetPrimaryMainFrame()->GetLastCommittedURL());
  EXPECT_EQ(
      shell()->web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin(),
      new_window->GetPrimaryMainFrame()->GetLastCommittedOrigin());
  EXPECT_EQ(shell()->web_contents()->GetPrimaryMainFrame()->GetProcess(),
            new_window->GetPrimaryMainFrame()->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->GetPrimaryMainFrame()->GetLastCommittedURL());
  EXPECT_EQ(
      shell()->web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin(),
      new_window->GetPrimaryMainFrame()->GetLastCommittedOrigin());
  EXPECT_EQ(shell()->web_contents()->GetPrimaryMainFrame()->GetProcess(),
            new_window->GetPrimaryMainFrame()->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::kPrivateStateTokens);
  }

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

// Test that the browser correctly reports a bad message when a child frame
// attempts to navigate with a Private State 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->version =
      network::mojom::TrustTokenMajorVersion::kPrivateStateTokenV1;
  params->operation = 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->GetPrimaryMainFrame();
  ASSERT_FALSE(parent->IsFeatureEnabled(
      blink::mojom::PermissionsPolicyFeature::kTrustTokenRedemption));

  RenderFrameHost* child = static_cast<WebContentsImpl*>(web_contents)
                               ->GetPrimaryFrameTree()
                               .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.
  std::ignore =
      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 Private State 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->version =
      network::mojom::TrustTokenMajorVersion::kPrivateStateTokenV1;
  params->operation = 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->GetPrimaryMainFrame();
  ASSERT_FALSE(parent->IsFeatureEnabled(
      blink::mojom::PermissionsPolicyFeature::kTrustTokenRedemption));

  RenderFrameHost* child = static_cast<WebContentsImpl*>(web_contents)
                               ->GetPrimaryFrameTree()
                               .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.
  std::ignore =
      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->GetPrimaryMainFrame();
  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.
  std::ignore = ExecJs(compromised_renderer,
                       JsReplace("location.href=$1", GURL("/title2.html")));

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

class FencedFrameSecurityExploitBrowserTestWithTrustTokensEnabled
    : public SecurityExploitBrowserTestWithTrustTokensEnabled {
 protected:
  FencedFrameSecurityExploitBrowserTestWithTrustTokensEnabled() = default;

  WebContentsImpl* web_contents() {
    return static_cast<WebContentsImpl*>(shell()->web_contents());
  }

  RenderFrameHostImpl* primary_main_frame_host() {
    return web_contents()->GetPrimaryMainFrame();
  }

  test::FencedFrameTestHelper& fenced_frame_test_helper() {
    return fenced_frame_test_helper_;
  }

 private:
  test::FencedFrameTestHelper fenced_frame_test_helper_;
};

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

  FencedFrameBeginNavigationTrustTokenParamsReplacer(
      const FencedFrameBeginNavigationTrustTokenParamsReplacer&) = delete;
  FencedFrameBeginNavigationTrustTokenParamsReplacer& operator=(
      const FencedFrameBeginNavigationTrustTokenParamsReplacer&) = 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 (render_frame_host->IsFencedFrameRoot()) {
      BeginNavigationTrustTokenParamsReplacer::WillDispatchBeginNavigation(
          render_frame_host, common_params, begin_params, blob_url_token,
          navigation_client);
    }
    return true;
  }
};

IN_PROC_BROWSER_TEST_F(
    FencedFrameSecurityExploitBrowserTestWithTrustTokensEnabled,
    BrowserForbidsTrustTokenParamsOnFencedFrameNav) {
  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.
  FencedFrameBeginNavigationTrustTokenParamsReplacer replacer(
      web_contents, network::mojom::TrustTokenParams::New());
  GURL start_url(embedded_test_server()->GetURL("/empty.html"));
  EXPECT_TRUE(NavigateToURL(shell(), start_url));

  RenderFrameHostImplWrapper primary_rfh(primary_main_frame_host());
  RenderFrameHostImplWrapper inner_fenced_frame_rfh(
      fenced_frame_test_helper().CreateFencedFrame(
          primary_rfh.get(),
          embedded_test_server()->GetURL("/fenced_frames/empty.html")));

  RenderFrameHost* compromised_renderer = inner_fenced_frame_rfh.get();
  RenderProcessHostBadMojoMessageWaiter kill_waiter(
      compromised_renderer->GetProcess());
  replacer.Activate();

  std::ignore = ExecJs(
      compromised_renderer,
      JsReplace("location.href=$1",
                embedded_test_server()->GetURL("/fenced_frames/title1.html")));

  absl::optional<std::string> result = kill_waiter.Wait();
  EXPECT_THAT(result,
              Optional(HasSubstr("Private State Token params in fenced frame "
                                 "nav")));
}

class SecurityExploitTestFencedFramesDisabled
    : public SecurityExploitBrowserTest {
 public:
  SecurityExploitTestFencedFramesDisabled() {
    feature_list_.InitAndDisableFeature(blink::features::kFencedFrames);
  }

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

// Ensure that we kill the renderer process if we try to create a
// fenced-frame when the blink::features::kFencedFrames feature is not enabled.
IN_PROC_BROWSER_TEST_F(SecurityExploitTestFencedFramesDisabled,
                       CreateFencedFrameWhenFeatureDisabled) {
  GURL foo("http://foo.com/simple_page.html");
  EXPECT_TRUE(NavigateToURL(shell(), foo));
  EXPECT_EQ(u"OK", shell()->web_contents()->GetTitle());
  EXPECT_FALSE(blink::features::IsFencedFramesEnabled());

  RenderFrameHostImpl* compromised_rfh = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetPrimaryMainFrame());

  mojo::PendingAssociatedRemote<blink::mojom::FencedFrameOwnerHost> remote;
  mojo::PendingAssociatedReceiver<blink::mojom::FencedFrameOwnerHost> receiver;
  receiver = remote.InitWithNewEndpointAndPassReceiver();

  auto remote_frame_interfaces =
      blink::mojom::RemoteFrameInterfacesFromRenderer::New();
  remote_frame_interfaces->frame_host_receiver =
      mojo::AssociatedRemote<blink::mojom::RemoteFrameHost>()
          .BindNewEndpointAndPassDedicatedReceiver();
  mojo::AssociatedRemote<blink::mojom::RemoteFrame> frame;
  std::ignore = frame.BindNewEndpointAndPassDedicatedReceiver();
  remote_frame_interfaces->frame = frame.Unbind();

  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      compromised_rfh->GetProcess());
  static_cast<blink::mojom::LocalFrameHost*>(compromised_rfh)
      ->CreateFencedFrame(
          std::move(receiver), blink::mojom::FencedFrameMode::kDefault,
          std::move(remote_frame_interfaces), blink::RemoteFrameToken(),
          base::UnguessableToken::Create());
  EXPECT_EQ(bad_message::RFH_FENCED_FRAME_MOJO_WHEN_DISABLED,
            kill_waiter.Wait());
}

// Ensure that we kill the renderer process if we try to do a top-level
// navigation using the special _unfencedTop IPC path when we are not inside
// a fenced frame. (Test from an iframe instead.)
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       UnfencedTopFromOutsideFencedFrame) {
  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())
                            ->GetPrimaryFrameTree()
                            .root();
  RenderFrameHostImpl* compromised_rfh =
      root->child_at(0)->current_frame_host();

  RenderProcessHostBadIpcMessageWaiter kill_waiter(
      compromised_rfh->GetProcess());

  GURL url("http://foo.com/simple_page.html");
  auto params = CreateOpenURLParams(url);
  params->is_unfenced_top_navigation = true;
  static_cast<mojom::FrameHost*>(compromised_rfh)->OpenURL(std::move(params));

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

class SecurityExploitBrowserTestFencedFrames
    : public SecurityExploitBrowserTest {
 public:
  SecurityExploitBrowserTestFencedFrames() {
    scoped_feature_list_.InitAndEnableFeatureWithParameters(
        blink::features::kFencedFrames, {});
  }

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

  void SetUpCommandLine(base::CommandLine* command_line) override {
    https_server()->AddDefaultHandlers(GetTestDataFilePath());
    https_server()->ServeFilesFromSourceDirectory(GetTestDataFilePath());
    https_server()->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
    SetupCrossSiteRedirector(https_server());

    // 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(https_server()->InitializeAndListen());
  }

  test::FencedFrameTestHelper& fenced_frame_test_helper() {
    return fenced_frame_test_helper_;
  }

  net::EmbeddedTestServer* https_server() { return &https_server_; }

 private:
  test::FencedFrameTestHelper fenced_frame_test_helper_{};
  base::test::ScopedFeatureList scoped_feature_list_;
  net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
};

IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestFencedFrames,
                       NavigateFencedFrameToInvalidURL) {
  GURL main_frame_url(https_server()->GetURL("a.test", "/simple_page.html"));
  std::vector<GURL> invalid_urls = {
      GURL("http://example.com"),
      GURL("http://example.com?<\n=block"),
      GURL("about:srcdoc"),
      GURL("data:text/html,<p>foo"),
      GURL("blob:https://example.com/a9400bf5-aaa8-4166-86e4-492c50f4ca2b"),
      GURL("file://folder"),
      GURL("javascript:console.log('foo');"),
      GetWebUIURL(kChromeUIHistogramHost),
      GURL(blink::kChromeUIHangURL)};

  for (const GURL& invalid_url : invalid_urls) {
    EXPECT_FALSE(blink::IsValidFencedFrameURL(invalid_url));
    EXPECT_TRUE(blink::features::IsFencedFramesEnabled());
    EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
    EXPECT_EQ(u"OK", shell()->web_contents()->GetTitle());

    RenderFrameHostImpl* compromised_rfh = static_cast<RenderFrameHostImpl*>(
        shell()->web_contents()->GetPrimaryMainFrame());

    mojo::AssociatedRemote<blink::mojom::FencedFrameOwnerHost> remote;
    mojo::PendingAssociatedReceiver<blink::mojom::FencedFrameOwnerHost>
        pending_receiver = remote.BindNewEndpointAndPassReceiver();

    auto remote_frame_interfaces =
        blink::mojom::RemoteFrameInterfacesFromRenderer::New();
    remote_frame_interfaces->frame_host_receiver =
        mojo::AssociatedRemote<blink::mojom::RemoteFrameHost>()
            .BindNewEndpointAndPassDedicatedReceiver();
    mojo::AssociatedRemote<blink::mojom::RemoteFrame> frame;
    std::ignore = frame.BindNewEndpointAndPassDedicatedReceiver();
    remote_frame_interfaces->frame = frame.Unbind();

    RenderProcessHostBadIpcMessageWaiter kill_waiter(
        compromised_rfh->GetProcess());
    static_cast<blink::mojom::LocalFrameHost*>(compromised_rfh)
        ->CreateFencedFrame(std::move(pending_receiver),
                            blink::mojom::FencedFrameMode::kDefault,
                            std::move(remote_frame_interfaces),
                            blink::RemoteFrameToken(),
                            base::UnguessableToken::Create());
    EXPECT_EQ(compromised_rfh->GetFencedFrames().size(), 1u);

    FencedFrame* fenced_frame = compromised_rfh->GetFencedFrames()[0];
    static_cast<blink::mojom::FencedFrameOwnerHost*>(fenced_frame)
        ->Navigate(invalid_url, base::TimeTicks());
    EXPECT_EQ(bad_message::FF_NAVIGATION_INVALID_URL, kill_waiter.Wait());
  }
}

IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestFencedFrames,
                       ChangeFencedFrameSandboxFlags) {
  GURL main_frame_url(https_server()->GetURL("a.test", "/simple_page.html"));

  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
  RenderFrameHostImpl* root_rfh = static_cast<RenderFrameHostImpl*>(
      shell()->web_contents()->GetPrimaryMainFrame());

  const GURL fenced_frame_url =
      https_server()->GetURL("a.test", "/fenced_frames/sandbox_flags.html");
  constexpr char kAddFencedFrameScript[] = R"({
      const fenced_frame = document.createElement('fencedframe');
      fenced_frame.src = $1;
      document.body.appendChild(fenced_frame);
    })";
  EXPECT_TRUE(
      ExecJs(root_rfh, JsReplace(kAddFencedFrameScript, fenced_frame_url)));

  RenderFrameHostImpl* fenced_rfh = nullptr;
  RenderFrameHostImpl* parent_rfh = nullptr;

  std::vector<FencedFrame*> fenced_frames = root_rfh->GetFencedFrames();
  EXPECT_EQ(fenced_frames.size(), 1u);
  FencedFrame* new_fenced_frame = fenced_frames.back();
  fenced_rfh = new_fenced_frame->GetInnerRoot();
  parent_rfh = fenced_rfh;

  RenderProcessHostBadIpcMessageWaiter kill_waiter(fenced_rfh->GetProcess());

  blink::FramePolicy first_policy =
      fenced_rfh->frame_tree_node()->pending_frame_policy();

  first_policy.sandbox_flags = blink::kFencedFrameMandatoryUnsandboxedFlags;
  static_cast<blink::mojom::LocalFrameHost*>(parent_rfh)
      ->DidChangeFramePolicy(std::move(fenced_rfh->GetFrameToken()),
                             std::move(first_policy));

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

INSTANTIATE_TEST_SUITE_P(
    SecurityExploitBrowserTestMojoBlobURLs,
    SecurityExploitBrowserTestMojoBlobURLsP,
    ::testing::Values(SecurityExploitBrowserTestMojoBlobURLsTestCase::
                          kSupportPartitionedBlobUrlDisabled,
                      SecurityExploitBrowserTestMojoBlobURLsTestCase::
                          kSupportPartitionedBlobUrlEnabled));

}  // namespace content
