diff options
Diffstat (limited to 'browser/base/content/test/alerts')
11 files changed, 573 insertions, 0 deletions
diff --git a/browser/base/content/test/alerts/.eslintrc.js b/browser/base/content/test/alerts/.eslintrc.js new file mode 100644 index 000000000..7c8021192 --- /dev/null +++ b/browser/base/content/test/alerts/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + "extends": [ + "../../../../../testing/mochitest/browser.eslintrc.js" + ] +}; diff --git a/browser/base/content/test/alerts/browser.ini b/browser/base/content/test/alerts/browser.ini new file mode 100644 index 000000000..07fcf5253 --- /dev/null +++ b/browser/base/content/test/alerts/browser.ini @@ -0,0 +1,12 @@ +[DEFAULT] +support-files = + head.js + file_dom_notifications.html + +[browser_notification_close.js] +[browser_notification_do_not_disturb.js] +[browser_notification_open_settings.js] +[browser_notification_remove_permission.js] +[browser_notification_permission_migration.js] +[browser_notification_replace.js] +[browser_notification_tab_switching.js] diff --git a/browser/base/content/test/alerts/browser_notification_close.js b/browser/base/content/test/alerts/browser_notification_close.js new file mode 100644 index 000000000..bbd444212 --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_close.js @@ -0,0 +1,71 @@ +"use strict"; + +const {PlacesTestUtils} = + Cu.import("resource://testing-common/PlacesTestUtils.jsm", {}); + +let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; +let oldShowFavicons; + +add_task(function* test_notificationClose() { + let pm = Services.perms; + let notificationURI = makeURI(notificationURL); + pm.add(notificationURI, "desktop-notification", pm.ALLOW_ACTION); + + oldShowFavicons = Services.prefs.getBoolPref("alerts.showFavicons"); + Services.prefs.setBoolPref("alerts.showFavicons", true); + + yield PlacesTestUtils.addVisits(notificationURI); + let faviconURI = yield new Promise(resolve => { + let faviconURI = makeURI("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC"); + PlacesUtils.favicons.setAndFetchFaviconForPage(notificationURI, faviconURI, + true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, + (faviconURI, iconSize, iconData, mimeType) => resolve(faviconURI), + Services.scriptSecurityManager.getSystemPrincipal()); + }); + + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: notificationURL + }, function* dummyTabTask(aBrowser) { + yield openNotification(aBrowser, "showNotification2"); + + info("Notification alert showing"); + + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + yield closeNotification(aBrowser); + return; + } + + let alertTitleLabel = alertWindow.document.getElementById("alertTitleLabel"); + is(alertTitleLabel.value, "Test title", "Title text of notification should be present"); + let alertTextLabel = alertWindow.document.getElementById("alertTextLabel"); + is(alertTextLabel.textContent, "Test body 2", "Body text of notification should be present"); + let alertIcon = alertWindow.document.getElementById("alertIcon"); + is(alertIcon.src, faviconURI.spec, "Icon of notification should be present"); + + let alertCloseButton = alertWindow.document.querySelector(".alertCloseButton"); + is(alertCloseButton.localName, "toolbarbutton", "close button found"); + let promiseBeforeUnloadEvent = + BrowserTestUtils.waitForEvent(alertWindow, "beforeunload"); + let closedTime = alertWindow.Date.now(); + alertCloseButton.click(); + info("Clicked on close button"); + yield promiseBeforeUnloadEvent; + + ok(true, "Alert should close when the close button is clicked"); + let currentTime = alertWindow.Date.now(); + // The notification will self-close at 12 seconds, so this checks + // that the notification closed before the timeout. + ok(currentTime - closedTime < 5000, + "Close requested at " + closedTime + ", actually closed at " + currentTime); + }); +}); + +add_task(function* cleanup() { + Services.perms.remove(makeURI(notificationURL), "desktop-notification"); + if (typeof oldShowFavicons == "boolean") { + Services.prefs.setBoolPref("alerts.showFavicons", oldShowFavicons); + } +}); diff --git a/browser/base/content/test/alerts/browser_notification_do_not_disturb.js b/browser/base/content/test/alerts/browser_notification_do_not_disturb.js new file mode 100644 index 000000000..92c689fd2 --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_do_not_disturb.js @@ -0,0 +1,80 @@ +"use strict"; + +var tab; +var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; + +const ALERT_SERVICE = Cc["@mozilla.org/alerts-service;1"] + .getService(Ci.nsIAlertsService) + .QueryInterface(Ci.nsIAlertsDoNotDisturb); + +function test () { + waitForExplicitFinish(); + + try { + // Only run the test if the do-not-disturb + // interface has been implemented. + ALERT_SERVICE.manualDoNotDisturb; + ok(true, "Alert service implements do-not-disturb interface"); + } catch (e) { + ok(true, "Alert service doesn't implement do-not-disturb interface, exiting test"); + finish(); + return; + } + + let pm = Services.perms; + registerCleanupFunction(function() { + ALERT_SERVICE.manualDoNotDisturb = false; + pm.remove(makeURI(notificationURL), "desktop-notification"); + gBrowser.removeTab(tab); + window.restore(); + }); + + pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION); + + // Make sure that do-not-disturb is not enabled. + ok(!ALERT_SERVICE.manualDoNotDisturb, "Alert service should not be disabled when test starts"); + ALERT_SERVICE.manualDoNotDisturb = false; + + tab = gBrowser.addTab(notificationURL); + gBrowser.selectedTab = tab; + tab.linkedBrowser.addEventListener("load", onLoad, true); +} + +function onLoad() { + tab.linkedBrowser.removeEventListener("load", onLoad, true); + openNotification(tab.linkedBrowser, "showNotification2").then(onAlertShowing); +} + +function onAlertShowing() { + info("Notification alert showing"); + + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + closeNotification(tab.linkedBrowser).then(finish); + return; + } + let doNotDisturbMenuItem = alertWindow.document.getElementById("doNotDisturbMenuItem"); + is(doNotDisturbMenuItem.localName, "menuitem", "menuitem found"); + alertWindow.addEventListener("beforeunload", onAlertClosing); + doNotDisturbMenuItem.click(); + info("Clicked on do-not-disturb menuitem"); +} + +function onAlertClosing(event) { + event.target.removeEventListener("beforeunload", onAlertClosing); + + ok(ALERT_SERVICE.manualDoNotDisturb, "Alert service should be disabled after clicking menuitem"); + + // The notification should not appear, but there is + // no way from the client-side to know that it was + // blocked, except for waiting some time and realizing + // that the "onshow" event never fired. + openNotification(tab.linkedBrowser, "showNotification2", 2000) + .then(onAlert2Showing, finish); +} + +function onAlert2Showing() { + ok(false, "the second alert should not have been shown"); + closeNotification(tab.linkedBrowser).then(finish); +} diff --git a/browser/base/content/test/alerts/browser_notification_open_settings.js b/browser/base/content/test/alerts/browser_notification_open_settings.js new file mode 100644 index 000000000..5306fd90a --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_open_settings.js @@ -0,0 +1,58 @@ +"use strict"; + +var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; + +add_task(function* test_settingsOpen_observer() { + info("Opening a dummy tab so openPreferences=>switchToTabHavingURI doesn't use the blank tab."); + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "about:robots" + }, function* dummyTabTask(aBrowser) { + let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#content"); + info("simulate a notifications-open-settings notification"); + let uri = NetUtil.newURI("https://example.com"); + let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); + Services.obs.notifyObservers(principal, "notifications-open-settings", null); + let tab = yield tabPromise; + ok(tab, "The notification settings tab opened"); + yield BrowserTestUtils.removeTab(tab); + }); +}); + +add_task(function* test_settingsOpen_button() { + let pm = Services.perms; + info("Adding notification permission"); + pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION); + + try { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: notificationURL + }, function* tabTask(aBrowser) { + info("Waiting for notification"); + yield openNotification(aBrowser, "showNotification2"); + + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + yield closeNotification(aBrowser); + return; + } + + let closePromise = promiseWindowClosed(alertWindow); + let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:preferences#content"); + let openSettingsMenuItem = alertWindow.document.getElementById("openSettingsMenuItem"); + openSettingsMenuItem.click(); + + info("Waiting for notification settings tab"); + let tab = yield tabPromise; + ok(tab, "The notification settings tab opened"); + + yield closePromise; + yield BrowserTestUtils.removeTab(tab); + }); + } finally { + info("Removing notification permission"); + pm.remove(makeURI(notificationURL), "desktop-notification"); + } +}); diff --git a/browser/base/content/test/alerts/browser_notification_permission_migration.js b/browser/base/content/test/alerts/browser_notification_permission_migration.js new file mode 100644 index 000000000..b015e59a7 --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_permission_migration.js @@ -0,0 +1,45 @@ +const UI_VERSION = 32; + +var gBrowserGlue = Cc["@mozilla.org/browser/browserglue;1"] + .getService(Ci.nsIObserver); +var notificationURI = makeURI("http://example.org"); +var pm = Services.perms; +var currentUIVersion; + +add_task(function* setup() { + currentUIVersion = Services.prefs.getIntPref("browser.migration.version"); + Services.prefs.setIntPref("browser.migration.version", UI_VERSION - 1); + pm.add(notificationURI, "desktop-notification", pm.ALLOW_ACTION); +}); + +add_task(function* test_permissionMigration() { + if ("@mozilla.org/system-alerts-service;1" in Cc) { + ok(true, "Notifications don't use XUL windows on all platforms."); + return; + } + + info("Waiting for migration notification"); + let alertWindowPromise = promiseAlertWindow(); + gBrowserGlue.observe(null, "browser-glue-test", "force-ui-migration"); + let alertWindow = yield alertWindowPromise; + + info("Clicking on notification"); + let url = + Services.urlFormatter.formatURLPref("app.support.baseURL") + + "push#w_upgraded-notifications"; + let closePromise = promiseWindowClosed(alertWindow); + let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, url); + EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), {}, alertWindow); + + info("Waiting for migration info tab"); + let tab = yield tabPromise; + ok(tab, "The migration info tab opened"); + + yield closePromise; + yield BrowserTestUtils.removeTab(tab); +}); + +add_task(function* cleanup() { + Services.prefs.setIntPref("browser.migration.version", currentUIVersion); + pm.remove(notificationURI, "desktop-notification"); +}); diff --git a/browser/base/content/test/alerts/browser_notification_remove_permission.js b/browser/base/content/test/alerts/browser_notification_remove_permission.js new file mode 100644 index 000000000..bd36faeae --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_remove_permission.js @@ -0,0 +1,72 @@ +"use strict"; + +var tab; +var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; +var alertWindowClosed = false; +var permRemoved = false; + +function test () { + waitForExplicitFinish(); + + let pm = Services.perms; + registerCleanupFunction(function() { + pm.remove(makeURI(notificationURL), "desktop-notification"); + gBrowser.removeTab(tab); + window.restore(); + }); + + pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION); + + tab = gBrowser.addTab(notificationURL); + gBrowser.selectedTab = tab; + tab.linkedBrowser.addEventListener("load", onLoad, true); +} + +function onLoad() { + tab.linkedBrowser.removeEventListener("load", onLoad, true); + openNotification(tab.linkedBrowser, "showNotification2").then(onAlertShowing); +} + +function onAlertShowing() { + info("Notification alert showing"); + + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + closeNotification(tab.linkedBrowser).then(finish); + return; + } + ok(Services.perms.testExactPermission(makeURI(notificationURL), "desktop-notification"), + "Permission should exist prior to removal"); + let disableForOriginMenuItem = alertWindow.document.getElementById("disableForOriginMenuItem"); + is(disableForOriginMenuItem.localName, "menuitem", "menuitem found"); + Services.obs.addObserver(permObserver, "perm-changed", false); + alertWindow.addEventListener("beforeunload", onAlertClosing); + disableForOriginMenuItem.click(); + info("Clicked on disable-for-origin menuitem") +} + +function permObserver(subject, topic, data) { + if (topic != "perm-changed") { + return; + } + + let permission = subject.QueryInterface(Ci.nsIPermission); + is(permission.type, "desktop-notification", "desktop-notification permission changed"); + is(data, "deleted", "desktop-notification permission deleted"); + + Services.obs.removeObserver(permObserver, "perm-changed"); + permRemoved = true; + if (alertWindowClosed) { + finish(); + } +} + +function onAlertClosing(event) { + event.target.removeEventListener("beforeunload", onAlertClosing); + + alertWindowClosed = true; + if (permRemoved) { + finish(); + } +} diff --git a/browser/base/content/test/alerts/browser_notification_replace.js b/browser/base/content/test/alerts/browser_notification_replace.js new file mode 100644 index 000000000..e678dc438 --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_replace.js @@ -0,0 +1,38 @@ +"use strict"; + +let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; + +add_task(function* test_notificationReplace() { + let pm = Services.perms; + pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION); + + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: notificationURL + }, function* dummyTabTask(aBrowser) { + yield ContentTask.spawn(aBrowser, {}, function* () { + let win = content.window.wrappedJSObject; + let notification = win.showNotification1(); + let promiseCloseEvent = ContentTaskUtils.waitForEvent(notification, "close"); + + let showEvent = yield ContentTaskUtils.waitForEvent(notification, "show"); + Assert.equal(showEvent.target.body, "Test body 1", "Showed tagged notification"); + + let newNotification = win.showNotification2(); + let newShowEvent = yield ContentTaskUtils.waitForEvent(newNotification, "show"); + Assert.equal(newShowEvent.target.body, "Test body 2", "Showed new notification with same tag"); + + let closeEvent = yield promiseCloseEvent; + Assert.equal(closeEvent.target.body, "Test body 1", "Closed previous tagged notification"); + + let promiseNewCloseEvent = ContentTaskUtils.waitForEvent(newNotification, "close"); + newNotification.close(); + let newCloseEvent = yield promiseNewCloseEvent; + Assert.equal(newCloseEvent.target.body, "Test body 2", "Closed new notification"); + }); + }); +}); + +add_task(function* cleanup() { + Services.perms.remove(makeURI(notificationURL), "desktop-notification"); +}); diff --git a/browser/base/content/test/alerts/browser_notification_tab_switching.js b/browser/base/content/test/alerts/browser_notification_tab_switching.js new file mode 100644 index 000000000..7e46c0722 --- /dev/null +++ b/browser/base/content/test/alerts/browser_notification_tab_switching.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +"use strict"; + +var tab; +var notification; +var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html"; +var newWindowOpenedFromTab; + +add_task(function* test_notificationPreventDefaultAndSwitchTabs() { + let pm = Services.perms; + pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION); + + let originalTab = gBrowser.selectedTab; + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: notificationURL + }, function* dummyTabTask(aBrowser) { + // Put new tab in background so it is obvious when it is re-focused. + yield BrowserTestUtils.switchTab(gBrowser, originalTab); + isnot(gBrowser.selectedBrowser, aBrowser, "Notification page loaded as a background tab"); + + // First, show a notification that will be have the tab-switching prevented. + function promiseNotificationEvent(evt) { + return ContentTask.spawn(aBrowser, evt, function* (evt) { + return yield new Promise(resolve => { + let notification = content.wrappedJSObject._notification; + notification.addEventListener(evt, function l(event) { + notification.removeEventListener(evt, l); + resolve({ defaultPrevented: event.defaultPrevented }); + }); + }); + }); + } + yield openNotification(aBrowser, "showNotification1"); + info("Notification alert showing"); + let alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + if (!alertWindow) { + ok(true, "Notifications don't use XUL windows on all platforms."); + yield closeNotification(aBrowser); + return; + } + info("Clicking on notification"); + let promiseClickEvent = promiseNotificationEvent("click"); + + // NB: This executeSoon is needed to allow the non-e10s runs of this test + // a chance to set the event listener on the page. Otherwise, we + // synchronously fire the click event before we listen for the event. + executeSoon(() => { + EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), + {}, alertWindow); + }); + let clickEvent = yield promiseClickEvent; + ok(clickEvent.defaultPrevented, "The event handler for the first notification cancels the event"); + isnot(gBrowser.selectedBrowser, aBrowser, "Notification page still a background tab"); + let notificationClosed = promiseNotificationEvent("close"); + yield closeNotification(aBrowser); + yield notificationClosed; + + // Second, show a notification that will cause the tab to get switched. + yield openNotification(aBrowser, "showNotification2"); + alertWindow = Services.wm.getMostRecentWindow("alert:alert"); + let promiseTabSelect = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabSelect"); + EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), + {}, + alertWindow); + yield promiseTabSelect; + is(gBrowser.selectedBrowser.currentURI.spec, notificationURL, + "Clicking on the second notification should select its originating tab"); + notificationClosed = promiseNotificationEvent("close"); + yield closeNotification(aBrowser); + yield notificationClosed; + }); +}); + +add_task(function* cleanup() { + Services.perms.remove(makeURI(notificationURL), "desktop-notification"); +}); diff --git a/browser/base/content/test/alerts/file_dom_notifications.html b/browser/base/content/test/alerts/file_dom_notifications.html new file mode 100644 index 000000000..6deede8fc --- /dev/null +++ b/browser/base/content/test/alerts/file_dom_notifications.html @@ -0,0 +1,39 @@ +<html> +<head> +<meta charset="utf-8"> +<script> +"use strict"; + +function showNotification1() { + var options = { + dir: undefined, + lang: undefined, + body: "Test body 1", + tag: "Test tag", + icon: undefined, + }; + var n = new Notification("Test title", options); + n.addEventListener("click", function(event) { + event.preventDefault(); + }); + return n; +} + +function showNotification2() { + var options = { + dir: undefined, + lang: undefined, + body: "Test body 2", + tag: "Test tag", + icon: undefined, + }; + return new Notification("Test title", options); +} +</script> +</head> +<body> +<form id="notificationForm" onsubmit="showNotification();"> + <input type="submit" value="Show notification" id="submit"/> +</form> +</body> +</html> diff --git a/browser/base/content/test/alerts/head.js b/browser/base/content/test/alerts/head.js new file mode 100644 index 000000000..21257de31 --- /dev/null +++ b/browser/base/content/test/alerts/head.js @@ -0,0 +1,71 @@ +function promiseAlertWindow() { + return new Promise(function(resolve) { + let listener = { + onOpenWindow(window) { + let alertWindow = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); + alertWindow.addEventListener("load", function onLoad() { + alertWindow.removeEventListener("load", onLoad); + let windowType = alertWindow.document.documentElement.getAttribute("windowtype"); + if (windowType != "alert:alert") { + return; + } + Services.wm.removeListener(listener); + resolve(alertWindow); + }); + }, + }; + Services.wm.addListener(listener); + }); +} + +/** + * Similar to `BrowserTestUtils.closeWindow`, but + * doesn't call `window.close()`. + */ +function promiseWindowClosed(window) { + return new Promise(function(resolve) { + Services.ww.registerNotification(function observer(subject, topic, data) { + if (topic == "domwindowclosed" && subject == window) { + Services.ww.unregisterNotification(observer); + resolve(); + } + }); + }); +} + +/** + * These two functions work with file_dom_notifications.html to open the + * notification and close it. + * + * |fn| can be showNotification1 or showNotification2. + * if |timeout| is passed, then the promise returned from this function is + * rejected after the requested number of miliseconds. + */ +function openNotification(aBrowser, fn, timeout) { + return ContentTask.spawn(aBrowser, { fn, timeout }, function* ({ fn, timeout }) { + let win = content.wrappedJSObject; + let notification = win[fn](); + win._notification = notification; + yield new Promise((resolve, reject) => { + function listener() { + notification.removeEventListener("show", listener); + resolve(); + } + + notification.addEventListener("show", listener); + + if (timeout) { + content.setTimeout(() => { + notification.removeEventListener("show", listener); + reject("timed out"); + }, timeout); + } + }); + }); +} + +function closeNotification(aBrowser) { + return ContentTask.spawn(aBrowser, null, function() { + content.wrappedJSObject._notification.close(); + }); +} |