<!--
  Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>

<head>
  <meta charset="utf-8">
  <title>Test for Permissions API</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>

<body>
  <pre id="test"></pre>
  <script type="application/javascript">
  /*globals SpecialPowers, SimpleTest, is, ok, */
  'use strict';

  function setPermission(type, allow) {
    return new Promise(resolve => {
      SpecialPowers.popPermissions(() => {
        SpecialPowers.pushPermissions(
          [{ type, allow, context: document }],
          resolve
        );
      });
    });
  }

  function checkPermission(aIFrame, aExpectedState, aName) {
    return SpecialPowers.spawn(
      aIFrame,
      [{name: aName, expectedState: aExpectedState}],
      async aInput => {
        try {
          let result = await content.navigator
                                    .permissions
                                    .query({ name: aInput.name });
          is(
            SpecialPowers.wrap(result).state,
            aInput.expectedState,
            `correct state for '${aInput.name}'`
          );
        } catch (e) {
          ok(false, `query should not have rejected for '${aInput.name}'`)
        }
      }
    );
  }

  function createIframe(aId, aAllow) {
    return new Promise((resolve) => {
      const iframe = document.createElement('iframe');
      iframe.id = aId;
      iframe.src = 'https://example.org/tests/dom/permission/tests/file_empty.html';
      if (aAllow) {
        iframe.allow = aAllow;
      }
      iframe.onload = () => resolve(iframe);
      document.body.appendChild(iframe);
    });
  }

  function removeIframe(aId) {
    return new Promise((resolve) => {
      document.body.removeChild(document.getElementById(aId));
      resolve();
    });
  }

  const {
    UNKNOWN_ACTION,
    PROMPT_ACTION,
    ALLOW_ACTION,
    DENY_ACTION
  } = SpecialPowers.Ci.nsIPermissionManager;

  const tests = [
    {
      id: 'query navigation top unknown',
      top: UNKNOWN_ACTION,
      name: 'geolocation',
      type: 'geo',
      expected: 'denied',
    },
    {
      id: 'query notifications top unknown',
      top: UNKNOWN_ACTION,
      name: 'notifications',
      type: 'desktop-notification',
      expected: 'denied',
    },
    {
      id: 'query push top unknown',
      top: UNKNOWN_ACTION,
      name: 'push',
      type: 'desktop-notification',
      expected: 'denied',
    },
    {
      id: 'query persistent-storage unknown',
      top: UNKNOWN_ACTION,
      name: 'persistent-storage',
      type: 'persistent-storage',
      expected: 'denied',
    },
    {
      id: 'query navigation top prompt',
      top: PROMPT_ACTION,
      name: 'geolocation',
      type: 'geo',
      expected: 'denied',
    },
    {
      id: 'query notifications top prompt',
      top: PROMPT_ACTION,
      name: 'notifications',
      type: 'desktop-notification',
      expected: 'denied',
    },
    {
      id: 'query push top prompt',
      top: PROMPT_ACTION,
      name: 'push',
      type: 'desktop-notification',
      expected: 'denied',
    },
    {
      id: 'query persistent-storage top prompt',
      top: PROMPT_ACTION,
      name: 'persistent-storage',
      type: 'persistent-storage',
      expected: 'denied',
    },
    {
      id: 'query navigation top denied',
      top: DENY_ACTION,
      name: 'geolocation',
      type: 'geo',
      expected: 'denied',
    },
    {
      id: 'query notifications top denied',
      top: DENY_ACTION,
      name: 'notifications',
      type: 'desktop-notification',
      expected: 'denied',
    },
    {
      id: 'query push top denied',
      top: DENY_ACTION,
      name: 'push',
      type: 'desktop-notification',
      expected: 'denied',
    },
    {
      id: 'query persistent-storage top denied',
      top: DENY_ACTION,
      name: 'persistent-storage',
      type: 'persistent-storage',
      expected: 'denied',
    },
    {
      id: 'query navigation top granted',
      top: ALLOW_ACTION,
      name: 'geolocation',
      type: 'geo',
      expected: 'denied',
    },
    {
      id: 'query notifications top granted',
      top: ALLOW_ACTION,
      name: 'notifications',
      type: 'desktop-notification',
      expected: 'denied',
    },
    {
      id: 'query push top granted',
      top: ALLOW_ACTION,
      name: 'push',
      type: 'desktop-notification',
      expected: 'denied',
    },
    {
      id: 'query persistent-storage top granted',
      top: ALLOW_ACTION,
      name: 'persistent-storage',
      type: 'persistent-storage',
      expected: 'denied',
    },
    {
      id: 'query navigation top denied, iframe has allow attribute',
      top: DENY_ACTION,
      allow: 'geolocation',
      name: 'geolocation',
      type: 'geo',
      expected: 'denied',
    },
    {
      id: 'query navigation top granted, iframe has allow attribute',
      top: ALLOW_ACTION,
      allow: 'geolocation',
      name: 'geolocation',
      type: 'geo',
      expected: 'granted',
    },
    {
      id: 'query navigation top prompt, iframe has allow attribute',
      top: PROMPT_ACTION,
      allow: 'geolocation',
      name: 'geolocation',
      type: 'geo',
      expected: 'prompt',
    },
    {
      id: 'query navigation top unknown, iframe has allow attribute',
      top: UNKNOWN_ACTION,
      allow: 'geolocation',
      name: 'geolocation',
      type: 'geo',
      expected: 'prompt',
    },

  ];

  SimpleTest.waitForExplicitFinish();

  async function nextTest() {
    if (!tests.length) {
      SimpleTest.finish();
      return;
    }

    let test = tests.shift();
    await setPermission(test.type, test.top)
      .then(() => createIframe(test.id, test.allow))
      .then(iframe => checkPermission(iframe, test.expected, test.name))
      .then(() => removeIframe(test.id));

    SimpleTest.executeSoon(nextTest);
  }

  SpecialPowers.pushPrefEnv({"set": [
    ["permissions.delegation.enabled", true],
  ]}).then(nextTest);
  </script>
</body>

</html>
