summaryrefslogtreecommitdiffstats
path: root/toolkit/components/pdfjs/content/web
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/pdfjs/content/web')
-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
7 files changed, 768 insertions, 455 deletions
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")
};