summaryrefslogtreecommitdiffstats
path: root/toolkit/components/pdfjs/content
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/pdfjs/content')
-rw-r--r--toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs4
-rw-r--r--toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs18
-rw-r--r--toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs1
-rw-r--r--toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs49
-rw-r--r--toolkit/components/pdfjs/content/PdfjsChild.sys.mjs19
-rw-r--r--toolkit/components/pdfjs/content/build/pdf.mjs726
-rw-r--r--toolkit/components/pdfjs/content/build/pdf.scripting.mjs4
-rw-r--r--toolkit/components/pdfjs/content/build/pdf.worker.mjs114
-rw-r--r--toolkit/components/pdfjs/content/web/images/gv-toolbarButton-openinapp.svg11
-rw-r--r--toolkit/components/pdfjs/content/web/viewer-geckoview.css8
-rw-r--r--toolkit/components/pdfjs/content/web/viewer-geckoview.html3
-rw-r--r--toolkit/components/pdfjs/content/web/viewer-geckoview.mjs439
-rw-r--r--toolkit/components/pdfjs/content/web/viewer.css292
-rw-r--r--toolkit/components/pdfjs/content/web/viewer.html19
-rw-r--r--toolkit/components/pdfjs/content/web/viewer.mjs451
15 files changed, 1484 insertions, 674 deletions
diff --git a/toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs b/toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs
index e838c67874..749532053b 100644
--- a/toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs
+++ b/toolkit/components/pdfjs/content/GeckoViewPdfjsChild.sys.mjs
@@ -17,9 +17,7 @@ import { GeckoViewActorChild } from "resource://gre/modules/GeckoViewActorChild.
export class GeckoViewPdfjsChild extends GeckoViewActorChild {
init(aSupportsFind) {
- if (aSupportsFind) {
- this.sendAsyncMessage("PDFJS:Parent:addEventListener");
- }
+ this.sendAsyncMessage("PDFJS:Parent:addEventListener", { aSupportsFind });
}
dispatchEvent(aType, aDetail) {
diff --git a/toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs b/toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs
index b07ed8c7b1..e27fdac51d 100644
--- a/toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs
+++ b/toolkit/components/pdfjs/content/GeckoViewPdfjsParent.sys.mjs
@@ -258,7 +258,7 @@ export class GeckoViewPdfjsParent extends GeckoViewActorParent {
case "PDFJS:Parent:updateMatchesCount":
return this.#updateMatchesCount(aMsg);
case "PDFJS:Parent:addEventListener":
- return this.#addEventListener();
+ return this.#addEventListener(aMsg);
case "PDFJS:Parent:saveURL":
return this.#save(aMsg);
case "PDFJS:Parent:getNimbus":
@@ -299,7 +299,16 @@ export class GeckoViewPdfjsParent extends GeckoViewActorParent {
this.#fileSaver = null;
}
- #addEventListener() {
+ #addEventListener({ data: { aSupportsFind } }) {
+ this.#fileSaver = new FileSaver(this.browser, this.eventDispatcher);
+ this.eventDispatcher.registerListener(this.#fileSaver, [
+ "GeckoView:PDFSave",
+ ]);
+
+ if (!aSupportsFind) {
+ return;
+ }
+
if (this.#findHandler) {
this.#findHandler.cleanup();
return;
@@ -311,11 +320,6 @@ export class GeckoViewPdfjsParent extends GeckoViewActorParent {
"GeckoView:DisplayMatches",
"GeckoView:FindInPage",
]);
-
- this.#fileSaver = new FileSaver(this.browser, this.eventDispatcher);
- this.eventDispatcher.registerListener(this.#fileSaver, [
- "GeckoView:PDFSave",
- ]);
}
#updateMatchesCount({ data }) {
diff --git a/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs b/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs
index 02d1095919..ee30631bff 100644
--- a/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs
+++ b/toolkit/components/pdfjs/content/PdfJsDefaultPreferences.sys.mjs
@@ -25,6 +25,7 @@ export const PdfJsDefaultPreferences = Object.freeze({
defaultZoomValue: "",
disablePageLabels: false,
enableHighlightEditor: false,
+ enableHighlightFloatingButton: false,
enableML: false,
enablePermissions: false,
enablePrintAutoRotate: true,
diff --git a/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs b/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs
index 050d730872..2a56cbb935 100644
--- a/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs
+++ b/toolkit/components/pdfjs/content/PdfStreamConverter.sys.mjs
@@ -19,6 +19,9 @@ const PDF_VIEWER_WEB_PAGE = "resource://pdf.js/web/viewer.html";
const MAX_NUMBER_OF_PREFS = 50;
const PDF_CONTENT_TYPE = "application/pdf";
+// Preferences
+const caretBrowsingModePref = "accessibility.browsewithcaret";
+
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
@@ -178,6 +181,45 @@ PdfDataListener.prototype = {
},
};
+class PrefObserver {
+ #domWindow;
+
+ constructor(domWindow) {
+ this.#domWindow = domWindow;
+ this.#init();
+ }
+
+ #init() {
+ Services.prefs.addObserver(
+ caretBrowsingModePref,
+ this,
+ /* aHoldWeak = */ true
+ );
+ }
+
+ observe(_aSubject, aTopic, aPrefName) {
+ if (aTopic != "nsPref:changed") {
+ return;
+ }
+
+ const actor = getActor(this.#domWindow);
+ if (!actor) {
+ return;
+ }
+ const eventName = "updatedPreference";
+ switch (aPrefName) {
+ case caretBrowsingModePref:
+ actor.dispatchEvent(eventName, {
+ name: "supportsCaretBrowsingMode",
+ value: Services.prefs.getBoolPref(caretBrowsingModePref),
+ });
+ break;
+ }
+ }
+
+ QueryInterface = ChromeUtils.generateQI([Ci.nsISupportsWeakReference]);
+}
+
/**
* All the privileged actions.
*/
@@ -187,6 +229,7 @@ class ChromeActions {
this.contentDispositionFilename = contentDispositionFilename;
this.sandbox = null;
this.unloadListener = null;
+ this.observer = new PrefObserver(domWindow);
}
createSandbox(data, sendResponse) {
@@ -300,7 +343,7 @@ class ChromeActions {
Services.prefs.getIntPref("mousewheel.with_meta.action") === 3,
supportsPinchToZoom: Services.prefs.getBoolPref("apz.allow_zooming"),
supportsCaretBrowsingMode: Services.prefs.getBoolPref(
- "accessibility.browsewithcaret"
+ caretBrowsingModePref
),
};
}
@@ -330,9 +373,8 @@ class ChromeActions {
}
reportTelemetry(data) {
- const probeInfo = JSON.parse(data);
const actor = getActor(this.domWindow);
- actor?.sendAsyncMessage("PDFJS:Parent:reportTelemetry", probeInfo);
+ actor?.sendAsyncMessage("PDFJS:Parent:reportTelemetry", data);
}
updateFindControlState(data) {
@@ -434,6 +476,7 @@ class ChromeActions {
hasSomethingToUndo: false,
hasSomethingToRedo: false,
hasSelectedEditor: false,
+ hasSelectedText: false,
};
}
const { editorStates } = doc;
diff --git a/toolkit/components/pdfjs/content/PdfjsChild.sys.mjs b/toolkit/components/pdfjs/content/PdfjsChild.sys.mjs
index 0b5276ec12..b4162966dd 100644
--- a/toolkit/components/pdfjs/content/PdfjsChild.sys.mjs
+++ b/toolkit/components/pdfjs/content/PdfjsChild.sys.mjs
@@ -14,30 +14,27 @@
*/
export class PdfjsChild extends JSWindowActorChild {
- init(supportsFind) {
- if (supportsFind) {
+ init(aSupportsFind) {
+ if (aSupportsFind) {
this.sendAsyncMessage("PDFJS:Parent:addEventListener");
}
}
- dispatchEvent(type, detail) {
+ dispatchEvent(aType, aDetail) {
+ aDetail &&= Cu.cloneInto(aDetail, this.contentWindow);
const contentWindow = this.contentWindow;
const forward = contentWindow.document.createEvent("CustomEvent");
- forward.initCustomEvent(type, true, true, detail);
+ forward.initCustomEvent(aType, true, true, aDetail);
contentWindow.dispatchEvent(forward);
}
receiveMessage(msg) {
switch (msg.name) {
- case "PDFJS:Child:handleEvent": {
- let detail = Cu.cloneInto(msg.data.detail, this.contentWindow);
- this.dispatchEvent(msg.data.type, detail);
+ case "PDFJS:Child:handleEvent":
+ this.dispatchEvent(msg.data.type, msg.data.detail);
break;
- }
-
case "PDFJS:Editing":
- let data = Cu.cloneInto(msg.data, this.contentWindow);
- this.dispatchEvent("editingaction", data);
+ this.dispatchEvent("editingaction", msg.data);
break;
case "PDFJS:ZoomIn":
case "PDFJS:ZoomOut":
diff --git a/toolkit/components/pdfjs/content/build/pdf.mjs b/toolkit/components/pdfjs/content/build/pdf.mjs
index 72dcbae165..4e51efdb78 100644
--- a/toolkit/components/pdfjs/content/build/pdf.mjs
+++ b/toolkit/components/pdfjs/content/build/pdf.mjs
@@ -139,7 +139,8 @@ const AnnotationEditorParamsType = {
HIGHLIGHT_COLOR: 31,
HIGHLIGHT_DEFAULT_COLOR: 32,
HIGHLIGHT_THICKNESS: 33,
- HIGHLIGHT_FREE: 34
+ HIGHLIGHT_FREE: 34,
+ HIGHLIGHT_SHOW_ALL: 35
};
const PermissionFlag = {
PRINT: 0x04,
@@ -1591,9 +1592,173 @@ function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true)
}
}
+;// CONCATENATED MODULE: ./src/display/editor/toolbar.js
+
+class EditorToolbar {
+ #toolbar = null;
+ #colorPicker = null;
+ #editor;
+ #buttons = null;
+ constructor(editor) {
+ this.#editor = editor;
+ }
+ render() {
+ const editToolbar = this.#toolbar = document.createElement("div");
+ editToolbar.className = "editToolbar";
+ editToolbar.setAttribute("role", "toolbar");
+ editToolbar.addEventListener("contextmenu", noContextMenu);
+ editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown);
+ const buttons = this.#buttons = document.createElement("div");
+ buttons.className = "buttons";
+ editToolbar.append(buttons);
+ const position = this.#editor.toolbarPosition;
+ if (position) {
+ const {
+ style
+ } = editToolbar;
+ const x = this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0];
+ style.insetInlineEnd = `${100 * x}%`;
+ style.top = `calc(${100 * position[1]}% + var(--editor-toolbar-vert-offset))`;
+ }
+ this.#addDeleteButton();
+ return editToolbar;
+ }
+ static #pointerDown(e) {
+ e.stopPropagation();
+ }
+ #focusIn(e) {
+ this.#editor._focusEventsAllowed = false;
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ #focusOut(e) {
+ this.#editor._focusEventsAllowed = true;
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ #addListenersToElement(element) {
+ element.addEventListener("focusin", this.#focusIn.bind(this), {
+ capture: true
+ });
+ element.addEventListener("focusout", this.#focusOut.bind(this), {
+ capture: true
+ });
+ element.addEventListener("contextmenu", noContextMenu);
+ }
+ hide() {
+ this.#toolbar.classList.add("hidden");
+ this.#colorPicker?.hideDropdown();
+ }
+ show() {
+ this.#toolbar.classList.remove("hidden");
+ }
+ #addDeleteButton() {
+ const button = document.createElement("button");
+ button.className = "delete";
+ button.tabIndex = 0;
+ button.setAttribute("data-l10n-id", `pdfjs-editor-remove-${this.#editor.editorType}-button`);
+ this.#addListenersToElement(button);
+ button.addEventListener("click", e => {
+ this.#editor._uiManager.delete();
+ });
+ this.#buttons.append(button);
+ }
+ get #divider() {
+ const divider = document.createElement("div");
+ divider.className = "divider";
+ return divider;
+ }
+ addAltTextButton(button) {
+ this.#addListenersToElement(button);
+ this.#buttons.prepend(button, this.#divider);
+ }
+ addColorPicker(colorPicker) {
+ this.#colorPicker = colorPicker;
+ const button = colorPicker.renderButton();
+ this.#addListenersToElement(button);
+ this.#buttons.prepend(button, this.#divider);
+ }
+ remove() {
+ this.#toolbar.remove();
+ this.#colorPicker?.destroy();
+ this.#colorPicker = null;
+ }
+}
+class HighlightToolbar {
+ #buttons = null;
+ #toolbar = null;
+ #uiManager;
+ constructor(uiManager) {
+ this.#uiManager = uiManager;
+ }
+ #render() {
+ const editToolbar = this.#toolbar = document.createElement("div");
+ editToolbar.className = "editToolbar";
+ editToolbar.setAttribute("role", "toolbar");
+ editToolbar.addEventListener("contextmenu", noContextMenu);
+ const buttons = this.#buttons = document.createElement("div");
+ buttons.className = "buttons";
+ editToolbar.append(buttons);
+ this.#addHighlightButton();
+ return editToolbar;
+ }
+ #getLastPoint(boxes, isLTR) {
+ let lastY = 0;
+ let lastX = 0;
+ for (const box of boxes) {
+ const y = box.y + box.height;
+ if (y < lastY) {
+ continue;
+ }
+ const x = box.x + (isLTR ? box.width : 0);
+ if (y > lastY) {
+ lastX = x;
+ lastY = y;
+ continue;
+ }
+ if (isLTR) {
+ if (x > lastX) {
+ lastX = x;
+ }
+ } else if (x < lastX) {
+ lastX = x;
+ }
+ }
+ return [isLTR ? 1 - lastX : lastX, lastY];
+ }
+ show(parent, boxes, isLTR) {
+ const [x, y] = this.#getLastPoint(boxes, isLTR);
+ const {
+ style
+ } = this.#toolbar ||= this.#render();
+ parent.append(this.#toolbar);
+ style.insetInlineEnd = `${100 * x}%`;
+ style.top = `calc(${100 * y}% + var(--editor-toolbar-vert-offset))`;
+ }
+ hide() {
+ this.#toolbar.remove();
+ }
+ #addHighlightButton() {
+ const button = document.createElement("button");
+ button.className = "highlightButton";
+ button.tabIndex = 0;
+ button.setAttribute("data-l10n-id", `pdfjs-highlight-floating-button`);
+ const span = document.createElement("span");
+ button.append(span);
+ span.className = "visuallyHidden";
+ span.setAttribute("data-l10n-id", "pdfjs-editor-highlight-button-label");
+ button.addEventListener("contextmenu", noContextMenu);
+ button.addEventListener("click", () => {
+ this.#uiManager.highlightSelection("floating_button");
+ });
+ this.#buttons.append(button);
+ }
+}
+
;// CONCATENATED MODULE: ./src/display/editor/tools.js
+
function bindEvents(obj, element, names) {
for (const name of names) {
element.addEventListener(name, obj[name].bind(obj));
@@ -1933,10 +2098,12 @@ class AnnotationEditorUIManager {
#draggingEditors = null;
#editorTypes = null;
#editorsToRescale = new Set();
+ #enableHighlightFloatingButton = false;
#filterFactory = null;
#focusMainContainerTimeoutId = null;
#highlightColors = null;
#highlightWhenShiftUp = false;
+ #highlightToolbar = null;
#idManager = new IdManager();
#isEnabled = false;
#isWaiting = false;
@@ -1947,6 +2114,7 @@ class AnnotationEditorUIManager {
#selectedEditors = new Set();
#selectedTextNode = null;
#pageColors = null;
+ #showAllStates = null;
#boundBlur = this.blur.bind(this);
#boundFocus = this.focus.bind(this);
#boundCopy = this.copy.bind(this);
@@ -2031,7 +2199,7 @@ class AnnotationEditorUIManager {
checker: arrowChecker
}]]));
}
- constructor(container, viewer, altTextManager, eventBus, pdfDocument, pageColors, highlightColors, mlManager) {
+ constructor(container, viewer, altTextManager, eventBus, pdfDocument, pageColors, highlightColors, enableHighlightFloatingButton, mlManager) {
this.#container = container;
this.#viewer = viewer;
this.#altTextManager = altTextManager;
@@ -2041,10 +2209,12 @@ class AnnotationEditorUIManager {
this._eventBus._on("scalechanging", this.#boundOnScaleChanging);
this._eventBus._on("rotationchanging", this.#boundOnRotationChanging);
this.#addSelectionListener();
+ this.#addKeyboardManager();
this.#annotationStorage = pdfDocument.annotationStorage;
this.#filterFactory = pdfDocument.filterFactory;
this.#pageColors = pageColors;
this.#highlightColors = highlightColors || null;
+ this.#enableHighlightFloatingButton = enableHighlightFloatingButton;
this.#mlManager = mlManager || null;
this.viewParameters = {
realScale: PixelsPerInch.PDF_TO_CSS_UNITS,
@@ -2069,6 +2239,8 @@ class AnnotationEditorUIManager {
this.#selectedEditors.clear();
this.#commandManager.destroy();
this.#altTextManager?.destroy();
+ this.#highlightToolbar?.hide();
+ this.#highlightToolbar = null;
if (this.#focusMainContainerTimeoutId) {
clearTimeout(this.#focusMainContainerTimeoutId);
this.#focusMainContainerTimeoutId = null;
@@ -2149,6 +2321,11 @@ class AnnotationEditorUIManager {
this.commitOrRemove();
this.viewParameters.rotation = pagesRotation;
}
+ #getAnchorElementForSelection({
+ anchorNode
+ }) {
+ return anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;
+ }
highlightSelection(methodOfCreation = "") {
const selection = document.getSelection();
if (!selection || selection.isCollapsed) {
@@ -2160,15 +2337,20 @@ class AnnotationEditorUIManager {
focusNode,
focusOffset
} = selection;
- const anchorElement = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;
+ const text = selection.toString();
+ const anchorElement = this.#getAnchorElementForSelection(selection);
const textLayer = anchorElement.closest(".textLayer");
const boxes = this.getSelectionBoxes(textLayer);
+ if (!boxes) {
+ return;
+ }
selection.empty();
if (this.#mode === AnnotationEditorType.NONE) {
this._eventBus.dispatch("showannotationeditorui", {
source: this,
mode: AnnotationEditorType.HIGHLIGHT
});
+ this.showAllEditors("highlight", true, true);
}
for (const layer of this.#allLayers.values()) {
if (layer.hasTextLayer(textLayer)) {
@@ -2181,12 +2363,27 @@ class AnnotationEditorUIManager {
anchorNode,
anchorOffset,
focusNode,
- focusOffset
+ focusOffset,
+ text
});
break;
}
}
}
+ #displayHighlightToolbar() {
+ const selection = document.getSelection();
+ if (!selection || selection.isCollapsed) {
+ return;
+ }
+ const anchorElement = this.#getAnchorElementForSelection(selection);
+ const textLayer = anchorElement.closest(".textLayer");
+ const boxes = this.getSelectionBoxes(textLayer);
+ if (!boxes) {
+ return;
+ }
+ this.#highlightToolbar ||= new HighlightToolbar(this);
+ this.#highlightToolbar.show(textLayer, boxes, this.direction === "ltr");
+ }
addToAnnotationStorage(editor) {
if (!editor.isEmpty() && this.#annotationStorage && !this.#annotationStorage.has(editor.id)) {
this.#annotationStorage.setValue(editor.id, editor);
@@ -2196,6 +2393,7 @@ class AnnotationEditorUIManager {
const selection = document.getSelection();
if (!selection || selection.isCollapsed) {
if (this.#selectedTextNode) {
+ this.#highlightToolbar?.hide();
this.#selectedTextNode = null;
this.#dispatchUpdateStates({
hasSelectedText: false
@@ -2209,9 +2407,11 @@ class AnnotationEditorUIManager {
if (anchorNode === this.#selectedTextNode) {
return;
}
- const anchorElement = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode;
- if (!anchorElement.closest(".textLayer")) {
+ const anchorElement = this.#getAnchorElementForSelection(selection);
+ const textLayer = anchorElement.closest(".textLayer");
+ if (!textLayer) {
if (this.#selectedTextNode) {
+ this.#highlightToolbar?.hide();
this.#selectedTextNode = null;
this.#dispatchUpdateStates({
hasSelectedText: false
@@ -2219,13 +2419,17 @@ class AnnotationEditorUIManager {
}
return;
}
+ this.#highlightToolbar?.hide();
this.#selectedTextNode = anchorNode;
this.#dispatchUpdateStates({
hasSelectedText: true
});
- if (this.#mode !== AnnotationEditorType.HIGHLIGHT) {
+ if (this.#mode !== AnnotationEditorType.HIGHLIGHT && this.#mode !== AnnotationEditorType.NONE) {
return;
}
+ if (this.#mode === AnnotationEditorType.HIGHLIGHT) {
+ this.showAllEditors("highlight", true, true);
+ }
this.#highlightWhenShiftUp = this.isShiftKeyDown;
if (!this.isShiftKeyDown) {
const pointerup = e => {
@@ -2235,13 +2439,20 @@ class AnnotationEditorUIManager {
window.removeEventListener("pointerup", pointerup);
window.removeEventListener("blur", pointerup);
if (e.type === "pointerup") {
- this.highlightSelection("main_toolbar");
+ this.#onSelectEnd("main_toolbar");
}
};
window.addEventListener("pointerup", pointerup);
window.addEventListener("blur", pointerup);
}
}
+ #onSelectEnd(methodOfCreation = "") {
+ if (this.#mode === AnnotationEditorType.HIGHLIGHT) {
+ this.highlightSelection(methodOfCreation);
+ } else if (this.#enableHighlightFloatingButton) {
+ this.#displayHighlightToolbar();
+ }
+ }
#addSelectionListener() {
document.addEventListener("selectionchange", this.#boundSelectionChange);
}
@@ -2260,7 +2471,7 @@ class AnnotationEditorUIManager {
this.isShiftKeyDown = false;
if (this.#highlightWhenShiftUp) {
this.#highlightWhenShiftUp = false;
- this.highlightSelection("main_toolbar");
+ this.#onSelectEnd("main_toolbar");
}
if (!this.hasSelection) {
return;
@@ -2398,7 +2609,7 @@ class AnnotationEditorUIManager {
if (!this.isShiftKeyDown && event.key === "Shift") {
this.isShiftKeyDown = true;
}
- if (!this.isEditorHandlingKeyboard) {
+ if (this.#mode !== AnnotationEditorType.NONE && !this.isEditorHandlingKeyboard) {
AnnotationEditorUIManager._keyboardManager.exec(this, event);
}
}
@@ -2407,7 +2618,7 @@ class AnnotationEditorUIManager {
this.isShiftKeyDown = false;
if (this.#highlightWhenShiftUp) {
this.#highlightWhenShiftUp = false;
- this.highlightSelection("main_toolbar");
+ this.#onSelectEnd("main_toolbar");
}
}
}
@@ -2447,7 +2658,6 @@ class AnnotationEditorUIManager {
setEditingState(isEditing) {
if (isEditing) {
this.#addFocusManager();
- this.#addKeyboardManager();
this.#addCopyPasteListeners();
this.#dispatchUpdateStates({
isEditing: this.#mode !== AnnotationEditorType.NONE,
@@ -2458,7 +2668,6 @@ class AnnotationEditorUIManager {
});
} else {
this.#removeFocusManager();
- this.#removeKeyboardManager();
this.#removeCopyPasteListeners();
this.#dispatchUpdateStates({
isEditing: false
@@ -2554,6 +2763,20 @@ class AnnotationEditorUIManager {
case AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR:
this.#mainHighlightColorPicker?.updateColor(value);
break;
+ case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL:
+ this._eventBus.dispatch("reporttelemetry", {
+ source: this,
+ details: {
+ type: "editing",
+ data: {
+ type: "highlight",
+ action: "toggle_visibility"
+ }
+ }
+ });
+ (this.#showAllStates ||= new Map()).set(type, value);
+ this.showAllEditors("highlight", value);
+ break;
}
for (const editor of this.#selectedEditors) {
editor.updateParams(type, value);
@@ -2562,6 +2785,17 @@ class AnnotationEditorUIManager {
editorType.updateDefaultParams(type, value);
}
}
+ showAllEditors(type, visible, updateButton = false) {
+ for (const editor of this.#allEditors.values()) {
+ if (editor.editorType === type) {
+ editor.show(visible);
+ }
+ }
+ const state = this.#showAllStates?.get(AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ?? true;
+ if (state !== visible) {
+ this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, visible]]);
+ }
+ }
enableWaiting(mustWait = false) {
if (this.#isWaiting === mustWait) {
return;
@@ -2582,6 +2816,9 @@ class AnnotationEditorUIManager {
for (const layer of this.#allLayers.values()) {
layer.enable();
}
+ for (const editor of this.#allEditors.values()) {
+ editor.enable();
+ }
}
}
#disableAll() {
@@ -2591,6 +2828,9 @@ class AnnotationEditorUIManager {
for (const layer of this.#allLayers.values()) {
layer.disable();
}
+ for (const editor of this.#allEditors.values()) {
+ editor.disable();
+ }
}
}
getEditors(pageIndex) {
@@ -2641,6 +2881,7 @@ class AnnotationEditorUIManager {
layer.addOrRebuild(editor);
} else {
this.addEditor(editor);
+ this.addToAnnotationStorage(editor);
}
}
setActiveEditor(editor) {
@@ -3172,98 +3413,6 @@ class AltText {
}
}
-;// CONCATENATED MODULE: ./src/display/editor/toolbar.js
-
-class EditorToolbar {
- #toolbar = null;
- #colorPicker = null;
- #editor;
- #buttons = null;
- constructor(editor) {
- this.#editor = editor;
- }
- render() {
- const editToolbar = this.#toolbar = document.createElement("div");
- editToolbar.className = "editToolbar";
- editToolbar.addEventListener("contextmenu", noContextMenu);
- editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown);
- const buttons = this.#buttons = document.createElement("div");
- buttons.className = "buttons";
- editToolbar.append(buttons);
- const position = this.#editor.toolbarPosition;
- if (position) {
- const {
- style
- } = editToolbar;
- const x = this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0];
- style.insetInlineEnd = `${100 * x}%`;
- style.top = `calc(${100 * position[1]}% + var(--editor-toolbar-vert-offset))`;
- }
- this.#addDeleteButton();
- return editToolbar;
- }
- static #pointerDown(e) {
- e.stopPropagation();
- }
- #focusIn(e) {
- this.#editor._focusEventsAllowed = false;
- e.preventDefault();
- e.stopPropagation();
- }
- #focusOut(e) {
- this.#editor._focusEventsAllowed = true;
- e.preventDefault();
- e.stopPropagation();
- }
- #addListenersToElement(element) {
- element.addEventListener("focusin", this.#focusIn.bind(this), {
- capture: true
- });
- element.addEventListener("focusout", this.#focusOut.bind(this), {
- capture: true
- });
- element.addEventListener("contextmenu", noContextMenu);
- }
- hide() {
- this.#toolbar.classList.add("hidden");
- this.#colorPicker?.hideDropdown();
- }
- show() {
- this.#toolbar.classList.remove("hidden");
- }
- #addDeleteButton() {
- const button = document.createElement("button");
- button.className = "delete";
- button.tabIndex = 0;
- button.setAttribute("data-l10n-id", `pdfjs-editor-remove-${this.#editor.editorType}-button`);
- this.#addListenersToElement(button);
- button.addEventListener("click", e => {
- this.#editor._uiManager.delete();
- });
- this.#buttons.append(button);
- }
- get #divider() {
- const divider = document.createElement("div");
- divider.className = "divider";
- return divider;
- }
- addAltTextButton(button) {
- this.#addListenersToElement(button);
- this.#buttons.prepend(button, this.#divider);
- }
- addColorPicker(colorPicker) {
- this.#colorPicker = colorPicker;
- const button = colorPicker.renderButton();
- this.#addListenersToElement(button);
- this.#buttons.prepend(button, this.#divider);
- }
- remove() {
- this.#toolbar.remove();
- this.#colorPicker?.destroy();
- this.#colorPicker = null;
- }
-}
-
;// CONCATENATED MODULE: ./src/display/editor/editor.js
@@ -3273,6 +3422,7 @@ class EditorToolbar {
class AnnotationEditor {
#allResizerDivs = null;
#altText = null;
+ #disabled = false;
#keepAspectRatio = false;
#resizersDiv = null;
#savedDimensions = null;
@@ -3289,6 +3439,7 @@ class AnnotationEditor {
#prevDragY = 0;
#telemetryTimeouts = null;
_initialOptions = Object.create(null);
+ _isVisible = true;
_uiManager = null;
_focusEventsAllowed = true;
_l10nPromise = null;
@@ -3555,6 +3706,9 @@ class AnnotationEditor {
return [-x, -y];
}
}
+ get _mustFixPosition() {
+ return true;
+ }
fixAndSetPosition(rotation = this.rotation) {
const [pageWidth, pageHeight] = this.pageDimensions;
let {
@@ -3567,23 +3721,25 @@ class AnnotationEditor {
height *= pageHeight;
x *= pageWidth;
y *= pageHeight;
- switch (rotation) {
- case 0:
- x = Math.max(0, Math.min(pageWidth - width, x));
- y = Math.max(0, Math.min(pageHeight - height, y));
- break;
- case 90:
- x = Math.max(0, Math.min(pageWidth - height, x));
- y = Math.min(pageHeight, Math.max(width, y));
- break;
- case 180:
- x = Math.min(pageWidth, Math.max(width, x));
- y = Math.min(pageHeight, Math.max(height, y));
- break;
- case 270:
- x = Math.min(pageWidth, Math.max(height, x));
- y = Math.max(0, Math.min(pageHeight - width, y));
- break;
+ if (this._mustFixPosition) {
+ switch (rotation) {
+ case 0:
+ x = Math.max(0, Math.min(pageWidth - width, x));
+ y = Math.max(0, Math.min(pageHeight - height, y));
+ break;
+ case 90:
+ x = Math.max(0, Math.min(pageWidth - height, x));
+ y = Math.min(pageHeight, Math.max(width, y));
+ break;
+ case 180:
+ x = Math.min(pageWidth, Math.max(width, x));
+ y = Math.min(pageHeight, Math.max(height, y));
+ break;
+ case 270:
+ x = Math.min(pageWidth, Math.max(height, x));
+ y = Math.max(0, Math.min(pageHeight - width, y));
+ break;
+ }
}
this.x = x /= pageWidth;
this.y = y /= pageHeight;
@@ -3902,7 +4058,10 @@ class AnnotationEditor {
this.div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360);
this.div.className = this.name;
this.div.setAttribute("id", this.id);
- this.div.setAttribute("tabIndex", 0);
+ this.div.tabIndex = this.#disabled ? -1 : 0;
+ if (!this._isVisible) {
+ this.div.classList.add("hidden");
+ }
this.setInForeground();
this.div.addEventListener("focusin", this.#boundFocusin);
this.div.addEventListener("focusout", this.#boundFocusout);
@@ -4100,6 +4259,7 @@ class AnnotationEditor {
}
this.#telemetryTimeouts = null;
}
+ this.parent = null;
}
get isResizable() {
return false;
@@ -4319,6 +4479,22 @@ class AnnotationEditor {
}
});
}
+ show(visible = this._isVisible) {
+ this.div.classList.toggle("hidden", !visible);
+ this._isVisible = visible;
+ }
+ enable() {
+ if (this.div) {
+ this.div.tabIndex = 0;
+ }
+ this.#disabled = false;
+ }
+ disable() {
+ if (this.div) {
+ this.div.tabIndex = -1;
+ }
+ this.#disabled = true;
+ }
}
class FakeEditor extends AnnotationEditor {
constructor(params) {
@@ -8373,18 +8549,44 @@ class Metadata {
const INTERNAL = Symbol("INTERNAL");
class OptionalContentGroup {
+ #isDisplay = false;
+ #isPrint = false;
+ #userSet = false;
#visible = true;
- constructor(name, intent) {
+ constructor(renderingIntent, {
+ name,
+ intent,
+ usage
+ }) {
+ this.#isDisplay = !!(renderingIntent & RenderingIntentFlag.DISPLAY);
+ this.#isPrint = !!(renderingIntent & RenderingIntentFlag.PRINT);
this.name = name;
this.intent = intent;
+ this.usage = usage;
}
get visible() {
- return this.#visible;
+ if (this.#userSet) {
+ return this.#visible;
+ }
+ if (!this.#visible) {
+ return false;
+ }
+ const {
+ print,
+ view
+ } = this.usage;
+ if (this.#isDisplay) {
+ return view?.viewState !== "OFF";
+ } else if (this.#isPrint) {
+ return print?.printState !== "OFF";
+ }
+ return true;
}
- _setVisible(internal, visible) {
+ _setVisible(internal, visible, userSet = false) {
if (internal !== INTERNAL) {
unreachable("Internal method `_setVisible` called.");
}
+ this.#userSet = userSet;
this.#visible = visible;
}
}
@@ -8393,7 +8595,8 @@ class OptionalContentConfig {
#groups = new Map();
#initialHash = null;
#order = null;
- constructor(data) {
+ constructor(data, renderingIntent = RenderingIntentFlag.DISPLAY) {
+ this.renderingIntent = renderingIntent;
this.name = null;
this.creator = null;
if (data === null) {
@@ -8403,7 +8606,7 @@ class OptionalContentConfig {
this.creator = data.creator;
this.#order = data.order;
for (const group of data.groups) {
- this.#groups.set(group.id, new OptionalContentGroup(group.name, group.intent));
+ this.#groups.set(group.id, new OptionalContentGroup(renderingIntent, group));
}
if (data.baseState === "OFF") {
for (const group of this.#groups.values()) {
@@ -8524,11 +8727,43 @@ class OptionalContentConfig {
return true;
}
setVisibility(id, visible = true) {
- if (!this.#groups.has(id)) {
+ const group = this.#groups.get(id);
+ if (!group) {
warn(`Optional content group not found: ${id}`);
return;
}
- this.#groups.get(id)._setVisible(INTERNAL, !!visible);
+ group._setVisible(INTERNAL, !!visible, true);
+ this.#cachedGetHash = null;
+ }
+ setOCGState({
+ state,
+ preserveRB
+ }) {
+ let operator;
+ for (const elem of state) {
+ switch (elem) {
+ case "ON":
+ case "OFF":
+ case "Toggle":
+ operator = elem;
+ continue;
+ }
+ const group = this.#groups.get(elem);
+ if (!group) {
+ continue;
+ }
+ switch (operator) {
+ case "ON":
+ group._setVisible(INTERNAL, true);
+ break;
+ case "OFF":
+ group._setVisible(INTERNAL, false);
+ break;
+ case "Toggle":
+ group._setVisible(INTERNAL, !group.visible);
+ break;
+ }
+ }
this.#cachedGetHash = null;
}
get hasInitialVisibility() {
@@ -8970,7 +9205,7 @@ function getDocument(src) {
}
const fetchDocParams = {
docId,
- apiVersion: "4.1.249",
+ apiVersion: "4.1.342",
data,
password,
disableAutoFetch,
@@ -9207,8 +9442,13 @@ class PDFDocumentProxy {
getOutline() {
return this._transport.getOutline();
}
- getOptionalContentConfig() {
- return this._transport.getOptionalContentConfig();
+ getOptionalContentConfig({
+ intent = "display"
+ } = {}) {
+ const {
+ renderingIntent
+ } = this._transport.getRenderingIntent(intent);
+ return this._transport.getOptionalContentConfig(renderingIntent);
}
getPermissions() {
return this._transport.getPermissions();
@@ -9299,8 +9539,10 @@ class PDFPageProxy {
getAnnotations({
intent = "display"
} = {}) {
- const intentArgs = this._transport.getRenderingIntent(intent);
- return this._transport.getAnnotations(this._pageIndex, intentArgs.renderingIntent);
+ const {
+ renderingIntent
+ } = this._transport.getRenderingIntent(intent);
+ return this._transport.getAnnotations(this._pageIndex, renderingIntent);
}
getJSActions() {
return this._transport.getPageJSActions(this._pageIndex);
@@ -9328,21 +9570,23 @@ class PDFPageProxy {
}) {
this._stats?.time("Overall");
const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage);
+ const {
+ renderingIntent,
+ cacheKey
+ } = intentArgs;
this.#pendingCleanup = false;
this.#abortDelayedCleanup();
- if (!optionalContentConfigPromise) {
- optionalContentConfigPromise = this._transport.getOptionalContentConfig();
- }
- let intentState = this._intentStates.get(intentArgs.cacheKey);
+ optionalContentConfigPromise ||= this._transport.getOptionalContentConfig(renderingIntent);
+ let intentState = this._intentStates.get(cacheKey);
if (!intentState) {
intentState = Object.create(null);
- this._intentStates.set(intentArgs.cacheKey, intentState);
+ this._intentStates.set(cacheKey, intentState);
}
if (intentState.streamReaderCancelTimeout) {
clearTimeout(intentState.streamReaderCancelTimeout);
intentState.streamReaderCancelTimeout = null;
}
- const intentPrint = !!(intentArgs.renderingIntent & RenderingIntentFlag.PRINT);
+ const intentPrint = !!(renderingIntent & RenderingIntentFlag.PRINT);
if (!intentState.displayReadyCapability) {
intentState.displayReadyCapability = new PromiseCapability();
intentState.operatorList = {
@@ -9399,6 +9643,9 @@ class PDFPageProxy {
return;
}
this._stats?.time("Rendering");
+ if (!(optionalContentConfig.renderingIntent & renderingIntent)) {
+ throw new Error("Must use the same `intent`-argument when calling the `PDFPageProxy.render` " + "and `PDFDocumentProxy.getOptionalContentConfig` methods.");
+ }
internalRenderTask.initializeGraphics({
transparency,
optionalContentConfig
@@ -10338,8 +10585,8 @@ class WorkerTransport {
getOutline() {
return this.messageHandler.sendWithPromise("GetOutline", null);
}
- getOptionalContentConfig() {
- return this.messageHandler.sendWithPromise("GetOptionalContentConfig", null).then(results => new OptionalContentConfig(results));
+ getOptionalContentConfig(renderingIntent) {
+ return this.#cacheSimpleMethod("GetOptionalContentConfig").then(data => new OptionalContentConfig(data, renderingIntent));
}
getPermissions() {
return this.messageHandler.sendWithPromise("GetPermissions", null);
@@ -10602,8 +10849,8 @@ class InternalRenderTask {
}
}
}
-const version = "4.1.249";
-const build = "d07f37f44";
+const version = "4.1.342";
+const build = "e384df6f1";
;// CONCATENATED MODULE: ./src/shared/scripting_utils.js
function makeColorComp(n) {
@@ -11002,9 +11249,12 @@ class AnnotationElement {
container.tabIndex = DEFAULT_TAB_INDEX;
}
container.style.zIndex = this.parent.zIndex++;
- if (this.data.popupRef) {
+ if (data.popupRef) {
container.setAttribute("aria-haspopup", "dialog");
}
+ if (data.alternativeText) {
+ container.title = data.alternativeText;
+ }
if (data.noRotate) {
container.classList.add("norotate");
}
@@ -11652,9 +11902,6 @@ class TextAnnotationElement extends AnnotationElement {
}
class WidgetAnnotationElement extends AnnotationElement {
render() {
- if (this.data.alternativeText) {
- this.container.title = this.data.alternativeText;
- }
return this.container;
}
showElementAndHideCanvas(element) {
@@ -12255,9 +12502,6 @@ class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
render() {
const container = super.render();
container.classList.add("buttonWidgetAnnotation", "pushButton");
- if (this.data.alternativeText) {
- container.title = this.data.alternativeText;
- }
const linkElement = container.lastChild;
if (this.enableScripting && this.hasJSActions && linkElement) {
this._setDefaultPropertiesFromJS(linkElement);
@@ -13271,11 +13515,13 @@ class AnnotationLayer {
+const EOL_PATTERN = /\r\n?|\n/g;
class FreeTextEditor extends AnnotationEditor {
#boundEditorDivBlur = this.editorDivBlur.bind(this);
#boundEditorDivFocus = this.editorDivFocus.bind(this);
#boundEditorDivInput = this.editorDivInput.bind(this);
#boundEditorDivKeydown = this.editorDivKeydown.bind(this);
+ #boundEditorDivPaste = this.editorDivPaste.bind(this);
#color;
#content = "";
#editorDivId = `${this.id}-editor`;
@@ -13428,6 +13674,7 @@ class FreeTextEditor extends AnnotationEditor {
this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus);
this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur);
this.editorDiv.addEventListener("input", this.#boundEditorDivInput);
+ this.editorDiv.addEventListener("paste", this.#boundEditorDivPaste);
}
disableEditMode() {
if (!this.isInEditMode()) {
@@ -13443,6 +13690,7 @@ class FreeTextEditor extends AnnotationEditor {
this.editorDiv.removeEventListener("focus", this.#boundEditorDivFocus);
this.editorDiv.removeEventListener("blur", this.#boundEditorDivBlur);
this.editorDiv.removeEventListener("input", this.#boundEditorDivInput);
+ this.editorDiv.removeEventListener("paste", this.#boundEditorDivPaste);
this.div.focus({
preventScroll: true
});
@@ -13484,10 +13732,8 @@ class FreeTextEditor extends AnnotationEditor {
#extractText() {
const buffer = [];
this.editorDiv.normalize();
- const EOL_PATTERN = /\r\n?|\n/g;
for (const child of this.editorDiv.childNodes) {
- const content = child.nodeType === Node.TEXT_NODE ? child.nodeValue : child.innerText;
- buffer.push(content.replaceAll(EOL_PATTERN, ""));
+ buffer.push(FreeTextEditor.#getNodeContent(child));
}
return buffer.join("\n");
}
@@ -13657,6 +13903,85 @@ class FreeTextEditor extends AnnotationEditor {
}
return this.div;
}
+ static #getNodeContent(node) {
+ return (node.nodeType === Node.TEXT_NODE ? node.nodeValue : node.innerText).replaceAll(EOL_PATTERN, "");
+ }
+ editorDivPaste(event) {
+ const clipboardData = event.clipboardData || window.clipboardData;
+ const {
+ types
+ } = clipboardData;
+ if (types.length === 1 && types[0] === "text/plain") {
+ return;
+ }
+ event.preventDefault();
+ const paste = FreeTextEditor.#deserializeContent(clipboardData.getData("text") || "").replaceAll(EOL_PATTERN, "\n");
+ if (!paste) {
+ return;
+ }
+ const selection = window.getSelection();
+ if (!selection.rangeCount) {
+ return;
+ }
+ this.editorDiv.normalize();
+ selection.deleteFromDocument();
+ const range = selection.getRangeAt(0);
+ if (!paste.includes("\n")) {
+ range.insertNode(document.createTextNode(paste));
+ this.editorDiv.normalize();
+ selection.collapseToStart();
+ return;
+ }
+ const {
+ startContainer,
+ startOffset
+ } = range;
+ const bufferBefore = [];
+ const bufferAfter = [];
+ if (startContainer.nodeType === Node.TEXT_NODE) {
+ const parent = startContainer.parentElement;
+ bufferAfter.push(startContainer.nodeValue.slice(startOffset).replaceAll(EOL_PATTERN, ""));
+ if (parent !== this.editorDiv) {
+ let buffer = bufferBefore;
+ for (const child of this.editorDiv.childNodes) {
+ if (child === parent) {
+ buffer = bufferAfter;
+ continue;
+ }
+ buffer.push(FreeTextEditor.#getNodeContent(child));
+ }
+ }
+ bufferBefore.push(startContainer.nodeValue.slice(0, startOffset).replaceAll(EOL_PATTERN, ""));
+ } else if (startContainer === this.editorDiv) {
+ let buffer = bufferBefore;
+ let i = 0;
+ for (const child of this.editorDiv.childNodes) {
+ if (i++ === startOffset) {
+ buffer = bufferAfter;
+ }
+ buffer.push(FreeTextEditor.#getNodeContent(child));
+ }
+ }
+ this.#content = `${bufferBefore.join("\n")}${paste}${bufferAfter.join("\n")}`;
+ this.#setContent();
+ const newRange = new Range();
+ let beforeLength = bufferBefore.reduce((acc, line) => acc + line.length, 0);
+ for (const {
+ firstChild
+ } of this.editorDiv.childNodes) {
+ if (firstChild.nodeType === Node.TEXT_NODE) {
+ const length = firstChild.nodeValue.length;
+ if (beforeLength <= length) {
+ newRange.setStart(firstChild, beforeLength);
+ newRange.setEnd(firstChild, beforeLength);
+ break;
+ }
+ beforeLength -= length;
+ }
+ }
+ selection.removeAllRanges();
+ selection.addRange(newRange);
+ }
#setContent() {
this.editorDiv.replaceChildren();
if (!this.#content) {
@@ -14392,6 +14717,7 @@ class ColorPicker {
#dropdown = null;
#dropdownWasFromKeyboard = false;
#isMainColorPicker = false;
+ #editor = null;
#eventBus;
#uiManager = null;
#type;
@@ -14405,6 +14731,7 @@ class ColorPicker {
if (editor) {
this.#isMainColorPicker = false;
this.#type = AnnotationEditorParamsType.HIGHLIGHT_COLOR;
+ this.#editor = editor;
} else {
this.#isMainColorPicker = true;
this.#type = AnnotationEditorParamsType.HIGHLIGHT_DEFAULT_COLOR;
@@ -14423,6 +14750,7 @@ class ColorPicker {
button.addEventListener("keydown", this.#boundKeyDown);
const swatch = this.#buttonSwatch = document.createElement("span");
swatch.className = "swatch";
+ swatch.setAttribute("aria-hidden", true);
swatch.style.backgroundColor = this.#defaultColor;
button.append(swatch);
return button;
@@ -14546,7 +14874,11 @@ class ColorPicker {
return this.#dropdown && !this.#dropdown.classList.contains("hidden");
}
_hideDropdownFromKeyboard() {
- if (this.#isMainColorPicker || !this.#isDropdownVisible) {
+ if (this.#isMainColorPicker) {
+ return;
+ }
+ if (!this.#isDropdownVisible) {
+ this.#editor?.unselect();
return;
}
this.hideDropdown();
@@ -14600,6 +14932,7 @@ class HighlightEditor extends AnnotationEditor {
#lastPoint = null;
#opacity;
#outlineId = null;
+ #text = "";
#thickness;
#methodOfCreation = "";
static _defaultColor = null;
@@ -14633,6 +14966,7 @@ class HighlightEditor extends AnnotationEditor {
this.#opacity = params.opacity || HighlightEditor._defaultOpacity;
this.#boxes = params.boxes || null;
this.#methodOfCreation = params.methodOfCreation || "";
+ this.#text = params.text || "";
this._isDraggable = false;
if (params.highlightId > -1) {
this.#isFreeHighlight = true;
@@ -14857,11 +15191,11 @@ class HighlightEditor extends AnnotationEditor {
this.div.focus();
}
remove() {
- super.remove();
this.#cleanDrawLayer();
this._reportTelemetry({
action: "deleted"
});
+ super.remove();
}
rebuild() {
if (!this.parent) {
@@ -14885,6 +15219,7 @@ class HighlightEditor extends AnnotationEditor {
mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor");
}
super.setParent(parent);
+ this.show(this._isVisible);
if (mustBeSelected) {
this.select();
}
@@ -14979,6 +15314,12 @@ class HighlightEditor extends AnnotationEditor {
return this.div;
}
const div = super.render();
+ if (this.#text) {
+ const mark = document.createElement("mark");
+ div.append(mark);
+ mark.append(document.createTextNode(this.#text));
+ mark.className = "visuallyHidden";
+ }
if (this.#isFreeHighlight) {
div.classList.add("free");
} else {
@@ -14986,6 +15327,7 @@ class HighlightEditor extends AnnotationEditor {
}
const highlightDiv = this.#highlightDiv = document.createElement("div");
div.append(highlightDiv);
+ highlightDiv.setAttribute("aria-hidden", "true");
highlightDiv.className = "internal";
highlightDiv.style.clipPath = this.#clipPathId;
const [parentWidth, parentHeight] = this.parentDimensions;
@@ -15029,16 +15371,32 @@ class HighlightEditor extends AnnotationEditor {
}
select() {
super.select();
+ if (!this.#outlineId) {
+ return;
+ }
this.parent?.drawLayer.removeClass(this.#outlineId, "hovered");
this.parent?.drawLayer.addClass(this.#outlineId, "selected");
}
unselect() {
super.unselect();
+ if (!this.#outlineId) {
+ return;
+ }
this.parent?.drawLayer.removeClass(this.#outlineId, "selected");
if (!this.#isFreeHighlight) {
this.#setCaret(false);
}
}
+ get _mustFixPosition() {
+ return !this.#isFreeHighlight;
+ }
+ show(visible = this._isVisible) {
+ super.show(visible);
+ if (this.parent) {
+ this.parent.drawLayer.show(this.#id, visible);
+ this.parent.drawLayer.show(this.#outlineId, visible);
+ }
+ }
#getRotation() {
return this.#isFreeHighlight ? this.rotation : 0;
}
@@ -15487,7 +15845,7 @@ class InkEditor extends AnnotationEditor {
this.allRawPaths.push(currentPath);
this.paths.push(bezier);
this.bezierPath2D.push(path2D);
- this.rebuild();
+ this._uiManager.rebuild(this);
};
const undo = () => {
this.allRawPaths.pop();
@@ -16114,7 +16472,7 @@ class StampEditor extends AnnotationEditor {
if (this.div === null) {
return;
}
- if (this.#bitmapId) {
+ if (this.#bitmapId && this.#canvas === null) {
this.#getBitmap();
}
if (!this.isAttachedToDOM) {
@@ -16126,7 +16484,7 @@ class StampEditor extends AnnotationEditor {
this.div.focus();
}
isEmpty() {
- return !(this.#bitmapPromise || this.#bitmap || this.#bitmapUrl || this.#bitmapFile);
+ return !(this.#bitmapPromise || this.#bitmap || this.#bitmapUrl || this.#bitmapFile || this.#bitmapId);
}
get isResizable() {
return true;
@@ -16142,6 +16500,7 @@ class StampEditor extends AnnotationEditor {
}
super.render();
this.div.hidden = true;
+ this.addAltTextButton();
if (this.#bitmap) {
this.#createCanvas();
} else {
@@ -16186,7 +16545,6 @@ class StampEditor extends AnnotationEditor {
this._reportTelemetry({
action: "inserted_image"
});
- this.addAltTextButton();
if (this.#bitmapFileName) {
canvas.setAttribute("aria-label", this.#bitmapFileName);
}
@@ -16404,9 +16762,9 @@ class AnnotationEditorLayer {
#accessibilityManager;
#allowClick = false;
#annotationLayer = null;
- #boundPointerup = this.pointerup.bind(this);
- #boundPointerdown = this.pointerdown.bind(this);
- #boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this);
+ #boundPointerup = null;
+ #boundPointerdown = null;
+ #boundTextLayerPointerDown = null;
#editorFocusTimeoutId = null;
#editors = new Map();
#hadPointerDown = false;
@@ -16448,6 +16806,9 @@ class AnnotationEditorLayer {
get isEmpty() {
return this.#editors.size === 0;
}
+ get isInvisible() {
+ return this.isEmpty && this.#uiManager.getMode() === AnnotationEditorType.NONE;
+ }
updateToolbar(mode) {
this.#uiManager.updateToolbar(mode);
}
@@ -16519,6 +16880,7 @@ class AnnotationEditorLayer {
this.#annotationLayer?.div.classList.toggle("disabled", !enabled);
}
enable() {
+ this.div.tabIndex = 0;
this.togglePointerEvents(true);
const annotationElementIds = new Set();
for (const editor of this.#editors.values()) {
@@ -16549,6 +16911,7 @@ class AnnotationEditorLayer {
}
disable() {
this.#isDisabling = true;
+ this.div.tabIndex = -1;
this.togglePointerEvents(false);
const hiddenAnnotationIds = new Set();
for (const editor of this.#editors.values()) {
@@ -16597,14 +16960,18 @@ class AnnotationEditorLayer {
this.#uiManager.setActiveEditor(editor);
}
enableTextSelection() {
- if (this.#textLayer?.div) {
+ this.div.tabIndex = -1;
+ if (this.#textLayer?.div && !this.#boundTextLayerPointerDown) {
+ this.#boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this);
this.#textLayer.div.addEventListener("pointerdown", this.#boundTextLayerPointerDown);
this.#textLayer.div.classList.add("highlighting");
}
}
disableTextSelection() {
- if (this.#textLayer?.div) {
+ this.div.tabIndex = 0;
+ if (this.#textLayer?.div && this.#boundTextLayerPointerDown) {
this.#textLayer.div.removeEventListener("pointerdown", this.#boundTextLayerPointerDown);
+ this.#boundTextLayerPointerDown = null;
this.#textLayer.div.classList.remove("highlighting");
}
}
@@ -16617,6 +16984,7 @@ class AnnotationEditorLayer {
if (event.button !== 0 || event.ctrlKey && isMac) {
return;
}
+ this.#uiManager.showAllEditors("highlight", true, true);
this.#textLayer.div.classList.add("free");
HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", event);
this.#textLayer.div.addEventListener("pointerup", () => {
@@ -16628,12 +16996,22 @@ class AnnotationEditorLayer {
}
}
enableClick() {
+ if (this.#boundPointerdown) {
+ return;
+ }
+ this.#boundPointerdown = this.pointerdown.bind(this);
+ this.#boundPointerup = this.pointerup.bind(this);
this.div.addEventListener("pointerdown", this.#boundPointerdown);
this.div.addEventListener("pointerup", this.#boundPointerup);
}
disableClick() {
+ if (!this.#boundPointerdown) {
+ return;
+ }
this.div.removeEventListener("pointerdown", this.#boundPointerdown);
this.div.removeEventListener("pointerup", this.#boundPointerup);
+ this.#boundPointerdown = null;
+ this.#boundPointerup = null;
}
attach(editor) {
this.#editors.set(editor.id, editor);
@@ -16678,6 +17056,9 @@ class AnnotationEditorLayer {
}
}
add(editor) {
+ if (editor.parent === this && editor.isAttachedToDOM) {
+ return;
+ }
this.changeParent(editor);
this.#uiManager.addEditor(editor);
this.attach(editor);
@@ -16720,6 +17101,7 @@ class AnnotationEditorLayer {
if (editor.needsToBeRebuilt()) {
editor.parent ||= this;
editor.rebuild();
+ editor.show();
} else {
this.add(editor);
}
@@ -16910,6 +17292,7 @@ class AnnotationEditorLayer {
setLayerDimensions(this.div, viewport);
for (const editor of this.#uiManager.getEditors(this.pageIndex)) {
this.add(editor);
+ editor.rebuild();
}
this.updateMode();
}
@@ -16917,6 +17300,7 @@ class AnnotationEditorLayer {
viewport
}) {
this.#uiManager.commitOrRemove();
+ this.#cleanup();
const oldRotation = this.viewport.rotation;
const rotation = viewport.rotation;
this.viewport = viewport;
@@ -16928,7 +17312,7 @@ class AnnotationEditorLayer {
editor.rotate(rotation);
}
}
- this.updateMode();
+ this.addInkEditorIfNeeded(false);
}
get pageDimensions() {
const {
@@ -16990,6 +17374,7 @@ class DrawLayer {
#createSVG(box) {
const svg = DrawLayer._svgFactory.create(1, 1, true);
this.#parent.append(svg);
+ svg.setAttribute("aria-hidden", true);
DrawLayer.#setBox(svg, box);
return svg;
}
@@ -17102,6 +17487,9 @@ class DrawLayer {
updateBox(id, box) {
DrawLayer.#setBox(this.#mapping.get(id), box);
}
+ show(id, visible) {
+ this.#mapping.get(id).classList.toggle("hidden", !visible);
+ }
rotate(id, angle) {
this.#mapping.get(id).setAttribute("data-main-rotation", angle);
}
@@ -17146,8 +17534,8 @@ class DrawLayer {
-const pdfjsVersion = "4.1.249";
-const pdfjsBuild = "d07f37f44";
+const pdfjsVersion = "4.1.342";
+const pdfjsBuild = "e384df6f1";
var __webpack_exports__AbortException = __webpack_exports__.AbortException;
var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer;
diff --git a/toolkit/components/pdfjs/content/build/pdf.scripting.mjs b/toolkit/components/pdfjs/content/build/pdf.scripting.mjs
index d667676f1a..f590e83af3 100644
--- a/toolkit/components/pdfjs/content/build/pdf.scripting.mjs
+++ b/toolkit/components/pdfjs/content/build/pdf.scripting.mjs
@@ -3957,8 +3957,8 @@ function initSandbox(params) {
;// CONCATENATED MODULE: ./src/pdf.scripting.js
-const pdfjsVersion = "4.1.249";
-const pdfjsBuild = "d07f37f44";
+const pdfjsVersion = "4.1.342";
+const pdfjsBuild = "e384df6f1";
globalThis.pdfjsScripting = {
initSandbox: initSandbox
};
diff --git a/toolkit/components/pdfjs/content/build/pdf.worker.mjs b/toolkit/components/pdfjs/content/build/pdf.worker.mjs
index 8929572511..e2cd54cf56 100644
--- a/toolkit/components/pdfjs/content/build/pdf.worker.mjs
+++ b/toolkit/components/pdfjs/content/build/pdf.worker.mjs
@@ -94,7 +94,8 @@ const AnnotationEditorParamsType = {
HIGHLIGHT_COLOR: 31,
HIGHLIGHT_DEFAULT_COLOR: 32,
HIGHLIGHT_THICKNESS: 33,
- HIGHLIGHT_FREE: 34
+ HIGHLIGHT_FREE: 34,
+ HIGHLIGHT_SHOW_ALL: 35
};
const PermissionFlag = {
PRINT: 0x04,
@@ -31442,17 +31443,25 @@ class PartialEvaluator {
}
const SMALL_IMAGE_DIMENSIONS = 200;
if (isInline && !dict.has("SMask") && !dict.has("Mask") && w + h < SMALL_IMAGE_DIMENSIONS) {
- const imageObj = new PDFImage({
- xref: this.xref,
- res: resources,
- image,
- isInline,
- pdfFunctionFactory: this._pdfFunctionFactory,
- localColorSpaceCache
- });
- imgData = await imageObj.createImageData(true, false);
- operatorList.isOffscreenCanvasSupported = this.options.isOffscreenCanvasSupported;
- operatorList.addImageOps(OPS.paintInlineImageXObject, [imgData], optionalContent);
+ try {
+ const imageObj = new PDFImage({
+ xref: this.xref,
+ res: resources,
+ image,
+ isInline,
+ pdfFunctionFactory: this._pdfFunctionFactory,
+ localColorSpaceCache
+ });
+ imgData = await imageObj.createImageData(true, false);
+ operatorList.isOffscreenCanvasSupported = this.options.isOffscreenCanvasSupported;
+ operatorList.addImageOps(OPS.paintInlineImageXObject, [imgData], optionalContent);
+ } catch (reason) {
+ const msg = `Unable to decode inline image: "${reason}".`;
+ if (!this.options.ignoreErrors) {
+ throw new Error(msg);
+ }
+ warn(msg);
+ }
return;
}
let objId = `img_${this.idFactory.createObjId()}`,
@@ -38663,14 +38672,9 @@ class Catalog {
continue;
}
groupRefs.put(groupRef);
- const group = this.xref.fetch(groupRef);
- groups.push({
- id: groupRef.toString(),
- name: typeof group.get("Name") === "string" ? stringToPDFString(group.get("Name")) : null,
- intent: typeof group.get("Intent") === "string" ? stringToPDFString(group.get("Intent")) : null
- });
+ groups.push(this.#readOptionalContentGroup(groupRef));
}
- config = this._readOptionalContentConfig(defaultConfig, groupRefs);
+ config = this.#readOptionalContentConfig(defaultConfig, groupRefs);
config.groups = groups;
} catch (ex) {
if (ex instanceof MissingDataException) {
@@ -38680,7 +38684,62 @@ class Catalog {
}
return shadow(this, "optionalContentConfig", config);
}
- _readOptionalContentConfig(config, contentGroupRefs) {
+ #readOptionalContentGroup(groupRef) {
+ const group = this.xref.fetch(groupRef);
+ const obj = {
+ id: groupRef.toString(),
+ name: null,
+ intent: null,
+ usage: {
+ print: null,
+ view: null
+ }
+ };
+ const name = group.get("Name");
+ if (typeof name === "string") {
+ obj.name = stringToPDFString(name);
+ }
+ let intent = group.getArray("Intent");
+ if (!Array.isArray(intent)) {
+ intent = [intent];
+ }
+ if (intent.every(i => i instanceof Name)) {
+ obj.intent = intent.map(i => i.name);
+ }
+ const usage = group.get("Usage");
+ if (!(usage instanceof Dict)) {
+ return obj;
+ }
+ const usageObj = obj.usage;
+ const print = usage.get("Print");
+ if (print instanceof Dict) {
+ const printState = print.get("PrintState");
+ if (printState instanceof Name) {
+ switch (printState.name) {
+ case "ON":
+ case "OFF":
+ usageObj.print = {
+ printState: printState.name
+ };
+ }
+ }
+ }
+ const view = usage.get("View");
+ if (view instanceof Dict) {
+ const viewState = view.get("ViewState");
+ if (viewState instanceof Name) {
+ switch (viewState.name) {
+ case "ON":
+ case "OFF":
+ usageObj.view = {
+ viewState: viewState.name
+ };
+ }
+ }
+ }
+ return obj;
+ }
+ #readOptionalContentConfig(config, contentGroupRefs) {
function parseOnOff(refs) {
const onParsed = [];
if (Array.isArray(refs)) {
@@ -55084,17 +55143,24 @@ class Page {
}));
}
const sortedAnnotations = [];
- let popupAnnotations;
+ let popupAnnotations, widgetAnnotations;
for (const annotation of await Promise.all(annotationPromises)) {
if (!annotation) {
continue;
}
+ if (annotation instanceof WidgetAnnotation) {
+ (widgetAnnotations ||= []).push(annotation);
+ continue;
+ }
if (annotation instanceof PopupAnnotation) {
(popupAnnotations ||= []).push(annotation);
continue;
}
sortedAnnotations.push(annotation);
}
+ if (widgetAnnotations) {
+ sortedAnnotations.push(...widgetAnnotations);
+ }
if (popupAnnotations) {
sortedAnnotations.push(...popupAnnotations);
}
@@ -56659,7 +56725,7 @@ class WorkerMessageHandler {
docId,
apiVersion
} = docParams;
- const workerVersion = "4.1.249";
+ const workerVersion = "4.1.342";
if (apiVersion !== workerVersion) {
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
}
@@ -57221,8 +57287,8 @@ if (typeof window === "undefined" && !isNodeJS && typeof self !== "undefined" &&
;// CONCATENATED MODULE: ./src/pdf.worker.js
-const pdfjsVersion = "4.1.249";
-const pdfjsBuild = "d07f37f44";
+const pdfjsVersion = "4.1.342";
+const pdfjsBuild = "e384df6f1";
var __webpack_exports__WorkerMessageHandler = __webpack_exports__.WorkerMessageHandler;
export { __webpack_exports__WorkerMessageHandler as WorkerMessageHandler };
diff --git a/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-openinapp.svg b/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-openinapp.svg
deleted file mode 100644
index 80ec891aad..0000000000
--- a/toolkit/components/pdfjs/content/web/images/gv-toolbarButton-openinapp.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M4 4.5H6.5V7H4V4.5Z" fill="black"/>
-<path d="M6.5 10.5H4V13H6.5V10.5Z" fill="black"/>
-<path d="M13.25 10.5H10.75V13H13.25V10.5Z" fill="black"/>
-<path d="M17.5 10.5H20V13H17.5V10.5Z" fill="black"/>
-<path d="M6.5 16.5H4V19H6.5V16.5Z" fill="black"/>
-<path d="M10.75 16.5H13.25V19H10.75V16.5Z" fill="black"/>
-<path d="M20 16.5H17.5V19H20V16.5Z" fill="black"/>
-<path d="M13.25 4.5H10.75V7H13.25V4.5Z" fill="black"/>
-<path d="M17.5 4.5H20V7H17.5V4.5Z" fill="black"/>
-</svg>
diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.css b/toolkit/components/pdfjs/content/web/viewer-geckoview.css
index 16e27e4eac..c336b4f7fc 100644
--- a/toolkit/components/pdfjs/content/web/viewer-geckoview.css
+++ b/toolkit/components/pdfjs/content/web/viewer-geckoview.css
@@ -23,7 +23,6 @@
text-size-adjust:none;
forced-color-adjust:none;
transform-origin:0 0;
- z-index:2;
caret-color:CanvasText;
&.highlighting{
@@ -162,7 +161,6 @@
left:0;
pointer-events:none;
transform-origin:0 0;
- z-index:3;
&[data-main-rotation="90"] .norotate{
transform:rotate(270deg) translateX(-100%);
@@ -817,7 +815,6 @@
overflow:hidden;
width:100%;
height:100%;
- z-index:1;
}
.pdfViewer .page{
@@ -947,7 +944,6 @@
--toolbar-fg-color:#15141a;
--toolbarButton-download-icon:url(images/gv-toolbarButton-download.svg);
- --toolbarButton-openinapp-icon:url(images/gv-toolbarButton-openinapp.svg);
}
:root:dir(rtl){
@@ -1140,10 +1136,6 @@ body{
mask-image:var(--toolbarButton-download-icon);
}
-#openInApp::before{
- mask-image:var(--toolbarButton-openinapp-icon);
-}
-
.dialogButton{
width:auto;
margin:3px 4px 2px !important;
diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.html b/toolkit/components/pdfjs/content/web/viewer-geckoview.html
index 1c0296a481..ba52e298ed 100644
--- a/toolkit/components/pdfjs/content/web/viewer-geckoview.html
+++ b/toolkit/components/pdfjs/content/web/viewer-geckoview.html
@@ -45,9 +45,6 @@ See https://github.com/adobe-type-tools/cmap-resources
<button id="download" class="toolbarButton" title="Download" tabindex="31" data-l10n-id="pdfjs-download-button">
<span data-l10n-id="pdfjs-download-button-label">Download</span>
</button>
- <button id="openInApp" class="toolbarButton" title="Open in app" tabindex="32" data-l10n-id="pdfjs-open-in-app-button">
- <span data-l10n-id="pdfjs-open-in-app-button-label">Open in app</span>
- </button>
</div>
<div id="viewerContainer" tabindex="0">
diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs b/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs
index 8ba8147a9f..866c4a405a 100644
--- a/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs
+++ b/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs
@@ -606,6 +606,10 @@ const defaultOptions = {
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
},
+ enableHighlightFloatingButton: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
enableML: {
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
@@ -651,7 +655,7 @@ const defaultOptions = {
kind: OptionKind.VIEWER
},
maxCanvasPixels: {
- value: 16777216,
+ value: 2 ** 25,
kind: OptionKind.VIEWER
},
forcePageColors: {
@@ -768,28 +772,20 @@ class AppOptions {
constructor() {
throw new Error("Cannot initialize AppOptions.");
}
+ static getCompat(name) {
+ return compatibilityParams[name] ?? undefined;
+ }
static get(name) {
- const userOption = userOptions[name];
- if (userOption !== undefined) {
- return userOption;
- }
- const defaultOption = defaultOptions[name];
- if (defaultOption !== undefined) {
- return compatibilityParams[name] ?? defaultOption.value;
- }
- return undefined;
+ return userOptions[name] ?? compatibilityParams[name] ?? defaultOptions[name]?.value ?? undefined;
}
- static getAll(kind = null) {
+ static getAll(kind = null, defaultOnly = false) {
const options = Object.create(null);
for (const name in defaultOptions) {
const defaultOption = defaultOptions[name];
- if (kind) {
- if (!(kind & defaultOption.kind)) {
- continue;
- }
+ if (kind && !(kind & defaultOption.kind)) {
+ continue;
}
- const userOption = userOptions[name];
- options[name] = userOption !== undefined ? userOption : compatibilityParams[name] ?? defaultOption.value;
+ options[name] = defaultOnly ? defaultOption.value : userOptions[name] ?? compatibilityParams[name] ?? defaultOption.value;
}
return options;
}
@@ -1112,30 +1108,7 @@ class PDFLinkService {
if (pdfDocument !== this.pdfDocument) {
return;
}
- let operator;
- for (const elem of action.state) {
- switch (elem) {
- case "ON":
- case "OFF":
- case "Toggle":
- operator = elem;
- continue;
- }
- switch (operator) {
- case "ON":
- optionalContentConfig.setVisibility(elem, true);
- break;
- case "OFF":
- optionalContentConfig.setVisibility(elem, false);
- break;
- case "Toggle":
- const group = optionalContentConfig.getGroup(elem);
- if (group) {
- optionalContentConfig.setVisibility(elem, !group.visible);
- }
- break;
- }
- }
+ optionalContentConfig.setOCGState(action);
this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig);
}
cachePageRef(pageNum, pageRef) {
@@ -1423,7 +1396,7 @@ class BaseExternalServices {
}
updateFindControlState(data) {}
updateFindMatchesCount(data) {}
- initPassiveLoading(callbacks) {}
+ initPassiveLoading() {}
reportTelemetry(data) {}
async createL10n() {
throw new Error("Not implemented: createL10n");
@@ -1440,6 +1413,16 @@ class BaseExternalServices {
;// CONCATENATED MODULE: ./web/preferences.js
class BasePreferences {
+ #browserDefaults = Object.freeze({
+ canvasMaxAreaInBytes: -1,
+ isInAutomation: false,
+ supportsCaretBrowsingMode: false,
+ supportsDocumentFonts: true,
+ supportsIntegratedFind: false,
+ supportsMouseWheelZoomCtrlKey: true,
+ supportsMouseWheelZoomMetaKey: true,
+ supportsPinchToZoom: true
+ });
#defaults = Object.freeze({
annotationEditorMode: 0,
annotationMode: 2,
@@ -1448,6 +1431,7 @@ class BasePreferences {
defaultZoomValue: "",
disablePageLabels: false,
enableHighlightEditor: false,
+ enableHighlightFloatingButton: false,
enableML: false,
enablePermissions: false,
enablePrintAutoRotate: true,
@@ -1482,26 +1466,19 @@ class BasePreferences {
browserPrefs,
prefs
}) => {
- const BROWSER_PREFS = {
- canvasMaxAreaInBytes: -1,
- isInAutomation: false,
- supportsCaretBrowsingMode: false,
- supportsDocumentFonts: true,
- supportsIntegratedFind: false,
- supportsMouseWheelZoomCtrlKey: true,
- supportsMouseWheelZoomMetaKey: true,
- supportsPinchToZoom: true
- };
const options = Object.create(null);
- for (const [name, defaultVal] of Object.entries(BROWSER_PREFS)) {
+ for (const [name, val] of Object.entries(this.#browserDefaults)) {
const prefVal = browserPrefs?.[name];
- options[name] = typeof prefVal === typeof defaultVal ? prefVal : defaultVal;
+ options[name] = typeof prefVal === typeof val ? prefVal : val;
}
- for (const [name, defaultVal] of Object.entries(this.#defaults)) {
+ for (const [name, val] of Object.entries(this.#defaults)) {
const prefVal = prefs?.[name];
- options[name] = this.#prefs[name] = typeof prefVal === typeof defaultVal ? prefVal : defaultVal;
+ options[name] = this.#prefs[name] = typeof prefVal === typeof val ? prefVal : val;
}
AppOptions.setAll(options, true);
+ window.addEventListener("updatedPreference", evt => {
+ this.#updatePref(evt.detail);
+ });
});
}
async _writeToStorage(prefObj) {
@@ -1510,6 +1487,24 @@ class BasePreferences {
async _readFromStorage(prefObj) {
throw new Error("Not implemented: _readFromStorage");
}
+ #updatePref({
+ name,
+ value
+ }) {
+ if (name in this.#browserDefaults) {
+ if (typeof value !== typeof this.#browserDefaults[name]) {
+ return;
+ }
+ } else if (name in this.#defaults) {
+ if (typeof value !== typeof this.#defaults[name]) {
+ return;
+ }
+ this.#prefs[name] = value;
+ } else {
+ return;
+ }
+ AppOptions.set(name, value);
+ }
async reset() {
throw new Error("Please use `about:config` to change preferences.");
}
@@ -1517,12 +1512,7 @@ class BasePreferences {
throw new Error("Please use `about:config` to change preferences.");
}
async get(name) {
- await this.#initializedPromise;
- const defaultValue = this.#defaults[name];
- if (defaultValue === undefined) {
- throw new Error(`Get preference: "${name}" is undefined.`);
- }
- return this.#prefs[name] ?? defaultValue;
+ throw new Error("Not implemented: get");
}
get initializedPromise() {
return this.#initializedPromise;
@@ -1805,8 +1795,7 @@ class Preferences extends BasePreferences {
try {
const hasUnchangedAnnotations = pdfDocument.annotationStorage.size === 0;
const hasWillPrint = pdfViewer.enableScripting && !!(await pdfDocument.getJSActions())?.WillPrint;
- const hasUnchangedOptionalContent = (await pdfViewer.optionalContentConfigPromise).hasInitialVisibility;
- result = hasUnchangedAnnotations && !hasWillPrint && hasUnchangedOptionalContent;
+ result = hasUnchangedAnnotations && !hasWillPrint;
} catch {
console.warn("Unable to check if the document can be downloaded.");
}
@@ -1860,7 +1849,7 @@ class ExternalServices extends BaseExternalServices {
updateFindMatchesCount(data) {
FirefoxCom.request("updateFindMatchesCount", data);
}
- initPassiveLoading(callbacks) {
+ initPassiveLoading() {
let pdfDataRangeTransport;
window.addEventListener("message", function windowMessage(e) {
if (e.source !== null) {
@@ -1874,11 +1863,13 @@ class ExternalServices extends BaseExternalServices {
switch (args.pdfjsLoadAction) {
case "supportsRangedLoading":
if (args.done && !args.data) {
- callbacks.onError();
+ viewerApp._documentError(null);
break;
}
pdfDataRangeTransport = new FirefoxComDataRangeTransport(args.length, args.data, args.done, args.filename);
- callbacks.onOpenWithTransport(pdfDataRangeTransport);
+ viewerApp.open({
+ range: pdfDataRangeTransport
+ });
break;
case "range":
pdfDataRangeTransport.onDataRange(args.begin, args.chunk);
@@ -1894,21 +1885,26 @@ class ExternalServices extends BaseExternalServices {
pdfDataRangeTransport?.onDataProgressiveDone();
break;
case "progress":
- callbacks.onProgress(args.loaded, args.total);
+ viewerApp.progress(args.loaded / args.total);
break;
case "complete":
if (!args.data) {
- callbacks.onError(args.errorCode);
+ viewerApp._documentError(null, {
+ message: args.errorCode
+ });
break;
}
- callbacks.onOpenWithData(args.data, args.filename);
+ viewerApp.open({
+ data: args.data,
+ filename: args.filename
+ });
break;
}
});
FirefoxCom.request("initPassiveLoading", null);
}
reportTelemetry(data) {
- FirefoxCom.request("reportTelemetry", JSON.stringify(data));
+ FirefoxCom.request("reportTelemetry", data);
}
updateEditorStates(data) {
FirefoxCom.request("updateEditorStates", data);
@@ -3671,14 +3667,15 @@ class FirefoxPrintService {
pagesOverview,
printContainer,
printResolution,
- optionalContentConfigPromise = null,
printAnnotationStoragePromise = null
}) {
this.pdfDocument = pdfDocument;
this.pagesOverview = pagesOverview;
this.printContainer = printContainer;
this._printResolution = printResolution || 150;
- this._optionalContentConfigPromise = optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
+ this._optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
+ intent: "print"
+ });
this._printAnnotationStoragePromise = printAnnotationStoragePromise || Promise.resolve();
}
layout() {
@@ -4206,10 +4203,10 @@ class PDFScriptingManager {
class AnnotationEditorLayerBuilder {
#annotationLayer = null;
#drawLayer = null;
+ #onAppend = null;
#textLayer = null;
#uiManager;
constructor(options) {
- this.pageDiv = options.pageDiv;
this.pdfPage = options.pdfPage;
this.accessibilityManager = options.accessibilityManager;
this.l10n = options.l10n;
@@ -4220,6 +4217,7 @@ class AnnotationEditorLayerBuilder {
this.#annotationLayer = options.annotationLayer || null;
this.#textLayer = options.textLayer || null;
this.#drawLayer = options.drawLayer || null;
+ this.#onAppend = options.onAppend || null;
}
async render(viewport, intent = "display") {
if (intent !== "display") {
@@ -4240,10 +4238,9 @@ class AnnotationEditorLayerBuilder {
}
const div = this.div = document.createElement("div");
div.className = "annotationEditorLayer";
- div.tabIndex = 0;
div.hidden = true;
div.dir = this.#uiManager.direction;
- this.pageDiv.append(div);
+ this.#onAppend?.(div);
this.annotationEditorLayer = new AnnotationEditorLayer({
uiManager: this.#uiManager,
div,
@@ -4269,9 +4266,7 @@ class AnnotationEditorLayerBuilder {
if (!this.div) {
return;
}
- this.pageDiv = null;
this.annotationEditorLayer.destroy();
- this.div.remove();
}
hide() {
if (!this.div) {
@@ -4280,7 +4275,7 @@ class AnnotationEditorLayerBuilder {
this.div.hidden = true;
}
show() {
- if (!this.div || this.annotationEditorLayer.isEmpty) {
+ if (!this.div || this.annotationEditorLayer.isInvisible) {
return;
}
this.div.hidden = false;
@@ -4291,9 +4286,9 @@ class AnnotationEditorLayerBuilder {
class AnnotationLayerBuilder {
+ #onAppend = null;
#onPresentationModeChanged = null;
constructor({
- pageDiv,
pdfPage,
linkService,
downloadManager,
@@ -4304,9 +4299,9 @@ class AnnotationLayerBuilder {
hasJSActionsPromise = null,
fieldObjectsPromise = null,
annotationCanvasMap = null,
- accessibilityManager = null
+ accessibilityManager = null,
+ onAppend = null
}) {
- this.pageDiv = pageDiv;
this.pdfPage = pdfPage;
this.linkService = linkService;
this.downloadManager = downloadManager;
@@ -4318,6 +4313,7 @@ class AnnotationLayerBuilder {
this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
this._annotationCanvasMap = annotationCanvasMap;
this._accessibilityManager = accessibilityManager;
+ this.#onAppend = onAppend;
this.annotationLayer = null;
this.div = null;
this._cancelled = false;
@@ -4343,7 +4339,7 @@ class AnnotationLayerBuilder {
}
const div = this.div = document.createElement("div");
div.className = "annotationLayer";
- this.pageDiv.append(div);
+ this.#onAppend?.(div);
if (annotations.length === 0) {
this.hide();
return;
@@ -4937,13 +4933,15 @@ class TextHighlighter {
class TextLayerBuilder {
#enablePermissions = false;
+ #onAppend = null;
#rotation = 0;
#scale = 0;
#textContentSource = null;
constructor({
highlighter = null,
accessibilityManager = null,
- enablePermissions = false
+ enablePermissions = false,
+ onAppend = null
}) {
this.textContentItemsStr = [];
this.renderingDone = false;
@@ -4953,8 +4951,9 @@ class TextLayerBuilder {
this.highlighter = highlighter;
this.accessibilityManager = accessibilityManager;
this.#enablePermissions = enablePermissions === true;
- this.onAppend = null;
+ this.#onAppend = onAppend;
this.div = document.createElement("div");
+ this.div.tabIndex = 0;
this.div.className = "textLayer";
}
#finishRendering() {
@@ -5009,7 +5008,7 @@ class TextLayerBuilder {
this.#finishRendering();
this.#scale = scale;
this.#rotation = rotation;
- this.onAppend(this.div);
+ this.#onAppend?.(this.div);
this.highlighter?.enable();
this.accessibilityManager?.enable();
}
@@ -5083,8 +5082,8 @@ class TextLayerBuilder {
-const MAX_CANVAS_PIXELS = compatibilityParams.maxCanvasPixels || 16777216;
const DEFAULT_LAYER_PROPERTIES = null;
+const LAYERS_ORDER = new Map([["canvasWrapper", 0], ["textLayer", 1], ["annotationLayer", 2], ["annotationEditorLayer", 3], ["xfaLayer", 3]]);
class PDFPageView {
#annotationMode = AnnotationMode.ENABLE_FORMS;
#hasRestrictedScaling = false;
@@ -5100,6 +5099,7 @@ class PDFPageView {
regularAnnotations: true
};
#viewportMap = new WeakMap();
+ #layers = [null, null, null, null];
constructor(options) {
const container = options.container;
const defaultViewport = options.defaultViewport;
@@ -5116,7 +5116,7 @@ class PDFPageView {
this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
this.imageResourcesPath = options.imageResourcesPath || "";
- this.maxCanvasPixels = options.maxCanvasPixels ?? MAX_CANVAS_PIXELS;
+ this.maxCanvasPixels = options.maxCanvasPixels ?? (AppOptions.getCompat("maxCanvasPixels") || 2 ** 25);
this.pageColors = options.pageColors || null;
this.eventBus = options.eventBus;
this.renderingQueue = options.renderingQueue;
@@ -5143,6 +5143,23 @@ class PDFPageView {
this.#setDimensions();
container?.append(div);
}
+ #addLayer(div, name) {
+ const pos = LAYERS_ORDER.get(name);
+ const oldDiv = this.#layers[pos];
+ this.#layers[pos] = div;
+ if (oldDiv) {
+ oldDiv.replaceWith(div);
+ return;
+ }
+ for (let i = pos - 1; i >= 0; i--) {
+ const layer = this.#layers[i];
+ if (layer) {
+ layer.after(div);
+ return;
+ }
+ }
+ this.div.prepend(div);
+ }
get renderingState() {
return this.#renderingState;
}
@@ -5256,7 +5273,7 @@ class PDFPageView {
} finally {
if (this.xfaLayer?.div) {
this.l10n.pause();
- this.div.append(this.xfaLayer.div);
+ this.#addLayer(this.xfaLayer.div, "xfaLayer");
this.l10n.resume();
}
this.eventBus.dispatch("xfalayerrendered", {
@@ -5368,6 +5385,10 @@ class PDFPageView {
continue;
}
node.remove();
+ const layerIndex = this.#layers.indexOf(node);
+ if (layerIndex >= 0) {
+ this.#layers[layerIndex] = null;
+ }
}
div.removeAttribute("data-loaded");
if (annotationLayerNode) {
@@ -5627,19 +5648,20 @@ class PDFPageView {
this.renderingState = RenderingStates.RUNNING;
const canvasWrapper = document.createElement("div");
canvasWrapper.classList.add("canvasWrapper");
- div.append(canvasWrapper);
+ canvasWrapper.setAttribute("aria-hidden", true);
+ this.#addLayer(canvasWrapper, "canvasWrapper");
if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
this._accessibilityManager ||= new TextAccessibilityManager();
this.textLayer = new TextLayerBuilder({
highlighter: this._textHighlighter,
accessibilityManager: this._accessibilityManager,
- enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS
+ enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS,
+ onAppend: textLayerDiv => {
+ this.l10n.pause();
+ this.#addLayer(textLayerDiv, "textLayer");
+ this.l10n.resume();
+ }
});
- this.textLayer.onAppend = textLayerDiv => {
- this.l10n.pause();
- this.div.append(textLayerDiv);
- this.l10n.resume();
- };
}
if (!this.annotationLayer && this.#annotationMode !== AnnotationMode.DISABLE) {
const {
@@ -5652,7 +5674,6 @@ class PDFPageView {
} = this.#layerProperties;
this._annotationCanvasMap ||= new Map();
this.annotationLayer = new AnnotationLayerBuilder({
- pageDiv: div,
pdfPage,
annotationStorage,
imageResourcesPath: this.imageResourcesPath,
@@ -5663,7 +5684,10 @@ class PDFPageView {
hasJSActionsPromise,
fieldObjectsPromise,
annotationCanvasMap: this._annotationCanvasMap,
- accessibilityManager: this._accessibilityManager
+ accessibilityManager: this._accessibilityManager,
+ onAppend: annotationLayerDiv => {
+ this.#addLayer(annotationLayerDiv, "annotationLayer");
+ }
});
}
const renderContinueCallback = cont => {
@@ -5752,13 +5776,15 @@ class PDFPageView {
if (!this.annotationEditorLayer) {
this.annotationEditorLayer = new AnnotationEditorLayerBuilder({
uiManager: annotationEditorUIManager,
- pageDiv: div,
pdfPage,
l10n,
accessibilityManager: this._accessibilityManager,
annotationLayer: this.annotationLayer?.annotationLayer,
textLayer: this.textLayer,
- drawLayer: this.drawLayer.getDrawLayer()
+ drawLayer: this.drawLayer.getDrawLayer(),
+ onAppend: annotationEditorLayerDiv => {
+ this.#addLayer(annotationEditorLayerDiv, "annotationEditorLayer");
+ }
});
}
this.#renderAnnotationEditorLayer();
@@ -5883,6 +5909,7 @@ class PDFViewer {
#annotationMode = AnnotationMode.ENABLE_FORMS;
#containerTopLeft = null;
#copyCallbackBound = null;
+ #enableHighlightFloatingButton = false;
#enablePermissions = false;
#mlManager = null;
#getAllTextInProgress = false;
@@ -5895,7 +5922,7 @@ class PDFViewer {
#scaleTimeoutId = null;
#textLayerMode = TextLayerMode.ENABLE;
constructor(options) {
- const viewerVersion = "4.1.249";
+ const viewerVersion = "4.1.342";
if (version !== viewerVersion) {
throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
}
@@ -5915,6 +5942,7 @@ class PDFViewer {
this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
this.#annotationEditorMode = options.annotationEditorMode ?? AnnotationEditorType.NONE;
this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null;
+ this.#enableHighlightFloatingButton = options.enableHighlightFloatingButton === true;
this.imageResourcesPath = options.imageResourcesPath || "";
this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
this.maxCanvasPixels = options.maxCanvasPixels;
@@ -6225,7 +6253,9 @@ class PDFViewer {
}
const pagesCount = pdfDocument.numPages;
const firstPagePromise = pdfDocument.getPage(1);
- const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
+ const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
+ intent: "display"
+ });
const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve();
if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
console.warn("Forcing PAGE-scrolling for performance reasons, given the length of the document.");
@@ -6281,7 +6311,7 @@ class PDFViewer {
if (pdfDocument.isPureXfa) {
console.warn("Warning: XFA-editing is not implemented.");
} else if (isValidAnnotationEditorMode(mode)) {
- this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, this.viewer, this.#altTextManager, this.eventBus, pdfDocument, this.pageColors, this.#annotationEditorHighlightColors, this.#mlManager);
+ this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, this.viewer, this.#altTextManager, this.eventBus, pdfDocument, this.pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#mlManager);
this.eventBus.dispatch("annotationeditoruimanager", {
source: this,
uiManager: this.#annotationEditorUIManager
@@ -6942,7 +6972,9 @@ class PDFViewer {
}
if (!this._optionalContentConfigPromise) {
console.error("optionalContentConfigPromise: Not initialized yet.");
- return this.pdfDocument.getOptionalContentConfig();
+ return this.pdfDocument.getOptionalContentConfig({
+ intent: "display"
+ });
}
return this._optionalContentConfigPromise;
}
@@ -7281,10 +7313,6 @@ class Toolbar {
element: options.download,
eventName: "download",
nimbusName: "download-button"
- }, {
- element: options.openInApp,
- eventName: "openinexternalapp",
- nimbusName: "open-in-app-button"
}];
if (nimbusData) {
this.#buttons = [];
@@ -7645,6 +7673,7 @@ const PDFViewerApplication = {
annotationMode: AppOptions.get("annotationMode"),
annotationEditorMode,
annotationEditorHighlightColors: AppOptions.get("highlightEditorColors"),
+ enableHighlightFloatingButton: AppOptions.get("enableHighlightFloatingButton"),
imageResourcesPath: AppOptions.get("imageResourcesPath"),
enablePrintAutoRotate: AppOptions.get("enablePrintAutoRotate"),
maxCanvasPixels: AppOptions.get("maxCanvasPixels"),
@@ -7784,40 +7813,8 @@ const PDFViewerApplication = {
if (this.supportsIntegratedFind) {
appConfig.toolbar?.viewFind?.classList.add("hidden");
}
- this.initPassiveLoading(file);
- const {
- mainContainer
- } = appConfig;
- ({
- scrollTop: this._lastScrollTop,
- scrollLeft: this._lastScrollLeft
- } = mainContainer);
- const scroll = () => {
- if (this._lastScrollTop === mainContainer.scrollTop && this._lastScrollLeft === mainContainer.scrollLeft) {
- return;
- }
- mainContainer.removeEventListener("scroll", scroll, {
- passive: true
- });
- this._isScrolling = true;
- const scrollend = () => {
- ({
- scrollTop: this._lastScrollTop,
- scrollLeft: this._lastScrollLeft
- } = mainContainer);
- this._isScrolling = false;
- mainContainer.addEventListener("scroll", scroll, {
- passive: true
- });
- mainContainer.removeEventListener("scrollend", scrollend);
- mainContainer.removeEventListener("blur", scrollend);
- };
- mainContainer.addEventListener("scrollend", scrollend);
- mainContainer.addEventListener("blur", scrollend);
- };
- mainContainer.addEventListener("scroll", scroll, {
- passive: true
- });
+ this.setTitleUsingUrl(file, file);
+ this.externalServices.initPassiveLoading();
},
get externalServices() {
return shadow(this, "externalServices", new ExternalServices());
@@ -7890,45 +7887,12 @@ const PDFViewerApplication = {
return shadow(this, "supportsMouseWheelZoomMetaKey", AppOptions.get("supportsMouseWheelZoomMetaKey"));
},
get supportsCaretBrowsingMode() {
- return shadow(this, "supportsCaretBrowsingMode", AppOptions.get("supportsCaretBrowsingMode"));
+ return AppOptions.get("supportsCaretBrowsingMode");
},
moveCaret(isUp, select) {
this._caretBrowsing ||= new CaretBrowsingMode(this.appConfig.mainContainer, this.appConfig.viewerContainer, this.appConfig.toolbar?.container);
this._caretBrowsing.moveCaret(isUp, select);
},
- initPassiveLoading(file) {
- this.setTitleUsingUrl(file, file);
- this.externalServices.initPassiveLoading({
- onOpenWithTransport: range => {
- this.open({
- range
- });
- },
- onOpenWithData: (data, contentDispositionFilename) => {
- if (isPdfFile(contentDispositionFilename)) {
- this._contentDispositionFilename = contentDispositionFilename;
- }
- this.open({
- data
- });
- },
- onOpenWithURL: (url, length, originalUrl) => {
- this.open({
- url,
- length,
- originalUrl
- });
- },
- onError: err => {
- this.l10n.get("pdfjs-loading-error").then(msg => {
- this._documentError(msg, err);
- });
- },
- onProgress: (loaded, total) => {
- this.progress(loaded / total);
- }
- });
- },
setTitleUsingUrl(url = "", downloadUrl = null) {
this.url = url;
this.baseUrl = url.split("#", 1)[0];
@@ -8016,6 +7980,9 @@ const PDFViewerApplication = {
}
const workerParams = AppOptions.getAll(OptionKind.WORKER);
Object.assign(GlobalWorkerOptions, workerParams);
+ if (args.data && isPdfFile(args.filename)) {
+ this._contentDispositionFilename = args.filename;
+ }
AppOptions.set("docBaseUrl", this.baseUrl);
const apiParams = AppOptions.getAll(OptionKind.API);
const loadingTask = getDocument({
@@ -8051,10 +8018,9 @@ const PDFViewerApplication = {
} else if (reason instanceof UnexpectedResponseException) {
key = "pdfjs-unexpected-response-error";
}
- return this.l10n.get(key).then(msg => {
- this._documentError(msg, {
- message: reason?.message
- });
+ return this._documentError(key, {
+ message: reason.message
+ }).then(() => {
throw reason;
});
});
@@ -8118,21 +8084,17 @@ const PDFViewerApplication = {
this.download(options);
}
},
- openInExternalApp() {
- this.downloadOrSave({
- openInExternalApp: true
- });
- },
- _documentError(message, moreInfo = null) {
+ async _documentError(key, moreInfo = null) {
this._unblockDocumentLoadEvent();
- this._otherError(message, moreInfo);
+ const message = await this._otherError(key || "pdfjs-loading-error", moreInfo);
this.eventBus.dispatch("documenterror", {
source: this,
message,
reason: moreInfo?.message ?? null
});
},
- _otherError(message, moreInfo = null) {
+ async _otherError(key, moreInfo = null) {
+ const message = await this.l10n.get(key);
const moreInfoText = [`PDF.js v${version || "?"} (build: ${build || "?"})`];
if (moreInfo) {
moreInfoText.push(`Message: ${moreInfo.message}`);
@@ -8148,6 +8110,7 @@ const PDFViewerApplication = {
}
}
console.error(`${message}\n\n${moreInfoText.join("\n")}`);
+ return message;
},
progress(level) {
if (!this.loadingBar || this.downloadComplete) {
@@ -8272,10 +8235,8 @@ const PDFViewerApplication = {
this._unblockDocumentLoadEvent();
this._initializeAutoPrint(pdfDocument, openActionPromise);
}, reason => {
- this.l10n.get("pdfjs-loading-error").then(msg => {
- this._documentError(msg, {
- message: reason?.message
- });
+ this._documentError("pdfjs-loading-error", {
+ message: reason.message
});
});
onePageRendered.then(data => {
@@ -8521,9 +8482,7 @@ const PDFViewerApplication = {
return;
}
if (!this.supportsPrinting) {
- this.l10n.get("pdfjs-printing-not-supported").then(msg => {
- this._otherError(msg);
- });
+ this._otherError("pdfjs-printing-not-supported");
return;
}
if (!this.pdfViewer.pageViewsReady) {
@@ -8537,7 +8496,6 @@ const PDFViewerApplication = {
pagesOverview: this.pdfViewer.getPagesOverview(),
printContainer: this.appConfig.printContainer,
printResolution: AppOptions.get("printResolution"),
- optionalContentConfigPromise: this.pdfViewer.optionalContentConfigPromise,
printAnnotationStoragePromise: this._printAnnotationStoragePromise
});
this.forceRendering();
@@ -8606,7 +8564,6 @@ const PDFViewerApplication = {
eventBus._on("switchannotationeditorparams", webViewerSwitchAnnotationEditorParams);
eventBus._on("print", webViewerPrint);
eventBus._on("download", webViewerDownload);
- eventBus._on("openinexternalapp", webViewerOpenInExternalApp);
eventBus._on("firstpage", webViewerFirstPage);
eventBus._on("lastpage", webViewerLastPage);
eventBus._on("nextpage", webViewerNextPage);
@@ -8638,7 +8595,10 @@ const PDFViewerApplication = {
bindWindowEvents() {
const {
eventBus,
- _boundEvents
+ _boundEvents,
+ appConfig: {
+ mainContainer
+ }
} = this;
function addWindowResolutionChange(evt = null) {
if (evt) {
@@ -8698,12 +8658,79 @@ const PDFViewerApplication = {
window.addEventListener("beforeprint", _boundEvents.windowBeforePrint);
window.addEventListener("afterprint", _boundEvents.windowAfterPrint);
window.addEventListener("updatefromsandbox", _boundEvents.windowUpdateFromSandbox);
+ ({
+ scrollTop: this._lastScrollTop,
+ scrollLeft: this._lastScrollLeft
+ } = mainContainer);
+ const scrollend = _boundEvents.mainContainerScrollend = () => {
+ ({
+ scrollTop: this._lastScrollTop,
+ scrollLeft: this._lastScrollLeft
+ } = mainContainer);
+ this._isScrolling = false;
+ mainContainer.addEventListener("scroll", scroll, {
+ passive: true
+ });
+ mainContainer.removeEventListener("scrollend", scrollend);
+ mainContainer.removeEventListener("blur", scrollend);
+ };
+ const scroll = _boundEvents.mainContainerScroll = () => {
+ if (this._isCtrlKeyDown || this._lastScrollTop === mainContainer.scrollTop && this._lastScrollLeft === mainContainer.scrollLeft) {
+ return;
+ }
+ mainContainer.removeEventListener("scroll", scroll, {
+ passive: true
+ });
+ this._isScrolling = true;
+ mainContainer.addEventListener("scrollend", scrollend);
+ mainContainer.addEventListener("blur", scrollend);
+ };
+ mainContainer.addEventListener("scroll", scroll, {
+ passive: true
+ });
},
unbindEvents() {
throw new Error("Not implemented: unbindEvents");
},
unbindWindowEvents() {
- throw new Error("Not implemented: unbindWindowEvents");
+ const {
+ _boundEvents,
+ appConfig: {
+ mainContainer
+ }
+ } = this;
+ window.removeEventListener("visibilitychange", webViewerVisibilityChange);
+ window.removeEventListener("wheel", webViewerWheel, {
+ passive: false
+ });
+ window.removeEventListener("touchstart", webViewerTouchStart, {
+ passive: false
+ });
+ window.removeEventListener("touchmove", webViewerTouchMove, {
+ passive: false
+ });
+ window.removeEventListener("touchend", webViewerTouchEnd, {
+ passive: false
+ });
+ window.removeEventListener("click", webViewerClick);
+ window.removeEventListener("keydown", webViewerKeyDown);
+ window.removeEventListener("keyup", webViewerKeyUp);
+ window.removeEventListener("resize", _boundEvents.windowResize);
+ window.removeEventListener("hashchange", _boundEvents.windowHashChange);
+ window.removeEventListener("beforeprint", _boundEvents.windowBeforePrint);
+ window.removeEventListener("afterprint", _boundEvents.windowAfterPrint);
+ window.removeEventListener("updatefromsandbox", _boundEvents.windowUpdateFromSandbox);
+ mainContainer.removeEventListener("scroll", _boundEvents.mainContainerScroll);
+ mainContainer.removeEventListener("scrollend", _boundEvents.mainContainerScrollend);
+ mainContainer.removeEventListener("blur", _boundEvents.mainContainerScrollend);
+ _boundEvents.removeWindowResolutionChange?.();
+ _boundEvents.windowResize = null;
+ _boundEvents.windowHashChange = null;
+ _boundEvents.windowBeforePrint = null;
+ _boundEvents.windowAfterPrint = null;
+ _boundEvents.windowUpdateFromSandbox = null;
+ _boundEvents.mainContainerScroll = null;
+ _boundEvents.mainContainerScrollend = null;
},
_accumulateTicks(ticks, prop) {
if (this[prop] > 0 && ticks < 0 || this[prop] < 0 && ticks > 0) {
@@ -8786,9 +8813,7 @@ function webViewerPageRendered({
}
}
if (error) {
- PDFViewerApplication.l10n.get("pdfjs-rendering-error").then(msg => {
- PDFViewerApplication._otherError(msg, error);
- });
+ PDFViewerApplication._otherError("pdfjs-rendering-error", error);
}
}
function webViewerPageMode({
@@ -8918,9 +8943,6 @@ function webViewerPrint() {
function webViewerDownload() {
PDFViewerApplication.downloadOrSave();
}
-function webViewerOpenInExternalApp() {
- PDFViewerApplication.openInExternalApp();
-}
function webViewerFirstPage() {
PDFViewerApplication.page = 1;
}
@@ -9509,8 +9531,8 @@ function webViewerReportTelemetry({
-const pdfjsVersion = "4.1.249";
-const pdfjsBuild = "d07f37f44";
+const pdfjsVersion = "4.1.342";
+const pdfjsBuild = "e384df6f1";
const AppConstants = null;
window.PDFViewerApplication = PDFViewerApplication;
window.PDFViewerApplicationConstants = AppConstants;
@@ -9524,8 +9546,7 @@ function getViewerConfiguration() {
toolbar: {
mainContainer,
container: document.getElementById("floatingToolbar"),
- download: document.getElementById("download"),
- openInApp: document.getElementById("openInApp")
+ download: document.getElementById("download")
},
passwordOverlay: {
dialog: document.getElementById("passwordDialog"),
diff --git a/toolkit/components/pdfjs/content/web/viewer.css b/toolkit/components/pdfjs/content/web/viewer.css
index 238df7ce7f..2999c89f3a 100644
--- a/toolkit/components/pdfjs/content/web/viewer.css
+++ b/toolkit/components/pdfjs/content/web/viewer.css
@@ -23,7 +23,6 @@
text-size-adjust:none;
forced-color-adjust:none;
transform-origin:0 0;
- z-index:2;
caret-color:CanvasText;
&.highlighting{
@@ -162,7 +161,6 @@
left:0;
pointer-events:none;
transform-origin:0 0;
- z-index:3;
&[data-main-rotation="90"] .norotate{
transform:rotate(270deg) translateX(-100%);
@@ -853,6 +851,208 @@
}
}
+.toggle-button{
+ --button-background-color:#f0f0f4;
+ --button-background-color-hover:#e0e0e6;
+ --button-background-color-active:#cfcfd8;
+ --color-accent-primary:#0060df;
+ --color-accent-primary-hover:#0250bb;
+ --color-accent-primary-active:#054096;
+ --border-interactive-color:#8f8f9d;
+ --border-radius-circle:9999px;
+ --border-width:1px;
+ --size-item-small:16px;
+ --size-item-large:32px;
+ --color-canvas:white;
+
+ @media (prefers-color-scheme: dark){
+ --button-background-color:color-mix(in srgb, currentColor 7%, transparent);
+ --button-background-color-hover:color-mix(
+ in srgb,
+ currentColor 14%,
+ transparent
+ );
+ --button-background-color-active:color-mix(
+ in srgb,
+ currentColor 21%,
+ transparent
+ );
+ --color-accent-primary:#0df;
+ --color-accent-primary-hover:#80ebff;
+ --color-accent-primary-active:#aaf2ff;
+ --border-interactive-color:#bfbfc9;
+ --color-canvas:#1c1b22;
+ }
+
+ @media (forced-colors: active){
+ --color-accent-primary:ButtonText;
+ --color-accent-primary-hover:SelectedItem;
+ --color-accent-primary-active:SelectedItem;
+ --border-interactive-color:ButtonText;
+ --button-background-color:ButtonFace;
+ --border-interactive-color-hover:SelectedItem;
+ --border-interactive-color-active:SelectedItem;
+ --border-interactive-color-disabled:GrayText;
+ --color-canvas:ButtonText;
+ }
+
+ --toggle-background-color:var(--button-background-color);
+ --toggle-background-color-hover:var(--button-background-color-hover);
+ --toggle-background-color-active:var(--button-background-color-active);
+ --toggle-background-color-pressed:var(--color-accent-primary);
+ --toggle-background-color-pressed-hover:var(--color-accent-primary-hover);
+ --toggle-background-color-pressed-active:var(--color-accent-primary-active);
+ --toggle-border-color:var(--border-interactive-color);
+ --toggle-border-color-hover:var(--toggle-border-color);
+ --toggle-border-color-active:var(--toggle-border-color);
+ --toggle-border-radius:var(--border-radius-circle);
+ --toggle-border-width:var(--border-width);
+ --toggle-height:var(--size-item-small);
+ --toggle-width:var(--size-item-large);
+ --toggle-dot-background-color:var(--toggle-border-color);
+ --toggle-dot-background-color-hover:var(--toggle-dot-background-color);
+ --toggle-dot-background-color-active:var(--toggle-dot-background-color);
+ --toggle-dot-background-color-on-pressed:var(--color-canvas);
+ --toggle-dot-margin:1px;
+ --toggle-dot-height:calc(
+ var(--toggle-height) - 2 * var(--toggle-dot-margin) - 2 *
+ var(--toggle-border-width)
+ );
+ --toggle-dot-width:var(--toggle-dot-height);
+ --toggle-dot-transform-x:calc(
+ var(--toggle-width) - 4 * var(--toggle-dot-margin) - var(--toggle-dot-width)
+ );
+
+ appearance:none;
+ padding:0;
+ margin:0;
+ border:var(--toggle-border-width) solid var(--toggle-border-color);
+ height:var(--toggle-height);
+ width:var(--toggle-width);
+ border-radius:var(--toggle-border-radius);
+ background:var(--toggle-background-color);
+ box-sizing:border-box;
+ flex-shrink:0;
+
+ &:focus-visible{
+ outline:var(--focus-outline);
+ outline-offset:var(--focus-outline-offset);
+ }
+
+ &:enabled:hover{
+ background:var(--toggle-background-color-hover);
+ border-color:var(--toggle-border-color);
+ }
+
+ &:enabled:active{
+ background:var(--toggle-background-color-active);
+ border-color:var(--toggle-border-color);
+ }
+
+ &[aria-pressed="true"]{
+ background:var(--toggle-background-color-pressed);
+ border-color:transparent;
+ }
+
+ &[aria-pressed="true"]:enabled:hover{
+ background:var(--toggle-background-color-pressed-hover);
+ border-color:transparent;
+ }
+
+ &[aria-pressed="true"]:enabled:active{
+ background:var(--toggle-background-color-pressed-active);
+ border-color:transparent;
+ }
+
+ &::before{
+ display:block;
+ content:"";
+ background-color:var(--toggle-dot-background-color);
+ height:var(--toggle-dot-height);
+ width:var(--toggle-dot-width);
+ margin:var(--toggle-dot-margin);
+ border-radius:var(--toggle-border-radius);
+ translate:0;
+ }
+
+ &[aria-pressed="true"]::before{
+ translate:var(--toggle-dot-transform-x);
+ background-color:var(--toggle-dot-background-color-on-pressed);
+ }
+
+ &[aria-pressed="true"]:enabled:hover::before,
+ &[aria-pressed="true"]:enabled:active::before{
+ background-color:var(--toggle-dot-background-color-on-pressed);
+ }
+
+ &[aria-pressed="true"]:-moz-locale-dir(rtl)::before,
+ &[aria-pressed="true"]:dir(rtl)::before{
+ translate:calc(-1 * var(--toggle-dot-transform-x));
+ }
+
+ @media (prefers-reduced-motion: no-preference){
+ &::before{
+ transition:translate 100ms;
+ }
+ }
+
+ @media (prefers-contrast){
+ &:enabled:hover{
+ border-color:var(--toggle-border-color-hover);
+ }
+
+ &:enabled:active{
+ border-color:var(--toggle-border-color-active);
+ }
+
+ &[aria-pressed="true"]:enabled{
+ border-color:var(--toggle-border-color);
+ position:relative;
+ }
+
+ &[aria-pressed="true"]:enabled:hover,
+ &[aria-pressed="true"]:enabled:hover:active{
+ border-color:var(--toggle-border-color-hover);
+ }
+
+ &[aria-pressed="true"]:enabled:active{
+ background-color:var(--toggle-dot-background-color-active);
+ border-color:var(--toggle-dot-background-color-hover);
+ }
+
+ &:hover::before,
+ &:active::before{
+ background-color:var(--toggle-dot-background-color-hover);
+ }
+ }
+
+ @media (forced-colors){
+ --toggle-dot-background-color:var(--color-accent-primary);
+ --toggle-dot-background-color-hover:var(--color-accent-primary-hover);
+ --toggle-dot-background-color-active:var(--color-accent-primary-active);
+ --toggle-dot-background-color-on-pressed:var(--button-background-color);
+ --toggle-background-color-disabled:var(--button-background-color-disabled);
+ --toggle-border-color-hover:var(--border-interactive-color-hover);
+ --toggle-border-color-active:var(--border-interactive-color-active);
+ --toggle-border-color-disabled:var(--border-interactive-color-disabled);
+
+ &[aria-pressed="true"]:enabled::after{
+ border:1px solid var(--button-background-color);
+ content:"";
+ position:absolute;
+ height:var(--toggle-height);
+ width:var(--toggle-width);
+ display:block;
+ border-radius:var(--toggle-border-radius);
+ inset:-2px;
+ }
+
+ &[aria-pressed="true"]:enabled:active::after{
+ border-color:var(--toggle-border-color-active);
+ }
+ }
+}
+
:root{
--outline-width:2px;
--outline-color:#0060df;
@@ -878,6 +1078,19 @@
--editorHighlight-editing-cursor:url(images/cursor-editorTextHighlight.svg) 24 24, text;
--editorFreeHighlight-editing-cursor:url(images/cursor-editorFreeHighlight.svg) 1 18, pointer;
}
+.visuallyHidden{
+ position:absolute;
+ top:0;
+ left:0;
+ border:0;
+ margin:0;
+ padding:0;
+ width:0;
+ height:0;
+ overflow:hidden;
+ white-space:nowrap;
+ font-size:0;
+}
.textLayer.highlighting{
cursor:var(--editorFreeHighlight-editing-cursor);
@@ -926,7 +1139,6 @@
font-size:calc(100px * var(--scale-factor));
transform-origin:0 0;
cursor:auto;
- z-index:4;
}
.annotationEditorLayer.waiting{
@@ -995,10 +1207,12 @@
}
.annotationEditorLayer
- :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor){
+ :is(.freeTextEditor, .inkEditor, .stampEditor, .highlightEditor),
+.textLayer{
.editToolbar{
--editor-toolbar-delete-image:url(images/editor-toolbar-delete.svg);
--editor-toolbar-bg-color:#f0f0f4;
+ --editor-toolbar-highlight-image:url(images/toolbarButton-editorHighlight.svg);
--editor-toolbar-fg-color:#2e2e56;
--editor-toolbar-border-color:#8f8f9d;
--editor-toolbar-hover-border-color:var(--editor-toolbar-border-color);
@@ -1084,6 +1298,25 @@
margin-inline:2px;
}
+ .highlightButton{
+ width:var(--editor-toolbar-height);
+
+ &::before{
+ content:"";
+ mask-image:var(--editor-toolbar-highlight-image);
+ mask-repeat:no-repeat;
+ mask-position:center;
+ display:inline-block;
+ background-color:var(--editor-toolbar-fg-color);
+ width:100%;
+ height:100%;
+ }
+
+ &:hover::before{
+ background-color:var(--editor-toolbar-hover-fg-color);
+ }
+ }
+
.delete{
width:var(--editor-toolbar-height);
@@ -2003,7 +2236,12 @@
--example-color:CanvasText;
}
- &::before{
+ :is(& > .editorParamsSlider[disabled]){
+ opacity:0.4;
+ }
+
+ &::before,
+ &::after{
content:"";
width:8px;
aspect-ratio:1;
@@ -2011,20 +2249,46 @@
border-radius:100%;
background-color:var(--example-color);
}
+ &::after{
+ width:24px;
+ }
.editorParamsSlider{
width:unset;
height:14px;
}
+ }
+ }
- &::after{
- content:"";
- width:24px;
- aspect-ratio:1;
- display:block;
- border-radius:100%;
- background-color:var(--example-color);
+ #editorHighlightVisibility{
+ display:flex;
+ flex-direction:column;
+ align-items:flex-start;
+ gap:8px;
+ align-self:stretch;
+
+ .divider{
+ --divider-color:#d7d7db;
+
+ @media (prefers-color-scheme: dark){
+ --divider-color:#8f8f9d;
+ }
+
+ @media screen and (forced-colors: active){
+ --divider-color:CanvasText;
}
+
+ margin-block:4px;
+ width:100%;
+ height:1px;
+ background-color:var(--divider-color);
+ }
+
+ .toggler{
+ display:flex;
+ justify-content:space-between;
+ align-items:center;
+ align-self:stretch;
}
}
}
@@ -2084,7 +2348,6 @@
overflow:hidden;
width:100%;
height:100%;
- z-index:1;
}
.pdfViewer .page{
@@ -2655,6 +2918,7 @@ body{
font-style:normal;
}
.loadingInput:has(> &[data-status="pending"])::after{
+ display:block;
visibility:visible;
}
&[data-status="notFound"]{
@@ -3249,6 +3513,7 @@ a:is(.toolbarButton, .secondaryToolbarButton)[href="#"]{
transition-property:none;
.loadingInput:has(> &.loading)::after{
+ display: block;
visibility:visible;
transition-property:visibility;
@@ -3260,6 +3525,7 @@ a:is(.toolbarButton, .secondaryToolbarButton)[href="#"]{
&::after{
position:absolute;
visibility:hidden;
+ display: none;
top:calc(50% - 8px);
width:16px;
height:16px;
diff --git a/toolkit/components/pdfjs/content/web/viewer.html b/toolkit/components/pdfjs/content/web/viewer.html
index 59438b64b4..941e17b58d 100644
--- a/toolkit/components/pdfjs/content/web/viewer.html
+++ b/toolkit/components/pdfjs/content/web/viewer.html
@@ -127,6 +127,13 @@ See https://github.com/adobe-type-tools/cmap-resources
<input type="range" id="editorFreeHighlightThickness" class="editorParamsSlider" data-l10n-id="pdfjs-editor-free-highlight-thickness-title" value="12" min="8" max="24" step="1" tabindex="101">
</div>
</div>
+ <div id="editorHighlightVisibility">
+ <div class="divider"></div>
+ <div class="toggler">
+ <label for="editorHighlightShowAll" class="editorParamsLabel" data-l10n-id="pdfjs-editor-highlight-show-all-button-label">Show all</label>
+ <button id="editorHighlightShowAll" class="toggle-button" data-l10n-id="pdfjs-editor-highlight-show-all-button" aria-pressed="true" tabindex="102"></button>
+ </div>
+ </div>
</div>
</div>
@@ -134,11 +141,11 @@ See https://github.com/adobe-type-tools/cmap-resources
<div class="editorParamsToolbarContainer">
<div class="editorParamsSetter">
<label for="editorFreeTextColor" class="editorParamsLabel" data-l10n-id="pdfjs-editor-free-text-color-input">Color</label>
- <input type="color" id="editorFreeTextColor" class="editorParamsColor" tabindex="102">
+ <input type="color" id="editorFreeTextColor" class="editorParamsColor" tabindex="103">
</div>
<div class="editorParamsSetter">
<label for="editorFreeTextFontSize" class="editorParamsLabel" data-l10n-id="pdfjs-editor-free-text-size-input">Size</label>
- <input type="range" id="editorFreeTextFontSize" class="editorParamsSlider" value="10" min="5" max="100" step="1" tabindex="103">
+ <input type="range" id="editorFreeTextFontSize" class="editorParamsSlider" value="10" min="5" max="100" step="1" tabindex="104">
</div>
</div>
</div>
@@ -147,22 +154,22 @@ See https://github.com/adobe-type-tools/cmap-resources
<div class="editorParamsToolbarContainer">
<div class="editorParamsSetter">
<label for="editorInkColor" class="editorParamsLabel" data-l10n-id="pdfjs-editor-ink-color-input">Color</label>
- <input type="color" id="editorInkColor" class="editorParamsColor" tabindex="104">
+ <input type="color" id="editorInkColor" class="editorParamsColor" tabindex="105">
</div>
<div class="editorParamsSetter">
<label for="editorInkThickness" class="editorParamsLabel" data-l10n-id="pdfjs-editor-ink-thickness-input">Thickness</label>
- <input type="range" id="editorInkThickness" class="editorParamsSlider" value="1" min="1" max="20" step="1" tabindex="105">
+ <input type="range" id="editorInkThickness" class="editorParamsSlider" value="1" min="1" max="20" step="1" tabindex="106">
</div>
<div class="editorParamsSetter">
<label for="editorInkOpacity" class="editorParamsLabel" data-l10n-id="pdfjs-editor-ink-opacity-input">Opacity</label>
- <input type="range" id="editorInkOpacity" class="editorParamsSlider" value="100" min="1" max="100" step="1" tabindex="106">
+ <input type="range" id="editorInkOpacity" class="editorParamsSlider" value="100" min="1" max="100" step="1" tabindex="107">
</div>
</div>
</div>
<div class="editorParamsToolbar hidden doorHangerRight" id="editorStampParamsToolbar">
<div class="editorParamsToolbarContainer">
- <button id="editorStampAddImage" class="secondaryToolbarButton" title="Add image" tabindex="107" data-l10n-id="pdfjs-editor-stamp-add-image-button">
+ <button id="editorStampAddImage" class="secondaryToolbarButton" title="Add image" tabindex="108" data-l10n-id="pdfjs-editor-stamp-add-image-button">
<span class="editorParamsLabel" data-l10n-id="pdfjs-editor-stamp-add-image-button-label">Add image</span>
</button>
</div>
diff --git a/toolkit/components/pdfjs/content/web/viewer.mjs b/toolkit/components/pdfjs/content/web/viewer.mjs
index a047a9f7c1..778ce57e1a 100644
--- a/toolkit/components/pdfjs/content/web/viewer.mjs
+++ b/toolkit/components/pdfjs/content/web/viewer.mjs
@@ -606,6 +606,10 @@ const defaultOptions = {
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
},
+ enableHighlightFloatingButton: {
+ value: false,
+ kind: OptionKind.VIEWER + OptionKind.PREFERENCE
+ },
enableML: {
value: false,
kind: OptionKind.VIEWER + OptionKind.PREFERENCE
@@ -651,7 +655,7 @@ const defaultOptions = {
kind: OptionKind.VIEWER
},
maxCanvasPixels: {
- value: 16777216,
+ value: 2 ** 25,
kind: OptionKind.VIEWER
},
forcePageColors: {
@@ -768,28 +772,20 @@ class AppOptions {
constructor() {
throw new Error("Cannot initialize AppOptions.");
}
+ static getCompat(name) {
+ return compatibilityParams[name] ?? undefined;
+ }
static get(name) {
- const userOption = userOptions[name];
- if (userOption !== undefined) {
- return userOption;
- }
- const defaultOption = defaultOptions[name];
- if (defaultOption !== undefined) {
- return compatibilityParams[name] ?? defaultOption.value;
- }
- return undefined;
+ return userOptions[name] ?? compatibilityParams[name] ?? defaultOptions[name]?.value ?? undefined;
}
- static getAll(kind = null) {
+ static getAll(kind = null, defaultOnly = false) {
const options = Object.create(null);
for (const name in defaultOptions) {
const defaultOption = defaultOptions[name];
- if (kind) {
- if (!(kind & defaultOption.kind)) {
- continue;
- }
+ if (kind && !(kind & defaultOption.kind)) {
+ continue;
}
- const userOption = userOptions[name];
- options[name] = userOption !== undefined ? userOption : compatibilityParams[name] ?? defaultOption.value;
+ options[name] = defaultOnly ? defaultOption.value : userOptions[name] ?? compatibilityParams[name] ?? defaultOption.value;
}
return options;
}
@@ -1112,30 +1108,7 @@ class PDFLinkService {
if (pdfDocument !== this.pdfDocument) {
return;
}
- let operator;
- for (const elem of action.state) {
- switch (elem) {
- case "ON":
- case "OFF":
- case "Toggle":
- operator = elem;
- continue;
- }
- switch (operator) {
- case "ON":
- optionalContentConfig.setVisibility(elem, true);
- break;
- case "OFF":
- optionalContentConfig.setVisibility(elem, false);
- break;
- case "Toggle":
- const group = optionalContentConfig.getGroup(elem);
- if (group) {
- optionalContentConfig.setVisibility(elem, !group.visible);
- }
- break;
- }
- }
+ optionalContentConfig.setOCGState(action);
this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig);
}
cachePageRef(pageNum, pageRef) {
@@ -1423,7 +1396,7 @@ class BaseExternalServices {
}
updateFindControlState(data) {}
updateFindMatchesCount(data) {}
- initPassiveLoading(callbacks) {}
+ initPassiveLoading() {}
reportTelemetry(data) {}
async createL10n() {
throw new Error("Not implemented: createL10n");
@@ -1440,6 +1413,16 @@ class BaseExternalServices {
;// CONCATENATED MODULE: ./web/preferences.js
class BasePreferences {
+ #browserDefaults = Object.freeze({
+ canvasMaxAreaInBytes: -1,
+ isInAutomation: false,
+ supportsCaretBrowsingMode: false,
+ supportsDocumentFonts: true,
+ supportsIntegratedFind: false,
+ supportsMouseWheelZoomCtrlKey: true,
+ supportsMouseWheelZoomMetaKey: true,
+ supportsPinchToZoom: true
+ });
#defaults = Object.freeze({
annotationEditorMode: 0,
annotationMode: 2,
@@ -1448,6 +1431,7 @@ class BasePreferences {
defaultZoomValue: "",
disablePageLabels: false,
enableHighlightEditor: false,
+ enableHighlightFloatingButton: false,
enableML: false,
enablePermissions: false,
enablePrintAutoRotate: true,
@@ -1482,26 +1466,19 @@ class BasePreferences {
browserPrefs,
prefs
}) => {
- const BROWSER_PREFS = {
- canvasMaxAreaInBytes: -1,
- isInAutomation: false,
- supportsCaretBrowsingMode: false,
- supportsDocumentFonts: true,
- supportsIntegratedFind: false,
- supportsMouseWheelZoomCtrlKey: true,
- supportsMouseWheelZoomMetaKey: true,
- supportsPinchToZoom: true
- };
const options = Object.create(null);
- for (const [name, defaultVal] of Object.entries(BROWSER_PREFS)) {
+ for (const [name, val] of Object.entries(this.#browserDefaults)) {
const prefVal = browserPrefs?.[name];
- options[name] = typeof prefVal === typeof defaultVal ? prefVal : defaultVal;
+ options[name] = typeof prefVal === typeof val ? prefVal : val;
}
- for (const [name, defaultVal] of Object.entries(this.#defaults)) {
+ for (const [name, val] of Object.entries(this.#defaults)) {
const prefVal = prefs?.[name];
- options[name] = this.#prefs[name] = typeof prefVal === typeof defaultVal ? prefVal : defaultVal;
+ options[name] = this.#prefs[name] = typeof prefVal === typeof val ? prefVal : val;
}
AppOptions.setAll(options, true);
+ window.addEventListener("updatedPreference", evt => {
+ this.#updatePref(evt.detail);
+ });
});
}
async _writeToStorage(prefObj) {
@@ -1510,6 +1487,24 @@ class BasePreferences {
async _readFromStorage(prefObj) {
throw new Error("Not implemented: _readFromStorage");
}
+ #updatePref({
+ name,
+ value
+ }) {
+ if (name in this.#browserDefaults) {
+ if (typeof value !== typeof this.#browserDefaults[name]) {
+ return;
+ }
+ } else if (name in this.#defaults) {
+ if (typeof value !== typeof this.#defaults[name]) {
+ return;
+ }
+ this.#prefs[name] = value;
+ } else {
+ return;
+ }
+ AppOptions.set(name, value);
+ }
async reset() {
throw new Error("Please use `about:config` to change preferences.");
}
@@ -1517,12 +1512,7 @@ class BasePreferences {
throw new Error("Please use `about:config` to change preferences.");
}
async get(name) {
- await this.#initializedPromise;
- const defaultValue = this.#defaults[name];
- if (defaultValue === undefined) {
- throw new Error(`Get preference: "${name}" is undefined.`);
- }
- return this.#prefs[name] ?? defaultValue;
+ throw new Error("Not implemented: get");
}
get initializedPromise() {
return this.#initializedPromise;
@@ -1824,7 +1814,7 @@ class ExternalServices extends BaseExternalServices {
updateFindMatchesCount(data) {
FirefoxCom.request("updateFindMatchesCount", data);
}
- initPassiveLoading(callbacks) {
+ initPassiveLoading() {
let pdfDataRangeTransport;
window.addEventListener("message", function windowMessage(e) {
if (e.source !== null) {
@@ -1838,11 +1828,13 @@ class ExternalServices extends BaseExternalServices {
switch (args.pdfjsLoadAction) {
case "supportsRangedLoading":
if (args.done && !args.data) {
- callbacks.onError();
+ viewerApp._documentError(null);
break;
}
pdfDataRangeTransport = new FirefoxComDataRangeTransport(args.length, args.data, args.done, args.filename);
- callbacks.onOpenWithTransport(pdfDataRangeTransport);
+ viewerApp.open({
+ range: pdfDataRangeTransport
+ });
break;
case "range":
pdfDataRangeTransport.onDataRange(args.begin, args.chunk);
@@ -1858,21 +1850,26 @@ class ExternalServices extends BaseExternalServices {
pdfDataRangeTransport?.onDataProgressiveDone();
break;
case "progress":
- callbacks.onProgress(args.loaded, args.total);
+ viewerApp.progress(args.loaded / args.total);
break;
case "complete":
if (!args.data) {
- callbacks.onError(args.errorCode);
+ viewerApp._documentError(null, {
+ message: args.errorCode
+ });
break;
}
- callbacks.onOpenWithData(args.data, args.filename);
+ viewerApp.open({
+ data: args.data,
+ filename: args.filename
+ });
break;
}
});
FirefoxCom.request("initPassiveLoading", null);
}
reportTelemetry(data) {
- FirefoxCom.request("reportTelemetry", JSON.stringify(data));
+ FirefoxCom.request("reportTelemetry", data);
}
updateEditorStates(data) {
FirefoxCom.request("updateEditorStates", data);
@@ -2150,7 +2147,8 @@ class AnnotationEditorParams {
editorInkThickness,
editorInkOpacity,
editorStampAddImage,
- editorFreeHighlightThickness
+ editorFreeHighlightThickness,
+ editorHighlightShowAll
}) {
const dispatchEvent = (typeStr, value) => {
this.eventBus.dispatch("switchannotationeditorparams", {
@@ -2180,6 +2178,11 @@ class AnnotationEditorParams {
editorFreeHighlightThickness.addEventListener("input", function () {
dispatchEvent("HIGHLIGHT_THICKNESS", this.valueAsNumber);
});
+ editorHighlightShowAll.addEventListener("click", function () {
+ const checked = this.getAttribute("aria-pressed") === "true";
+ this.setAttribute("aria-pressed", !checked);
+ dispatchEvent("HIGHLIGHT_SHOW_ALL", !checked);
+ });
this.eventBus._on("annotationeditorparamschanged", evt => {
for (const [type, value] of evt.details) {
switch (type) {
@@ -2204,6 +2207,9 @@ class AnnotationEditorParams {
case AnnotationEditorParamsType.HIGHLIGHT_FREE:
editorFreeHighlightThickness.disabled = !value;
break;
+ case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL:
+ editorHighlightShowAll.setAttribute("aria-pressed", value);
+ break;
}
}
});
@@ -4690,7 +4696,9 @@ class PDFLayerViewer extends BaseTreeViewer {
return;
}
const pdfDocument = this._pdfDocument;
- const optionalContentConfig = await (promise || pdfDocument.getOptionalContentConfig());
+ const optionalContentConfig = await (promise || pdfDocument.getOptionalContentConfig({
+ intent: "display"
+ }));
if (pdfDocument !== this._pdfDocument) {
return;
}
@@ -5429,14 +5437,15 @@ class FirefoxPrintService {
pagesOverview,
printContainer,
printResolution,
- optionalContentConfigPromise = null,
printAnnotationStoragePromise = null
}) {
this.pdfDocument = pdfDocument;
this.pagesOverview = pagesOverview;
this.printContainer = printContainer;
this._printResolution = printResolution || 150;
- this._optionalContentConfigPromise = optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
+ this._optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
+ intent: "print"
+ });
this._printAnnotationStoragePromise = printAnnotationStoragePromise || Promise.resolve();
}
layout() {
@@ -6680,7 +6689,9 @@ class PDFThumbnailViewer {
return;
}
const firstPagePromise = pdfDocument.getPage(1);
- const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
+ const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
+ intent: "display"
+ });
firstPagePromise.then(firstPdfPage => {
const pagesCount = pdfDocument.numPages;
const viewport = firstPdfPage.getViewport({
@@ -6770,10 +6781,10 @@ class PDFThumbnailViewer {
class AnnotationEditorLayerBuilder {
#annotationLayer = null;
#drawLayer = null;
+ #onAppend = null;
#textLayer = null;
#uiManager;
constructor(options) {
- this.pageDiv = options.pageDiv;
this.pdfPage = options.pdfPage;
this.accessibilityManager = options.accessibilityManager;
this.l10n = options.l10n;
@@ -6784,6 +6795,7 @@ class AnnotationEditorLayerBuilder {
this.#annotationLayer = options.annotationLayer || null;
this.#textLayer = options.textLayer || null;
this.#drawLayer = options.drawLayer || null;
+ this.#onAppend = options.onAppend || null;
}
async render(viewport, intent = "display") {
if (intent !== "display") {
@@ -6804,10 +6816,9 @@ class AnnotationEditorLayerBuilder {
}
const div = this.div = document.createElement("div");
div.className = "annotationEditorLayer";
- div.tabIndex = 0;
div.hidden = true;
div.dir = this.#uiManager.direction;
- this.pageDiv.append(div);
+ this.#onAppend?.(div);
this.annotationEditorLayer = new AnnotationEditorLayer({
uiManager: this.#uiManager,
div,
@@ -6833,9 +6844,7 @@ class AnnotationEditorLayerBuilder {
if (!this.div) {
return;
}
- this.pageDiv = null;
this.annotationEditorLayer.destroy();
- this.div.remove();
}
hide() {
if (!this.div) {
@@ -6844,7 +6853,7 @@ class AnnotationEditorLayerBuilder {
this.div.hidden = true;
}
show() {
- if (!this.div || this.annotationEditorLayer.isEmpty) {
+ if (!this.div || this.annotationEditorLayer.isInvisible) {
return;
}
this.div.hidden = false;
@@ -6855,9 +6864,9 @@ class AnnotationEditorLayerBuilder {
class AnnotationLayerBuilder {
+ #onAppend = null;
#onPresentationModeChanged = null;
constructor({
- pageDiv,
pdfPage,
linkService,
downloadManager,
@@ -6868,9 +6877,9 @@ class AnnotationLayerBuilder {
hasJSActionsPromise = null,
fieldObjectsPromise = null,
annotationCanvasMap = null,
- accessibilityManager = null
+ accessibilityManager = null,
+ onAppend = null
}) {
- this.pageDiv = pageDiv;
this.pdfPage = pdfPage;
this.linkService = linkService;
this.downloadManager = downloadManager;
@@ -6882,6 +6891,7 @@ class AnnotationLayerBuilder {
this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
this._annotationCanvasMap = annotationCanvasMap;
this._accessibilityManager = accessibilityManager;
+ this.#onAppend = onAppend;
this.annotationLayer = null;
this.div = null;
this._cancelled = false;
@@ -6907,7 +6917,7 @@ class AnnotationLayerBuilder {
}
const div = this.div = document.createElement("div");
div.className = "annotationLayer";
- this.pageDiv.append(div);
+ this.#onAppend?.(div);
if (annotations.length === 0) {
this.hide();
return;
@@ -7501,13 +7511,15 @@ class TextHighlighter {
class TextLayerBuilder {
#enablePermissions = false;
+ #onAppend = null;
#rotation = 0;
#scale = 0;
#textContentSource = null;
constructor({
highlighter = null,
accessibilityManager = null,
- enablePermissions = false
+ enablePermissions = false,
+ onAppend = null
}) {
this.textContentItemsStr = [];
this.renderingDone = false;
@@ -7517,8 +7529,9 @@ class TextLayerBuilder {
this.highlighter = highlighter;
this.accessibilityManager = accessibilityManager;
this.#enablePermissions = enablePermissions === true;
- this.onAppend = null;
+ this.#onAppend = onAppend;
this.div = document.createElement("div");
+ this.div.tabIndex = 0;
this.div.className = "textLayer";
}
#finishRendering() {
@@ -7573,7 +7586,7 @@ class TextLayerBuilder {
this.#finishRendering();
this.#scale = scale;
this.#rotation = rotation;
- this.onAppend(this.div);
+ this.#onAppend?.(this.div);
this.highlighter?.enable();
this.accessibilityManager?.enable();
}
@@ -7647,8 +7660,8 @@ class TextLayerBuilder {
-const MAX_CANVAS_PIXELS = compatibilityParams.maxCanvasPixels || 16777216;
const DEFAULT_LAYER_PROPERTIES = null;
+const LAYERS_ORDER = new Map([["canvasWrapper", 0], ["textLayer", 1], ["annotationLayer", 2], ["annotationEditorLayer", 3], ["xfaLayer", 3]]);
class PDFPageView {
#annotationMode = AnnotationMode.ENABLE_FORMS;
#hasRestrictedScaling = false;
@@ -7664,6 +7677,7 @@ class PDFPageView {
regularAnnotations: true
};
#viewportMap = new WeakMap();
+ #layers = [null, null, null, null];
constructor(options) {
const container = options.container;
const defaultViewport = options.defaultViewport;
@@ -7680,7 +7694,7 @@ class PDFPageView {
this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
this.imageResourcesPath = options.imageResourcesPath || "";
- this.maxCanvasPixels = options.maxCanvasPixels ?? MAX_CANVAS_PIXELS;
+ this.maxCanvasPixels = options.maxCanvasPixels ?? (AppOptions.getCompat("maxCanvasPixels") || 2 ** 25);
this.pageColors = options.pageColors || null;
this.eventBus = options.eventBus;
this.renderingQueue = options.renderingQueue;
@@ -7707,6 +7721,23 @@ class PDFPageView {
this.#setDimensions();
container?.append(div);
}
+ #addLayer(div, name) {
+ const pos = LAYERS_ORDER.get(name);
+ const oldDiv = this.#layers[pos];
+ this.#layers[pos] = div;
+ if (oldDiv) {
+ oldDiv.replaceWith(div);
+ return;
+ }
+ for (let i = pos - 1; i >= 0; i--) {
+ const layer = this.#layers[i];
+ if (layer) {
+ layer.after(div);
+ return;
+ }
+ }
+ this.div.prepend(div);
+ }
get renderingState() {
return this.#renderingState;
}
@@ -7820,7 +7851,7 @@ class PDFPageView {
} finally {
if (this.xfaLayer?.div) {
this.l10n.pause();
- this.div.append(this.xfaLayer.div);
+ this.#addLayer(this.xfaLayer.div, "xfaLayer");
this.l10n.resume();
}
this.eventBus.dispatch("xfalayerrendered", {
@@ -7932,6 +7963,10 @@ class PDFPageView {
continue;
}
node.remove();
+ const layerIndex = this.#layers.indexOf(node);
+ if (layerIndex >= 0) {
+ this.#layers[layerIndex] = null;
+ }
}
div.removeAttribute("data-loaded");
if (annotationLayerNode) {
@@ -8191,19 +8226,20 @@ class PDFPageView {
this.renderingState = RenderingStates.RUNNING;
const canvasWrapper = document.createElement("div");
canvasWrapper.classList.add("canvasWrapper");
- div.append(canvasWrapper);
+ canvasWrapper.setAttribute("aria-hidden", true);
+ this.#addLayer(canvasWrapper, "canvasWrapper");
if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
this._accessibilityManager ||= new TextAccessibilityManager();
this.textLayer = new TextLayerBuilder({
highlighter: this._textHighlighter,
accessibilityManager: this._accessibilityManager,
- enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS
+ enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS,
+ onAppend: textLayerDiv => {
+ this.l10n.pause();
+ this.#addLayer(textLayerDiv, "textLayer");
+ this.l10n.resume();
+ }
});
- this.textLayer.onAppend = textLayerDiv => {
- this.l10n.pause();
- this.div.append(textLayerDiv);
- this.l10n.resume();
- };
}
if (!this.annotationLayer && this.#annotationMode !== AnnotationMode.DISABLE) {
const {
@@ -8216,7 +8252,6 @@ class PDFPageView {
} = this.#layerProperties;
this._annotationCanvasMap ||= new Map();
this.annotationLayer = new AnnotationLayerBuilder({
- pageDiv: div,
pdfPage,
annotationStorage,
imageResourcesPath: this.imageResourcesPath,
@@ -8227,7 +8262,10 @@ class PDFPageView {
hasJSActionsPromise,
fieldObjectsPromise,
annotationCanvasMap: this._annotationCanvasMap,
- accessibilityManager: this._accessibilityManager
+ accessibilityManager: this._accessibilityManager,
+ onAppend: annotationLayerDiv => {
+ this.#addLayer(annotationLayerDiv, "annotationLayer");
+ }
});
}
const renderContinueCallback = cont => {
@@ -8316,13 +8354,15 @@ class PDFPageView {
if (!this.annotationEditorLayer) {
this.annotationEditorLayer = new AnnotationEditorLayerBuilder({
uiManager: annotationEditorUIManager,
- pageDiv: div,
pdfPage,
l10n,
accessibilityManager: this._accessibilityManager,
annotationLayer: this.annotationLayer?.annotationLayer,
textLayer: this.textLayer,
- drawLayer: this.drawLayer.getDrawLayer()
+ drawLayer: this.drawLayer.getDrawLayer(),
+ onAppend: annotationEditorLayerDiv => {
+ this.#addLayer(annotationEditorLayerDiv, "annotationEditorLayer");
+ }
});
}
this.#renderAnnotationEditorLayer();
@@ -8447,6 +8487,7 @@ class PDFViewer {
#annotationMode = AnnotationMode.ENABLE_FORMS;
#containerTopLeft = null;
#copyCallbackBound = null;
+ #enableHighlightFloatingButton = false;
#enablePermissions = false;
#mlManager = null;
#getAllTextInProgress = false;
@@ -8459,7 +8500,7 @@ class PDFViewer {
#scaleTimeoutId = null;
#textLayerMode = TextLayerMode.ENABLE;
constructor(options) {
- const viewerVersion = "4.1.249";
+ const viewerVersion = "4.1.342";
if (version !== viewerVersion) {
throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
}
@@ -8479,6 +8520,7 @@ class PDFViewer {
this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
this.#annotationEditorMode = options.annotationEditorMode ?? AnnotationEditorType.NONE;
this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null;
+ this.#enableHighlightFloatingButton = options.enableHighlightFloatingButton === true;
this.imageResourcesPath = options.imageResourcesPath || "";
this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
this.maxCanvasPixels = options.maxCanvasPixels;
@@ -8789,7 +8831,9 @@ class PDFViewer {
}
const pagesCount = pdfDocument.numPages;
const firstPagePromise = pdfDocument.getPage(1);
- const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
+ const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
+ intent: "display"
+ });
const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve();
if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
console.warn("Forcing PAGE-scrolling for performance reasons, given the length of the document.");
@@ -8845,7 +8889,7 @@ class PDFViewer {
if (pdfDocument.isPureXfa) {
console.warn("Warning: XFA-editing is not implemented.");
} else if (isValidAnnotationEditorMode(mode)) {
- this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, this.viewer, this.#altTextManager, this.eventBus, pdfDocument, this.pageColors, this.#annotationEditorHighlightColors, this.#mlManager);
+ this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, this.viewer, this.#altTextManager, this.eventBus, pdfDocument, this.pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#mlManager);
this.eventBus.dispatch("annotationeditoruimanager", {
source: this,
uiManager: this.#annotationEditorUIManager
@@ -9506,7 +9550,9 @@ class PDFViewer {
}
if (!this._optionalContentConfigPromise) {
console.error("optionalContentConfigPromise: Not initialized yet.");
- return this.pdfDocument.getOptionalContentConfig();
+ return this.pdfDocument.getOptionalContentConfig({
+ intent: "display"
+ });
}
return this._optionalContentConfigPromise;
}
@@ -10694,6 +10740,7 @@ const PDFViewerApplication = {
annotationMode: AppOptions.get("annotationMode"),
annotationEditorMode,
annotationEditorHighlightColors: AppOptions.get("highlightEditorColors"),
+ enableHighlightFloatingButton: AppOptions.get("enableHighlightFloatingButton"),
imageResourcesPath: AppOptions.get("imageResourcesPath"),
enablePrintAutoRotate: AppOptions.get("enablePrintAutoRotate"),
maxCanvasPixels: AppOptions.get("maxCanvasPixels"),
@@ -10833,40 +10880,8 @@ const PDFViewerApplication = {
if (this.supportsIntegratedFind) {
appConfig.toolbar?.viewFind?.classList.add("hidden");
}
- this.initPassiveLoading(file);
- const {
- mainContainer
- } = appConfig;
- ({
- scrollTop: this._lastScrollTop,
- scrollLeft: this._lastScrollLeft
- } = mainContainer);
- const scroll = () => {
- if (this._lastScrollTop === mainContainer.scrollTop && this._lastScrollLeft === mainContainer.scrollLeft) {
- return;
- }
- mainContainer.removeEventListener("scroll", scroll, {
- passive: true
- });
- this._isScrolling = true;
- const scrollend = () => {
- ({
- scrollTop: this._lastScrollTop,
- scrollLeft: this._lastScrollLeft
- } = mainContainer);
- this._isScrolling = false;
- mainContainer.addEventListener("scroll", scroll, {
- passive: true
- });
- mainContainer.removeEventListener("scrollend", scrollend);
- mainContainer.removeEventListener("blur", scrollend);
- };
- mainContainer.addEventListener("scrollend", scrollend);
- mainContainer.addEventListener("blur", scrollend);
- };
- mainContainer.addEventListener("scroll", scroll, {
- passive: true
- });
+ this.setTitleUsingUrl(file, file);
+ this.externalServices.initPassiveLoading();
},
get externalServices() {
return shadow(this, "externalServices", new ExternalServices());
@@ -10939,45 +10954,12 @@ const PDFViewerApplication = {
return shadow(this, "supportsMouseWheelZoomMetaKey", AppOptions.get("supportsMouseWheelZoomMetaKey"));
},
get supportsCaretBrowsingMode() {
- return shadow(this, "supportsCaretBrowsingMode", AppOptions.get("supportsCaretBrowsingMode"));
+ return AppOptions.get("supportsCaretBrowsingMode");
},
moveCaret(isUp, select) {
this._caretBrowsing ||= new CaretBrowsingMode(this.appConfig.mainContainer, this.appConfig.viewerContainer, this.appConfig.toolbar?.container);
this._caretBrowsing.moveCaret(isUp, select);
},
- initPassiveLoading(file) {
- this.setTitleUsingUrl(file, file);
- this.externalServices.initPassiveLoading({
- onOpenWithTransport: range => {
- this.open({
- range
- });
- },
- onOpenWithData: (data, contentDispositionFilename) => {
- if (isPdfFile(contentDispositionFilename)) {
- this._contentDispositionFilename = contentDispositionFilename;
- }
- this.open({
- data
- });
- },
- onOpenWithURL: (url, length, originalUrl) => {
- this.open({
- url,
- length,
- originalUrl
- });
- },
- onError: err => {
- this.l10n.get("pdfjs-loading-error").then(msg => {
- this._documentError(msg, err);
- });
- },
- onProgress: (loaded, total) => {
- this.progress(loaded / total);
- }
- });
- },
setTitleUsingUrl(url = "", downloadUrl = null) {
this.url = url;
this.baseUrl = url.split("#", 1)[0];
@@ -11065,6 +11047,9 @@ const PDFViewerApplication = {
}
const workerParams = AppOptions.getAll(OptionKind.WORKER);
Object.assign(GlobalWorkerOptions, workerParams);
+ if (args.data && isPdfFile(args.filename)) {
+ this._contentDispositionFilename = args.filename;
+ }
AppOptions.set("docBaseUrl", this.baseUrl);
const apiParams = AppOptions.getAll(OptionKind.API);
const loadingTask = getDocument({
@@ -11100,10 +11085,9 @@ const PDFViewerApplication = {
} else if (reason instanceof UnexpectedResponseException) {
key = "pdfjs-unexpected-response-error";
}
- return this.l10n.get(key).then(msg => {
- this._documentError(msg, {
- message: reason?.message
- });
+ return this._documentError(key, {
+ message: reason.message
+ }).then(() => {
throw reason;
});
});
@@ -11167,21 +11151,17 @@ const PDFViewerApplication = {
this.download(options);
}
},
- openInExternalApp() {
- this.downloadOrSave({
- openInExternalApp: true
- });
- },
- _documentError(message, moreInfo = null) {
+ async _documentError(key, moreInfo = null) {
this._unblockDocumentLoadEvent();
- this._otherError(message, moreInfo);
+ const message = await this._otherError(key || "pdfjs-loading-error", moreInfo);
this.eventBus.dispatch("documenterror", {
source: this,
message,
reason: moreInfo?.message ?? null
});
},
- _otherError(message, moreInfo = null) {
+ async _otherError(key, moreInfo = null) {
+ const message = await this.l10n.get(key);
const moreInfoText = [`PDF.js v${version || "?"} (build: ${build || "?"})`];
if (moreInfo) {
moreInfoText.push(`Message: ${moreInfo.message}`);
@@ -11197,6 +11177,7 @@ const PDFViewerApplication = {
}
}
console.error(`${message}\n\n${moreInfoText.join("\n")}`);
+ return message;
},
progress(level) {
if (!this.loadingBar || this.downloadComplete) {
@@ -11321,10 +11302,8 @@ const PDFViewerApplication = {
this._unblockDocumentLoadEvent();
this._initializeAutoPrint(pdfDocument, openActionPromise);
}, reason => {
- this.l10n.get("pdfjs-loading-error").then(msg => {
- this._documentError(msg, {
- message: reason?.message
- });
+ this._documentError("pdfjs-loading-error", {
+ message: reason.message
});
});
onePageRendered.then(data => {
@@ -11603,9 +11582,7 @@ const PDFViewerApplication = {
return;
}
if (!this.supportsPrinting) {
- this.l10n.get("pdfjs-printing-not-supported").then(msg => {
- this._otherError(msg);
- });
+ this._otherError("pdfjs-printing-not-supported");
return;
}
if (!this.pdfViewer.pageViewsReady) {
@@ -11619,7 +11596,6 @@ const PDFViewerApplication = {
pagesOverview: this.pdfViewer.getPagesOverview(),
printContainer: this.appConfig.printContainer,
printResolution: AppOptions.get("printResolution"),
- optionalContentConfigPromise: this.pdfViewer.optionalContentConfigPromise,
printAnnotationStoragePromise: this._printAnnotationStoragePromise
});
this.forceRendering();
@@ -11688,7 +11664,6 @@ const PDFViewerApplication = {
eventBus._on("switchannotationeditorparams", webViewerSwitchAnnotationEditorParams);
eventBus._on("print", webViewerPrint);
eventBus._on("download", webViewerDownload);
- eventBus._on("openinexternalapp", webViewerOpenInExternalApp);
eventBus._on("firstpage", webViewerFirstPage);
eventBus._on("lastpage", webViewerLastPage);
eventBus._on("nextpage", webViewerNextPage);
@@ -11720,7 +11695,10 @@ const PDFViewerApplication = {
bindWindowEvents() {
const {
eventBus,
- _boundEvents
+ _boundEvents,
+ appConfig: {
+ mainContainer
+ }
} = this;
function addWindowResolutionChange(evt = null) {
if (evt) {
@@ -11780,12 +11758,79 @@ const PDFViewerApplication = {
window.addEventListener("beforeprint", _boundEvents.windowBeforePrint);
window.addEventListener("afterprint", _boundEvents.windowAfterPrint);
window.addEventListener("updatefromsandbox", _boundEvents.windowUpdateFromSandbox);
+ ({
+ scrollTop: this._lastScrollTop,
+ scrollLeft: this._lastScrollLeft
+ } = mainContainer);
+ const scrollend = _boundEvents.mainContainerScrollend = () => {
+ ({
+ scrollTop: this._lastScrollTop,
+ scrollLeft: this._lastScrollLeft
+ } = mainContainer);
+ this._isScrolling = false;
+ mainContainer.addEventListener("scroll", scroll, {
+ passive: true
+ });
+ mainContainer.removeEventListener("scrollend", scrollend);
+ mainContainer.removeEventListener("blur", scrollend);
+ };
+ const scroll = _boundEvents.mainContainerScroll = () => {
+ if (this._isCtrlKeyDown || this._lastScrollTop === mainContainer.scrollTop && this._lastScrollLeft === mainContainer.scrollLeft) {
+ return;
+ }
+ mainContainer.removeEventListener("scroll", scroll, {
+ passive: true
+ });
+ this._isScrolling = true;
+ mainContainer.addEventListener("scrollend", scrollend);
+ mainContainer.addEventListener("blur", scrollend);
+ };
+ mainContainer.addEventListener("scroll", scroll, {
+ passive: true
+ });
},
unbindEvents() {
throw new Error("Not implemented: unbindEvents");
},
unbindWindowEvents() {
- throw new Error("Not implemented: unbindWindowEvents");
+ const {
+ _boundEvents,
+ appConfig: {
+ mainContainer
+ }
+ } = this;
+ window.removeEventListener("visibilitychange", webViewerVisibilityChange);
+ window.removeEventListener("wheel", webViewerWheel, {
+ passive: false
+ });
+ window.removeEventListener("touchstart", webViewerTouchStart, {
+ passive: false
+ });
+ window.removeEventListener("touchmove", webViewerTouchMove, {
+ passive: false
+ });
+ window.removeEventListener("touchend", webViewerTouchEnd, {
+ passive: false
+ });
+ window.removeEventListener("click", webViewerClick);
+ window.removeEventListener("keydown", webViewerKeyDown);
+ window.removeEventListener("keyup", webViewerKeyUp);
+ window.removeEventListener("resize", _boundEvents.windowResize);
+ window.removeEventListener("hashchange", _boundEvents.windowHashChange);
+ window.removeEventListener("beforeprint", _boundEvents.windowBeforePrint);
+ window.removeEventListener("afterprint", _boundEvents.windowAfterPrint);
+ window.removeEventListener("updatefromsandbox", _boundEvents.windowUpdateFromSandbox);
+ mainContainer.removeEventListener("scroll", _boundEvents.mainContainerScroll);
+ mainContainer.removeEventListener("scrollend", _boundEvents.mainContainerScrollend);
+ mainContainer.removeEventListener("blur", _boundEvents.mainContainerScrollend);
+ _boundEvents.removeWindowResolutionChange?.();
+ _boundEvents.windowResize = null;
+ _boundEvents.windowHashChange = null;
+ _boundEvents.windowBeforePrint = null;
+ _boundEvents.windowAfterPrint = null;
+ _boundEvents.windowUpdateFromSandbox = null;
+ _boundEvents.mainContainerScroll = null;
+ _boundEvents.mainContainerScrollend = null;
},
_accumulateTicks(ticks, prop) {
if (this[prop] > 0 && ticks < 0 || this[prop] < 0 && ticks > 0) {
@@ -11868,9 +11913,7 @@ function webViewerPageRendered({
}
}
if (error) {
- PDFViewerApplication.l10n.get("pdfjs-rendering-error").then(msg => {
- PDFViewerApplication._otherError(msg, error);
- });
+ PDFViewerApplication._otherError("pdfjs-rendering-error", error);
}
}
function webViewerPageMode({
@@ -12000,9 +12043,6 @@ function webViewerPrint() {
function webViewerDownload() {
PDFViewerApplication.downloadOrSave();
}
-function webViewerOpenInExternalApp() {
- PDFViewerApplication.openInExternalApp();
-}
function webViewerFirstPage() {
PDFViewerApplication.page = 1;
}
@@ -12591,8 +12631,8 @@ function webViewerReportTelemetry({
-const pdfjsVersion = "4.1.249";
-const pdfjsBuild = "d07f37f44";
+const pdfjsVersion = "4.1.342";
+const pdfjsBuild = "e384df6f1";
const AppConstants = null;
window.PDFViewerApplication = PDFViewerApplication;
window.PDFViewerApplicationConstants = AppConstants;
@@ -12718,7 +12758,8 @@ function getViewerConfiguration() {
editorInkThickness: document.getElementById("editorInkThickness"),
editorInkOpacity: document.getElementById("editorInkOpacity"),
editorStampAddImage: document.getElementById("editorStampAddImage"),
- editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness")
+ editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness"),
+ editorHighlightShowAll: document.getElementById("editorHighlightShowAll")
},
printContainer: document.getElementById("printContainer")
};