// 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/macros.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/interstitial_page.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/navigation_policy.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/test_navigation_observer.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_security_test_util.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.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/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/features.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/web/web_triggering_event_info.h"

using IPC::IpcSecurityTestUtil;

namespace content {

namespace {

// This request id is used by tests that call CreateLoaderAndStart. The id is
// sufficiently large that it doesn't collide with ids used by previous
// navigation requests.
const int kRequestIdNotPreviouslyUsed = 10000;

// 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,
                                             int* target_routing_id) {
  GURL foo("http://foo.com/simple_page.html");

  // Start off with initial navigation, so we get the first process allocated.
  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("https://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,
      url::Origin::Create(foo), false, nullptr, std::string(), Referrer(),
      WindowOpenDisposition::CURRENT_TAB, false, true,
      blink::WebTriggeringEventInfo::kFromTrustedEvent, std::string(),
      nullptr /* blob_url_loader_factory */);

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

network::ResourceRequest CreateXHRRequest(const char* url) {
  network::ResourceRequest request;
  request.method = "GET";
  request.url = GURL(url);
  request.referrer_policy = Referrer::GetDefaultReferrerPolicy();
  request.request_initiator = url::Origin();
  request.load_flags = 0;
  request.plugin_child_id = -1;
  request.resource_type = RESOURCE_TYPE_XHR;
  request.appcache_host_id = blink::mojom::kAppCacheNoHostId;
  request.should_reset_appcache = false;
  request.is_main_frame = true;
  request.transition_type = ui::PAGE_TRANSITION_LINK;
  request.allow_download = true;
  return request;
}

network::ResourceRequest CreateXHRRequestWithOrigin(const char* origin) {
  network::ResourceRequest request =
      CreateXHRRequest("http://bar.com/simple_page.html");
  request.site_for_cookies = GURL(origin);
  request.headers.SetHeader(net::HttpRequestHeaders::kOrigin, origin);
  return request;
}

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, contents.c_str(), contents.length(), 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:
  explicit BlobURLStoreInterceptor(GURL target_url) : target_url_(target_url) {}

  void Intercept(
      mojo::StrongAssociatedBindingPtr<blink::mojom::BlobURLStore> binding) {
    url_store_ = binding->SwapImplForTesting(this);
  }

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

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

 private:
  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::PostTaskWithTraits(
        FROM_HERE, {BrowserThread::IO},
        base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
  }

  static void CreateLoaderAndStart(
      RenderFrameHost* frame,
      int route_id,
      int request_id,
      const network::ResourceRequest& resource_request) {
    network::mojom::URLLoaderPtr loader;
    network::TestURLLoaderClient client;
    CreateLoaderAndStart(frame, mojo::MakeRequest(&loader), route_id,
                         request_id, resource_request,
                         client.CreateInterfacePtr().PassInterface());
  }

  static void CreateLoaderAndStart(
      RenderFrameHost* frame,
      network::mojom::URLLoaderRequest request,
      int route_id,
      int request_id,
      const network::ResourceRequest& resource_request,
      network::mojom::URLLoaderClientPtrInfo client) {
    network::mojom::URLLoaderFactoryPtr factory;
    frame->GetProcess()->CreateURLLoaderFactory(frame->GetLastCommittedOrigin(),
                                                nullptr /* header_client */,
                                                mojo::MakeRequest(&factory));
    factory->CreateLoaderAndStart(
        std::move(request), route_id, request_id,
        network::mojom::kURLLoadOptionNone, resource_request,
        network::mojom::URLLoaderClientPtr(std::move(client)),
        net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
  }

  void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) {
    NavigateToURL(shell, GURL("http://foo.com/simple_page.html"));
    RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
        shell->web_contents()->GetMainFrame());

    if (block_loaders) {
      // Test the case where loaders are placed into blocked_loaders_map_.
      rfh->BlockRequestsForFrame();
    }

    // URLRequestSlowDownloadJob waits for another request to kFinishDownloadUrl
    // to finish all pending requests. It is never sent, so the following URL
    // blocks indefinitely, which is good because the request stays alive and
    // the test can try to reuse the request id without a race.
    const char* blocking_url = net::URLRequestSlowDownloadJob::kUnknownSizeUrl;
    network::ResourceRequest request(CreateXHRRequest(blocking_url));

    // Use the same request id twice.
    RenderProcessHostKillWaiter kill_waiter(rfh->GetProcess());
    // We need to keep loader and client to keep the requests alive.
    network::mojom::URLLoaderPtr loader1, loader2;
    network::TestURLLoaderClient client1, client2;

    CreateLoaderAndStart(rfh, mojo::MakeRequest(&loader1), rfh->GetRoutingID(),
                         kRequestIdNotPreviouslyUsed, request,
                         client1.CreateInterfacePtr().PassInterface());
    CreateLoaderAndStart(rfh, mojo::MakeRequest(&loader2), rfh->GetRoutingID(),
                         kRequestIdNotPreviouslyUsed, request,
                         client2.CreateInterfacePtr().PassInterface());
    EXPECT_EQ(bad_message::RDH_INVALID_REQUEST_ID, kill_waiter.Wait());
  }

 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");
  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;
  blink::mojom::FileChooserPtr 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");

  NavigateToURL(shell(), foo);
  EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
  EXPECT_EQ(0, shell()->web_contents()->GetMainFrame()->GetEnabledBindings());

  RenderViewHost* compromised_renderer =
      shell()->web_contents()->GetRenderViewHost();
  RenderProcessHostKillWaiter 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(), &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(), &duplicate_routing_id);
  EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);

  mojom::WidgetPtr widget;
  std::unique_ptr<MockWidgetImpl> widget_impl =
      std::make_unique<MockWidgetImpl>(mojo::MakeRequest(&widget));

  // 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->render_view_host()->CreateNewWidget(duplicate_routing_id,
                                                   std::move(widget));

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

  blink::mojom::FileChooserPtr 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 SecurityExploitTestInterstitialPage : public InterstitialPageDelegate {
 public:
  explicit SecurityExploitTestInterstitialPage(WebContents* contents) {
    InterstitialPage* interstitial = InterstitialPage::Create(
        contents, true, contents->GetLastCommittedURL(), this);
    interstitial->Show();
  }

  // InterstitialPageDelegate implementation.
  void CommandReceived(const std::string& command) override {
    last_command_ = command;
  }

  std::string GetHTMLContents() override {
    return "<html><head><script>"
           "window.domAutomationController.send(\"okay\");"
           "</script></head>"
           "<body>this page is an interstitial</body></html>";
  }

  std::string last_command() { return last_command_; }

 private:
  std::string last_command_;
  DISALLOW_COPY_AND_ASSIGN(SecurityExploitTestInterstitialPage);
};

// Fails due to InterstitialPage's reliance on PostNonNestableTask
// http://crbug.com/432737
#if defined(OS_ANDROID)
#define MAYBE_InterstitialCommandFromUnderlyingContent \
  DISABLED_InterstitialCommandFromUnderlyingContent
#else
#define MAYBE_InterstitialCommandFromUnderlyingContent \
  InterstitialCommandFromUnderlyingContent
#endif

// The interstitial should not be controllable by the underlying content.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       MAYBE_InterstitialCommandFromUnderlyingContent) {
  // Start off with initial navigation, to allocate the process.
  GURL foo("http://foo.com/simple_page.html");
  NavigateToURL(shell(), foo);
  EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());

  DOMMessageQueue message_queue;

  // Install and show an interstitial page.
  SecurityExploitTestInterstitialPage* interstitial =
      new SecurityExploitTestInterstitialPage(shell()->web_contents());

  ASSERT_EQ("", interstitial->last_command());
  WaitForInterstitialAttach(shell()->web_contents());

  InterstitialPage* interstitial_page =
      shell()->web_contents()->GetInterstitialPage();
  ASSERT_TRUE(interstitial_page != nullptr);
  ASSERT_TRUE(shell()->web_contents()->ShowingInterstitialPage());
  ASSERT_TRUE(interstitial_page->GetDelegateForTesting() == interstitial);

  // The interstitial page ought to be able to send a message.
  std::string message;
  ASSERT_TRUE(message_queue.WaitForMessage(&message));
  ASSERT_EQ("\"okay\"", message);
  ASSERT_EQ("\"okay\"", interstitial->last_command());

  // Send an automation message from the underlying content and wait for it to
  // be dispatched on this thread. This message should not be received by the
  // interstitial.
  RenderFrameHost* compromised_renderer =
      shell()->web_contents()->GetMainFrame();
  FrameHostMsg_DomOperationResponse evil(compromised_renderer->GetRoutingID(),
                                         "evil");
  IpcSecurityTestUtil::PwnMessageReceived(
      compromised_renderer->GetProcess()->GetChannel(), evil);

  ASSERT_TRUE(message_queue.WaitForMessage(&message));
  ASSERT_EQ("evil", message)
      << "Automation message should be received by WebContents.";
  ASSERT_EQ("\"okay\"", interstitial->last_command())
      << "Interstitial should not be affected.";

  // Send a second message from the interstitial page, and make sure that the
  // "evil" message doesn't arrive in the intervening period.
  ExecuteScriptAsync(interstitial_page->GetMainFrame(),
                     "window.domAutomationController.send(\"okay2\");");
  ASSERT_TRUE(message_queue.WaitForMessage(&message));
  ASSERT_EQ("\"okay2\"", message);
  ASSERT_EQ("\"okay2\"", interstitial->last_command());
}

// Intercepts the HTTP origin header and on being invoked once it is found
// aborts the requeest.
void OnHttpHeaderReceived(const std::string& header,
                          const std::string& value,
                          int child_process_id,
                          content::ResourceContext* resource_context,
                          OnHeaderProcessedCallback callback) {
  std::move(callback).Run(HeaderInterceptorResult::KILL);
}

// Renderer processes should not be able to spoof Origin HTTP headers.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
  // https://crbug.com/862176
  if (base::FeatureList::IsEnabled(network::features::kNetworkService))
    return;

  // Create a set of IPC messages with various Origin headers.
  network::ResourceRequest chrome_origin_msg(
      CreateXHRRequestWithOrigin("chrome://settings"));
  network::ResourceRequest embedder_isolated_origin_msg(
      CreateXHRRequestWithOrigin("https://isolated.bar.com"));
  network::ResourceRequest invalid_origin_msg(
      CreateXHRRequestWithOrigin("invalidurl"));
  network::ResourceRequest invalid_scheme_origin_msg(
      CreateXHRRequestWithOrigin("fake-scheme://foo"));

  GURL web_url("http://foo.com/simple_page.html");
  NavigateToURL(shell(), web_url);
  RenderFrameHost* web_rfh = shell()->web_contents()->GetMainFrame();

  // Web processes cannot make XHRs with chrome:// Origin headers.
  {
    RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());

    CreateLoaderAndStart(web_rfh, web_rfh->GetRoutingID(),
                         kRequestIdNotPreviouslyUsed, chrome_origin_msg);
    EXPECT_EQ(bad_message::RDH_ILLEGAL_ORIGIN, kill_waiter.Wait());
  }

  // Web processes cannot make XHRs with URLs that the content embedder expects
  // to have process isolation.  Ideally this would test chrome-extension://
  // URLs for Chrome Apps, but those can't be tested inside content/ and the
  // ResourceRequest IPC can't be created in a test outside content/.
  NavigateToURL(shell(), web_url);
  {
    content::ResourceDispatcherHost::Get()->RegisterInterceptor(
        "Origin", "", base::Bind(&OnHttpHeaderReceived));

    RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());
    CreateLoaderAndStart(web_rfh, web_rfh->GetRoutingID(),
                         kRequestIdNotPreviouslyUsed,
                         embedder_isolated_origin_msg);
    EXPECT_EQ(bad_message::RDH_ILLEGAL_ORIGIN, kill_waiter.Wait());
  }

  // Web processes cannot make XHRs with invalid Origin headers.
  NavigateToURL(shell(), web_url);
  {
    RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());
    CreateLoaderAndStart(web_rfh, web_rfh->GetRoutingID(),
                         kRequestIdNotPreviouslyUsed, invalid_origin_msg);
    EXPECT_EQ(bad_message::RDH_ILLEGAL_ORIGIN, kill_waiter.Wait());
  }

  // Web processes cannot make XHRs with invalid scheme Origin headers.
  NavigateToURL(shell(), web_url);
  {
    RenderProcessHostKillWaiter kill_waiter(web_rfh->GetProcess());
    CreateLoaderAndStart(web_rfh, web_rfh->GetRoutingID(),
                         kRequestIdNotPreviouslyUsed,
                         invalid_scheme_origin_msg);
    EXPECT_EQ(bad_message::RDH_ILLEGAL_ORIGIN, kill_waiter.Wait());
  }
}

// Renderer process should not be able to create multiple requests with the same
// id.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidRequestId) {
  // This test is specific to the ResourceDispatcherHost implementation, which
  // is not used with network service enabled.
  if (base::FeatureList::IsEnabled(network::features::kNetworkService))
    return;

  // Existing loader in pending_loaders_.
  TryCreateDuplicateRequestIds(shell(), false);
}

IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidBlockedRequestId) {
  // This test is specific to the ResourceDispatcherHost implementation, which
  // is not used with network service enabled.
  if (base::FeatureList::IsEnabled(network::features::kNetworkService))
    return;

  // Existing loader in blocked_loaders_map_.
  TryCreateDuplicateRequestIds(shell(), true);
}

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

  RenderProcessHostKillWaiter 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
// DocumentInterfaceBroker, InterfaceProviderRequest-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());
  RenderProcessHostKillWaiter kill_waiter(frame->GetProcess());

  ScopedInterfaceParamsReplacer replacer(shell()->web_contents(), nullptr);
  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 behing and leak
  // NavigationRequests - see https://crbug.com/869193.
  EXPECT_EQ(0u, frame->GetNavigationEntryIdsPendingCommit().size());
}

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

  RenderProcessHostKillWaiter 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_LT(
      0, base::WriteFile(file_path, file_content.data(), file_content.size()));

  // 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.uses_post = true;
  params.resource_request_body = new network::ResourceRequestBody;
  params.resource_request_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;
  params.is_history_navigation_in_new_child = false;

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

  service_manager::mojom::InterfaceProviderPtr isolated_interface_provider;
  blink::mojom::DocumentInterfaceBrokerPtr
      isolated_document_interface_broker_content;
  blink::mojom::DocumentInterfaceBrokerPtr
      isolated_document_interface_broker_blink;
  static_cast<mojom::FrameHost*>(child0_0->current_frame_host())
      ->DidCommitProvisionalLoad(
          std::move(params),
          mojom::DidCommitProvisionalLoadInterfaceParams::New(
              mojo::MakeRequest(&isolated_interface_provider),
              mojo::MakeRequest(&isolated_document_interface_broker_content),
              mojo::MakeRequest(&isolated_document_interface_broker_blink)));

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

// Check that when site isolation is enabled, an origin can't create a blob URL
// for a different origin.  See https://crbug.com/886976.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                       CreateBlobURLInDifferentOrigin) {
  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();

  // All these are attacker controlled values.
  std::string blob_type = "text/html";
  std::string blob_contents = "<html><body>pwned.</body></html>";
  std::string blob_path = "5881f76e-10d2-410d-8c61-ef210502acfd";

  // Target a different origin.
  std::string target_origin = "http://b.com";

  // 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::unique_ptr<BlobHandle> blob = CreateMemoryBackedBlob(
      rfh->GetSiteInstance()->GetBrowserContext(), blob_contents, blob_type);
  std::string blob_id = blob->GetUUID();

  base::HistogramTester histograms;
  // Try registering a blob URL for b.com.  This IPC should result
  // in a kill because a.com should not be abllowed to create blob URLs outside
  // of its own origin.
  RenderProcessHostWatcher crash_observer(
      rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
  PwnMessageHelper::RegisterBlobURL(
      rfh->GetProcess(), GURL("blob:" + target_origin + "/" + blob_path),
      blob_id);
  // If the process is killed, this test passes.
  crash_observer.Wait();
  histograms.ExpectUniqueSample("Stability.BadMessageTerminated.Content",
                                139 /* BDH_DISALLOWED_ORIGIN */, 1);
}

class SecurityExploitBrowserTestMojoBlobURLs
    : public SecurityExploitBrowserTest {
 public:
  SecurityExploitBrowserTestMojoBlobURLs() {
    scoped_feature_list_.InitAndEnableFeature(blink::features::kMojoBlobURLs);
  }

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

 private:
  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_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";
  BlobURLStoreInterceptor interceptor(
      GURL("blob:" + target_origin + "/" + blob_path));
  auto intercept_hook = base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
                                            base::Unretained(&interceptor));
  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.
  base::HistogramTester histograms;
  RenderProcessHostWatcher crash_observer(
      rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);

  // 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.
  crash_observer.Wait();
  histograms.ExpectUniqueSample("Stability.BadMessageTerminated.Content", 123,
                                1);
}

// 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.uses_post = false;
  params.disposition = WindowOpenDisposition::CURRENT_TAB;
  params.should_replace_current_entry = false;
  params.user_gesture = true;
  params.is_history_navigation_in_new_child = false;

  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.
  RenderProcessHostKillWaiter 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.
  RenderProcessHostKillWaiter 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,
      CommonNavigationParams* common_params,
      mojom::BeginNavigationParamsPtr* begin_params,
      blink::mojom::BlobURLTokenPtr* blob_url_token,
      mojom::NavigationClientAssociatedPtrInfo* navigation_client,
      blink::mojom::NavigationInitiatorPtr* 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) {
  // Explicitly isolating a.com helps ensure that this test is applicable on
  // platforms without site-per-process.
  IsolateOrigin("a.com");

  // 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, url::Origin::Create(GURL("http://b.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();
  RenderProcessHostKillWaiter kill_waiter(main_process);

  // Have the main frame navigate and lie that the initiator origin is b.com.
  injector.Activate();
  EXPECT_TRUE(ExecJs(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();
  RenderProcessHostKillWaiter kill_waiter(main_process);

  // Have the main frame submit a BeginNavigation IPC with a missing initiator.
  injector.Activate();
  EXPECT_TRUE(ExecJs(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 content
