270 lines
7.7 KiB
JavaScript
270 lines
7.7 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
|
*/
|
|
|
|
const ABOUT_ADDONS_URL = "chrome://mozapps/content/extensions/aboutaddons.html";
|
|
|
|
const dragService = Cc["@mozilla.org/widget/dragservice;1"].getService(
|
|
Ci.nsIDragService
|
|
);
|
|
|
|
// Test that the drag-drop-addon-installer component installs add-ons and is
|
|
// included in about:addons. There is an issue with EventUtils.synthesizeDrop
|
|
// where it throws an exception when you give it an subbrowser so we test
|
|
// the component directly.
|
|
|
|
async function checkInstallConfirmation(...names) {
|
|
let notificationCount = 0;
|
|
let observer = {
|
|
observe(aSubject) {
|
|
let installInfo = aSubject.wrappedJSObject;
|
|
isnot(
|
|
installInfo.browser,
|
|
null,
|
|
"Notification should have non-null browser"
|
|
);
|
|
|
|
is(
|
|
installInfo.installs.length,
|
|
1,
|
|
"Got one AddonInstall instance as expected"
|
|
);
|
|
|
|
Assert.deepEqual(
|
|
installInfo.installs[0].installTelemetryInfo,
|
|
{ source: "about:addons", method: "drag-and-drop" },
|
|
"Got the expected installTelemetryInfo"
|
|
);
|
|
|
|
notificationCount++;
|
|
},
|
|
};
|
|
Services.obs.addObserver(observer, "addon-install-started");
|
|
|
|
let results = [];
|
|
|
|
let promise = promisePopupNotificationShown("addon-webext-permissions");
|
|
for (let i = 0; i < names.length; i++) {
|
|
let panel = await promise;
|
|
let name = panel.getAttribute("name");
|
|
results.push(name);
|
|
|
|
info(`Saw install for ${name}`);
|
|
if (results.length < names.length) {
|
|
info(
|
|
`Waiting for installs for ${names.filter(n => !results.includes(n))}`
|
|
);
|
|
|
|
promise = promisePopupNotificationShown("addon-webext-permissions");
|
|
}
|
|
panel.secondaryButton.click();
|
|
}
|
|
|
|
Assert.deepEqual(results.sort(), names.sort(), "Got expected installs");
|
|
|
|
is(
|
|
notificationCount,
|
|
names.length,
|
|
`Saw ${names.length} addon-install-started notification`
|
|
);
|
|
Services.obs.removeObserver(observer, "addon-install-started");
|
|
}
|
|
|
|
function getDragOverTarget(win) {
|
|
return win.document.querySelector("categories-box");
|
|
}
|
|
|
|
function getDropTarget(win) {
|
|
return win.document.querySelector("drag-drop-addon-installer");
|
|
}
|
|
|
|
function withTestPage(fn) {
|
|
return BrowserTestUtils.withNewTab(
|
|
{ url: ABOUT_ADDONS_URL, gBrowser },
|
|
async browser => {
|
|
let win = browser.contentWindow;
|
|
await win.customElements.whenDefined("drag-drop-addon-installer");
|
|
await fn(browser);
|
|
}
|
|
);
|
|
}
|
|
|
|
function initDragSession(win, { dragData, dropEffect }) {
|
|
let dropAction;
|
|
switch (dropEffect) {
|
|
case null:
|
|
case undefined:
|
|
case "move":
|
|
dropAction = _EU_Ci.nsIDragService.DRAGDROP_ACTION_MOVE;
|
|
break;
|
|
case "copy":
|
|
dropAction = _EU_Ci.nsIDragService.DRAGDROP_ACTION_COPY;
|
|
break;
|
|
case "link":
|
|
dropAction = _EU_Ci.nsIDragService.DRAGDROP_ACTION_LINK;
|
|
break;
|
|
default:
|
|
throw new Error(`${dropEffect} is an invalid drop effect value`);
|
|
}
|
|
|
|
const dataTransfer = new DataTransfer();
|
|
dataTransfer.dropEffect = dropEffect;
|
|
|
|
for (let i = 0; i < dragData.length; i++) {
|
|
const item = dragData[i];
|
|
for (let j = 0; j < item.length; j++) {
|
|
dataTransfer.mozSetDataAt(item[j].type, item[j].data, i);
|
|
}
|
|
}
|
|
|
|
dragService.startDragSessionForTests(win, dropAction);
|
|
const session = dragService.getCurrentSession(win);
|
|
session.dataTransfer = dataTransfer;
|
|
|
|
return session;
|
|
}
|
|
|
|
async function simulateDragAndDrop(win, dragData) {
|
|
const dropTarget = getDropTarget(win);
|
|
const dragOverTarget = getDragOverTarget(win);
|
|
const dropEffect = "move";
|
|
|
|
const session = initDragSession(win, { dragData, dropEffect });
|
|
|
|
info("Simulate drag over and wait for the drop target to be visible");
|
|
|
|
EventUtils.synthesizeDragOver(
|
|
dragOverTarget,
|
|
dragOverTarget,
|
|
dragData,
|
|
dropEffect,
|
|
win
|
|
);
|
|
|
|
// This make sure that the fake dataTransfer has still
|
|
// the expected drop effect after the synthesizeDragOver call.
|
|
session.dataTransfer.dropEffect = "move";
|
|
|
|
await BrowserTestUtils.waitForCondition(
|
|
() => !dropTarget.hidden,
|
|
"Wait for the drop target element to be visible"
|
|
);
|
|
|
|
info("Simulate drop dragData on drop target");
|
|
|
|
EventUtils.synthesizeDropAfterDragOver(
|
|
null,
|
|
session.dataTransfer,
|
|
dropTarget,
|
|
win,
|
|
{ _domDispatchOnly: true }
|
|
);
|
|
|
|
dragService.getDragSession(win).endDragSession(true);
|
|
}
|
|
|
|
// Simulates dropping a URL onto the manager
|
|
add_task(async function test_drop_url() {
|
|
for (let fileType of ["xpi", "zip"]) {
|
|
await withTestPage(async browser => {
|
|
const url = TESTROOT + `addons/browser_dragdrop1.${fileType}`;
|
|
const promise = checkInstallConfirmation("Drag Drop test 1");
|
|
|
|
await simulateDragAndDrop(browser.contentWindow, [
|
|
[{ type: "text/x-moz-url", data: url }],
|
|
]);
|
|
|
|
await promise;
|
|
});
|
|
}
|
|
});
|
|
|
|
// Simulates dropping a file onto the manager
|
|
add_task(async function test_drop_file() {
|
|
for (let fileType of ["xpi", "zip"]) {
|
|
await withTestPage(async browser => {
|
|
let fileurl = get_addon_file_url(`browser_dragdrop1.${fileType}`);
|
|
let promise = checkInstallConfirmation("Drag Drop test 1");
|
|
|
|
await simulateDragAndDrop(browser.contentWindow, [
|
|
[{ type: "application/x-moz-file", data: fileurl.file }],
|
|
]);
|
|
|
|
await promise;
|
|
});
|
|
}
|
|
});
|
|
|
|
// Simulates dropping two urls onto the manager
|
|
add_task(async function test_drop_multiple_urls() {
|
|
await withTestPage(async browser => {
|
|
let url1 = TESTROOT + "addons/browser_dragdrop1.xpi";
|
|
let url2 = TESTROOT2 + "addons/browser_dragdrop2.zip";
|
|
let promise = checkInstallConfirmation(
|
|
"Drag Drop test 1",
|
|
"Drag Drop test 2"
|
|
);
|
|
|
|
await simulateDragAndDrop(browser.contentWindow, [
|
|
[{ type: "text/x-moz-url", data: url1 }],
|
|
[{ type: "text/x-moz-url", data: url2 }],
|
|
]);
|
|
|
|
await promise;
|
|
});
|
|
}).skip(); // TODO(rpl): this fails because mozSetDataAt throws IndexSizeError.
|
|
|
|
// Simulates dropping two files onto the manager
|
|
add_task(async function test_drop_multiple_files() {
|
|
await withTestPage(async browser => {
|
|
let fileurl1 = get_addon_file_url("browser_dragdrop1.zip");
|
|
let fileurl2 = get_addon_file_url("browser_dragdrop2.xpi");
|
|
let promise = checkInstallConfirmation(
|
|
"Drag Drop test 1",
|
|
"Drag Drop test 2"
|
|
);
|
|
|
|
await simulateDragAndDrop(browser.contentWindow, [
|
|
[{ type: "application/x-moz-file", data: fileurl1.file }],
|
|
[{ type: "application/x-moz-file", data: fileurl2.file }],
|
|
]);
|
|
|
|
await promise;
|
|
});
|
|
}).skip(); // TODO(rpl): this fails because mozSetDataAt throws IndexSizeError.
|
|
|
|
// Simulates dropping a file and a url onto the manager (weird, but should still work)
|
|
add_task(async function test_drop_file_and_url() {
|
|
await withTestPage(async browser => {
|
|
let url = TESTROOT + "addons/browser_dragdrop1.xpi";
|
|
let fileurl = get_addon_file_url("browser_dragdrop2.zip");
|
|
let promise = checkInstallConfirmation(
|
|
"Drag Drop test 1",
|
|
"Drag Drop test 2"
|
|
);
|
|
|
|
await simulateDragAndDrop(browser.contentWindow, [
|
|
[{ type: "text/x-moz-url", data: url }],
|
|
[{ type: "application/x-moz-file", data: fileurl.file }],
|
|
]);
|
|
|
|
await promise;
|
|
});
|
|
}).skip(); // TODO(rpl): this fails because mozSetDataAt throws IndexSizeError.
|
|
|
|
// Test that drag-and-drop of an incompatible addon generates
|
|
// an error.
|
|
add_task(async function test_drop_incompat_file() {
|
|
await withTestPage(async browser => {
|
|
let url = `${TESTROOT}/addons/browser_dragdrop_incompat.xpi`;
|
|
|
|
let panelPromise = promisePopupNotificationShown("addon-install-failed");
|
|
await simulateDragAndDrop(browser.contentWindow, [
|
|
[{ type: "text/x-moz-url", data: url }],
|
|
]);
|
|
|
|
let panel = await panelPromise;
|
|
ok(panel, "Got addon-install-failed popup");
|
|
panel.button.click();
|
|
});
|
|
});
|