Bug 1867739 - Add an entry in the context menu in order to be able to highlight the selected text in a pdf r=Gijs,fluent-reviewers,bolsson

Differential Revision: https://phabricator.services.mozilla.com/D202335
This commit is contained in:
Calixte 2024-03-11 11:23:07 +00:00
parent 144e79e880
commit a6291cbfce
6 changed files with 129 additions and 45 deletions

View File

@ -313,6 +313,9 @@
<menuitem id="context-selectall"
data-l10n-id="text-action-select-all"
command="cmd_selectAll"/>
<menuitem id="context-pdfjs-highlight-selection"
data-l10n-id="text-action-highlight-selection"
oncommand="gContextMenu.pdfJSCmd('highlightSelection');"/>
<menuitem id="context-reveal-password"
type="checkbox"
data-l10n-id="main-context-menu-reveal-password"

View File

@ -392,6 +392,11 @@ class nsContextMenu {
this.showItem(id, this.inPDFEditor);
}
this.showItem(
"context-pdfjs-highlight-selection",
this.pdfEditorStates?.hasSelectedText
);
if (!this.inPDFEditor) {
return;
}

View File

@ -433,6 +433,7 @@ class ChromeActions {
hasSomethingToUndo: false,
hasSomethingToRedo: false,
hasSelectedEditor: false,
hasSelectedText: false,
};
}
const { editorStates } = doc;

View File

@ -32,9 +32,9 @@ async function openContextMenuAt(browser, x, y) {
* Open a context menu and get the pdfjs entries
* @param {Object} browser
* @param {Object} box
* @returns {Map<string,HTMLElement>} the pdfjs menu entries.
* @returns {Promise<Map<string,HTMLElement>>} the pdfjs menu entries.
*/
async function getContextMenuItems(browser, box) {
function getContextMenuItems(browser, box) {
return new Promise(resolve => {
setTimeout(async () => {
const { x, y, width, height } = box;
@ -48,6 +48,7 @@ async function getContextMenuItems(browser, box) {
"context-pdfjs-delete",
"context-pdfjs-selectall",
"context-sep-pdfjs-selectall",
"context-pdfjs-highlight-selection",
];
await openContextMenuAt(browser, x + width / 2, y + height / 2);
@ -68,7 +69,7 @@ async function getContextMenuItems(browser, box) {
* and returs the pdfjs menu entries.
* @param {Object} browser
* @param {string} selector
* @returns {Map<string,HTMLElement>} the pdfjs menu entries.
* @returns {Promise<Map<string,HTMLElement>>} the pdfjs menu entries.
*/
async function getContextMenuItemsOn(browser, selector) {
const box = await SpecialPowers.spawn(
@ -129,35 +130,36 @@ function assertMenuitems(menuitems, expected) {
elmt =>
!elmt.id.includes("-sep-") &&
!elmt.hidden &&
elmt.getAttribute("disabled") === "false"
["", "false"].includes(elmt.getAttribute("disabled"))
)
.map(elmt => elmt.id),
expected
);
}
async function waitAndCheckEmptyContextMenu(browser) {
// check that PDF is opened with internal viewer
await waitForPdfJSAllLayers(browser, TESTROOT + "file_pdfjs_test.pdf", [
["annotationEditorLayer", "annotationLayer", "textLayer", "canvasWrapper"],
["annotationEditorLayer", "textLayer", "canvasWrapper"],
]);
const spanBox = await getSpanBox(browser, "and found references");
const menuitems = await getContextMenuItems(browser, spanBox);
// Nothing have been edited, hence the context menu doesn't contain any
// pdf entries.
Assert.ok(
[...menuitems.values()].every(elmt => elmt.hidden),
"No visible pdf menuitem"
);
await hideContextMenu(browser);
}
// Text copy, paste, undo, redo, delete and select all in using the context
// menu.
add_task(async function test() {
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let handlerInfo = mimeService.getFromTypeAndExtension(
"application/pdf",
"pdf"
);
// Make sure pdf.js is the default handler.
is(
handlerInfo.alwaysAskBeforeHandling,
false,
"pdf handler defaults to always-ask is false"
);
is(
handlerInfo.preferredAction,
Ci.nsIHandlerInfo.handleInternally,
"pdf handler defaults to internal"
);
info("Pref action: " + handlerInfo.preferredAction);
add_task(async function test_copy_paste_undo_redo() {
makePDFJSHandler();
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
@ -168,27 +170,8 @@ add_task(async function test() {
set: [["pdfjs.annotationEditorMode", 0]],
});
// check that PDF is opened with internal viewer
await waitForPdfJSAllLayers(browser, TESTROOT + "file_pdfjs_test.pdf", [
[
"annotationEditorLayer",
"annotationLayer",
"textLayer",
"canvasWrapper",
],
["annotationEditorLayer", "textLayer", "canvasWrapper"],
]);
await waitAndCheckEmptyContextMenu(browser);
const spanBox = await getSpanBox(browser, "and found references");
let menuitems = await getContextMenuItems(browser, spanBox);
// Nothing have been edited, hence the context menu doesn't contain any
// pdf entries.
Assert.ok(
[...menuitems.values()].every(elmt => elmt.hidden),
"No visible pdf menuitem"
);
await hideContextMenu(browser);
await enableEditor(browser, "FreeText");
await addFreeText(browser, "hello", spanBox);
@ -211,7 +194,7 @@ add_task(async function test() {
Assert.equal(await countElements(browser, ".selectedEditor"), 0);
menuitems = await getContextMenuItems(browser, spanBox);
let menuitems = await getContextMenuItems(browser, spanBox);
assertMenuitems(menuitems, [
"context-pdfjs-undo", // Last created editor is undoable
"context-pdfjs-selectall", // and selectable.
@ -374,6 +357,73 @@ add_task(async function test() {
await SpecialPowers.spawn(browser, [], async function () {
var viewer = content.wrappedJSObject.PDFViewerApplication;
viewer.pdfDocument.annotationStorage.resetModified();
await viewer.close();
});
}
);
});
add_task(async function test_highlight_selection() {
makePDFJSHandler();
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:blank" },
async function (browser) {
await SpecialPowers.pushPrefEnv({
set: [
["pdfjs.annotationEditorMode", 0],
["pdfjs.enableHighlightEditor", true],
],
});
await waitAndCheckEmptyContextMenu(browser);
const spanBox = await getSpanBox(browser, "and found references");
const selectChangePromise = BrowserTestUtils.waitForEvent(
document,
"selectionchange",
false,
null,
true
);
await clickAt(
browser,
spanBox.x + spanBox.width / 2,
spanBox.y + spanBox.height / 2,
2
);
await selectChangePromise;
await TestUtils.waitForTick();
const mozBox = await getSpanBox(browser, "Mozilla automated testing");
const menuitems = await getContextMenuItems(browser, mozBox);
assertMenuitems(menuitems, ["context-pdfjs-highlight-selection"]);
const telemetryPromise = BrowserTestUtils.waitForContentEvent(
browser,
"reporttelemetry",
false,
null,
true
);
await clickOnItem(
browser,
menuitems,
"context-pdfjs-highlight-selection"
);
await telemetryPromise;
Assert.equal(
await countElements(browser, ".highlightEditor"),
1,
"An highlight editor must have been added"
);
await SpecialPowers.spawn(browser, [], async function () {
var viewer = content.wrappedJSObject.PDFViewerApplication;
viewer.pdfDocument.annotationStorage.resetModified();
await viewer.close();
});
}

View File

@ -426,3 +426,25 @@ async function cleanupDownloads(listId = Downloads.PUBLIC) {
await download.finalize();
}
}
function makePDFJSHandler() {
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let handlerInfo = mimeService.getFromTypeAndExtension(
"application/pdf",
"pdf"
);
// Make sure pdf.js is the default handler.
is(
handlerInfo.alwaysAskBeforeHandling,
false,
"pdf handler defaults to always-ask is false"
);
is(
handlerInfo.preferredAction,
Ci.nsIHandlerInfo.handleInternally,
"pdf handler defaults to internal"
);
info("Pref action: " + handlerInfo.preferredAction);
}

View File

@ -83,3 +83,6 @@ text-action-spell-dictionaries =
text-action-search-text-box-clear =
.title = Clear
text-action-highlight-selection =
.label = Highlight Selection