summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/notification
diff options
context:
space:
mode:
Diffstat (limited to 'dom/tests/mochitest/notification')
-rw-r--r--dom/tests/mochitest/notification/MockServices.js117
-rw-r--r--dom/tests/mochitest/notification/NotificationTest.js136
-rw-r--r--dom/tests/mochitest/notification/desktop-notification/create_notification.html16
-rw-r--r--dom/tests/mochitest/notification/desktop-notification/moz.build6
-rw-r--r--dom/tests/mochitest/notification/desktop-notification/notification_common.js70
-rw-r--r--dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html50
-rw-r--r--dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html53
-rw-r--r--dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html34
-rw-r--r--dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html110
-rw-r--r--dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul85
-rw-r--r--dom/tests/mochitest/notification/mochitest.ini10
-rw-r--r--dom/tests/mochitest/notification/test_bug931307.html34
-rw-r--r--dom/tests/mochitest/notification/test_notification_basics.html129
-rw-r--r--dom/tests/mochitest/notification/test_notification_storage.html158
14 files changed, 1008 insertions, 0 deletions
diff --git a/dom/tests/mochitest/notification/MockServices.js b/dom/tests/mochitest/notification/MockServices.js
new file mode 100644
index 000000000..f809b2438
--- /dev/null
+++ b/dom/tests/mochitest/notification/MockServices.js
@@ -0,0 +1,117 @@
+var MockServices = (function () {
+ "use strict";
+
+ const MOCK_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components)
+ .ID("{48068bc2-40ab-4904-8afd-4cdfb3a385f3}");
+ const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
+
+ const MOCK_SYSTEM_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components)
+ .ID("{e86d888c-e41b-4b78-9104-2f2742a532de}");
+ const SYSTEM_ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/system-alerts-service;1";
+
+ var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager
+ .QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar);
+
+ var activeAlertNotifications = Object.create(null);
+
+ var activeAppNotifications = Object.create(null);
+
+ window.addEventListener('mock-notification-close-event', function(e) {
+ for (var alertName in activeAlertNotifications) {
+ var notif = activeAlertNotifications[alertName];
+ if (notif.title === e.detail.title) {
+ notif.listener.observe(null, "alertfinished", null);
+ delete activeAlertNotifications[alertName];
+ delete activeAppNotifications[alertName];
+ return;
+ }
+ }
+ });
+
+ var mockAlertsService = {
+ showPersistentNotification: function(persistentData, alert, alertListener) {
+ this.showAlert(alert, alertListener);
+ },
+
+ showAlert: function(alert, alertListener) {
+ var listener = SpecialPowers.wrap(alertListener);
+ activeAlertNotifications[alert.name] = {
+ listener: listener,
+ cookie: alert.cookie,
+ title: alert.title
+ };
+
+ // fake async alert show event
+ if (listener) {
+ setTimeout(function () {
+ listener.observe(null, "alertshow", alert.cookie);
+ }, 100);
+ setTimeout(function () {
+ listener.observe(null, "alertclickcallback", alert.cookie);
+ }, 100);
+ }
+ },
+
+ showAlertNotification: function(imageUrl, title, text, textClickable,
+ cookie, alertListener, name) {
+ this.showAlert({
+ name: name,
+ cookie: cookie,
+ title: title
+ }, alertListener);
+ },
+
+ closeAlert: function(name) {
+ var alertNotification = activeAlertNotifications[name];
+ if (alertNotification) {
+ if (alertNotification.listener) {
+ alertNotification.listener.observe(null, "alertfinished", alertNotification.cookie);
+ }
+ delete activeAlertNotifications[name];
+ }
+
+ var appNotification = activeAppNotifications[name];
+ if (appNotification) {
+ delete activeAppNotifications[name];
+ }
+ },
+
+ QueryInterface: function(aIID) {
+ if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
+ SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
+ return this;
+ }
+ throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
+ },
+
+ createInstance: function(aOuter, aIID) {
+ if (aOuter != null) {
+ throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION;
+ }
+ return this.QueryInterface(aIID);
+ }
+ };
+ mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService);
+
+ // MockServices API
+ return {
+ register: function () {
+ registrar.registerFactory(MOCK_ALERTS_CID, "alerts service",
+ ALERTS_SERVICE_CONTRACT_ID,
+ mockAlertsService);
+
+ registrar.registerFactory(MOCK_SYSTEM_ALERTS_CID, "system alerts service",
+ SYSTEM_ALERTS_SERVICE_CONTRACT_ID,
+ mockAlertsService);
+ },
+
+ unregister: function () {
+ registrar.unregisterFactory(MOCK_ALERTS_CID, mockAlertsService);
+ registrar.unregisterFactory(MOCK_SYSTEM_ALERTS_CID, mockAlertsService);
+ },
+
+ activeAlertNotifications: activeAlertNotifications,
+
+ activeAppNotifications: activeAppNotifications,
+ };
+})();
diff --git a/dom/tests/mochitest/notification/NotificationTest.js b/dom/tests/mochitest/notification/NotificationTest.js
new file mode 100644
index 000000000..f17dc1d49
--- /dev/null
+++ b/dom/tests/mochitest/notification/NotificationTest.js
@@ -0,0 +1,136 @@
+var NotificationTest = (function () {
+ "use strict";
+
+ function info(msg, name) {
+ SimpleTest.info("::Notification Tests::" + (name || ""), msg);
+ }
+
+ function setup_testing_env() {
+ SimpleTest.waitForExplicitFinish();
+ // turn on testing pref (used by notification.cpp, and mock the alerts
+ SpecialPowers.setBoolPref("notification.prompt.testing", true);
+ }
+
+ function teardown_testing_env() {
+ SimpleTest.finish();
+ }
+
+ function executeTests(tests, callback) {
+ // context is `this` object in test functions
+ // it can be used to track data between tests
+ var context = {};
+
+ (function executeRemainingTests(remainingTests) {
+ if (!remainingTests.length) {
+ return callback();
+ }
+
+ var nextTest = remainingTests.shift();
+ var finishTest = executeRemainingTests.bind(null, remainingTests);
+ var startTest = nextTest.call.bind(nextTest, context, finishTest);
+
+ try {
+ startTest();
+ // if no callback was defined for test function,
+ // we must manually invoke finish to continue
+ if (nextTest.length === 0) {
+ finishTest();
+ }
+ } catch (e) {
+ ok(false, "Test threw exception!");
+ finishTest();
+ }
+ })(tests);
+ }
+
+ var fakeCustomData = (function () {
+ var buffer = new ArrayBuffer(2);
+ var dv = new DataView(buffer).setInt16(0, 42, true);
+ var canvas = document.createElement("canvas");
+ canvas.width = canvas.height = 100;
+ var context = canvas.getContext("2d");
+
+ var map = new Map();
+ var set = new Set();
+ map.set("test", 42);
+ set.add(4); set.add(2);
+
+ return {
+ primitives: {
+ a: 123,
+ b: "test",
+ c: true,
+ d: [1, 2, 3]
+ },
+ date: new Date(2013, 2, 1, 1, 10),
+ regexp: new RegExp("[^.]+"),
+ arrayBuffer: buffer,
+ imageData: context.createImageData(100, 100),
+ map: map,
+ set: set
+ };
+ })();
+
+ // NotificationTest API
+ return {
+ run: function (tests, callback) {
+ setup_testing_env();
+
+ addLoadEvent(function () {
+ executeTests(tests, function () {
+ teardown_testing_env();
+ callback && callback();
+ });
+ });
+ },
+
+ allowNotifications: function () {
+ SpecialPowers.setBoolPref("notification.prompt.testing.allow", true);
+ },
+
+ denyNotifications: function () {
+ SpecialPowers.setBoolPref("notification.prompt.testing.allow", false);
+ },
+
+ clickNotification: function (notification) {
+ // TODO: how??
+ },
+
+ fireCloseEvent: function (title) {
+ window.dispatchEvent(new CustomEvent("mock-notification-close-event", {
+ detail: {
+ title: title
+ }
+ }));
+ },
+
+ info: info,
+
+ customDataMatches: function(dataObj) {
+ var url = "http://www.domain.com";
+ try {
+ return (JSON.stringify(dataObj.primitives) ===
+ JSON.stringify(fakeCustomData.primitives)) &&
+ (dataObj.date.toDateString() ===
+ fakeCustomData.date.toDateString()) &&
+ (dataObj.regexp.exec(url)[0].substr(7) === "www") &&
+ (new Int16Array(dataObj.arrayBuffer)[0] === 42) &&
+ (JSON.stringify(dataObj.imageData.data) ===
+ JSON.stringify(fakeCustomData.imageData.data)) &&
+ (dataObj.map.get("test") == 42) &&
+ (dataObj.set.has(4) && dataObj.set.has(2));
+ } catch(e) {
+ return false;
+ }
+ },
+
+ payload: {
+ body: "Body",
+ tag: "fakeTag",
+ icon: "icon.jpg",
+ lang: "en-US",
+ dir: "ltr",
+ data: fakeCustomData
+ }
+ };
+})();
diff --git a/dom/tests/mochitest/notification/desktop-notification/create_notification.html b/dom/tests/mochitest/notification/desktop-notification/create_notification.html
new file mode 100644
index 000000000..b0387e4ff
--- /dev/null
+++ b/dom/tests/mochitest/notification/desktop-notification/create_notification.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head><meta charset=utf-8>
+ <title>Create a notification</title>
+</head>
+<body>
+<script>
+
+var notification = new Notification("This is a title", {
+ body: "This is a notification body",
+ tag: "sometag",
+ });
+
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/notification/desktop-notification/moz.build b/dom/tests/mochitest/notification/desktop-notification/moz.build
new file mode 100644
index 000000000..28919c271
--- /dev/null
+++ b/dom/tests/mochitest/notification/desktop-notification/moz.build
@@ -0,0 +1,6 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
diff --git a/dom/tests/mochitest/notification/desktop-notification/notification_common.js b/dom/tests/mochitest/notification/desktop-notification/notification_common.js
new file mode 100644
index 000000000..921b1e753
--- /dev/null
+++ b/dom/tests/mochitest/notification/desktop-notification/notification_common.js
@@ -0,0 +1,70 @@
+const MOCK_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{48068bc2-40ab-4904-8afd-4cdfb3a385f3}");
+const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
+
+const MOCK_SYSTEM_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{e86d888c-e41b-4b78-9104-2f2742a532de}");
+const SYSTEM_ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/system-alerts-service;1";
+
+var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager.
+ QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar);
+
+var mockAlertsService = {
+ showAlert: function(alert, alertListener) {
+ // probably should do this async....
+ SpecialPowers.wrap(alertListener).observe(null, "alertshow", alert.cookie);
+
+ if (SpecialPowers.getBoolPref("notification.prompt.testing.click_on_notification") == true) {
+ SpecialPowers.wrap(alertListener).observe(null, "alertclickcallback", alert.cookie);
+ }
+
+ SpecialPowers.wrap(alertListener).observe(null, "alertfinished", alert.cookie);
+ },
+
+ showAlertNotification: function(imageUrl, title, text, textClickable,
+ cookie, alertListener, name, bidi,
+ lang, data) {
+ return this.showAlert({
+ cookie: cookie
+ }, alertListener);
+ },
+
+ QueryInterface: function(aIID) {
+ if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
+ SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
+ return this;
+ }
+ throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
+ },
+
+ createInstance: function(aOuter, aIID) {
+ if (aOuter != null) {
+ throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION;
+ }
+ return this.QueryInterface(aIID);
+ }
+};
+mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService);
+
+function setup_notifications(allowPrompt, forceClick, callback) {
+ SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true],
+ ["notification.prompt.testing.allow", allowPrompt],
+ ["notification.prompt.testing.click_on_notification", forceClick]]},
+ callback);
+
+ registrar.registerFactory(MOCK_SYSTEM_ALERTS_CID, "system alerts service",
+ SYSTEM_ALERTS_SERVICE_CONTRACT_ID,
+ mockAlertsService);
+
+ registrar.registerFactory(MOCK_ALERTS_CID, "alerts service",
+ ALERTS_SERVICE_CONTRACT_ID,
+ mockAlertsService);
+}
+
+function reset_notifications() {
+ registrar.unregisterFactory(MOCK_SYSTEM_ALERTS_CID, mockAlertsService);
+ registrar.unregisterFactory(MOCK_ALERTS_CID, mockAlertsService);
+}
+
+function is_feature_enabled() {
+ return navigator.mozNotification && SpecialPowers.getBoolPref("notification.feature.enabled");
+}
+
diff --git a/dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html b/dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html
new file mode 100644
index 000000000..75f3c84b4
--- /dev/null
+++ b/dom/tests/mochitest/notification/desktop-notification/test_basic_notification.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=573588
+-->
+<head>
+ <title>Basic functional test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="notification_common.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573588">Basic property tests</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+<script type="text/javascript">
+ if (is_feature_enabled()) {
+ SimpleTest.waitForExplicitFinish();
+
+ function showNotifications() {
+ ok(navigator.mozNotification, "test for notification.");
+
+ var notification = navigator.mozNotification.createNotification("test", "test");
+ ok(notification, "test to ensure we can create a notification");
+
+ notification.onclose = function() {
+ ok(true, "notification was display and is now closing");
+ reset_notifications();
+ SimpleTest.finish();
+ };
+
+ notification.onclick = function() {
+ ok(false, "Click should not have been called.");
+ reset_notifications();
+ SimpleTest.finish();
+ };
+
+ notification.show();
+ }
+
+ setup_notifications(true, false, showNotifications);
+ } else {
+ ok(true, "Desktop notifications not enabled.");
+ }
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html b/dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html
new file mode 100644
index 000000000..defa0f412
--- /dev/null
+++ b/dom/tests/mochitest/notification/desktop-notification/test_basic_notification_click.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=573588
+-->
+<head>
+ <title>Basic functional test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="notification_common.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573588">Basic property tests</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+<script type="text/javascript">
+ if (is_feature_enabled()) {
+ SimpleTest.waitForExplicitFinish();
+
+ var click_was_called = false;
+
+ function showNotifications() {
+ ok(navigator.mozNotification, "test for notification.");
+
+ var notification = navigator.mozNotification.createNotification("test", "test");
+ ok(notification, "test to ensure we can create a notification");
+
+ notification.onclose = function() {
+ ok(true, "notification was display and is now closing");
+ ok(click_was_called, "was notification clicked?");
+
+ reset_notifications();
+ SimpleTest.finish();
+ };
+
+ notification.onclick = function() {
+ ok(true, "Click was called. Good.");
+ click_was_called = true;
+ };
+
+ notification.show();
+ }
+
+ setup_notifications(true, true, showNotifications);
+ } else {
+ ok(true, "Desktop notifications not enabled.");
+ }
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html b/dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html
new file mode 100644
index 000000000..c0c9699ae
--- /dev/null
+++ b/dom/tests/mochitest/notification/desktop-notification/test_leak_windowClose.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=605309
+-->
+<head>
+ <title>Test for leak when window closes</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="notification_common.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script>
+if (is_feature_enabled()) {
+ SimpleTest.waitForExplicitFinish();
+
+ function boom()
+ {
+ document.documentElement.focus();
+ var x = navigator.mozNotification;
+ document.documentElement.addEventListener('', function(){x}, false);
+ ok(true, "load callback called");
+ SimpleTest.finish();
+ }
+
+ window.addEventListener("load", boom, false);
+} else {
+ ok(true, "Desktop notifications not enabled.");
+}
+</script>
+</head>
+<body>
+<p> I like to write tests </p>
+</body>
+</html>
diff --git a/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html b/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html
new file mode 100644
index 000000000..37bcb16c0
--- /dev/null
+++ b/dom/tests/mochitest/notification/desktop-notification/test_notification_tag.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=782211
+-->
+<head>
+ <title>Bug 782211</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=782211">Bug 782211</a>
+<p id="display"></p>
+<iframe name="sameDomain"></iframe>
+<iframe name="anotherSameDomain"></iframe>
+<iframe name="crossDomain"></iframe>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+<script type="text/javascript">
+ const MOCK_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{dbe37e64-d9a3-402c-8d8a-0826c619f7ad}");
+ const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
+
+ var mockAlertsService = {
+ showAlert: function(alert, alertListener) {
+ notificationsCreated.push(alert.name);
+ if (notificationsCreated.length == 3) {
+ checkNotifications();
+ }
+ },
+
+ showAlertNotification: function(imageUrl, title, text, textClickable,
+ cookie, alertListener, name, dir,
+ lang, data) {
+ this.showAlert({ name: name });
+ },
+
+ QueryInterface: function(aIID) {
+ if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
+ SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
+ return this;
+ }
+ throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
+ },
+
+ createInstance: function(aOuter, aIID) {
+ if (aOuter != null) {
+ throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION;
+ }
+ return this.QueryInterface(aIID);
+ }
+ };
+ mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService);
+
+ var notificationsCreated = [];
+ function checkNotifications() {
+ // notifications created by the test1 origin
+ var test1notifications = [];
+ // notifications created by the test2 origin
+ var test2notifications = [];
+ for (var i = 0; i < notificationsCreated.length; i++) {
+ var notificationName = notificationsCreated[i];
+ if (notificationName.indexOf("test1") !== -1) {
+ test1notifications.push(notificationsCreated[i]);
+ } else if (notificationName.indexOf("test2") !== -1) {
+ test2notifications.push(notificationsCreated[i]);
+ }
+ }
+
+ is(test1notifications.length, 2, "2 notifications should be created by test1.example.org:80 origin.");
+ is(test1notifications[0], test1notifications[1], "notification names should be identical.");
+ is(test2notifications.length, 1, "1 notification should be created by test2.example.org:80 origin.");
+
+ // Register original alerts service.
+ SpecialPowers.wrap(SpecialPowers.Components).
+ manager.QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar).
+ unregisterFactory(MOCK_CID, mockAlertsService);
+
+ SimpleTest.finish();
+ }
+
+ if (window.Notification) {
+ SimpleTest.waitForExplicitFinish();
+
+ function showNotifications() {
+ SpecialPowers.wrap(SpecialPowers.Components).
+ manager.QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar).
+ registerFactory(MOCK_CID, "alerts service", ALERTS_SERVICE_CONTRACT_ID, mockAlertsService);
+
+ // Load two frames with the same origin that create notification with the same tag.
+ // Both pages should generate notifications with the same name, and thus the second
+ // notification should replace the first.
+ frames["sameDomain"].location.href = "http://test1.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
+ frames["anotherSameDomain"].location.href = "http://test1.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
+
+ // Load a frame with a different origin that creates a notification with the same tag.
+ // The notification name should be different and thus no notifications should be replaced.
+ frames["crossDomain"].location.href = "http://test2.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
+ }
+
+ SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true],
+ ["notification.prompt.testing.allow", true]]},
+ showNotifications);
+ } else {
+ ok(true, "Notifications are not enabled on the platform.");
+ }
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul b/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul
new file mode 100644
index 000000000..1690bc101
--- /dev/null
+++ b/dom/tests/mochitest/notification/desktop-notification/test_system_principal.xul
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=874090
+-->
+<window title="Mozilla Bug 874090" onload="runTests()"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=874090"
+ target="_blank">Mozilla Bug 874090</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript">
+ <![CDATA[
+ /** Test for Bug 874090 **/
+ const MOCK_CID = Components.ID("{2a0f83c4-8818-4914-a184-f1172b4eaaa7}");
+ const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
+
+ var mockAlertsService = {
+ showAlert: function(alert, alertListener) {
+ ok(true, "System principal was granted permission and is able to call showAlert.");
+ unregisterMock();
+ SimpleTest.finish();
+ },
+
+ showAlertNotification: function(imageUrl, title, text, textClickable,
+ cookie, alertListener, name, dir, lang, data) {
+ this.showAlert();
+ },
+
+ QueryInterface: function(aIID) {
+ if (aIID.equals(Components.interfaces.nsISupports) ||
+ aIID.equals(Components.interfaces.nsIAlertsService)) {
+ return this;
+ }
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ },
+
+ createInstance: function(aOuter, aIID) {
+ if (aOuter != null) {
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+ }
+ return this.QueryInterface(aIID);
+ }
+ };
+
+ function registerMock() {
+ Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).
+ registerFactory(MOCK_CID, "alerts service", ALERTS_SERVICE_CONTRACT_ID, mockAlertsService);
+ }
+
+ function unregisterMock() {
+ Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).
+ unregisterFactory(MOCK_CID, mockAlertsService);
+ }
+
+ function runTests() {
+ registerMock();
+
+ is(Notification.permission, "granted", "System principal should be automatically granted permission.");
+
+ Notification.requestPermission(function(permission) {
+ is(permission, "granted", "System principal should be granted permission when calling requestPermission.");
+
+ if (permission == "granted") {
+ // Create a notification and make sure that it is able to call into
+ // the mock alert service to show the notification.
+ new Notification("Hello");
+ } else {
+ unregisterMock();
+ SimpleTest.finish();
+ }
+ });
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ ]]>
+ </script>
+</window>
diff --git a/dom/tests/mochitest/notification/mochitest.ini b/dom/tests/mochitest/notification/mochitest.ini
new file mode 100644
index 000000000..c0de5ed46
--- /dev/null
+++ b/dom/tests/mochitest/notification/mochitest.ini
@@ -0,0 +1,10 @@
+[DEFAULT]
+
+support-files =
+ MockServices.js
+ NotificationTest.js
+
+[test_notification_basics.html]
+[test_notification_storage.html]
+[test_bug931307.html]
+skip-if = (os == 'android') # Bug 1258975 on android.
diff --git a/dom/tests/mochitest/notification/test_bug931307.html b/dom/tests/mochitest/notification/test_bug931307.html
new file mode 100644
index 000000000..bd31c7061
--- /dev/null
+++ b/dom/tests/mochitest/notification/test_bug931307.html
@@ -0,0 +1,34 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+ <title>Bug 931307</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript"><!--
+
+SimpleTest.waitForExplicitFinish();
+var notification = new Notification("");
+var promise = Notification.get();
+promise.then(
+ function onSuccess() {
+ ok(true, "No error when creating a notification without title");
+ },
+ function onFailure() {
+ ok(false, "Should not throw error when creating a notification without title");
+ }
+).then(() => {
+ notification.close();
+}).then(() => {
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/notification/test_notification_basics.html b/dom/tests/mochitest/notification/test_notification_basics.html
new file mode 100644
index 000000000..3d0465c3f
--- /dev/null
+++ b/dom/tests/mochitest/notification/test_notification_basics.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Notification Basics</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="MockServices.js"></script>
+ <script type="text/javascript" src="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">
+
+ var info = NotificationTest.info;
+ var options;
+
+ SimpleTest.requestFlakyTimeout("untriaged");
+
+ var steps = [
+ function () {
+ info("Test notification spec");
+ ok(Notification, "Notification constructor exists");
+ ok(Notification.permission, "Notification.permission exists");
+ ok(Notification.requestPermission, "Notification.requestPermission exists");
+ ok(Notification.get, "Notification.get exists");
+ },
+
+ function () {
+ info("Test requestPermission without callback");
+ Notification.requestPermission();
+ },
+
+ function (done) {
+ info("Test requestPermission deny");
+ function assertPermissionDenied(perm) {
+ is(perm, "denied", "Permission should be denied.");
+ is(Notification.permission, "denied", "Permission should be denied.");
+ }
+ NotificationTest.denyNotifications();
+ Notification.requestPermission()
+ .then(assertPermissionDenied)
+ .then(_ => Notification.requestPermission(assertPermissionDenied))
+ .catch(err => {
+ ok(!err, "requestPermission should not reject promise");
+ })
+ .then(done);
+ },
+
+ function (done) {
+ info("Test requestPermission grant");
+ function assertPermissionGranted(perm) {
+ is(perm, "granted", "Permission should be granted.");
+ is(Notification.permission, "granted", "Permission should be granted");
+ }
+ NotificationTest.allowNotifications();
+ Notification.requestPermission()
+ .then(assertPermissionGranted)
+ .then(_ => Notification.requestPermission(assertPermissionGranted))
+ .catch(err => {
+ ok(!err, "requestPermission should not reject promise");
+ })
+ .then(done);
+ },
+
+ function (done) {
+ info("Test invalid requestPermission");
+ Notification.requestPermission({})
+ .then(_ => {
+ ok(false, "Non callable arg to requestPermission should reject promise");
+ }, err => {
+ ok(true, "Non callable arg to requestPermission should reject promise");
+ })
+ .then(done);
+ },
+
+ function (done) {
+ info("Test create notification");
+
+ options = NotificationTest.payload;
+
+ var notification = new Notification("This is a title", options);
+
+ ok(notification, "Notification exists");
+ is(notification.onclick, null, "onclick() should be null");
+ is(notification.onshow, null, "onshow() should be null");
+ is(notification.onerror, null, "onerror() should be null");
+ is(notification.onclose, null, "onclose() should be null");
+ is(typeof notification.close, "function", "close() should exist");
+ is(typeof notification.data, "object", "data should be a JS object");
+
+ is(notification.dir, options.dir, "auto should get set");
+ is(notification.lang, options.lang, "lang should get set");
+ is(notification.body, options.body, "body should get set");
+ is(notification.tag, options.tag, "tag should get set");
+ is(notification.icon, options.icon, "icon should get set");
+ ok(NotificationTest.customDataMatches(notification.data),
+ "data should get set");
+
+ // store notification in test context
+ this.notification = notification;
+
+ notification.onshow = function () {
+ ok(true, "onshow handler should be called");
+ done();
+ };
+ },
+
+ function (done) {
+ info("Test closing a notification");
+ var notification = this.notification;
+
+ notification.onclose = function () {
+ ok(true, "onclose handler should be called");
+ done();
+ };
+
+ notification.close();
+ }
+ ];
+
+ MockServices.register();
+ NotificationTest.run(steps, function () {
+ MockServices.unregister();
+ });
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/notification/test_notification_storage.html b/dom/tests/mochitest/notification/test_notification_storage.html
new file mode 100644
index 000000000..ce5530cb8
--- /dev/null
+++ b/dom/tests/mochitest/notification/test_notification_storage.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Notification Basics</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="MockServices.js"></script>
+ <script type="text/javascript" src="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 deleteAllNotifications(done) {
+ var promise = Notification.get();
+ promise.then(function (notifications) {
+ notifications.forEach(function(notification) {
+ notification.close();
+ });
+ done();
+ });
+ }
+
+ var info = NotificationTest.info;
+
+ var steps = [
+ function (done) {
+ info("Test that Notifcation.get fulfills the promise");
+ var promise = Notification.get();
+ ok(promise.then, "should return a promise");
+
+ // Create a new notification to make sure
+ // Notification.get() works while creating
+ var notification = new Notification("this is a test");
+
+ promise.then(function () {
+ ok(true, "promise should be fulfilled");
+ done();
+ });
+ },
+
+ deleteAllNotifications,
+
+ function (done) {
+ info("Test adding a notification, and making sure get returns it");
+ NotificationTest.allowNotifications();
+ var options = NotificationTest.payload;
+
+ var notification = new Notification("This is a title", options);
+ var promise = Notification.get();
+ promise.then(function (notifications) {
+ ok(notifications.length, "should return notifications");
+ for (var i = 0; i < notifications.length; i++) {
+ var notification = notifications[i];
+ if (notification.tag === options.tag) {
+ ok(true, "should contain newly created notification");
+ for (var key in options) {
+ if (key === "data") {
+ ok(NotificationTest.customDataMatches(notification.data),
+ "data property should match");
+ continue;
+ }
+ is(notification[key], options[key], key + " property should match");
+ }
+ notification.close();
+ return;
+ }
+ }
+ ok(false, "should contain newly created notification");
+ notification.close();
+ });
+ notification.onclose = done;
+ },
+
+ function (done) {
+ info("Testing fetching notification by tag filter");
+ var n1 = new Notification("title1", {tag: "tag1"});
+ var n2 = new Notification("title2", {tag: "tag2"});
+ var n3 = new Notification("title3", {tag: "tag3"});
+ var promise = Notification.get({tag: "tag3"});
+ promise.then(function (notifications) {
+ var notification = notifications[0];
+ is(notifications.length, 1, "should return 1 notification");
+ is(notifications[0].title, "title3", "titles should match");
+ is(notifications[0].tag, "tag3", "tags should match");
+ var closeCount = 0;
+ var waitForAll = function () {
+ if (++closeCount >= 3) {
+ done();
+ }
+ };
+ n1.onclose = waitForAll;
+ n2.onclose = waitForAll;
+ n3.onclose = waitForAll;
+ n1.close();
+ n2.close();
+ n3.close();
+ });
+ },
+
+ deleteAllNotifications,
+
+ function (done) {
+ info("Testing fetching no notifications");
+ var promise = Notification.get();
+ promise.then(function (notifications) {
+ is(notifications.length, 0, "should return 0 notifications");
+ done();
+ });
+ },
+
+ function (done) {
+ info("Testing fetching multiple notifications");
+ var n1 = new Notification("title1");
+ var n2 = new Notification("title2");
+ var n3 = new Notification("title3");
+ var promise = Notification.get();
+ promise.then(function (notifications) {
+ is(notifications.length, 3, "should return 3 notifications");
+ n1.close();
+ n2.close();
+ n3.close();
+ done();
+ });
+ },
+
+ deleteAllNotifications,
+
+ function (done) {
+ info("Testing 'alertfinished' removes the notification from DB");
+ var n = new Notification("test-title" + Math.random());
+ n.onclose = function() {
+ Notification.get().then(function(notifications) {
+ is(notifications.length, 0, "should return 0 notifications");
+ done();
+ });
+ };
+ info("Installing 'onshow' for " + n.title);
+ n.onshow = function() {
+ info("Triggered 'onshow' for " + n.title);
+ window.setTimeout(function() {
+ NotificationTest.fireCloseEvent(n.title);
+ }, 100);
+ };
+ }
+ ];
+
+ MockServices.register();
+ NotificationTest.run(steps, function () {
+ MockServices.unregister();
+ });
+</script>
+</body>
+</html>