407 lines
13 KiB
JavaScript
407 lines
13 KiB
JavaScript
SimpleTest.requestCompleteLog();
|
|
const { HandlerServiceTestUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/HandlerServiceTestUtils.sys.mjs"
|
|
);
|
|
|
|
let gHandlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
|
|
Ci.nsIHandlerService
|
|
);
|
|
|
|
let gOldMailHandlers = [];
|
|
let gDummyHandlers = [];
|
|
let gOriginalPreferredMailHandler;
|
|
let gOriginalPreferredPDFHandler;
|
|
|
|
registerCleanupFunction(function () {
|
|
function removeDummyHandlers(handlers) {
|
|
// Remove any of the dummy handlers we created.
|
|
for (let i = handlers.Count() - 1; i >= 0; i--) {
|
|
try {
|
|
if (
|
|
gDummyHandlers.some(
|
|
h =>
|
|
h.uriTemplate ==
|
|
handlers.queryElementAt(i, Ci.nsIWebHandlerApp).uriTemplate
|
|
)
|
|
) {
|
|
handlers.removeElementAt(i);
|
|
}
|
|
} catch (ex) {
|
|
/* ignore non-web-app handlers */
|
|
}
|
|
}
|
|
}
|
|
// Re-add the original protocol handlers:
|
|
let mailHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("mailto");
|
|
let mailHandlers = mailHandlerInfo.possibleApplicationHandlers;
|
|
for (let h of gOldMailHandlers) {
|
|
mailHandlers.appendElement(h);
|
|
}
|
|
removeDummyHandlers(mailHandlers);
|
|
mailHandlerInfo.preferredApplicationHandler = gOriginalPreferredMailHandler;
|
|
gHandlerService.store(mailHandlerInfo);
|
|
|
|
let pdfHandlerInfo =
|
|
HandlerServiceTestUtils.getHandlerInfo("application/pdf");
|
|
removeDummyHandlers(pdfHandlerInfo.possibleApplicationHandlers);
|
|
pdfHandlerInfo.preferredApplicationHandler = gOriginalPreferredPDFHandler;
|
|
gHandlerService.store(pdfHandlerInfo);
|
|
|
|
gBrowser.removeCurrentTab();
|
|
});
|
|
|
|
function scrubMailtoHandlers(handlerInfo) {
|
|
// Remove extant web handlers because they have icons that
|
|
// we fetch from the web, which isn't allowed in tests.
|
|
let handlers = handlerInfo.possibleApplicationHandlers;
|
|
for (let i = handlers.Count() - 1; i >= 0; i--) {
|
|
try {
|
|
let handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp);
|
|
gOldMailHandlers.push(handler);
|
|
// If we get here, this is a web handler app. Remove it:
|
|
handlers.removeElementAt(i);
|
|
} catch (ex) {}
|
|
}
|
|
}
|
|
|
|
add_setup(async function () {
|
|
// Create our dummy handlers
|
|
let handler1 = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance(
|
|
Ci.nsIWebHandlerApp
|
|
);
|
|
handler1.name = "Handler 1";
|
|
handler1.uriTemplate = "https://example.com/first/%s";
|
|
|
|
let handler2 = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance(
|
|
Ci.nsIWebHandlerApp
|
|
);
|
|
handler2.name = "Handler 2";
|
|
handler2.uriTemplate = "https://example.org/second/%s";
|
|
gDummyHandlers.push(handler1, handler2);
|
|
|
|
function substituteWebHandlers(handlerInfo) {
|
|
// Append the dummy handlers to replace them:
|
|
let handlers = handlerInfo.possibleApplicationHandlers;
|
|
handlers.appendElement(handler1);
|
|
handlers.appendElement(handler2);
|
|
gHandlerService.store(handlerInfo);
|
|
}
|
|
// Set up our mailto handler test infrastructure.
|
|
let mailtoHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("mailto");
|
|
scrubMailtoHandlers(mailtoHandlerInfo);
|
|
gOriginalPreferredMailHandler = mailtoHandlerInfo.preferredApplicationHandler;
|
|
substituteWebHandlers(mailtoHandlerInfo);
|
|
|
|
// Now do the same for pdf handler:
|
|
let pdfHandlerInfo =
|
|
HandlerServiceTestUtils.getHandlerInfo("application/pdf");
|
|
// PDF doesn't have built-in web handlers, so no need to scrub.
|
|
gOriginalPreferredPDFHandler = pdfHandlerInfo.preferredApplicationHandler;
|
|
substituteWebHandlers(pdfHandlerInfo);
|
|
|
|
await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true });
|
|
info("Preferences page opened on the general pane.");
|
|
|
|
await gBrowser.selectedBrowser.contentWindow.promiseLoadHandlersList;
|
|
info("Apps list loaded.");
|
|
});
|
|
|
|
async function selectStandardOptions(itemToUse) {
|
|
async function selectItemInPopup(item) {
|
|
let popupShown = BrowserTestUtils.waitForEvent(popup, "popupshown");
|
|
// Synthesizing the mouse on the .actionsMenu menulist somehow just selects
|
|
// the top row. Probably something to do with the multiple layers of anon
|
|
// content - workaround by using the `.open` setter instead.
|
|
list.open = true;
|
|
await popupShown;
|
|
let popupHidden = BrowserTestUtils.waitForEvent(popup, "popuphidden");
|
|
if (typeof item == "function") {
|
|
item = item();
|
|
}
|
|
popup.activateItem(item);
|
|
await popupHidden;
|
|
return item;
|
|
}
|
|
|
|
let itemType = itemToUse.getAttribute("type");
|
|
// Center the item. Center rather than top so it doesn't get blocked by
|
|
// the search header.
|
|
itemToUse.scrollIntoView({ block: "center" });
|
|
itemToUse.closest("richlistbox").selectItem(itemToUse);
|
|
Assert.ok(itemToUse.selected, "Should be able to select our item.");
|
|
// Force reflow to make sure it's visible and the container dropdown isn't
|
|
// hidden.
|
|
itemToUse.getBoundingClientRect().top;
|
|
let list = itemToUse.querySelector(".actionsMenu");
|
|
let popup = list.menupopup;
|
|
|
|
// select one of our test cases:
|
|
let handlerItem = list.querySelector("menuitem[data-l10n-args*='Handler 1']");
|
|
await selectItemInPopup(handlerItem);
|
|
let { preferredAction, alwaysAskBeforeHandling } =
|
|
HandlerServiceTestUtils.getHandlerInfo(itemType);
|
|
Assert.notEqual(
|
|
preferredAction,
|
|
Ci.nsIHandlerInfo.alwaysAsk,
|
|
"Should have selected something other than 'always ask' (" + itemType + ")"
|
|
);
|
|
Assert.ok(
|
|
!alwaysAskBeforeHandling,
|
|
"Should have turned off asking before handling (" + itemType + ")"
|
|
);
|
|
|
|
// Test the alwaysAsk option
|
|
let alwaysAskItem = list.getElementsByAttribute(
|
|
"action",
|
|
Ci.nsIHandlerInfo.alwaysAsk
|
|
)[0];
|
|
await selectItemInPopup(alwaysAskItem);
|
|
Assert.equal(
|
|
list.selectedItem,
|
|
alwaysAskItem,
|
|
"Should have selected always ask item (" + itemType + ")"
|
|
);
|
|
alwaysAskBeforeHandling =
|
|
HandlerServiceTestUtils.getHandlerInfo(itemType).alwaysAskBeforeHandling;
|
|
Assert.ok(
|
|
alwaysAskBeforeHandling,
|
|
"Should have turned on asking before handling (" + itemType + ")"
|
|
);
|
|
|
|
let useDefaultItem = list.getElementsByAttribute(
|
|
"action",
|
|
Ci.nsIHandlerInfo.useSystemDefault
|
|
);
|
|
useDefaultItem = useDefaultItem && useDefaultItem[0];
|
|
if (useDefaultItem) {
|
|
await selectItemInPopup(useDefaultItem);
|
|
Assert.equal(
|
|
list.selectedItem,
|
|
useDefaultItem,
|
|
"Should have selected 'use default' item (" + itemType + ")"
|
|
);
|
|
preferredAction =
|
|
HandlerServiceTestUtils.getHandlerInfo(itemType).preferredAction;
|
|
Assert.equal(
|
|
preferredAction,
|
|
Ci.nsIHandlerInfo.useSystemDefault,
|
|
"Should have selected 'use default' (" + itemType + ")"
|
|
);
|
|
} else {
|
|
// Whether there's a "use default" item depends on the OS, so it's not
|
|
// possible to rely on it being the case or not.
|
|
info("No 'Use default' item, so not testing (" + itemType + ")");
|
|
}
|
|
|
|
// Select a web app item.
|
|
let webAppItems = Array.from(
|
|
popup.getElementsByAttribute("action", Ci.nsIHandlerInfo.useHelperApp)
|
|
);
|
|
webAppItems = webAppItems.filter(
|
|
item => item.handlerApp instanceof Ci.nsIWebHandlerApp
|
|
);
|
|
Assert.equal(
|
|
webAppItems.length,
|
|
2,
|
|
"Should have 2 web application handler. (" + itemType + ")"
|
|
);
|
|
Assert.notEqual(
|
|
webAppItems[0].label,
|
|
webAppItems[1].label,
|
|
"Should have 2 different web app handlers"
|
|
);
|
|
let selectedItem = await selectItemInPopup(webAppItems[0]);
|
|
|
|
// Test that the selected item label is the same as the label
|
|
// of the menu item.
|
|
let win = gBrowser.selectedBrowser.contentWindow;
|
|
await win.document.l10n.translateFragment(selectedItem);
|
|
await win.document.l10n.translateFragment(itemToUse);
|
|
Assert.equal(
|
|
selectedItem.label,
|
|
itemToUse.querySelector(".actionContainer label").value,
|
|
"Should have selected correct item (" + itemType + ")"
|
|
);
|
|
let { preferredApplicationHandler } =
|
|
HandlerServiceTestUtils.getHandlerInfo(itemType);
|
|
preferredApplicationHandler.QueryInterface(Ci.nsIWebHandlerApp);
|
|
Assert.equal(
|
|
selectedItem.handlerApp.uriTemplate,
|
|
preferredApplicationHandler.uriTemplate,
|
|
"App should actually be selected in the backend. (" + itemType + ")"
|
|
);
|
|
|
|
// select the other web app item
|
|
selectedItem = await selectItemInPopup(webAppItems[1]);
|
|
|
|
// Test that the selected item label is the same as the label
|
|
// of the menu item
|
|
await win.document.l10n.translateFragment(selectedItem);
|
|
await win.document.l10n.translateFragment(itemToUse);
|
|
Assert.equal(
|
|
selectedItem.label,
|
|
itemToUse.querySelector(".actionContainer label").value,
|
|
"Should have selected correct item (" + itemType + ")"
|
|
);
|
|
preferredApplicationHandler =
|
|
HandlerServiceTestUtils.getHandlerInfo(
|
|
itemType
|
|
).preferredApplicationHandler;
|
|
preferredApplicationHandler.QueryInterface(Ci.nsIWebHandlerApp);
|
|
Assert.equal(
|
|
selectedItem.handlerApp.uriTemplate,
|
|
preferredApplicationHandler.uriTemplate,
|
|
"App should actually be selected in the backend. (" + itemType + ")"
|
|
);
|
|
}
|
|
|
|
add_task(async function checkDropdownBehavior() {
|
|
let win = gBrowser.selectedBrowser.contentWindow;
|
|
|
|
let container = win.document.getElementById("handlersView");
|
|
|
|
// First check a protocol handler item.
|
|
let mailItem = container.querySelector("richlistitem[type='mailto']");
|
|
Assert.ok(mailItem, "mailItem is present in handlersView.");
|
|
await selectStandardOptions(mailItem);
|
|
|
|
// Then check a content menu item.
|
|
let pdfItem = container.querySelector("richlistitem[type='application/pdf']");
|
|
Assert.ok(pdfItem, "pdfItem is present in handlersView.");
|
|
await selectStandardOptions(pdfItem);
|
|
});
|
|
|
|
add_task(async function sortingCheck() {
|
|
let win = gBrowser.selectedBrowser.contentWindow;
|
|
const handlerView = win.document.getElementById("handlersView");
|
|
const typeColumn = win.document.getElementById("typeColumn");
|
|
Assert.ok(typeColumn, "typeColumn is present in handlersView.");
|
|
|
|
let expectedNumberOfItems =
|
|
handlerView.querySelectorAll("richlistitem").length;
|
|
|
|
// Test default sorting
|
|
assertSortByType("ascending");
|
|
|
|
const oldDir = typeColumn.getAttribute("sortDirection");
|
|
|
|
// click on an item and sort again:
|
|
let itemToUse = handlerView.querySelector("richlistitem[type=mailto]");
|
|
itemToUse.scrollIntoView({ block: "center" });
|
|
itemToUse.closest("richlistbox").selectItem(itemToUse);
|
|
|
|
// Test sorting on the type column
|
|
typeColumn.click();
|
|
assertSortByType("descending");
|
|
Assert.notEqual(
|
|
oldDir,
|
|
typeColumn.getAttribute("sortDirection"),
|
|
"Sort direction should change"
|
|
);
|
|
|
|
typeColumn.click();
|
|
assertSortByType("ascending");
|
|
|
|
const actionColumn = win.document.getElementById("actionColumn");
|
|
Assert.ok(actionColumn, "actionColumn is present in handlersView.");
|
|
|
|
// Test sorting on the action column
|
|
const oldActionDir = actionColumn.getAttribute("sortDirection");
|
|
actionColumn.click();
|
|
assertSortByAction("ascending");
|
|
Assert.notEqual(
|
|
oldActionDir,
|
|
actionColumn.getAttribute("sortDirection"),
|
|
"Sort direction should change"
|
|
);
|
|
|
|
actionColumn.click();
|
|
assertSortByAction("descending");
|
|
|
|
// Restore the default sort order
|
|
typeColumn.click();
|
|
assertSortByType("ascending");
|
|
|
|
function assertSortByAction(order) {
|
|
Assert.equal(
|
|
actionColumn.getAttribute("sortDirection"),
|
|
order,
|
|
`Sort direction should be ${order}`
|
|
);
|
|
let siteItems = handlerView.getElementsByTagName("richlistitem");
|
|
Assert.equal(
|
|
siteItems.length,
|
|
expectedNumberOfItems,
|
|
"Number of items should not change."
|
|
);
|
|
for (let i = 0; i < siteItems.length - 1; ++i) {
|
|
let aType = (
|
|
siteItems[i].getAttribute("actionDescription") || ""
|
|
).toLowerCase();
|
|
let bType = (
|
|
siteItems[i + 1].getAttribute("actionDescription") || ""
|
|
).toLowerCase();
|
|
let result = 0;
|
|
if (aType > bType) {
|
|
result = 1;
|
|
} else if (bType > aType) {
|
|
result = -1;
|
|
}
|
|
if (order == "ascending") {
|
|
Assert.lessOrEqual(
|
|
result,
|
|
0,
|
|
"Should sort applications in the ascending order by action"
|
|
);
|
|
} else {
|
|
Assert.greaterOrEqual(
|
|
result,
|
|
0,
|
|
"Should sort applications in the descending order by action"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function assertSortByType(order) {
|
|
Assert.equal(
|
|
typeColumn.getAttribute("sortDirection"),
|
|
order,
|
|
`Sort direction should be ${order}`
|
|
);
|
|
|
|
let siteItems = handlerView.getElementsByTagName("richlistitem");
|
|
Assert.equal(
|
|
siteItems.length,
|
|
expectedNumberOfItems,
|
|
"Number of items should not change."
|
|
);
|
|
for (let i = 0; i < siteItems.length - 1; ++i) {
|
|
let aType = (
|
|
siteItems[i].getAttribute("typeDescription") || ""
|
|
).toLowerCase();
|
|
let bType = (
|
|
siteItems[i + 1].getAttribute("typeDescription") || ""
|
|
).toLowerCase();
|
|
let result = 0;
|
|
if (aType > bType) {
|
|
result = 1;
|
|
} else if (bType > aType) {
|
|
result = -1;
|
|
}
|
|
if (order == "ascending") {
|
|
Assert.lessOrEqual(
|
|
result,
|
|
0,
|
|
"Should sort applications in the ascending order by type"
|
|
);
|
|
} else {
|
|
Assert.greaterOrEqual(
|
|
result,
|
|
0,
|
|
"Should sort applications in the descending order by type"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|