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

#include <stdint.h>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.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/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_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/web_contents_impl.h"
#include "content/common/frame.mojom.h"
#include "content/common/frame_messages.h"
#include "content/common/render_message_filter.mojom.h"
#include "content/common/view_messages.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/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/navigation_policy.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/did_commit_navigation_interceptor.h"
#include "content/test/frame_host_interceptor.h"
#include "content/test/mock_widget_impl.h"
#include "content/test/test_content_browser_client.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_security_test_util.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/base/filename_util.h"
#include "net/base/network_isolation_key.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/url_request/url_request_slow_download_job.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/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/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/navigation/triggering_event_info.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-test-utils.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"

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 (AreDefaultSiteInstancesEnabled()) {
    // 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(base::ASCIIToUTF16("OK"), shell->web_contents()->GetTitle());

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

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

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

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

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

  return next_rfh;
}

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

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

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

  void Register(mojo::PendingRemote<blink::mojom::Blob> blob,
                const GURL& url,
                RegisterCallback callback) override {
    GetForwardingInterface()->Register(std::move(blob), target_url_,
                                       std::move(callback));
  }

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

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

// Constructs a WebContentsDelegate that mocks a file dialog.
// Unlike content::FileChooserDelegate, this class doesn't make a response in
// RunFileChooser(), and a user needs to call Choose().
class DelayedFileChooserDelegate : public WebContentsDelegate {
 public:
  void Choose(const base::FilePath& file) {
    auto file_info = blink::mojom::FileChooserFileInfo::NewNativeFile(
        blink::mojom::NativeFileInfo::New(file, base::string16()));
    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,
                      std::unique_ptr<FileSelectListener> listener,
                      const blink::mojom::FileChooserParams& params) override {
    listener_ = std::move(listener);
  }

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

 private:
  std::unique_ptr<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();

    base::PostTask(
        FROM_HERE, {BrowserThread::IO},
        base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
  }

 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(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());

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

  mojo::test::BadMessageObserver bad_message_observer;
  mojo::Remote<blink::mojom::FileChooser> factory =
      static_cast<RenderFrameHostImpl*>(compromised_renderer)
          ->BindFileChooserForTesting();
  factory->OpenFileChooser(
      std::move(params), blink::mojom::FileChooser::OpenFileChooserCallback());
  factory.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(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
  EXPECT_EQ(0, shell()->web_contents()->GetMainFrame()->GetEnabledBindings());

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

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

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

// This is a test for crbug.com/312016. It tries to create two RenderWidgetHosts
// with the same process and routing ids, which causes a collision. It is almost
// identical to the AttemptDuplicateRenderViewHost test case.
// Crashes on all platforms.  http://crbug.com/939338
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       DISABLED_AttemptDuplicateRenderWidgetHost) {
  int 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);

  mojo::PendingRemote<mojom::Widget> widget;
  std::unique_ptr<MockWidgetImpl> widget_impl =
      std::make_unique<MockWidgetImpl>(widget.InitWithNewPipeAndPassReceiver());

  // Since this test executes on the UI thread and hopping threads might cause
  // different timing in the test, let's simulate a CreateNewWidget call coming
  // from the IO thread.  Use the existing window routing id to cause a
  // deliberate collision.
  pending_rfh->CreateNewWidget(
      std::move(widget),
      mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>(),
      mojo::PendingAssociatedRemote<blink::mojom::Widget>(), base::DoNothing());

  // If the above operation doesn't crash, the test has succeeded!
}

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

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

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

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

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

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

  void SetUpCommandLine(base::CommandLine* command_line) override {
    // TODO(yoichio): This is temporary switch to support chrome internal
    // components migration from the old web APIs.
    // After completion of the migration, we should remove this.
    // See https://crbug.com/911943 for detail.
    command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
                                    "HTMLImports");
  }

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

 private:
  DISALLOW_COPY_AND_ASSIGN(CorsExploitBrowserTest);
};

// This is a regression test for https://crbug.com/961614 - it makes sure that
// the trustworthy |request_initiator_site_lock| takes precedent over
// the untrustworthy |request.request_initiator|.
//
// For spoofing a |request.request_initiator| that doesn't match
// |request_initiator_site_lock|, the test relies on a misfeature of HTML
// Imports.  It is unclear how to replicate such spoofing once HTML imports are
// deprecated.
IN_PROC_BROWSER_TEST_F(CorsExploitBrowserTest,
                       OriginHeaderSpoofViaHtmlImports) {
  std::string victim_path = "/victim/secret.json";
  net::test_server::ControllableHttpResponse victim_response(
      embedded_test_server(), victim_path, false);

  ASSERT_TRUE(embedded_test_server()->Start());
  GURL attacker_url(
      embedded_test_server()->GetURL("attacker.com", "/title1.html"));
  GURL module_url(embedded_test_server()->GetURL(
      "module.com", "/cross_site_document_blocking/html_import3.html"));
  GURL victim_url(embedded_test_server()->GetURL("victim.com", victim_path));

  EXPECT_TRUE(NavigateToURL(shell(), attacker_url));

  // From a renderer process locked to attacker.com, load a HTML Import from
  // module.com.  HTML Imports implementation allows attacker.com to issue
  // requests on behalf of the module.com module - here attacker.com initiates a
  // request for a victim.com resource.
  const char kScriptTemplate[] = R"(
      link = document.createElement('link');
      link.rel = 'import';
      link.href = $1;
      link.onload = () => {
          with(link.import.documentElement.appendChild(
              link.import.createElement('script'))) {
            crossOrigin = 'use-credentials';
            src = $2
          }
      };
      document.documentElement.appendChild(link);
  )";
  std::string script = JsReplace(kScriptTemplate, module_url, victim_url);
  ASSERT_TRUE(ExecJs(shell(), script));

  // Verify that attacker.com-controlled request for a victim.com resource uses
  // CORS and has `Origin: http://attacker.com` request header (rather than
  // `Origin: http://module.com`).
  victim_response.WaitForRequest();
  net::test_server::HttpRequest::HeaderMap headers =
      victim_response.http_request()->headers;
  ASSERT_TRUE(base::Contains(headers, "Origin"));
  EXPECT_EQ(url::Origin::Create(attacker_url).Serialize(), headers["Origin"]);
}

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

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

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

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

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

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

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

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() override = default;

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

    return true;
  }

 private:
  mojom::DidCommitProvisionalLoadInterfaceParamsPtr params_override_;

  DISALLOW_COPY_AND_ASSIGN(ScopedInterfaceParamsReplacer);
};

}  // namespace

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

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

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

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

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

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

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

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

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

  // Simulate an IPC message asking to POST a file that the renderer shouldn't
  // have access to.
  FrameHostMsg_OpenURL_Params params;
  params.url = target_url;
  params.post_body = new network::ResourceRequestBody;
  params.post_body->AppendFileRange(file_path, 0, file_content.size(),
                                    base::Time());
  params.disposition = WindowOpenDisposition::CURRENT_TAB;
  params.should_replace_current_entry = true;
  params.user_gesture = true;

  FrameHostMsg_OpenURL msg(root->current_frame_host()->routing_id(), params);
  IPC::IpcSecurityTestUtil::PwnMessageReceived(
      root->current_frame_host()->GetProcess()->GetChannel(), msg);

  // Verify that the malicious navigation did not commit the navigation to
  // |target_url|.
  WaitForLoadStop(shell()->web_contents());
  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());
}

// Test that forging a frame's unique name and commit won't allow changing the
// PageState of a cross-process FrameNavigationEntry.
// See https://crbug.com/766262.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, PageStateToWrongEntry) {
  IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());

  // Commit a page with nested iframes and a separate cross-process iframe.
  GURL main_url(embedded_test_server()->GetURL(
      "a.com", "/cross_site_iframe_factory.html?a(a(a),b)"));
  EXPECT_TRUE(NavigateToURL(shell(), main_url));
  NavigationEntryImpl* back_entry = static_cast<NavigationEntryImpl*>(
      shell()->web_contents()->GetController().GetLastCommittedEntry());
  int nav_entry_id = back_entry->GetUniqueID();

  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                            ->GetFrameTree()
                            ->root();
  FrameTreeNode* child0_0 = root->child_at(0)->child_at(0);
  std::string child0_0_unique_name = child0_0->unique_name();
  FrameTreeNode* child1 = root->child_at(1);
  GURL child1_url = child1->current_url();
  int child1_pid = child1->current_frame_host()->GetProcess()->GetID();
  PageState child1_page_state = back_entry->GetFrameEntry(child1)->page_state();

  // Add a history item in the nested frame.  It's important to do it there and
  // not the main frame for the repro to work, since we don't walk the subtree
  // when navigating back/forward between same document items.
  TestNavigationObserver fragment_observer(shell()->web_contents());
  EXPECT_TRUE(ExecuteScript(child0_0, "location.href = '#foo';"));
  fragment_observer.Wait();

  // Simulate a name change IPC from the nested iframe, matching the cross-site
  // iframe's unique name.
  child0_0->SetFrameName("foo", child1->unique_name());

  // Simulate a back navigation from the now renamed nested iframe, which would
  // put a PageState on the cross-site iframe's FrameNavigationEntry.  Forge a
  // data URL within the PageState that differs from child1_url.
  std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params =
      std::make_unique<FrameHostMsg_DidCommitProvisionalLoad_Params>();
  params->nav_entry_id = nav_entry_id;
  params->did_create_new_entry = false;
  params->url = GURL("about:blank");
  params->transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
  params->should_update_history = false;
  params->gesture = NavigationGestureAuto;
  params->method = "GET";
  params->page_state = PageState::CreateFromURL(GURL("data:text/html,foo"));
  params->origin = url::Origin::Create(GURL("about:blank"));

  mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
      isolated_interface_provider;
  static_cast<mojom::FrameHost*>(child0_0->current_frame_host())
      ->DidCommitProvisionalLoad(
          std::move(params),
          mojom::DidCommitProvisionalLoadInterfaceParams::New(
              isolated_interface_provider.InitWithNewPipeAndPassReceiver(),
              mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
                  .InitWithNewPipeAndPassReceiver()));

  // Make sure we haven't changed the FrameNavigationEntry.  An attack would
  // modify the PageState but leave the SiteInstance as it was.
  EXPECT_EQ(child1->current_frame_host()->GetSiteInstance(),
            back_entry->GetFrameEntry(child1)->site_instance());
  EXPECT_EQ(child1_page_state, back_entry->GetFrameEntry(child1)->page_state());

  // Put the frame's unique name back.
  child0_0->SetFrameName("bar", child0_0_unique_name);

  // Go forward after the fake back navigation.
  TestNavigationObserver forward_observer(shell()->web_contents());
  shell()->web_contents()->GetController().GoForward();
  forward_observer.Wait();

  // Go back to the possibly corrupted entry and ensure we didn't load the data
  // URL in the previous process.  A test failure here would appear as a failure
  // of the URL check and not the process ID check.
  TestNavigationObserver back_observer(shell()->web_contents());
  shell()->web_contents()->GetController().GoBack();
  back_observer.Wait();
  EXPECT_EQ(child1_pid, child1->current_frame_host()->GetProcess()->GetID());
  ASSERT_EQ(child1_url, child1->current_url());
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  // Simulate an IPC message where the top frame asks the remote subframe to
  // navigate to a file: URL.
  GURL file_url("file:///");
  FrameHostMsg_OpenURL_Params params;
  params.url = file_url;
  params.disposition = WindowOpenDisposition::CURRENT_TAB;
  params.should_replace_current_entry = false;
  params.user_gesture = true;

  SiteInstance* a_com_instance = root->current_frame_host()->GetSiteInstance();
  RenderFrameProxyHost* proxy =
      child->render_manager()->GetRenderFrameProxyHost(a_com_instance);
  EXPECT_TRUE(proxy);

  {
    FrameHostMsg_OpenURL msg(proxy->GetRoutingID(), params);
    IPC::IpcSecurityTestUtil::PwnMessageReceived(
        proxy->GetProcess()->GetChannel(), msg);
  }

  // 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_TRUE(WaitForLoadStop(shell()->web_contents()));
  EXPECT_EQ(GURL(kBlockedURL),
            child->current_frame_host()->GetLastCommittedURL());

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

  GURL chrome_url(std::string(kChromeUIScheme) + "://" +
                  std::string(kChromeUIGpuHost));
  params.url = chrome_url;
  {
    FrameHostMsg_OpenURL msg(proxy->GetRoutingID(), params);
    IPC::IpcSecurityTestUtil::PwnMessageReceived(
        proxy->GetProcess()->GetChannel(), msg);
  }
  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
  EXPECT_EQ(GURL(kBlockedURL),
            child->current_frame_host()->GetLastCommittedURL());
}

class PostMessageIpcInterceptor : public BrowserMessageFilter {
 public:
  // Starts listening for IPC messages to |process|, intercepting
  // FrameHostMsg_RouteMessageEvent and storing once it comes.
  explicit PostMessageIpcInterceptor(RenderProcessHost* process)
      : BrowserMessageFilter(FrameMsgStart) {
    process->AddFilter(this);
  }

  // Waits for FrameMsg_PostMessage_Params (if it didn't come yet) and returns
  // message payload to the caller.
  void WaitForMessage(int32_t* out_routing_id,
                      FrameMsg_PostMessage_Params* out_params) {
    run_loop_.Run();
    *out_routing_id = intercepted_routing_id_;
    *out_params = intercepted_params_;
  }

 private:
  ~PostMessageIpcInterceptor() override = default;

  void OnRouteMessageEvent(const FrameMsg_PostMessage_Params& params) {
    intercepted_params_ = params;

    // UaF would have happened without the call below - the call ensures that
    // the data is still valid even once the original message is destroyed.
    intercepted_params_.message->data.EnsureDataIsOwned();
  }

  bool OnMessageReceived(const IPC::Message& message) override {
    // Only intercept one message.
    if (already_intercepted_)
      return false;

    // See if we got FrameHostMsg_RouteMessageEvent and if so unpack and store
    // its payload in OnRouteMessageEvent.
    bool handled = true;
    IPC_BEGIN_MESSAGE_MAP(PostMessageIpcInterceptor, message)
      IPC_MESSAGE_HANDLER(FrameHostMsg_RouteMessageEvent, OnRouteMessageEvent)
      IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP()

    // If we got FrameHostMsg_RouteMessageEvent, then also store the routing ID
    // and signal to the main test thread that it can stop waiting.
    if (handled) {
      already_intercepted_ = true;
      intercepted_routing_id_ = message.routing_id();
      run_loop_.Quit();
    }

    return handled;
  }

  bool already_intercepted_ = false;
  int32_t intercepted_routing_id_;
  FrameMsg_PostMessage_Params intercepted_params_;
  base::RunLoop run_loop_;

  DISALLOW_COPY_AND_ASSIGN(PostMessageIpcInterceptor);
};

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

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

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

  // Prepare to intercept FrameHostMsg_RouteMessageEvent IPC message that will
  // come from the subframe process.
  RenderProcessHost* subframe_process = subframe->GetProcess();
  auto ipc_interceptor =
      base::MakeRefCounted<PostMessageIpcInterceptor>(subframe_process);

  // Post a message from the subframe to the cross-site parent and intercept the
  // associated IPC message.
  EXPECT_TRUE(ExecJs(subframe, "parent.postMessage('blah', '*')"));
  int intercepted_routing_id;
  FrameMsg_PostMessage_Params intercepted_params;
  ipc_interceptor->WaitForMessage(&intercepted_routing_id, &intercepted_params);

  // Change the intercepted message to simulate a compromised subframe renderer
  // lying that the |source_origin| of the postMessage is the origin of the
  // parent (not of the subframe).
  url::Origin invalid_origin =
      web_contents->GetMainFrame()->GetLastCommittedOrigin();
  FrameMsg_PostMessage_Params evil_params = intercepted_params;
  evil_params.source_origin = base::UTF8ToUTF16(invalid_origin.Serialize());
  FrameHostMsg_RouteMessageEvent evil_msg(intercepted_routing_id, evil_params);

  // Inject the invalid IPC and verify that the renderer gets terminated.
  RenderProcessHostBadIpcMessageWaiter kill_waiter(subframe_process);
  IpcSecurityTestUtil::PwnMessageReceived(subframe_process->GetChannel(),
                                          evil_msg);
  EXPECT_EQ(bad_message::RFPH_POST_MESSAGE_INVALID_SOURCE_ORIGIN,
            kill_waiter.Wait());
}

class OpenUrlIpcInterceptor : public BrowserMessageFilter {
 public:
  // Starts listening for IPC messages to |process|, intercepting
  // FrameHostMsg_OpenURL IPC message and storing once it comes.
  explicit OpenUrlIpcInterceptor(RenderProcessHost* process)
      : BrowserMessageFilter(FrameMsgStart) {
    process->AddFilter(this);
  }

  // Waits for FrameHostMsg_OpenURL (if it didn't come yet) and returns
  // message payload to the caller.
  void WaitForMessage(int32_t* out_routing_id,
                      FrameHostMsg_OpenURL_Params* out_params) {
    run_loop_.Run();
    *out_routing_id = intercepted_routing_id_;
    *out_params = intercepted_params_;
  }

 private:
  ~OpenUrlIpcInterceptor() override = default;

  void OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
    intercepted_params_ = params;
  }

  bool OnMessageReceived(const IPC::Message& message) override {
    // Only intercept one message.
    if (already_intercepted_)
      return false;

    // See if we got FrameHostMsg_RouteMessageEvent and if so unpack and store
    // its payload in OnRouteMessageEvent.
    bool handled = true;
    IPC_BEGIN_MESSAGE_MAP(OpenUrlIpcInterceptor, message)
      IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
      IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP()

    // If we got FrameHostMsg_RouteMessageEvent, then also store the routing ID
    // and signal to the main test thread that it can stop waiting.
    if (handled) {
      already_intercepted_ = true;
      intercepted_routing_id_ = message.routing_id();
      run_loop_.Quit();
    }

    return handled;
  }

  bool already_intercepted_ = false;
  int32_t intercepted_routing_id_;
  FrameHostMsg_OpenURL_Params intercepted_params_;
  base::RunLoop run_loop_;

  DISALLOW_COPY_AND_ASSIGN(OpenUrlIpcInterceptor);
};

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));
  RenderFrameHost* main_frame = shell()->web_contents()->GetMainFrame();
  RenderProcessHost* main_process = main_frame->GetProcess();
  EXPECT_EQ(2u, shell()->web_contents()->GetAllFrames().size());
  RenderFrameHost* subframe = shell()->web_contents()->GetAllFrames()[1];
  RenderProcessHost* subframe_process = subframe->GetProcess();
  EXPECT_NE(main_process->GetID(), subframe_process->GetID());

  // Prepare to intercept FrameHostMsg_OpenURL IPC message that will come from
  // the main frame process.
  auto ipc_interceptor =
      base::MakeRefCounted<OpenUrlIpcInterceptor>(main_process);

  // Have the main frame request navigation in the "remote" subframe.  This will
  // result in FrameHostMsg_OpenURL IPC being sent to the RenderFrameProxyHost.
  EXPECT_TRUE(ExecJs(shell()->web_contents()->GetMainFrame(),
                     "window.frames[0].location = '/title1.html';"));
  int intercepted_routing_id;
  FrameHostMsg_OpenURL_Params intercepted_params;
  ipc_interceptor->WaitForMessage(&intercepted_routing_id, &intercepted_params);

  // Change the intercepted message to simulate a compromised subframe renderer
  // lying that the |initiator_origin| is the origin of the |subframe|.
  FrameHostMsg_OpenURL_Params evil_params = intercepted_params;
  evil_params.initiator_origin = subframe->GetLastCommittedOrigin();
  FrameHostMsg_OpenURL evil_msg(intercepted_routing_id, evil_params);

  // Inject the invalid IPC and verify that the renderer gets terminated.
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_process);
  IpcSecurityTestUtil::PwnMessageReceived(main_process->GetChannel(), evil_msg);
  EXPECT_EQ(bad_message::INVALID_INITIATOR_ORIGIN, kill_waiter.Wait());
}

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

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

    return true;
  }

  void Activate() { is_activated_ = true; }

 private:
  base::Optional<url::Origin> initiator_to_inject_;
  bool is_activated_ = false;

  DISALLOW_COPY_AND_ASSIGN(BeginNavigationInitiatorReplacer);
};

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

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

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

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

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

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

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

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

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

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

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

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

namespace {

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

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

 private:
  GURL replacement_url_;

  DISALLOW_COPY_AND_ASSIGN(DidCommitUrlReplacer);
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return true;
  }

  void Activate() { is_activated_ = true; }

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

  DISALLOW_COPY_AND_ASSIGN(BeginNavigationTransitionReplacer);
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return true;
  }

  void Activate() { is_activated_ = true; }

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

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

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

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

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

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

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

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

  replacer.Activate();

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

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

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

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

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

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

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

  replacer.Activate();

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

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

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

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

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

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

  replacer.Activate();

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

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

}  // namespace content
