Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'linux' && os_version == '18.04' && asan OR os == 'linux' && os_version == '18.04' && tsan OR win11_2009 && asan
- Manifest: browser/components/preferences/tests/browser.toml
/* Any copyright is dedicated to the Public Domain.
/**
* First Test
* Checks if buttons are disabled/enabled and visible/hidden correctly.
*/
add_task(async function testButtons() {
// Let's make sure HTTPS-Only and HTTPS-First Mode is off.
await setHttpsOnlyPref("off");
await setHttpsFirstPref("off");
// Open the privacy-pane in about:preferences
await openPreferencesViaOpenPreferencesAPI("panePrivacy", {
leaveOpen: true,
});
// Get button-element to open the exceptions-dialog
const exceptionButton = gBrowser.contentDocument.getElementById(
"httpsOnlyExceptionButton"
);
is(
exceptionButton.disabled,
true,
"HTTPS-Only exception button should be disabled when HTTPS-Only Mode is disabled."
);
await setHttpsOnlyPref("private");
is(
exceptionButton.disabled,
false,
"HTTPS-Only exception button should be enabled when HTTPS-Only Mode is only enabled in private browsing."
);
await setHttpsOnlyPref("everywhere");
is(
exceptionButton.disabled,
false,
"HTTPS-Only exception button should be enabled when HTTPS-Only Mode enabled everywhere."
);
await setHttpsOnlyPref("off");
is(
exceptionButton.disabled,
true,
"Turning off HTTPS-Only should disable the exception button again."
);
await setHttpsFirstPref("private");
is(
exceptionButton.disabled,
false,
"HTTPS-Only exception button should be enabled when HTTPS-Only Mode is disabled and HTTPS-First Mode is only enabled in private browsing."
);
await setHttpsFirstPref("everywhere");
is(
exceptionButton.disabled,
false,
"HTTPS-Only exception button should be enabled when HTTPS-Only Mode is disabled and HTTPS-First Mode enabled everywhere."
);
// Now that the button is clickable, we open the dialog
// to check if the correct buttons are visible
let promiseSubDialogLoaded = promiseLoadSubDialog(
"chrome://browser/content/preferences/dialogs/permissions.xhtml"
);
exceptionButton.doCommand();
let win = await promiseSubDialogLoaded;
const dialogDoc = win.document;
is(
dialogDoc.getElementById("btnBlock").hidden,
true,
"Block button should not be visible in HTTPS-Only Dialog."
);
is(
dialogDoc.getElementById("btnCookieSession").hidden,
true,
"Cookie specific allow button should not be visible in HTTPS-Only Dialog."
);
is(
dialogDoc.getElementById("btnAllow").hidden,
true,
"Allow button should not be visible in HTTPS-Only Dialog."
);
is(
dialogDoc.getElementById("btnHttpsOnlyOff").hidden,
false,
"HTTPS-Only off button should be visible in HTTPS-Only Dialog."
);
is(
dialogDoc.getElementById("btnHttpsOnlyOffTmp").hidden,
false,
"HTTPS-Only temporary off button should be visible in HTTPS-Only Dialog."
);
// Reset prefs and close the tab
await SpecialPowers.flushPrefEnv();
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
/**
* Second Test
* Checks permissions are added and removed correctly.
*
* Each test opens a new dialog, performs an action (second argument),
* then closes the dialog and checks if the changes were made (third argument).
*/
add_task(async function checkDialogFunctionality() {
// Enable HTTPS-Only Mode for every window, so the exceptions dialog is accessible.
await setHttpsOnlyPref("everywhere");
// Open the privacy-pane in about:preferences
await openPreferencesViaOpenPreferencesAPI("panePrivacy", {
leaveOpen: true,
});
const preferencesDoc = gBrowser.contentDocument;
// Test if we can add permanent exceptions
await runTest(
preferencesDoc,
elements => {
assertListContents(elements, []);
elements.url.value = "test.com";
elements.btnAllow.doCommand();
},
() => [
{
type: "https-only-load-insecure",
data: "added",
capability: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: Ci.nsIPermissionManager.EXPIRE_NEVER,
},
]
);
// Test if items are retained, and if temporary exceptions are added correctly
await runTest(
preferencesDoc,
elements => {
elements.url.value = "1.1.1.1:8080";
elements.btnAllowSession.doCommand();
assertListContents(elements, [
]);
},
() => [
{
type: "https-only-load-insecure",
data: "added",
capability: Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION,
expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
},
]
);
// Test if we can remove the permissions one-by-one
await runTest(
preferencesDoc,
elements => {
while (elements.richlistbox.itemCount) {
elements.richlistbox.selectedIndex = 0;
elements.btnRemove.doCommand();
}
assertListContents(elements, []);
},
elements => {
let richlistItems = elements.richlistbox.getElementsByAttribute(
"origin",
"*"
);
let observances = [];
for (let item of richlistItems) {
observances.push({
type: "https-only-load-insecure",
origin: item.getAttribute("origin"),
data: "deleted",
});
}
return observances;
}
);
// Test if all inputs with an https scheme are added with an http scheme,
await runTest(
preferencesDoc,
elements => {
assertListContents(elements, []);
elements.btnAllow.doCommand();
elements.btnAllow.doCommand();
elements.btnAllow.doCommand();
assertListContents(elements, [
]);
elements.btnAllow.doCommand();
assertListContents(elements, [
]);
},
() => [
{
type: "https-only-load-insecure",
data: "added",
capability: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: Ci.nsIPermissionManager.EXPIRE_NEVER,
},
{
type: "https-only-load-insecure",
data: "added",
capability: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: Ci.nsIPermissionManager.EXPIRE_NEVER,
},
{
type: "https-only-load-insecure",
data: "added",
capability: Ci.nsIPermissionManager.ALLOW_ACTION,
expireType: Ci.nsIPermissionManager.EXPIRE_NEVER,
},
]
);
// Test if we can remove all permissions at once
await runTest(
preferencesDoc,
elements => {
elements.btnRemoveAll.doCommand();
assertListContents(elements, []);
},
elements => {
let richlistItems = elements.richlistbox.getElementsByAttribute(
"origin",
"*"
);
let observances = [];
for (let item of richlistItems) {
observances.push({
type: "https-only-load-insecure",
origin: item.getAttribute("origin"),
data: "deleted",
});
}
return observances;
}
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
/**
* Changes HTTPS-Only Mode pref
* @param {string} state "everywhere", "private", "off"
*/
async function setHttpsOnlyPref(state) {
await SpecialPowers.pushPrefEnv({
set: [
["dom.security.https_only_mode", state === "everywhere"],
["dom.security.https_only_mode_pbm", state === "private"],
],
});
}
/**
* Changes HTTPS-First Mode pref
* @param {string} state "everywhere", "private", "off"
*/
async function setHttpsFirstPref(state) {
await SpecialPowers.pushPrefEnv({
set: [
["dom.security.https_first", state === "everywhere"],
["dom.security.https_first_pbm", state === "private"],
],
});
}
/**
* Opens new exceptions dialog, runs test function
* @param {HTMLElement} preferencesDoc document of about:preferences tab
* @param {function} test function to call when dialog is open
* @param {Array} observances permission changes to observe (order is important)
*/
async function runTest(preferencesDoc, test, observancesFn) {
// Click on exception-button and wait for dialog to open
let promiseSubDialogLoaded = promiseLoadSubDialog(
"chrome://browser/content/preferences/dialogs/permissions.xhtml"
);
preferencesDoc.getElementById("httpsOnlyExceptionButton").doCommand();
let win = await promiseSubDialogLoaded;
// Create a bunch of references to UI-elements for the test-function
const doc = win.document;
let elements = {
richlistbox: doc.getElementById("permissionsBox"),
url: doc.getElementById("url"),
btnAllow: doc.getElementById("btnHttpsOnlyOff"),
btnAllowSession: doc.getElementById("btnHttpsOnlyOffTmp"),
btnRemove: doc.getElementById("removePermission"),
btnRemoveAll: doc.getElementById("removeAllPermissions"),
allowL10nId: win.gPermissionManager._getCapabilityL10nId(
Ci.nsIPermissionManager.ALLOW_ACTION
),
allowSessionL10nId: win.gPermissionManager._getCapabilityL10nId(
Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION
),
};
// Some observances need to be computed based on the current state.
const observances = observancesFn(elements);
// Run test function
await test(elements);
// Click on "Save changes" and wait for permission changes.
let btnApplyChanges = doc.querySelector("dialog").getButton("accept");
let observeAllPromise = createObserveAllPromise(observances);
btnApplyChanges.doCommand();
await observeAllPromise;
}
function assertListContents(elements, expected) {
is(
elements.richlistbox.itemCount,
expected.length,
"Richlistbox should match the expected amount of exceptions."
);
for (let i = 0; i < expected.length; i++) {
let website = expected[i][0];
let listItem = elements.richlistbox.getElementsByAttribute(
"origin",
website
);
is(listItem.length, 1, "Each origin should be unique");
is(
listItem[0]
.querySelector(".website-capability-value")
.getAttribute("data-l10n-id"),
expected[i][1],
"List item capability should match expected l10n-id"
);
}
}