<!DOCTYPE HTML>
<html>
<head>
  <title>WebExtension test</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
  <script type="text/javascript" src="head.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>

<script type="text/javascript">
"use strict";

// The purpose of this test is to verify that the port.sender properties are
// not set for messages from iframes in background scripts. This is the toolkit
// version of the browser_ext_contentscript_nontab_connect.js test, and exists
// to provide test coverage for non-toolkit builds (e.g. Android).
//
// This used to be a xpcshell test (from bug 1488105), but became a mochitest
// because port.sender.tab and port.sender.frameId do not represent the real
// values in xpcshell tests.
// Specifically, ProxyMessenger.prototype.getSender uses the tabTracker, which
// expects real tabs instead of browsers from the ContentPage API in xpcshell
// tests.
add_task(async function connect_from_background_frame() {
  if (!SpecialPowers.getBoolPref("extensions.webextensions.remote", true)) {
    info("Cannot load remote content in parent process; skipping test task");
    return;
  }
  async function background() {
    const FRAME_URL = "https://example.com/tests/toolkit/components/extensions/test/mochitest/file_sample.html";
    browser.runtime.onConnect.addListener(port => {
      // The next two assertions are the reason for this being a mochitest
      // instead of a xpcshell test.
      browser.test.assertEq(port.sender.tab, undefined, "Sender is not a tab");
      browser.test.assertEq(port.sender.frameId, undefined, "frameId unset");
      browser.test.assertEq(port.sender.url, FRAME_URL, "Expected sender URL");
      port.onMessage.addListener(msg => {
        browser.test.assertEq("pong", msg, "Reply from content script");
        port.disconnect();
      });
      port.postMessage("ping");
    });

    await browser.contentScripts.register({
      matches: [FRAME_URL],
      js: [{ file: "contentscript.js" }],
      allFrames: true,
    });

    let f = document.createElement("iframe");
    f.src = FRAME_URL;
    document.body.appendChild(f);
  }

  function contentScript() {
    browser.test.log(`Running content script at ${document.URL}`);

    let port = browser.runtime.connect();
    port.onMessage.addListener(msg => {
      browser.test.assertEq("ping", msg, "Expected message to content script");
      port.postMessage("pong");
    });
    port.onDisconnect.addListener(() => {
      browser.test.sendMessage("disconnected_in_content_script");
    });
  }

  let extension = ExtensionTestUtils.loadExtension({
    manifest: {
      permissions: ["https://example.com/*"],
    },
    files: {
      "contentscript.js": contentScript,
    },
    background,
  });
  await extension.startup();
  await extension.awaitMessage("disconnected_in_content_script");
  await extension.unload();
});

// The test_ext_contentscript_fission_frame.html test already checks the
// behavior of onConnect in cross-origin frames, so here we just limit the test
// to checking that the port.sender properties are sensible.
add_task(async function connect_from_content_script_in_frame() {
  async function background() {
    const TAB_URL = "https://example.org/tests/toolkit/components/extensions/test/mochitest/file_contains_iframe.html";
    const FRAME_URL = "https://example.org/tests/toolkit/components/extensions/test/mochitest/file_contains_img.html";
    let createdTab;
    browser.runtime.onConnect.addListener(port => {
      // The next two assertions are the reason for this being a mochitest
      // instead of a xpcshell test.
      browser.test.assertEq(port.sender.tab.url, TAB_URL, "Sender is the tab");
      browser.test.assertTrue(port.sender.frameId > 0, "frameId is set");
      browser.test.assertEq(port.sender.url, FRAME_URL, "Expected sender URL");

      browser.test.assertEq(createdTab.id, port.sender.tab.id, "Tab to close");
      browser.tabs.remove(port.sender.tab.id).then(() => {
        browser.test.sendMessage("tab_port_checked_and_tab_closed");
      });
    });

    await browser.contentScripts.register({
      matches: [FRAME_URL],
      js: [{ file: "contentscript.js" }],
      allFrames: true,
    });

    createdTab = await browser.tabs.create({ url: TAB_URL });
  }

  function contentScript() {
    browser.test.log(`Running content script at ${document.URL}`);

    browser.runtime.connect();
  }

  let extension = ExtensionTestUtils.loadExtension({
    manifest: {
      permissions: ["https://example.org/*"],
    },
    files: {
      "contentscript.js": contentScript,
    },
    background,
  });
  await extension.startup();
  await extension.awaitMessage("tab_port_checked_and_tab_closed");
  await extension.unload();
});
</script>

</body>
</html>
