/**
* 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";
const { PermissionUI } = ChromeUtils.importESModule(
"resource:///modules/PermissionUI.sys.mjs"
);
const { PermissionTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/PermissionTestUtils.sys.mjs"
);
/**
* Tests the PermissionPromptForRequest prototype to ensure that a prompt
* can be displayed. Does not test permission handling.
*/
add_task(async
function test_permission_prompt_for_request() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url:
"http://example.com/",
},
async
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);
class TestPrompt
extends PermissionUI.PermissionPromptForRequest {
get request() {
return mockRequest;
}
get notificationID() {
return kTestNotificationID;
}
get message() {
return kTestMessage;
}
get promptActions() {
return [mainAction, secondaryAction];
}
}
let shownPromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
await 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();
await removePromise;
}
);
});
/**
* Tests that if the PermissionPrompt sets displayURI to false in popupOptions,
* then there is no URI shown on the popupnotification.
*/
add_task(async
function test_permission_prompt_for_popupOptions() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url:
"http://example.com/",
},
async
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);
class TestPrompt
extends PermissionUI.PermissionPromptForRequest {
get request() {
return mockRequest;
}
get notificationID() {
return kTestNotificationID;
}
get message() {
return kTestMessage;
}
get promptActions() {
return [mainAction, secondaryAction];
}
get popupOptions() {
return {
displayURI:
false,
};
}
}
let shownPromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
await shownPromise;
let notification = PopupNotifications.getNotification(
kTestNotificationID,
browser
);
Assert.ok(
!notification.options.displayURI,
"Should not show the URI of the requesting page"
);
let removePromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
notification.remove();
await 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(async
function test_with_permission_key() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url:
"http://example.com",
},
async
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: SitePermissions.ALLOW,
callback() {
allowed =
true;
},
};
let denied =
false;
let secondaryAction = {
label:
"Deny",
accessKey:
"D",
action: SitePermissions.BLOCK,
callback() {
denied =
true;
},
};
let mockRequest = makeMockPermissionRequest(browser);
let principal = mockRequest.principal;
registerCleanupFunction(
function () {
PermissionTestUtils.remove(principal.URI, kTestPermissionKey);
});
class TestPrompt
extends PermissionUI.PermissionPromptForRequest {
get request() {
return mockRequest;
}
get notificationID() {
return kTestNotificationID;
}
get permissionKey() {
return kTestPermissionKey;
}
get message() {
return kTestMessage;
}
get promptActions() {
return [mainAction, secondaryAction];
}
get popupOptions() {
return {
checkbox: {
label:
"Remember this decision",
show:
true,
checked:
true,
},
};
}
}
let shownPromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
await shownPromise;
let notification = PopupNotifications.getNotification(
kTestNotificationID,
browser
);
Assert.ok(notification,
"Should have gotten the notification");
let curPerm = SitePermissions.getForPrincipal(
principal,
kTestPermissionKey,
browser
);
Assert.equal(
curPerm.state,
SitePermissions.UNKNOWN,
"Should be no permission set to begin with."
);
// First test denying the permission request without the checkbox checked.
let popupNotification = getPopupNotificationNode();
popupNotification.checkbox.checked =
false;
Assert.equal(
notification.secondaryActions.length,
1,
"There should only be 1 secondary action"
);
await clickSecondaryAction();
curPerm = SitePermissions.getForPrincipal(
principal,
kTestPermissionKey,
browser
);
Assert.deepEqual(
curPerm,
{
state: SitePermissions.BLOCK,
scope: SitePermissions.SCOPE_TEMPORARY,
},
"Should have denied the action temporarily"
);
// Try getting the permission without passing the browser object (should fail).
curPerm = PermissionTestUtils.getPermissionObject(
principal.URI,
kTestPermissionKey
);
Assert.equal(
curPerm,
null,
"Should have made no permanent permission entry"
);
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
SitePermissions.removeFromPrincipal(
principal,
kTestPermissionKey,
browser
);
denied =
false;
mockRequest._cancelled =
false;
// Bring the PopupNotification back up now...
shownPromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
await shownPromise;
// Test denying the permission request.
Assert.equal(
notification.secondaryActions.length,
1,
"There should only be 1 secondary action"
);
await clickSecondaryAction();
curPerm = PermissionTestUtils.getPermissionObject(
principal.URI,
kTestPermissionKey
);
Assert.equal(
curPerm.capability,
Services.perms.DENY_ACTION,
"Should have denied the action"
);
Assert.equal(curPerm.expireTime, 0,
"Deny should be permanent");
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
PermissionTestUtils.remove(principal.URI, kTestPermissionKey);
denied =
false;
mockRequest._cancelled =
false;
// Bring the PopupNotification back up now...
shownPromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
await shownPromise;
// Test allowing the permission request.
await clickMainAction();
curPerm = PermissionTestUtils.getPermissionObject(
principal.URI,
kTestPermissionKey
);
Assert.equal(
curPerm.capability,
Services.perms.ALLOW_ACTION,
"Should have allowed the action"
);
Assert.equal(curPerm.expireTime, 0,
"Allow should be permanent");
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(async
function test_on_before_show() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url:
"http://example.com",
},
async
function (browser) {
const kTestNotificationID =
"test-notification";
const kTestMessage =
"Test message";
let mainAction = {
label:
"Test action",
accessKey:
"T",
};
let mockRequest = makeMockPermissionRequest(browser);
let beforeShown =
false;
class TestPrompt
extends PermissionUI.PermissionPromptForRequest {
get request() {
return mockRequest;
}
get notificationID() {
return kTestNotificationID;
}
get message() {
return kTestMessage;
}
get promptActions() {
return [mainAction];
}
get popupOptions() {
return {
checkbox: {
label:
"Remember this decision",
show:
true,
checked:
true,
},
};
}
onBeforeShow() {
beforeShown =
true;
return true;
}
}
let shownPromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
Assert.ok(beforeShown,
"Should have called onBeforeShown");
await shownPromise;
let notification = PopupNotifications.getNotification(
kTestNotificationID,
browser
);
let removePromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popuphidden"
);
notification.remove();
await removePromise;
}
);
});
/**
* Tests that we can open a PermissionPrompt without wrapping a
* nsIContentPermissionRequest.
*/
add_task(async
function test_no_request() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url:
"http://example.com",
},
async
function (browser) {
const kTestNotificationID =
"test-notification";
let allowed =
false;
let mainAction = {
label:
"Allow",
accessKey:
"M",
callback() {
allowed =
true;
},
};
let denied =
false;
let secondaryAction = {
label:
"Deny",
accessKey:
"D",
callback() {
denied =
true;
},
};
const kTestMessage =
"Test message with no request";
let principal = browser.contentPrincipal;
let beforeShown =
false;
class TestPrompt
extends PermissionUI.PermissionPromptForRequest {
get notificationID() {
return kTestNotificationID;
}
get principal() {
return principal;
}
get browser() {
return browser;
}
get message() {
return kTestMessage;
}
get promptActions() {
return [mainAction, secondaryAction];
}
onBeforeShow() {
beforeShown =
true;
return true;
}
}
let shownPromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
Assert.ok(beforeShown,
"Should have called onBeforeShown");
await 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"
);
await clickSecondaryAction();
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"
);
new TestPrompt().prompt();
await shownPromise;
// Next test allowing the permission request.
await clickMainAction();
Assert.ok(allowed,
"The mainAction callback should have fired");
}
);
});
/**
* Tests that when the tab is moved to a different window, the notification
* is transferred to the new window.
*/
add_task(async
function test_window_swap() {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url:
"http://example.com",
},
async
function (browser) {
const kTestNotificationID =
"test-notification";
const kTestMessage =
"Test message";
let mainAction = {
label:
"Test action",
accessKey:
"T",
};
let secondaryAction = {
label:
"Secondary",
accessKey:
"S",
};
let mockRequest = makeMockPermissionRequest(browser);
class TestPrompt
extends PermissionUI.PermissionPromptForRequest {
get request() {
return mockRequest;
}
get notificationID() {
return kTestNotificationID;
}
get message() {
return kTestMessage;
}
get promptActions() {
return [mainAction, secondaryAction];
}
}
let shownPromise = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
await shownPromise;
let newWindowOpened = BrowserTestUtils.waitForNewWindow();
gBrowser.replaceTabWithWindow(gBrowser.selectedTab);
let newWindow = await newWindowOpened;
// We may have already opened the panel, because it was open before we moved the tab.
if (newWindow.PopupNotifications.panel.state !=
"open") {
shownPromise = BrowserTestUtils.waitForEvent(
newWindow.PopupNotifications.panel,
"popupshown"
);
new TestPrompt().prompt();
await shownPromise;
}
let notification = newWindow.PopupNotifications.getNotification(
kTestNotificationID,
newWindow.gBrowser.selectedBrowser
);
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"
);
await BrowserTestUtils.closeWindow(newWindow);
}
);
});