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

#include <memory>

#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/api/storage/storage_api.h"
#include "extensions/browser/background_script_executor.h"
#include "extensions/browser/bad_message.h"
#include "extensions/browser/browsertest_util.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_frame_host.h"
#include "extensions/browser/extension_web_contents_observer.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/renderer_startup_helper.h"
#include "extensions/browser/script_executor.h"
#include "extensions/browser/service_worker/service_worker_host.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/mojom/frame.mojom-test-utils.h"
#include "extensions/common/mojom/service_worker_host.mojom-test-utils.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/test_extension_dir.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_database.mojom-forward.h"
#include "url/gurl.h"

namespace extensions {

// ExtensionFrameHostInterceptor is a helper for:
// - Intercepting mojom::LocalFrameHost method calls (e.g. methods
//   that would normally be handled / implemented by ExtensionFrameHost).
// - Allowing the test to mutate the method arguments (e.g. to simulate a
//   compromised renderer) before passing the method call to the usual handler.
class ExtensionFrameHostInterceptor
    : mojom::LocalFrameHostInterceptorForTesting {
 public:
  // The caller needs to ensure that `frame` stays alive longer than the
  // constructed ExtensionFrameHostInterceptor.
  explicit ExtensionFrameHostInterceptor(content::RenderFrameHost* frame)
      : frame_(frame),
        extension_frame_host_(
            ExtensionWebContentsObserver::GetForWebContents(
                content::WebContents::FromRenderFrameHost(frame_))
                ->extension_frame_host_for_testing()),
        scoped_swap_impl_(extension_frame_host_->receivers_for_testing(),
                          this) {}

  ~ExtensionFrameHostInterceptor() override = default;

  using RequestMutator =
      base::RepeatingCallback<void(mojom::RequestParams& request_params)>;
  void SetRequestMutator(RequestMutator request_mutator) {
    request_mutator_ = std::move(request_mutator);
  }

  using OpenChannelToExtensionMutator =
      base::RepeatingCallback<void(mojom::ExternalConnectionInfo& info)>;
  void SetOpenChannelToExtensionMutator(
      OpenChannelToExtensionMutator open_extension_mutator) {
    open_extension_mutator_ = std::move(open_extension_mutator);
  }

 private:
  mojom::LocalFrameHost* GetForwardingInterface() override {
    return scoped_swap_impl_.old_impl();
  }

  void Request(mojom::RequestParamsPtr params,
               RequestCallback callback) override {
    // `//extensions/common/mojom/frame.mojom` specifies that `params` is
    // non-optional.
    CHECK(params);

    content::RenderFrameHost* current_target_frame =
        extension_frame_host_->receivers_for_testing().GetCurrentTargetFrame();
    if (request_mutator_ && frame_ == current_target_frame) {
      request_mutator_.Run(*params);
    }

    GetForwardingInterface()->Request(std::move(params), std::move(callback));
  }

  void OpenChannelToExtension(
      mojom::ExternalConnectionInfoPtr info,
      mojom::ChannelType channel_type,
      const std::string& channel_name,
      const PortId& port_id,
      mojo::PendingAssociatedRemote<mojom::MessagePort> port,
      mojo::PendingAssociatedReceiver<mojom::MessagePortHost> port_host)
      override {
    CHECK(info);
    content::RenderFrameHost* current_target_frame =
        extension_frame_host_->receivers_for_testing().GetCurrentTargetFrame();
    if (open_extension_mutator_ && frame_ == current_target_frame) {
      open_extension_mutator_.Run(*info);
    }

    GetForwardingInterface()->OpenChannelToExtension(
        std::move(info), channel_type, channel_name, port_id, std::move(port),
        std::move(port_host));
  }

  const raw_ptr<content::RenderFrameHost> frame_ = nullptr;
  RequestMutator request_mutator_;
  OpenChannelToExtensionMutator open_extension_mutator_;
  const raw_ptr<ExtensionFrameHost> extension_frame_host_ = nullptr;
  const mojo::test::ScopedSwapImplForTesting<mojom::LocalFrameHost>
      scoped_swap_impl_;
};

class ServiceWorkerHostInterceptorForProcessDeath
    : public mojom::ServiceWorkerHostInterceptorForTesting {
 public:
  // We use `worker_id` to have an weak handle to the `ServiceWorkerHost`
  // which will be destroyed when this object mutates the IPC to cause
  // a bad message resulting in process death.
  explicit ServiceWorkerHostInterceptorForProcessDeath(
      const WorkerId& worker_id)
      : worker_id_(worker_id) {
    auto* host = extensions::ServiceWorkerHost::GetWorkerFor(worker_id_);
    CHECK(host);
    std::ignore = host->receiver_for_testing().SwapImplForTesting(this);
  }

  mojom::ServiceWorkerHost* GetForwardingInterface() override {
    // This should be non-null if this interface is still receiving events.
    auto* host = extensions::ServiceWorkerHost::GetWorkerFor(worker_id_);
    CHECK(host);
    return host;
  }

  void OpenChannelToExtension(
      mojom::ExternalConnectionInfoPtr info,
      mojom::ChannelType channel_type,
      const std::string& channel_name,
      const PortId& port_id,
      mojo::PendingAssociatedRemote<mojom::MessagePort> port,
      mojo::PendingAssociatedReceiver<mojom::MessagePortHost> port_host)
      override {
    CHECK(info);
    if (open_extension_mutator_) {
      open_extension_mutator_.Run(*info);
    }

    GetForwardingInterface()->OpenChannelToExtension(
        std::move(info), channel_type, channel_name, port_id, std::move(port),
        std::move(port_host));
  }

  using OpenChannelToExtensionMutator =
      base::RepeatingCallback<void(mojom::ExternalConnectionInfo& info)>;
  void SetOpenChannelToExtensionMutator(
      OpenChannelToExtensionMutator open_extension_mutator) {
    open_extension_mutator_ = std::move(open_extension_mutator);
  }

 private:
  OpenChannelToExtensionMutator open_extension_mutator_;
  const WorkerId worker_id_;
};

// Waits for a kill of the given RenderProcessHost and returns the
// BadMessageReason that caused an //extensions-triggerred kill.
//
// Example usage:
//   RenderProcessHostBadIpcMessageWaiter kill_waiter(render_process_host);
//   ... test code that triggers a renderer kill ...
//   EXPECT_EQ(bad_message::EFD_BAD_MESSAGE_PROCESS, kill_waiter.Wait());
class RenderProcessHostBadIpcMessageWaiter {
 public:
  explicit RenderProcessHostBadIpcMessageWaiter(
      content::RenderProcessHost* render_process_host)
      : internal_waiter_(render_process_host,
                         "Stability.BadMessageTerminated.Extensions") {}

  // Waits until the renderer process exits.  Returns the bad message that made
  // //extensions kill the renderer.  `std::nullopt` is returned if the
  // renderer was killed outside of //extensions or exited normally.
  [[nodiscard]] std::optional<bad_message::BadMessageReason> Wait() {
    std::optional<int> internal_result = internal_waiter_.Wait();
    if (!internal_result.has_value())
      return std::nullopt;
    return static_cast<bad_message::BadMessageReason>(internal_result.value());
  }

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

 private:
  content::RenderProcessHostKillWaiter internal_waiter_;
};

// Test suite covering how mojo/IPC messages are verified after being received
// from a (potentially compromised) renderer process.
class ExtensionSecurityExploitBrowserTest : public ExtensionBrowserTest {
 public:
  ExtensionSecurityExploitBrowserTest() = default;

  void SetUpOnMainThread() override {
    ExtensionBrowserTest::SetUpOnMainThread();

    host_resolver()->AddRule("*", "127.0.0.1");
    content::SetupCrossSiteRedirector(embedded_test_server());
    ASSERT_TRUE(embedded_test_server()->Start());
  }

  // Asks the `extension_id` to inject `content_script` into `web_contents`.
  // Returns true if the content script execution started successfully.
  bool ExecuteProgrammaticContentScript(content::WebContents* web_contents,
                                        const ExtensionId& extension_id,
                                        const std::string& content_script) {
    DCHECK(web_contents);
    int tab_id = ExtensionTabUtil::GetTabId(web_contents);
    const char kScriptTemplate[] = R"(
        chrome.scripting.executeScript({
            target: {tabId: %d},
            injectImmediately: true,
            func: () => { %s }
        });
    )";
    std::string background_script =
        base::StringPrintf(kScriptTemplate, tab_id, content_script.c_str());
    return BackgroundScriptExecutor::ExecuteScriptAsync(profile(), extension_id,
                                                        background_script);
  }

  // (Asynchronously) executes the given `script` in a user script world in
  // `web_contents`, associated with the given `extension_id`
  void ExecuteUserScript(content::WebContents& web_contents,
                         const ExtensionId& extension_id,
                         const std::string& script) {
    ScriptExecutor script_executor(&web_contents);
    std::vector<mojom::JSSourcePtr> sources;
    sources.push_back(mojom::JSSource::New(script, GURL()));
    script_executor.ExecuteScript(
        mojom::HostID(mojom::HostID::HostType::kExtensions, extension_id),
        mojom::CodeInjection::NewJs(mojom::JSInjection::New(
            std::move(sources), mojom::ExecutionWorld::kUserScript,
            /*world_id=*/std::nullopt,
            blink::mojom::WantResultOption::kWantResult,
            blink::mojom::UserActivationOption::kDoNotActivate,
            blink::mojom::PromiseResultOption::kAwait)),
        ScriptExecutor::SPECIFIED_FRAMES, {ExtensionApiFrameIdMap::kTopFrameId},
        mojom::MatchOriginAsFallbackBehavior::kNever,
        mojom::RunLocation::kDocumentIdle, ScriptExecutor::DEFAULT_PROCESS,
        GURL() /* webview_src */, base::DoNothing());
  }

  // Allows messaging APIs for user scripts created by the given `extension`.
  void AllowUserScriptMessaging(const Extension& extension) {
    RendererStartupHelperFactory::GetForBrowserContext(profile())
        ->SetUserScriptWorldProperties(
            extension, mojom::UserScriptWorldInfo::New(
                           extension.id(), /*world_id=*/std::nullopt,
                           /*csp=*/std::nullopt,
                           /*enable_messaging=*/true));
  }

  const Extension& active_extension() { return *active_extension_; }
  const ExtensionId& active_extension_id() { return active_extension_->id(); }
  const Extension& spoofed_extension() { return *spoofed_extension_; }
  const ExtensionId& spoofed_extension_id() { return spoofed_extension_->id(); }

  // Installs an `active_extension` and a separate, but otherwise identical
  // `spoofed_extension` (the only difference will be the extension id).
  void InstallTestExtensions() {
    auto install_extension =
        [this](TestExtensionDir& dir,
               const char* extra_manifest_bits) -> const Extension* {
      const char kManifestTemplate[] = R"(
          {
            %s
            "name": "ScriptInjectionTrackerBrowserTest - Programmatic",
            "version": "1.0",
            "manifest_version": 3,
            "host_permissions": ["http://foo.com/*"],
            "permissions": [
                "scripting",
                "tabs",
                "nativeMessaging",
                "storage"
            ],
            "background": {"service_worker": "background_script.js"}
          } )";
      dir.WriteManifest(
          base::StringPrintf(kManifestTemplate, extra_manifest_bits));
      dir.WriteFile(FILE_PATH_LITERAL("background_script.js"), "");
      dir.WriteFile(FILE_PATH_LITERAL("page.html"), "<p>page</p>");
      return LoadExtension(dir.UnpackedPath());
    };

    // The key below corresponds to the extension ID used by
    // ScopedTestNativeMessagingHost::kExtensionId.
    const char kActiveExtensionKey[] = R"(
        "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
    )";
    active_extension_ = install_extension(active_dir_, kActiveExtensionKey);
    spoofed_extension_ = install_extension(spoofed_dir_, "");
    ASSERT_TRUE(active_extension_);
    ASSERT_TRUE(spoofed_extension_);
    ASSERT_EQ(active_extension_id(),
              ScopedTestNativeMessagingHost::kExtensionId);
    ASSERT_NE(active_extension_id(), spoofed_extension_id());
  }

 private:
  TestExtensionDir active_dir_;
  TestExtensionDir spoofed_dir_;
  raw_ptr<const Extension, DanglingUntriaged> active_extension_ = nullptr;
  raw_ptr<const Extension, DanglingUntriaged> spoofed_extension_ = nullptr;
};

// Test suite for covering ExtensionHostMsg_OpenChannelToExtension IPC.
class OpenChannelToExtensionExploitTest
    : public ExtensionSecurityExploitBrowserTest {
 public:
  OpenChannelToExtensionExploitTest() = default;

  void SetUpOnMainThread() override {
    ExtensionSecurityExploitBrowserTest::SetUpOnMainThread();

    // Navigate to an arbitrary, mostly empty test page.  Make sure that a new
    // RenderProcessHost is created to make sure it is covered by the
    // `ipc_message_waiter_`.  (A WebUI -> http navigation should swap the
    // RenderProcessHost on all platforms.)
    GURL test_page_url =
        embedded_test_server()->GetURL("foo.com", "/title1.html");
    auto* web_contents = GetActiveWebContents();
    int old_process_id =
        web_contents->GetPrimaryMainFrame()->GetProcess()->GetDeprecatedID();
    EXPECT_TRUE(NavigateToURL(web_contents, GURL("chrome://version")));
    EXPECT_TRUE(NavigateToURL(web_contents, test_page_url));
    int new_process_id =
        web_contents->GetPrimaryMainFrame()->GetProcess()->GetDeprecatedID();
    EXPECT_NE(old_process_id, new_process_id);

    // Install the extensions (and potentially spawn new RenderProcessHosts)
    // only *after* the `ipc_message_waiter_` has been constructed.
    InstallTestExtensions();
  }
};

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromContentScript_BadExtensionIdInMessagingSource) {
  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from a content script of an `active_extension_id`.
  auto* web_contents = GetActiveWebContents();
  ASSERT_TRUE(ExecuteProgrammaticContentScript(
      web_contents, active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));

  content::RenderProcessHost* main_frame_process =
      web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
      web_contents->GetPrimaryMainFrame());
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kContentScript,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
        // Mutate the IPC payload.
        info.source_endpoint.extension_id = spoofed_extension_id();
      }));
  EXPECT_EQ(bad_message::EMF_INVALID_EXTENSION_ID_FOR_CONTENT_SCRIPT,
            kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromContentScript_UnexpectedNativeAppType) {
  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from a content script of an `active_extension_id`.
  auto* web_contents = GetActiveWebContents();
  ASSERT_TRUE(ExecuteProgrammaticContentScript(
      web_contents, active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));

  content::RenderProcessHost* main_frame_process =
      web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
      web_contents->GetPrimaryMainFrame());
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kContentScript,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
        // Mutate the IPC payload.
        info.source_endpoint.type = MessagingEndpoint::Type::kNativeApp;
      }));
  EXPECT_EQ(bad_message::EMF_INVALID_CHANNEL_SOURCE_TYPE, kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromContentScript_UnexpectedExtensionType) {
  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from a content script of an `active_extension_id`.
  auto* web_contents = GetActiveWebContents();
  ASSERT_TRUE(ExecuteProgrammaticContentScript(
      web_contents, active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));

  content::RenderProcessHost* main_frame_process =
      web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
      web_contents->GetPrimaryMainFrame());
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kContentScript,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
        // Mutate the IPC payload.
        info.source_endpoint.type = MessagingEndpoint::Type::kExtension;
      }));
  EXPECT_EQ(bad_message::EMF_INVALID_EXTENSION_ID_FOR_EXTENSION_SOURCE,
            kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromContentScript_NoExtensionIdForExtensionType) {
  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from a content script of an `active_extension_id`.
  auto* web_contents = GetActiveWebContents();
  ASSERT_TRUE(ExecuteProgrammaticContentScript(
      web_contents, active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));

  content::RenderProcessHost* main_frame_process =
      web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
      web_contents->GetPrimaryMainFrame());
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kContentScript,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);

        // Mutate the IPC payload.
        info.source_endpoint.type = MessagingEndpoint::Type::kExtension;
        info.source_endpoint.extension_id = std::nullopt;
      }));
  EXPECT_EQ(bad_message::EMF_NO_EXTENSION_ID_FOR_EXTENSION_SOURCE,
            kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromContentScript_BadSourceUrl_FromFrame) {
  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from a content script of an `active_extension_id`.
  auto* web_contents = GetActiveWebContents();
  ASSERT_TRUE(ExecuteProgrammaticContentScript(
      web_contents, active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));

  content::RenderProcessHost* main_frame_process =
      web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
      web_contents->GetPrimaryMainFrame());
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kContentScript,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);

        // Mutate `source_url` in the IPC payload.
        GURL actual_url = GetActiveWebContents()
                              ->GetPrimaryMainFrame()
                              ->GetLastCommittedURL();
        ASSERT_EQ(actual_url, info.source_url);
        GURL spoofed_url =
            embedded_test_server()->GetURL("spoofed.com", "/title1.html");
        ASSERT_NE(spoofed_url.host(), actual_url.host());
        info.source_url = spoofed_url;
      }));
  EXPECT_EQ(bad_message::EMF_INVALID_SOURCE_URL, kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromServiceWorker_BadSourceUrl) {
  // Navigate the test tab to an extension page.
  // TODO(crbug.com/40874764): Remove this test step - it is only here as
  // a workaround for the bug that impacts how renderer kills are detected when
  // there are no frames in a given renderer process.
  GURL test_page_url = active_extension().GetResourceURL("page.html");
  EXPECT_TRUE(NavigateToURL(GetActiveWebContents(), test_page_url));

  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from the service worker of an `active_extension_id`.
  ASSERT_TRUE(BackgroundScriptExecutor::ExecuteScriptAsync(
      profile(), active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'});"));

  std::vector<WorkerId> service_workers =
      ProcessManager::Get(profile())->GetServiceWorkersForExtension(
          active_extension_id());
  ASSERT_EQ(1u, service_workers.size());

  content::RenderProcessHost* service_worker_process =
      content::RenderProcessHost::FromID(service_workers[0].render_process_id);
  ASSERT_TRUE(service_worker_process);
  RenderProcessHostBadIpcMessageWaiter kill_waiter(service_worker_process);
  auto interceptor =
      std::make_unique<ServiceWorkerHostInterceptorForProcessDeath>(
          service_workers[0]);
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kExtension,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
        EXPECT_EQ(info.source_url.host(), active_extension_id());

        // Mutate `source_url` in the IPC payload.
        info.source_url =
            spoofed_extension().GetResourceURL("some_resource.html");
        EXPECT_EQ(info.source_url.host(), spoofed_extension_id());
      }));

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

// This is a regression test for https://crbug.com/1379558.
IN_PROC_BROWSER_TEST_F(ExtensionSecurityExploitBrowserTest,
                       SendMessageFromContentScriptInDataUrlFrame) {
  // Install a test extension that 1) declaratively injects content scripts into
  // all frames (including data: frames thanks to `match_origin_as_fallback`),
  // 2) sends a message from the content script to the extension, 3) echoes back
  // the `source_url` of the message sender via `chrome.test.sendMessage`.
  //
  // Note that `chrome.scripting.executeScript` is unable to inject content
  // scripts into data: frames (without additional permissions), because this
  // API doesn't have a knob equivalent to `match_origin_as_fallback`.  This is
  // the primary reason for using manifest-declared content scripts in this
  // test.
  TestExtensionDir dir;
  const char kManifestTemplate[] = R"(
      {
        "name": "source_url echo-er",
        "version": "1.0",
        "manifest_version": 3,
        "content_scripts": [{
          "all_frames": true,
          "match_about_blank": true,
          "match_origin_as_fallback": true,
          "matches": ["*://foo.com/*"],
          "js": ["content_script.js"]
        }],
        "background": {"service_worker": "background_script.js"}
      } )";
  dir.WriteManifest(kManifestTemplate);
  const char kBackgroundScript[] = R"(
      chrome.runtime.onMessage.addListener(
        function(request, sender, sendResponse) {
          chrome.test.sendMessage(sender.url);
        }
      );
  )";
  dir.WriteFile(FILE_PATH_LITERAL("background_script.js"), kBackgroundScript);
  const char kContentScript[] = R"(
      chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});
  )";
  dir.WriteFile(FILE_PATH_LITERAL("content_script.js"), kContentScript);
  const Extension* extension = LoadExtension(dir.UnpackedPath());
  ASSERT_TRUE(extension);

  // Navigate to foo.com (covered by `content_scripts.matches` above).
  GURL http_url = embedded_test_server()->GetURL("foo.com", "/title1.html");
  auto* web_contents = GetActiveWebContents();
  ASSERT_TRUE(NavigateToURL(web_contents, http_url));

  // Add a data: URL subframe and wait for its `source_url` to be echoed back.
  // The data: URL encodes `<p>foo</p>` HTML doc.
  const GURL kDataUrl("data:text/html;charset=utf-8;base64,PHA+Zm9vPC9wPg==");
  ExtensionTestMessageListener listener(kDataUrl.spec());
  const char kScriptTemplate[] = R"(
      new Promise(function (resolve, reject) {
          var iframe = document.createElement('iframe');
          iframe.src = $1;
          iframe.onload = () => {
              resolve("onload");
          };
          document.body.appendChild(iframe);
      });
  )";
  ASSERT_EQ("onload",
            content::EvalJs(web_contents,
                            content::JsReplace(kScriptTemplate, kDataUrl)));
  ASSERT_TRUE(listener.WaitUntilSatisfied());

  // The main verification here (against https://crbug.com/1379558) is that the
  // renderer process wasn't terminated (because of incorrectly classifying IPC
  // payload as spoofed / illegitimately claiming to come on behalf of the data
  // URL).  This verification happens at the test suite level (e.g. see
  // `content::NoRendererCrashesAssertion` for more details).
}

IN_PROC_BROWSER_TEST_F(ExtensionSecurityExploitBrowserTest,
                       SpoofedExtensionId_ExtensionFunctionDispatcher) {
  InstallTestExtensions();

  // Navigate to a test page.
  GURL test_page_url =
      embedded_test_server()->GetURL("foo.com", "/title1.html");
  auto* web_contents = GetActiveWebContents();
  ASSERT_TRUE(NavigateToURL(web_contents, test_page_url));
  content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame();

  // Verify the test setup by checking if the non-intercepted `chrome.storage`
  // API call will succeed.
  {
    ExtensionTestMessageListener listener("Got chrome.storage response");
    ASSERT_TRUE(ExecuteProgrammaticContentScript(web_contents,
                                                 active_extension_id(), R"(
          chrome.storage.local.set(
              { test_key: 'test value'},
              () => {
                  chrome.test.sendMessage('Got chrome.storage response');
              }
          ); )"));
    ASSERT_TRUE(listener.WaitUntilSatisfied());
  }

  // Prepare to mutate the extension id in the IPC associated with the
  // `chrome.storage.local.set`.
  auto interceptor =
      std::make_unique<ExtensionFrameHostInterceptor>(main_frame);
  interceptor->SetRequestMutator(
      base::BindLambdaForTesting([this](mojom::RequestParams& request_params) {
        if (request_params.name != "storage.set")
          return;

        EXPECT_EQ(active_extension_id(), request_params.extension_id);
        request_params.extension_id = spoofed_extension_id();
      }));

  // Trigger an IPC associated with the `chrome.storage.local.set` API and
  // verify that the mutated/spoofed extension id is detected and leads to
  // terminating the misbehaving renderer process.
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame->GetProcess());
  ASSERT_TRUE(ExecuteProgrammaticContentScript(GetActiveWebContents(),
                                               active_extension_id(),
                                               R"(
          chrome.storage.local.set({ test_key: 'test value2'}, () => {}); )"));
  EXPECT_EQ(bad_message::EFD_INVALID_EXTENSION_ID_FOR_PROCESS,
            kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromUserScript_BadExtensionIdInMessagingSource) {
  AllowUserScriptMessaging(active_extension());

  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from a user script of an `active_extension_id`.
  auto* web_contents = GetActiveWebContents();
  ExecuteUserScript(
      *web_contents, active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});");

  content::RenderProcessHost* main_frame_process =
      web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
      web_contents->GetPrimaryMainFrame());
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kUserScript,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
        // Mutate the IPC payload.
        info.source_endpoint.extension_id.reset();
      }));
  EXPECT_EQ(bad_message::EMF_INVALID_EXTENSION_ID_FOR_USER_SCRIPT,
            kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromUserScript_SpoofedExtensionIdInMessagingSource) {
  AllowUserScriptMessaging(active_extension());

  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from a user script of an `active_extension_id`.
  auto* web_contents = GetActiveWebContents();
  ExecuteUserScript(
      *web_contents, active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});");

  content::RenderProcessHost* main_frame_process =
      web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
      web_contents->GetPrimaryMainFrame());
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kUserScript,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
        // Mutate the IPC payload.
        info.source_endpoint.extension_id = spoofed_extension_id();
      }));
  EXPECT_EQ(bad_message::EMF_INVALID_EXTENSION_ID_FOR_USER_SCRIPT,
            kill_waiter.Wait());
}

IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
                       FromUserScript_TargetingAnotherExtensionId) {
  AllowUserScriptMessaging(active_extension());

  // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
  // from a user script of an `active_extension_id`.
  auto* web_contents = GetActiveWebContents();
  ExecuteUserScript(
      *web_contents, active_extension_id(),
      "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});");

  content::RenderProcessHost* main_frame_process =
      web_contents->GetPrimaryMainFrame()->GetProcess();
  RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
  auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
      web_contents->GetPrimaryMainFrame());
  interceptor->SetOpenChannelToExtensionMutator(
      base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) {
        EXPECT_EQ(MessagingEndpoint::Type::kUserScript,
                  info.source_endpoint.type);
        EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
        // Mutate the IPC payload.
        info.target_id = spoofed_extension_id();
      }));
  EXPECT_EQ(bad_message::EMF_INVALID_EXTERNAL_EXTENSION_ID_FOR_USER_SCRIPT,
            kill_waiter.Wait());
}

}  // namespace extensions
