Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Errors
- This test gets skipped with pattern: (os == 'win' && (asan || debug))
- This test failed 99 times in the preceding 30 days. quicksearch this test
- Manifest: toolkit/components/aboutthirdparty/tests/browser/browser.toml
/* 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
// Return card containers matching a given name
function getCardsByName(aContainer, aLeafName) {
const matchedCards = [];
const allCards = aContainer.querySelectorAll(".card");
for (const card of allCards) {
const nameLabel = card.querySelector(".module-name");
if (nameLabel.textContent == aLeafName) {
matchedCards.push(card);
}
}
return matchedCards;
}
function getDetailRow(aContainer, aLabel) {
return aContainer.querySelector(`[data-l10n-id=${aLabel}]`).parentElement;
}
function verifyClipboardData(aModuleJson) {
Assert.ok(
aModuleJson.hasOwnProperty("blocked"),
"Clipboard data should have blocked property."
);
const blocked = aModuleJson.blocked.filter(
x => x.name == kUserBlockedModuleName
);
Assert.equal(
blocked.length,
1,
"Blocked array should contain the blocked module one time."
);
Assert.ok(
aModuleJson.hasOwnProperty("modules"),
"Clipboard data should have modules property"
);
let aModuleArray = aModuleJson.modules;
const filtered = aModuleArray.filter(x => x.name == kExtensionModuleName);
Assert.equal(filtered.length, 1, "No duplicate data for the module.");
const kDeletedPropertiesOfModule = [
"application",
"dllFile",
"loadingOnMain",
"trustFlags",
];
const kDeletedPropertiesOfLoadingEvent = [
"baseAddress",
"isDependent",
"mainThread",
"moduleIndex",
"processUptimeMS",
];
for (const module of aModuleArray) {
for (const deletedProperty of kDeletedPropertiesOfModule) {
Assert.ok(
!module.hasOwnProperty(deletedProperty),
`The property \`${deletedProperty}\` is deleted.`
);
}
Assert.ok(
!module.hasOwnProperty("typeFlags") || module.typeFlags != 0,
"typeFlags does not exist or is non-zero."
);
for (const event of module.events) {
for (const deletedProperty of kDeletedPropertiesOfLoadingEvent) {
Assert.ok(
!event.hasOwnProperty(deletedProperty),
`The property \`${deletedProperty}\` is deleted.`
);
}
}
}
}
function verifyModuleSorting(compareFunc) {
const uninteresting = {
typeFlags: 0,
isCrasher: false,
loadingOnMain: 0,
};
const crasherNotBlocked = { ...uninteresting, isCrasher: true };
const crasherBlocked = {
...uninteresting,
isCrasher: true,
typeFlags: Ci.nsIAboutThirdParty.ModuleType_BlockedByUserAtLaunch,
};
const justBlocked = {
...uninteresting,
typeFlags: Ci.nsIAboutThirdParty.ModuleType_BlockedByUserAtLaunch,
};
const uninterestingButSlow = {
...uninteresting,
loadingOnMain: 10,
};
let modules = [
uninteresting,
uninterestingButSlow,
crasherNotBlocked,
justBlocked,
crasherBlocked,
];
modules.sort(compareFunc);
Assert.equal(
JSON.stringify([
crasherBlocked,
justBlocked,
crasherNotBlocked,
uninterestingButSlow,
uninteresting,
]),
JSON.stringify(modules),
"Modules sort in expected order"
);
}
add_task(async () => {
registerCleanupFunction(() => {
unregisterAll();
});
await registerObject();
registerExtensions();
loadShellExtension();
await kATP.collectSystemInfo();
Assert.equal(
kATP.lookupModuleType(kExtensionModuleName),
Ci.nsIAboutThirdParty.ModuleType_ShellExtension,
"lookupModuleType() returns a correct type " +
"after system info was collected."
);
await BrowserTestUtils.withNewTab("about:third-party", async () => {
if (!content.fetchDataDone) {
const mainDiv = content.document.getElementById("main");
await BrowserTestUtils.waitForMutationCondition(
mainDiv,
{ childList: true },
() => mainDiv.childElementCount > 0
);
Assert.ok(content.fetchDataDone, "onLoad() is completed.");
}
const reload = content.document.getElementById("button-reload");
if (!reload.hidden) {
reload.click();
await BrowserTestUtils.waitForMutationCondition(
reload,
{ attributes: true, attributeFilter: ["hidden"] },
() => reload.hidden
);
}
Assert.ok(
content.document.getElementById("no-data").hidden,
"The no-data message is hidden."
);
const blockedCards = getCardsByName(
content.document,
kUserBlockedModuleName
);
Assert.equal(
blockedCards.length,
1,
"Only one card matching the blocked module exists."
);
const blockedCard = blockedCards[0];
Assert.equal(
blockedCard.querySelectorAll(".button-block.module-blocked").length,
1,
"The blocked module has a button indicating it is blocked"
);
let blockedBlockButton = blockedCard.querySelector(
".button-block.module-blocked"
);
Assert.equal(
blockedBlockButton.getAttribute("data-l10n-id"),
"third-party-button-to-unblock-module",
"Button to block the module has correct title"
);
blockedBlockButton.click();
await BrowserTestUtils.promiseAlertDialogOpen("cancel");
Assert.ok(
!blockedBlockButton.classList.contains("module-blocked"),
"After clicking to unblock a module, button should not have module-blocked class."
);
Assert.equal(
blockedBlockButton.getAttribute("data-l10n-id"),
"third-party-button-to-block-module",
"After clicking to unblock a module, button should have correct title."
);
// Restore this to blocked for later tests
blockedBlockButton.click();
await BrowserTestUtils.promiseAlertDialogOpen("cancel");
Assert.ok(
blockedBlockButton.classList.contains("module-blocked"),
"After clicking to block a module, button should have module-blocked class."
);
Assert.equal(
blockedBlockButton.getAttribute("data-l10n-id"),
"third-party-button-to-unblock-module",
"After clicking to block a module, button should have correct title."
);
const cards = getCardsByName(content.document, kExtensionModuleName);
Assert.equal(cards.length, 1, "Only one card matching the module exists.");
const card = cards[0];
const blockButton = card.querySelector(".button-block");
Assert.ok(
!blockButton.classList.contains("blocklist-disabled"),
"Button to block the module does not indicate the blocklist is disabled."
);
Assert.ok(
!blockButton.classList.contains("module-blocked"),
"Button to block the module does not indicate the module is blocked."
);
Assert.ok(
card.querySelector(".image-warning").hidden,
"No warning sign for the module."
);
Assert.equal(
card.querySelector(".image-unsigned").hidden,
false,
"The module is labeled as unsigned."
);
Assert.equal(
card.querySelector(".tag-shellex").hidden,
false,
"The module is labeled as a shell extension."
);
Assert.equal(
card.querySelector(".tag-ime").hidden,
true,
"The module is not labeled as an IME."
);
const versionRow = getDetailRow(card, "third-party-detail-version");
Assert.equal(
versionRow.childNodes[1].textContent,
"1.2.3.4",
"The version matches a value in TestShellEx.rc."
);
const vendorRow = getDetailRow(card, "third-party-detail-vendor");
Assert.equal(
vendorRow.childNodes[1].textContent,
"Mozilla Corporation",
"The vendor name matches a value in TestShellEx.rc."
);
const occurrencesRow = getDetailRow(card, "third-party-detail-occurrences");
Assert.equal(
Number(occurrencesRow.childNodes[1].textContent),
1,
"The module was loaded once."
);
const durationRow = getDetailRow(card, "third-party-detail-duration");
Assert.ok(
Number(durationRow.childNodes[1].textContent),
"The duration row shows a valid number."
);
const eventTable = card.querySelector(".event-table");
const tableCells = eventTable.querySelectorAll("td");
Assert.equal(
tableCells.length,
3,
"The table has three cells as there is only one event."
);
Assert.equal(
tableCells[0].querySelector(".process-type").getAttribute("data-l10n-id"),
"process-type-default",
"The module was loaded into the main process."
);
Assert.ok(
Number(tableCells[0].querySelector(".process-id").textContent),
"A valid process ID is displayed."
);
Assert.equal(
tableCells[1].querySelector(".event-duration").textContent,
durationRow.childNodes[1].textContent,
"The event's duration is the same as the average " +
"as there is only one event."
);
Assert.equal(
tableCells[1].querySelector(".tag-background").hidden,
true,
"The icon handler is loaded in the main thread."
);
Assert.equal(
tableCells[2].getAttribute("data-l10n-id"),
"third-party-status-loaded",
"The module was really loaded without being blocked."
);
const button = content.document.getElementById("button-copy-to-clipboard");
button.click();
// Wait until copying is done and the button becomes clickable.
await BrowserTestUtils.waitForMutationCondition(
button,
{ attributes: true },
() => !button.disabled
);
const copiedJSON = JSON.parse(await navigator.clipboard.readText());
Assert.ok(copiedJSON instanceof Object, "Data is an object.");
verifyClipboardData(copiedJSON);
verifyModuleSorting(content.moduleCompareForDisplay);
});
});