<!DOCTYPE HTML>
<html>
<head>
  <title>ServiceWorkerRegistration.getNotifications() on main thread and worker thread.</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/MockServices.js"></script>
  <script type="text/javascript" src="/tests/dom/notification/test/mochitest/NotificationTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript">

  SimpleTest.requestFlakyTimeout("untriaged");

  function testFrame(src) {
    return new Promise(function(resolve, reject) {
      var iframe = document.createElement("iframe");
      iframe.src = src;
      window.callback = function(result) {
        iframe.src = "about:blank";
        document.body.removeChild(iframe);
        iframe = null;
        SpecialPowers.exactGC(function() {
          resolve(result);
        });
      };
      document.body.appendChild(iframe);
    });
  }

  function registerSW() {
    return testFrame('notification/register.html').then(function() {
      ok(true, "Registered service worker.");
    });
  }

  async function unregisterSW() {
    const reg = await navigator.serviceWorker.getRegistration("./notification/");
    await reg.unregister();
  }

  function testDismiss() {
    // Dismissed persistent notifications should be removed from the
    // notification list.
    var alertsService = SpecialPowers.Cc["@mozilla.org/alerts-service;1"]
                                     .getService(SpecialPowers.Ci.nsIAlertsService);
    return navigator.serviceWorker.getRegistration("./notification/")
      .then(function(reg) {
        return reg.showNotification(
          "This is a notification that will be closed", { tag: "dismiss" })
          .then(function() {
            return reg;
          });
      }).then(function(reg) {
        return reg.getNotifications()
          .then(function(notifications) {
            is(notifications.length, 1, "There should be one visible notification");
            is(notifications[0].tag, "dismiss", "Tag should match");

            // Simulate dismissing the notification by using the alerts service
            // directly, instead of `Notification#close`.
            var principal = SpecialPowers.wrap(document).nodePrincipal;
            var id = principal.origin + "#tag:dismiss";
            alertsService.closeAlert(id, principal);

            return reg;
          });
      }).then(function(reg) {
        return reg.getNotifications();
      }).then(function(notifications) {
        // Make sure dismissed notifications are no longer retrieved.
        is(notifications.length, 0, "There should be no more stored notifications");
      });
  }

  function testGet() {
    var options = NotificationTest.payload;
    return navigator.serviceWorker.getRegistration("./notification/")
      .then(function(reg) {
        return reg.showNotification("This is a title", options)
                 .then(function() {
                  return reg;
                 });
      }).then(function(reg) {
        return reg.getNotifications();
      }).then(function(notifications) {
        is(notifications.length, 1, "There should be one stored notification");
        var notification = notifications[0];
        ok(notification instanceof Notification, "Should be a Notification");
        is(notification.title, "This is a title", "Title should match");
        for (var key in options) {
          is(notification[key], options[key], key + " property should match");
        }
        notification.close();
      }).then(function() {
        return navigator.serviceWorker.getRegistration("./notification/").then(function(reg) {
          return reg.getNotifications();
        });
      }).then(function(notifications) {
        // Make sure closed notifications are no longer retrieved.
        is(notifications.length, 0, "There should be no more stored notifications");
      }).catch(function(e) {
        ok(false, "Something went wrong " + e.message);
      })
  }

  function testGetWorker() {
    todo(false, "navigator.serviceWorker is not available on workers yet");
    return Promise.resolve();
  }

  SimpleTest.waitForExplicitFinish();

  MockServices.register();
  SpecialPowers.pushPrefEnv({"set": [
    ["dom.serviceWorkers.exemptFromPerDomainMax", true],
    ["dom.serviceWorkers.enabled", true],
    ["dom.serviceWorkers.testing.enabled", true],
    ["dom.webnotifications.serviceworker.enabled", true],
    ["notification.prompt.testing", true],
  ]}, function() {
    registerSW()
      .then(testGet)
      .then(testGetWorker)
      .then(testDismiss)
      .then(unregisterSW)
      .then(function() {
        MockServices.unregister();
        SimpleTest.finish();
      });
  });
</script>
</body>
</html>
