fune/browser/components/preferences/in-content/tests/browser_applications_selection.js
2018-09-26 18:10:43 +00:00

275 lines
12 KiB
JavaScript

SimpleTest.requestCompleteLog();
ChromeUtils.import("resource://testing-common/HandlerServiceTestUtils.jsm", this);
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_task(async function setup() {
// 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 = "http://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();
}
item.click();
popup.hidePopup();
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[label*='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 always ask 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]);
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]);
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.");
// Test default sorting
assertSortByType("ascending");
const oldDir = typeColumn.getAttribute("sortDirection");
// 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");
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");
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");
}
}
}
});