127 lines
4 KiB
JavaScript
127 lines
4 KiB
JavaScript
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set sts=2 sw=2 et tw=80: */
|
|
"use strict";
|
|
|
|
const clipboard = SpecialPowers.Services.clipboard;
|
|
const clipboardTypes = [
|
|
clipboard.kGlobalClipboard,
|
|
clipboard.kSelectionClipboard,
|
|
clipboard.kFindClipboard,
|
|
clipboard.kSelectionCache,
|
|
];
|
|
const supportedClipboardTypes = clipboardTypes.filter(type =>
|
|
clipboard.isClipboardTypeSupported(type)
|
|
);
|
|
|
|
const kPasteMenuPopupId = "clipboardReadPasteMenuPopup";
|
|
const kPasteMenuItemId = "clipboardReadPasteMenuItem";
|
|
|
|
function waitForPasteMenuPopupEvent(aEventSuffix) {
|
|
// The element with id `kPasteMenuPopupId` is inserted dynamically, hence
|
|
// calling `BrowserTestUtils.waitForEvent` instead of
|
|
// `BrowserTestUtils.waitForPopupEvent`.
|
|
return BrowserTestUtils.waitForEvent(
|
|
document,
|
|
"popup" + aEventSuffix,
|
|
false /* capture */,
|
|
e => {
|
|
return e.target.getAttribute("id") == kPasteMenuPopupId;
|
|
}
|
|
);
|
|
}
|
|
|
|
async function waitForPasteContextMenu() {
|
|
await waitForPasteMenuPopupEvent("shown");
|
|
const pasteButton = document.getElementById(kPasteMenuItemId);
|
|
info("Wait for paste button enabled");
|
|
await BrowserTestUtils.waitForMutationCondition(
|
|
pasteButton,
|
|
{ attributeFilter: ["disabled"] },
|
|
() => !pasteButton.disabled,
|
|
"Wait for paste button enabled"
|
|
);
|
|
}
|
|
|
|
function promiseClickPasteButton() {
|
|
info("Wait for clicking paste contextmenu");
|
|
const pasteButton = document.getElementById(kPasteMenuItemId);
|
|
let promise = BrowserTestUtils.waitForEvent(pasteButton, "command");
|
|
document.getElementById(kPasteMenuPopupId).activateItem(pasteButton);
|
|
return promise;
|
|
}
|
|
|
|
async function getClipboardDataSnapshot(aBrowser, aClipboardType) {
|
|
await SpecialPowers.spawn(aBrowser, [aClipboardType], async type => {
|
|
return new Promise((resolve, reject) => {
|
|
SpecialPowers.Services.clipboard.getDataSnapshot(
|
|
["text/plain"],
|
|
type,
|
|
content.browsingContext.currentWindowContext,
|
|
content.document.nodePrincipal,
|
|
{
|
|
QueryInterface: SpecialPowers.ChromeUtils.generateQI([
|
|
"nsIClipboardGetDataSnapshotCallback",
|
|
]),
|
|
// nsIClipboardGetDataSnapshotCallback
|
|
onSuccess: () => {
|
|
resolve();
|
|
},
|
|
onError: aResult => {
|
|
reject(aResult);
|
|
},
|
|
}
|
|
);
|
|
});
|
|
});
|
|
}
|
|
|
|
add_setup(async function () {
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
// Avoid paste button delay enabling making test too long.
|
|
["security.dialog_enable_delay", 0],
|
|
],
|
|
});
|
|
});
|
|
|
|
supportedClipboardTypes.forEach(type => {
|
|
add_task(async function test_clipboard_contextmenu() {
|
|
await BrowserTestUtils.withNewTab(
|
|
"https://example.com",
|
|
async function (browser) {
|
|
info(`Test clipboard contextmenu for clipboard type ${type}`);
|
|
let pasteContextMenuPromise = waitForPasteContextMenu();
|
|
const asyncRead = getClipboardDataSnapshot(browser, type);
|
|
await pasteContextMenuPromise;
|
|
|
|
// We don't allow requests for different clipboard type to be
|
|
// consolidated, so when the context menu is shown for a specific
|
|
// clipboard type and has not yet got user response, any new requests
|
|
// for a different type should be rejected.
|
|
info(
|
|
"Test other clipboard types before interact with paste contextmenu"
|
|
);
|
|
for (let otherType of supportedClipboardTypes) {
|
|
if (type == otherType) {
|
|
continue;
|
|
}
|
|
|
|
info(`Test other clipboard type ${otherType}`);
|
|
await Assert.rejects(
|
|
getClipboardDataSnapshot(browser, otherType),
|
|
ex => ex == Cr.NS_ERROR_DOM_NOT_ALLOWED_ERR,
|
|
`Request for clipboard type ${otherType} should be rejected`
|
|
);
|
|
}
|
|
|
|
await promiseClickPasteButton();
|
|
try {
|
|
await asyncRead;
|
|
ok(true, `nsIClipboard.getDataSnapshot() should success`);
|
|
} catch (e) {
|
|
ok(false, `nsIClipboard.getDataSnapshot() should not fail with ${e}`);
|
|
}
|
|
}
|
|
);
|
|
});
|
|
});
|