<!DOCTYPE HTML>
<html>
<head>
  <title>Test for permissions</title>
  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
  <script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
  <link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>

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

function makeTest(manifestPermissions, optionalPermissions, checkFetch = true) {
  return async function() {
    function pageScript() {
      /* global PERMISSIONS */
      browser.test.onMessage.addListener(async msg => {
        if (msg == "set-cookie") {
          try {
            await browser.cookies.set({
              url: "http://example.com/",
              name: "COOKIE",
              value: "NOM NOM",
            });
            browser.test.sendMessage("set-cookie.result", {success: true});
          } catch (err) {
            dump(`set cookie failed with ${err.message}\n`);
            browser.test.sendMessage("set-cookie.result",
                                     {success: false, message: err.message});
          }
        } else if (msg == "remove") {
          browser.permissions.remove(PERMISSIONS).then(result => {
            browser.test.sendMessage("remove.result", result);
          });
        } else if (msg == "request") {
          browser.test.withHandlingUserInput(() => {
            browser.permissions.request(PERMISSIONS).then(result => {
              browser.test.sendMessage("request.result", result);
            });
          });
        }
      });

      browser.test.sendMessage("page-ready");
    }

    let extension = ExtensionTestUtils.loadExtension({
      background() {
        browser.test.sendMessage("ready", browser.runtime.getURL("page.html"));
      },

      manifest: {
        permissions: manifestPermissions,
        optional_permissions: [...(optionalPermissions.permissions || []),
                               ...(optionalPermissions.origins || [])],

        content_scripts: [{
          matches: ["http://mochi.test/*/file_sample.html"],
          js: ["content_script.js"],
        }],
      },

      files: {
        "content_script.js": async () => {
          let url = new URL(window.location.pathname, "http://example.com/");
          fetch(url, {}).then(response => {
            browser.test.sendMessage("fetch.result", response.ok);
          }).catch(err => {
            browser.test.sendMessage("fetch.result", false);
          });
        },

        "page.html": `<html><head>
          <script src="page.js"><\/script>
        </head></html>`,

        "page.js": `const PERMISSIONS = ${JSON.stringify(optionalPermissions)}; (${pageScript})();`,
      },
    });

    await extension.startup();

    function call(method) {
      extension.sendMessage(method);
      return extension.awaitMessage(`${method}.result`);
    }

    let base = window.location.href.replace(/^chrome:\/\/mochitests\/content/,
                                            "http://mochi.test:8888");
    let file = new URL("file_sample.html", base);

    async function testContentScript() {
      let win = window.open(file);
      let result = await extension.awaitMessage("fetch.result");
      win.close();
      return result;
    }

    let url = await extension.awaitMessage("ready");
    let win = window.open();
    win.location.href = url;
    await extension.awaitMessage("page-ready");

    // Using the cookies API from an extension page should fail
    let result = await call("set-cookie");
    is(result.success, false, "setting cookie failed");
    if (manifestPermissions.includes("cookies")) {
      ok(/^Permission denied/.test(result.message),
         "setting cookie failed with an appropriate error due to missing host permission");
    } else {
      ok(/browser\.cookies is undefined/.test(result.message),
         "setting cookie failed since cookies API is not present");
    }

    // Making a cross-origin request from a content script should fail
    if (checkFetch) {
      result = await testContentScript();
      is(result, false, "fetch() failed from content script due to lack of host permission");
    }

    result = await call("request");
    is(result, true, "permissions.request() succeeded");

    // Using the cookies API from an extension page should succeed
    result = await call("set-cookie");
    is(result.success, true, "setting cookie succeeded");

    // Making a cross-origin request from a content script should succeed
    if (checkFetch) {
      result = await testContentScript();
      is(result, true, "fetch() succeeded from content script due to lack of host permission");
    }

    // Now revoke our permissions
    result = await call("remove");

    // The cookies API should once again fail
    result = await call("set-cookie");
    is(result.success, false, "setting cookie failed");

    // As should the cross-origin request from a content script
    if (checkFetch) {
      result = await testContentScript();
      is(result, false, "fetch() failed from content script due to lack of host permission");
    }

    await extension.unload();
  };
}

add_task(function setup() {
  // Don't bother with prompts in this test.
  return SpecialPowers.pushPrefEnv({
    set: [["extensions.webextOptionalPermissionPrompts", false]],
  });
});

const ORIGIN = "*://example.com/";
add_task(makeTest([], {
  permissions: ["cookies"],
  origins: [ORIGIN],
}));

add_task(makeTest(["cookies"], {origins: [ORIGIN]}));
add_task(makeTest([ORIGIN], {permissions: ["cookies"]}, false));

</script>

</body>
</html>
