diff --git a/browser/modules/test/browser.ini b/browser/modules/test/browser.ini index fabca4b1cf73..364cd218c363 100644 --- a/browser/modules/test/browser.ini +++ b/browser/modules/test/browser.ini @@ -8,8 +8,6 @@ support-files = [browser_BrowserUITelemetry_syncedtabs.js] [browser_CaptivePortalWatcher.js] skip-if = os == "linux" || os == "win" || (os == "mac" && debug && e10s) # Bug 1279491, Bug 1287714 for OS X debug e10s -[browser_ProcessHangNotifications.js] -skip-if = !e10s [browser_ContentSearch.js] support-files = contentSearch.js @@ -17,6 +15,9 @@ support-files = contentSearchSuggestions.sjs contentSearchSuggestions.xml [browser_NetworkPrioritizer.js] +[browser_PermissionUI.js] +[browser_ProcessHangNotifications.js] +skip-if = !e10s [browser_SelfSupportBackend.js] support-files = ../../components/uitour/test/uitour.html diff --git a/browser/modules/test/browser_PermissionUI.js b/browser/modules/test/browser_PermissionUI.js new file mode 100644 index 000000000000..297db3d31780 --- /dev/null +++ b/browser/modules/test/browser_PermissionUI.js @@ -0,0 +1,396 @@ +/** + * These tests test the ability for the PermissionUI module to open + * permission prompts to the user. It also tests to ensure that + * add-ons can introduce their own permission prompts. + */ + +"use strict"; + +Cu.import("resource://gre/modules/Integration.jsm", this); +Cu.import("resource:///modules/PermissionUI.jsm", this); + +/** + * Given a at some non-internal web page, + * return something that resembles an nsIContentPermissionRequest, + * using the browsers currently loaded document to get a principal. + * + * @param browser () + * The browser that we'll create a nsIContentPermissionRequest + * for. + * @returns A nsIContentPermissionRequest-ish object. + */ +function makeMockPermissionRequest(browser) { + let result = { + types: null, + principal: browser.contentPrincipal, + requester: null, + _cancelled: false, + cancel() { + this._cancelled = true; + }, + _allowed: false, + allow() { + this._allowed = true; + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]), + }; + + // In the e10s-case, nsIContentPermissionRequest will have + // element defined. window is defined otherwise. + if (browser.isRemoteBrowser) { + result.element = browser; + } else { + result.window = browser.contentWindow; + } + + return result; +} + +/** + * For an opened PopupNotification, clicks on the main action, + * and waits for the panel to fully close. + * + * @return {Promise} + * Resolves once the panel has fired the "popuphidden" + * event. + */ +function clickMainAction() { + let removePromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden"); + let popupNotification = getPopupNotificationNode(); + popupNotification.button.click(); + return removePromise; +} + +/** + * For an opened PopupNotification, clicks on a secondary action, + * and waits for the panel to fully close. + * + * @param {int} index + * The 0-indexed index of the secondary menuitem to choose. + * @return {Promise} + * Resolves once the panel has fired the "popuphidden" + * event. + */ +function clickSecondaryAction(index) { + let removePromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden"); + let popupNotification = getPopupNotificationNode(); + let menuitems = popupNotification.children; + menuitems[index].click(); + return removePromise; +} + +/** + * Makes sure that 1 (and only 1) is being displayed + * by PopupNotification, and then returns that . + * + * @return {} + */ +function getPopupNotificationNode() { + // PopupNotification is a bit overloaded here, so to be + // clear, popupNotifications is a list of + // nodes. + let popupNotifications = PopupNotifications.panel.childNodes; + Assert.equal(popupNotifications.length, 1, + "Should be showing a "); + return popupNotifications[0]; +} + +/** + * Tests the PermissionPromptForRequest prototype to ensure that a prompt + * can be displayed. Does not test permission handling. + */ +add_task(function* test_permission_prompt_for_request() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "http://example.com/", + }, function*(browser) { + const kTestNotificationID = "test-notification"; + const kTestMessage = "Test message"; + let mainAction = { + label: "Main", + accessKey: "M", + }; + let secondaryAction = { + label: "Secondary", + accessKey: "S", + }; + + let mockRequest = makeMockPermissionRequest(browser); + let TestPrompt = { + __proto__: PermissionUI.PermissionPromptForRequestPrototype, + request: mockRequest, + notificationID: kTestNotificationID, + message: kTestMessage, + promptActions: [mainAction, secondaryAction], + }; + + let shownPromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown"); + TestPrompt.prompt(); + yield shownPromise; + let notification = + PopupNotifications.getNotification(kTestNotificationID, browser); + Assert.ok(notification, "Should have gotten the notification"); + + Assert.equal(notification.message, kTestMessage, + "Should be showing the right message"); + Assert.equal(notification.mainAction.label, mainAction.label, + "The main action should have the right label"); + Assert.equal(notification.mainAction.accessKey, mainAction.accessKey, + "The main action should have the right access key"); + Assert.equal(notification.secondaryActions.length, 1, + "There should only be 1 secondary action"); + Assert.equal(notification.secondaryActions[0].label, secondaryAction.label, + "The secondary action should have the right label"); + Assert.equal(notification.secondaryActions[0].accessKey, + secondaryAction.accessKey, + "The secondary action should have the right access key"); + Assert.ok(notification.options.displayURI.equals(mockRequest.principal.URI), + "Should be showing the URI of the requesting page"); + + let removePromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden"); + notification.remove(); + yield removePromise; + }); +}); + +/** + * Tests that if the PermissionPrompt has the permissionKey + * set that permissions can be set properly by the user. Also + * ensures that callbacks for promptActions are properly fired. + */ +add_task(function* test_with_permission_key() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "http://example.com", + }, function*(browser) { + const kTestNotificationID = "test-notification"; + const kTestMessage = "Test message"; + const kTestPermissionKey = "test-permission-key"; + + let allowed = false; + let mainAction = { + label: "Allow", + accessKey: "M", + action: Ci.nsIPermissionManager.ALLOW_ACTION, + expiryType: Ci.nsIPermissionManager.EXPIRE_SESSION, + callback: function() { + allowed = true; + } + }; + + let denied = false; + let secondaryAction = { + label: "Deny", + accessKey: "D", + action: Ci.nsIPermissionManager.DENY_ACTION, + expiryType: Ci.nsIPermissionManager.EXPIRE_SESSION, + callback: function() { + denied = true; + } + }; + + let mockRequest = makeMockPermissionRequest(browser); + let principal = mockRequest.principal; + registerCleanupFunction(function() { + Services.perms.removeFromPrincipal(principal, kTestPermissionKey); + }); + + let TestPrompt = { + __proto__: PermissionUI.PermissionPromptForRequestPrototype, + request: mockRequest, + notificationID: kTestNotificationID, + permissionKey: kTestPermissionKey, + message: kTestMessage, + promptActions: [mainAction, secondaryAction], + }; + + let shownPromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown"); + TestPrompt.prompt(); + yield shownPromise; + let notification = + PopupNotifications.getNotification(kTestNotificationID, browser); + Assert.ok(notification, "Should have gotten the notification"); + + let curPerm = + Services.perms.testPermissionFromPrincipal(principal, + kTestPermissionKey); + Assert.equal(curPerm, Ci.nsIPermissionManager.UNKNOWN_ACTION, + "Should be no permission set to begin with."); + + // First test denying the permission request. + Assert.equal(notification.secondaryActions.length, 1, + "There should only be 1 secondary action"); + yield clickSecondaryAction(0); + curPerm = Services.perms.testPermissionFromPrincipal(principal, + kTestPermissionKey); + Assert.equal(curPerm, Ci.nsIPermissionManager.DENY_ACTION, + "Should have denied the action"); + Assert.ok(denied, "The secondaryAction callback should have fired"); + Assert.ok(!allowed, "The mainAction callback should not have fired"); + Assert.ok(mockRequest._cancelled, + "The request should have been cancelled"); + Assert.ok(!mockRequest._allowed, + "The request should not have been allowed"); + + // Clear the permission and pretend we never denied + Services.perms.removeFromPrincipal(principal, kTestPermissionKey); + denied = false; + mockRequest._cancelled = false; + + // Bring the PopupNotification back up now... + shownPromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown"); + TestPrompt.prompt(); + yield shownPromise; + + // Next test allowing the permission request. + yield clickMainAction(); + curPerm = Services.perms.testPermissionFromPrincipal(principal, + kTestPermissionKey); + Assert.equal(curPerm, Ci.nsIPermissionManager.ALLOW_ACTION, + "Should have allowed the action"); + Assert.ok(!denied, "The secondaryAction callback should not have fired"); + Assert.ok(allowed, "The mainAction callback should have fired"); + Assert.ok(!mockRequest._cancelled, + "The request should not have been cancelled"); + Assert.ok(mockRequest._allowed, + "The request should have been allowed"); + }); +}); + +/** + * Tests that the onBeforeShow method will be called before + * the popup appears. + */ +add_task(function* test_on_before_show() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "http://example.com", + }, function*(browser) { + const kTestNotificationID = "test-notification"; + const kTestMessage = "Test message"; + + let mainAction = { + label: "Test action", + accessKey: "T", + }; + + let mockRequest = makeMockPermissionRequest(browser); + let beforeShown = false; + + let TestPrompt = { + __proto__: PermissionUI.PermissionPromptForRequestPrototype, + request: mockRequest, + notificationID: kTestNotificationID, + message: kTestMessage, + promptActions: [mainAction], + onBeforeShow() { + beforeShown = true; + } + }; + + let shownPromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown"); + TestPrompt.prompt(); + Assert.ok(beforeShown, "Should have called onBeforeShown"); + yield shownPromise; + let notification = + PopupNotifications.getNotification(kTestNotificationID, browser); + + let removePromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden"); + notification.remove(); + yield removePromise; + }); +}); + +/** + * Tests that we can open a PermissionPrompt without wrapping a + * nsIContentPermissionRequest. + */ +add_task(function* test_no_request() { + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: "http://example.com", + }, function*(browser) { + const kTestNotificationID = "test-notification"; + let allowed = false; + let mainAction = { + label: "Allow", + accessKey: "M", + callback: function() { + allowed = true; + } + }; + + let denied = false; + let secondaryAction = { + label: "Deny", + accessKey: "D", + callback: function() { + denied = true; + } + }; + + const kTestMessage = "Test message with no request"; + let principal = browser.contentPrincipal; + let beforeShown = false; + + let TestPrompt = { + __proto__: PermissionUI.PermissionPromptPrototype, + notificationID: kTestNotificationID, + principal, + browser, + message: kTestMessage, + promptActions: [mainAction, secondaryAction], + onBeforeShow() { + beforeShown = true; + } + }; + + let shownPromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown"); + TestPrompt.prompt(); + Assert.ok(beforeShown, "Should have called onBeforeShown"); + yield shownPromise; + let notification = + PopupNotifications.getNotification(kTestNotificationID, browser); + + Assert.equal(notification.message, kTestMessage, + "Should be showing the right message"); + Assert.equal(notification.mainAction.label, mainAction.label, + "The main action should have the right label"); + Assert.equal(notification.mainAction.accessKey, mainAction.accessKey, + "The main action should have the right access key"); + Assert.equal(notification.secondaryActions.length, 1, + "There should only be 1 secondary action"); + Assert.equal(notification.secondaryActions[0].label, secondaryAction.label, + "The secondary action should have the right label"); + Assert.equal(notification.secondaryActions[0].accessKey, + secondaryAction.accessKey, + "The secondary action should have the right access key"); + Assert.ok(notification.options.displayURI.equals(principal.URI), + "Should be showing the URI of the requesting page"); + + // First test denying the permission request. + Assert.equal(notification.secondaryActions.length, 1, + "There should only be 1 secondary action"); + yield clickSecondaryAction(0); + Assert.ok(denied, "The secondaryAction callback should have fired"); + Assert.ok(!allowed, "The mainAction callback should not have fired"); + + shownPromise = + BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown"); + TestPrompt.prompt(); + yield shownPromise; + + // Next test allowing the permission request. + yield clickMainAction(); + Assert.ok(allowed, "The mainAction callback should have fired"); + }); +});