Merge pull request #20607 from Snuffleupagus/rm-web-interfaces

Replace the various interfaces in `web/interfaces.js` with proper classes
This commit is contained in:
Tim van der Meij 2026-02-01 20:31:13 +01:00 committed by GitHub
commit 3f21efc942
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 331 additions and 516 deletions

View File

@ -28,4 +28,4 @@ jobs:
run: npm ci run: npm ci
- name: Run types tests - name: Run types tests
run: npx gulp typestest run: npx gulp types

View File

@ -231,7 +231,7 @@ function createWebpackAlias(defines) {
libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js"; libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js";
libraryAlias["display-network"] = "src/display/network.js"; libraryAlias["display-network"] = "src/display/network.js";
viewerAlias["web-download_manager"] = "web/download_manager.js"; viewerAlias["web-download_manager"] = "web/chromecom.js";
viewerAlias["web-external_services"] = "web/chromecom.js"; viewerAlias["web-external_services"] = "web/chromecom.js";
viewerAlias["web-null_l10n"] = "web/l10n.js"; viewerAlias["web-null_l10n"] = "web/l10n.js";
viewerAlias["web-preferences"] = "web/chromecom.js"; viewerAlias["web-preferences"] = "web/chromecom.js";

View File

@ -18,9 +18,6 @@
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../../web/text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */ /** @typedef {import("../../web/text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../../web/interfaces").IDownloadManager} IDownloadManager */
/** @typedef {import("../../web/interfaces").IPDFLinkService} IPDFLinkService */
// eslint-disable-next-line max-len
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */ /** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../../web/struct_tree_layer_builder.js").StructTreeLayerBuilder} StructTreeLayerBuilder */ /** @typedef {import("../../web/struct_tree_layer_builder.js").StructTreeLayerBuilder} StructTreeLayerBuilder */
@ -57,8 +54,8 @@ const TIMEZONE_OFFSET = new Date().getTimezoneOffset() * 60 * 1000;
* @typedef {Object} AnnotationElementParameters * @typedef {Object} AnnotationElementParameters
* @property {Object} data * @property {Object} data
* @property {HTMLDivElement} layer * @property {HTMLDivElement} layer
* @property {IPDFLinkService} linkService * @property {PDFLinkService} linkService
* @property {IDownloadManager} [downloadManager] * @property {BaseDownloadManager} [downloadManager]
* @property {AnnotationStorage} [annotationStorage] * @property {AnnotationStorage} [annotationStorage]
* @property {string} [imageResourcesPath] - Path for image resources, mainly * @property {string} [imageResourcesPath] - Path for image resources, mainly
* for annotation icons. Include trailing slash. * for annotation icons. Include trailing slash.
@ -3736,8 +3733,8 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
* @property {HTMLDivElement} div * @property {HTMLDivElement} div
* @property {Array} annotations * @property {Array} annotations
* @property {PDFPageProxy} page * @property {PDFPageProxy} page
* @property {IPDFLinkService} linkService * @property {PDFLinkService} linkService
* @property {IDownloadManager} [downloadManager] * @property {BaseDownloadManager} [downloadManager]
* @property {AnnotationStorage} [annotationStorage] * @property {AnnotationStorage} [annotationStorage]
* @property {string} [imageResourcesPath] - Path for image resources, mainly * @property {string} [imageResourcesPath] - Path for image resources, mainly
* for annotation icons. Include trailing slash. * for annotation icons. Include trailing slash.
@ -4018,8 +4015,6 @@ class AnnotationLayer {
* Add link annotations to the annotation layer. * Add link annotations to the annotation layer.
* *
* @param {Array<Object>} annotations * @param {Array<Object>} annotations
* @param {IPDFLinkService} linkService
* @memberof AnnotationLayer
*/ */
async addLinkAnnotations(annotations) { async addLinkAnnotations(annotations) {
const elementParams = { const elementParams = {

View File

@ -18,7 +18,6 @@
/** @typedef {import("../display_utils.js").PageViewport} PageViewport */ /** @typedef {import("../display_utils.js").PageViewport} PageViewport */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../../../web/text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */ /** @typedef {import("../../../web/text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
/** @typedef {import("../../../web/interfaces").IL10n} IL10n */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../annotation_layer.js").AnnotationLayer} AnnotationLayer */ /** @typedef {import("../annotation_layer.js").AnnotationLayer} AnnotationLayer */
/** @typedef {import("../draw_layer.js").DrawLayer} DrawLayer */ /** @typedef {import("../draw_layer.js").DrawLayer} DrawLayer */
@ -47,7 +46,7 @@ import { StampEditor } from "./stamp.js";
* @property {boolean} enabled * @property {boolean} enabled
* @property {TextAccessibilityManager} [accessibilityManager] * @property {TextAccessibilityManager} [accessibilityManager]
* @property {number} pageIndex * @property {number} pageIndex
* @property {IL10n} l10n * @property {L10n} l10n
* @property {AnnotationLayer} [annotationLayer] * @property {AnnotationLayer} [annotationLayer]
* @property {HTMLDivElement} [textLayer] * @property {HTMLDivElement} [textLayer]
* @property {DrawLayer} drawLayer * @property {DrawLayer} drawLayer

View File

@ -16,7 +16,6 @@
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./annotation_storage").AnnotationStorage} AnnotationStorage */ /** @typedef {import("./annotation_storage").AnnotationStorage} AnnotationStorage */
/** @typedef {import("./display_utils").PageViewport} PageViewport */ /** @typedef {import("./display_utils").PageViewport} PageViewport */
/** @typedef {import("../../web/interfaces").IPDFLinkService} IPDFLinkService */
import { XfaText } from "./xfa_text.js"; import { XfaText } from "./xfa_text.js";
@ -26,7 +25,7 @@ import { XfaText } from "./xfa_text.js";
* @property {HTMLDivElement} div * @property {HTMLDivElement} div
* @property {Object} xfaHtml * @property {Object} xfaHtml
* @property {AnnotationStorage} [annotationStorage] * @property {AnnotationStorage} [annotationStorage]
* @property {IPDFLinkService} linkService * @property {PDFLinkService} linkService
* @property {string} [intent] - (default value is 'display'). * @property {string} [intent] - (default value is 'display').
*/ */

View File

@ -22,7 +22,6 @@ import {
import { import {
parseQueryString, parseQueryString,
ProgressBar, ProgressBar,
RenderingStates,
ScrollMode, ScrollMode,
SpreadMode, SpreadMode,
} from "../../web/ui_utils.js"; } from "../../web/ui_utils.js";
@ -35,6 +34,7 @@ import { PDFPageView } from "../../web/pdf_page_view.js";
import { PDFScriptingManager } from "../../web/pdf_scripting_manager.component.js"; import { PDFScriptingManager } from "../../web/pdf_scripting_manager.component.js";
import { PDFSinglePageViewer } from "../../web/pdf_single_page_viewer.js"; import { PDFSinglePageViewer } from "../../web/pdf_single_page_viewer.js";
import { PDFViewer } from "../../web/pdf_viewer.js"; import { PDFViewer } from "../../web/pdf_viewer.js";
import { RenderingStates } from "../../web/renderable_view.js";
import { StructTreeLayerBuilder } from "../../web/struct_tree_layer_builder.js"; import { StructTreeLayerBuilder } from "../../web/struct_tree_layer_builder.js";
import { TextLayerBuilder } from "../../web/text_layer_builder.js"; import { TextLayerBuilder } from "../../web/text_layer_builder.js";
import { XfaLayerBuilder } from "../../web/xfa_layer_builder.js"; import { XfaLayerBuilder } from "../../web/xfa_layer_builder.js";

View File

@ -20,7 +20,6 @@
/** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */ /** @typedef {import("../src/display/editor/tools.js").AnnotationEditorUIManager} AnnotationEditorUIManager */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */ /** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
/** @typedef {import("./interfaces").IL10n} IL10n */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/annotation_layer.js").AnnotationLayer} AnnotationLayer */ /** @typedef {import("../src/display/annotation_layer.js").AnnotationLayer} AnnotationLayer */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
@ -33,7 +32,7 @@ import { GenericL10n } from "web-null_l10n";
* @typedef {Object} AnnotationEditorLayerBuilderOptions * @typedef {Object} AnnotationEditorLayerBuilderOptions
* @property {AnnotationEditorUIManager} [uiManager] * @property {AnnotationEditorUIManager} [uiManager]
* @property {PDFPageProxy} pdfPage * @property {PDFPageProxy} pdfPage
* @property {IL10n} [l10n] * @property {L10n} [l10n]
* @property {StructTreeLayerBuilder} [structTreeLayer] * @property {StructTreeLayerBuilder} [structTreeLayer]
* @property {TextAccessibilityManager} [accessibilityManager] * @property {TextAccessibilityManager} [accessibilityManager]
* @property {AnnotationLayer} [annotationLayer] * @property {AnnotationLayer} [annotationLayer]

View File

@ -18,8 +18,6 @@
/** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */ /** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/annotation_storage").AnnotationStorage} AnnotationStorage */ /** @typedef {import("../src/display/annotation_storage").AnnotationStorage} AnnotationStorage */
/** @typedef {import("./interfaces").IDownloadManager} IDownloadManager */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./struct_tree_layer_builder.js").StructTreeLayerBuilder} StructTreeLayerBuilder */ /** @typedef {import("./struct_tree_layer_builder.js").StructTreeLayerBuilder} StructTreeLayerBuilder */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
@ -43,8 +41,8 @@ import { PresentationModeState } from "./ui_utils.js";
* @property {string} [imageResourcesPath] - Path for image resources, mainly * @property {string} [imageResourcesPath] - Path for image resources, mainly
* for annotation icons. Include trailing slash. * for annotation icons. Include trailing slash.
* @property {boolean} renderForms * @property {boolean} renderForms
* @property {IPDFLinkService} linkService * @property {PDFLinkService} linkService
* @property {IDownloadManager} [downloadManager] * @property {BaseDownloadManager} [downloadManager]
* @property {boolean} [enableComment] * @property {boolean} [enableComment]
* @property {boolean} [enableScripting] * @property {boolean} [enableScripting]
* @property {Promise<boolean>} [hasJSActionsPromise] * @property {Promise<boolean>} [hasJSActionsPromise]

View File

@ -13,7 +13,6 @@
* limitations under the License. * limitations under the License.
*/ */
/** @typedef {import("./interfaces.js").IL10n} IL10n */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/api.js").PDFDocumentProxy} PDFDocumentProxy */ /** @typedef {import("../src/display/api.js").PDFDocumentProxy} PDFDocumentProxy */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
@ -34,7 +33,6 @@ import {
normalizeWheelEventDirection, normalizeWheelEventDirection,
parseQueryString, parseQueryString,
ProgressBar, ProgressBar,
RenderingStates,
ScrollMode, ScrollMode,
SidebarView, SidebarView,
SpreadMode, SpreadMode,
@ -92,6 +90,7 @@ import { PdfTextExtractor } from "./pdf_text_extractor.js";
import { PDFThumbnailViewer } from "web-pdf_thumbnail_viewer"; import { PDFThumbnailViewer } from "web-pdf_thumbnail_viewer";
import { PDFViewer } from "./pdf_viewer.js"; import { PDFViewer } from "./pdf_viewer.js";
import { Preferences } from "web-preferences"; import { Preferences } from "web-preferences";
import { RenderingStates } from "./renderable_view.js";
import { SecondaryToolbar } from "web-secondary_toolbar"; import { SecondaryToolbar } from "web-secondary_toolbar";
import { SignatureManager } from "web-signature_manager"; import { SignatureManager } from "web-signature_manager";
import { Toolbar } from "web-toolbar"; import { Toolbar } from "web-toolbar";
@ -160,7 +159,7 @@ const PDFViewerApplication = {
secondaryToolbar: null, secondaryToolbar: null,
/** @type {EventBus} */ /** @type {EventBus} */
eventBus: null, eventBus: null,
/** @type {IL10n} */ /** @type {L10n} */
l10n: null, l10n: null,
/** @type {AnnotationEditorParams} */ /** @type {AnnotationEditorParams} */
annotationEditorParams: null, annotationEditorParams: null,
@ -2457,10 +2456,7 @@ const PDFViewerApplication = {
}; };
initCom(PDFViewerApplication); initCom(PDFViewerApplication);
PDFPrintServiceFactory.initGlobals(PDFViewerApplication);
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
PDFPrintServiceFactory.initGlobals(PDFViewerApplication);
}
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) { if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
const HOSTED_VIEWER_ORIGINS = new Set([ const HOSTED_VIEWER_ORIGINS = new Set([

View File

@ -0,0 +1,103 @@
/* Copyright 2013 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { isPdfFile } from "pdfjs-lib";
class BaseDownloadManager {
#openBlobUrls = new WeakMap();
constructor() {
if (
(typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) &&
this.constructor === BaseDownloadManager
) {
throw new Error("Cannot initialize BaseDownloadManager.");
}
}
_triggerDownload(blobUrl, originalUrl, filename, isAttachment = false) {
throw new Error("Not implemented: _triggerDownload");
}
_getOpenDataUrl(blobUrl, filename, dest = null) {
throw new Error("Not implemented: _getOpenDataUrl");
}
/**
* @param {Uint8Array} data
* @param {string} filename
* @param {string} [contentType]
*/
downloadData(data, filename, contentType) {
const blobUrl = URL.createObjectURL(
new Blob([data], { type: contentType })
);
this._triggerDownload(
blobUrl,
/* originalUrl = */ blobUrl,
filename,
/* isAttachment = */ true
);
}
/**
* @param {Uint8Array} data
* @param {string} filename
* @param {string | null} [dest]
* @returns {boolean} Indicating if the data was opened.
*/
openOrDownloadData(data, filename, dest = null) {
const isPdfData = isPdfFile(filename);
const contentType = isPdfData ? "application/pdf" : "";
if (isPdfData) {
let blobUrl;
try {
blobUrl = this.#openBlobUrls.getOrInsertComputed(data, () =>
URL.createObjectURL(new Blob([data], { type: contentType }))
);
const viewerUrl = this._getOpenDataUrl(blobUrl, filename, dest);
window.open(viewerUrl);
return true;
} catch (ex) {
console.error("openOrDownloadData:", ex);
// Release the `blobUrl`, since opening it failed, and fallback to
// downloading the PDF file.
URL.revokeObjectURL(blobUrl);
this.#openBlobUrls.delete(data);
}
}
this.downloadData(data, filename, contentType);
return false;
}
/**
* @param {Uint8Array} data
* @param {string} url
* @param {string} filename
*/
download(data, url, filename) {
const blobUrl = data
? URL.createObjectURL(new Blob([data], { type: "application/pdf" }))
: null;
this._triggerDownload(blobUrl, /* originalUrl = */ url, filename);
}
}
export { BaseDownloadManager };

View File

@ -13,10 +13,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { RenderableView, RenderingStates } from "./renderable_view.js";
import { RenderingCancelledException } from "pdfjs-lib"; import { RenderingCancelledException } from "pdfjs-lib";
import { RenderingStates } from "./ui_utils.js";
class BasePDFPageView { class BasePDFPageView extends RenderableView {
#loadingId = null; #loadingId = null;
#minDurationToUpdateCanvas = 0; #minDurationToUpdateCanvas = 0;
@ -48,11 +48,8 @@ class BasePDFPageView {
renderingQueue = null; renderingQueue = null;
renderTask = null;
resume = null;
constructor(options) { constructor(options) {
super();
this.eventBus = options.eventBus; this.eventBus = options.eventBus;
this.id = options.id; this.id = options.id;
this.pageColors = options.pageColors || null; this.pageColors = options.pageColors || null;

View File

@ -17,6 +17,7 @@
import { AppOptions } from "./app_options.js"; import { AppOptions } from "./app_options.js";
import { BaseExternalServices } from "./external_services.js"; import { BaseExternalServices } from "./external_services.js";
import { BasePreferences } from "./preferences.js"; import { BasePreferences } from "./preferences.js";
import { DownloadManager as GenericDownloadManager } from "./download_manager.js";
import { GenericL10n } from "./genericl10n.js"; import { GenericL10n } from "./genericl10n.js";
import { GenericScripting } from "./generic_scripting.js"; import { GenericScripting } from "./generic_scripting.js";
import { SignatureStorage } from "./generic_signature_storage.js"; import { SignatureStorage } from "./generic_signature_storage.js";
@ -310,6 +311,25 @@ function setReferer(url, callback) {
} }
} }
/**
* This "should" really extend the `BaseDownloadManager` class,
* however doing it this way instead reduces code duplication.
*/
class DownloadManager extends GenericDownloadManager {
_getOpenDataUrl(blobUrl, filename, dest = null) {
// In the Chrome extension, the URL is rewritten using the history API
// in viewer.js, so an absolute URL must be generated.
let url =
chrome.runtime.getURL("/content/web/viewer.html") +
"?file=" +
encodeURIComponent(blobUrl + "#" + filename);
if (dest) {
url += `#${escape(dest)}`;
}
return url;
}
}
// chrome.storage.sync is not supported in every Chromium-derivate. // chrome.storage.sync is not supported in every Chromium-derivate.
// Note: The background page takes care of migrating values from // Note: The background page takes care of migrating values from
// chrome.storage.local to chrome.storage.sync when needed. // chrome.storage.local to chrome.storage.sync when needed.
@ -437,4 +457,4 @@ class MLManager {
} }
} }
export { ExternalServices, initCom, MLManager, Preferences }; export { DownloadManager, ExternalServices, initCom, MLManager, Preferences };

View File

@ -13,9 +13,8 @@
* limitations under the License. * limitations under the License.
*/ */
/** @typedef {import("./interfaces").IDownloadManager} IDownloadManager */ import { BaseDownloadManager } from "./base_download_manager.js";
import { createValidAbsoluteUrl } from "pdfjs-lib";
import { createValidAbsoluteUrl, isPdfFile } from "pdfjs-lib";
if (typeof PDFJSDev !== "undefined" && !PDFJSDev.test("CHROME || GENERIC")) { if (typeof PDFJSDev !== "undefined" && !PDFJSDev.test("CHROME || GENERIC")) {
throw new Error( throw new Error(
@ -24,11 +23,17 @@ if (typeof PDFJSDev !== "undefined" && !PDFJSDev.test("CHROME || GENERIC")) {
); );
} }
function download(blobUrl, filename) { class DownloadManager extends BaseDownloadManager {
const a = document.createElement("a"); _triggerDownload(blobUrl, originalUrl, filename, isAttachment = false) {
if (!a.click) { if (!blobUrl && !isAttachment) {
throw new Error('DownloadManager: "a.click()" is not supported.'); // Fallback to downloading non-attachments by their URL.
if (!createValidAbsoluteUrl(originalUrl, "http://example.com")) {
throw new Error(`_triggerDownload - not a valid URL: ${originalUrl}`);
} }
blobUrl = originalUrl + "#pdfjs.action=download";
}
const a = document.createElement("a");
a.href = blobUrl; a.href = blobUrl;
a.target = "_parent"; a.target = "_parent";
// Use a.download if available. This increases the likelihood that // Use a.download if available. This increases the likelihood that
@ -41,84 +46,18 @@ function download(blobUrl, filename) {
(document.body || document.documentElement).append(a); (document.body || document.documentElement).append(a);
a.click(); a.click();
a.remove(); a.remove();
}
/**
* @implements {IDownloadManager}
*/
class DownloadManager {
#openBlobUrls = new WeakMap();
downloadData(data, filename, contentType) {
const blobUrl = URL.createObjectURL(
new Blob([data], { type: contentType })
);
download(blobUrl, filename);
} }
/** _getOpenDataUrl(blobUrl, filename, dest = null) {
* @returns {boolean} Indicating if the data was opened. if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("COMPONENTS")) {
*/ throw new Error("Opening data is not supported in `COMPONENTS` builds.");
openOrDownloadData(data, filename, dest = null) {
const isPdfData = isPdfFile(filename);
const contentType = isPdfData ? "application/pdf" : "";
if (
(typeof PDFJSDev === "undefined" || !PDFJSDev.test("COMPONENTS")) &&
isPdfData
) {
let blobUrl = this.#openBlobUrls.get(data);
if (!blobUrl) {
blobUrl = URL.createObjectURL(new Blob([data], { type: contentType }));
this.#openBlobUrls.set(data, blobUrl);
} }
let viewerUrl;
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
// The current URL is the viewer, let's use it and append the file. // The current URL is the viewer, let's use it and append the file.
viewerUrl = "?file=" + encodeURIComponent(blobUrl + "#" + filename); let url = "?file=" + encodeURIComponent(blobUrl + "#" + filename);
} else if (PDFJSDev.test("CHROME")) {
// In the Chrome extension, the URL is rewritten using the history API
// in viewer.js, so an absolute URL must be generated.
viewerUrl =
// eslint-disable-next-line no-undef
chrome.runtime.getURL("/content/web/viewer.html") +
"?file=" +
encodeURIComponent(blobUrl + "#" + filename);
}
if (dest) { if (dest) {
viewerUrl += `#${escape(dest)}`; url += `#${escape(dest)}`;
} }
return url;
try {
window.open(viewerUrl);
return true;
} catch (ex) {
console.error("openOrDownloadData:", ex);
// Release the `blobUrl`, since opening it failed, and fallback to
// downloading the PDF file.
URL.revokeObjectURL(blobUrl);
this.#openBlobUrls.delete(data);
}
}
this.downloadData(data, filename, contentType);
return false;
}
download(data, url, filename) {
let blobUrl;
if (data) {
blobUrl = URL.createObjectURL(
new Blob([data], { type: "application/pdf" })
);
} else {
if (!createValidAbsoluteUrl(url, "http://example.com")) {
console.error(`download - not a valid URL: ${url}`);
return;
}
blobUrl = url + "#pdfjs.action=download";
}
download(blobUrl, filename);
} }
} }

View File

@ -13,8 +13,6 @@
* limitations under the License. * limitations under the License.
*/ */
/** @typedef {import("./interfaces.js").IL10n} IL10n */
class BaseExternalServices { class BaseExternalServices {
constructor() { constructor() {
if ( if (
@ -36,7 +34,7 @@ class BaseExternalServices {
reportText(data) {} reportText(data) {}
/** /**
* @returns {Promise<IL10n>} * @returns {Promise<L10n>}
*/ */
async createL10n() { async createL10n() {
throw new Error("Not implemented: createL10n"); throw new Error("Not implemented: createL10n");

View File

@ -19,7 +19,10 @@ import {
RenderingCancelledException, RenderingCancelledException,
shadow, shadow,
} from "pdfjs-lib"; } from "pdfjs-lib";
import { getXfaHtmlForPrinting } from "./print_utils.js"; import {
BasePrintServiceFactory,
getXfaHtmlForPrinting,
} from "./print_utils.js";
// Creates a placeholder with div and canvas with right size for the page. // Creates a placeholder with div and canvas with right size for the page.
function composePage( function composePage(
@ -194,10 +197,7 @@ class FirefoxPrintService {
} }
} }
/** class PDFPrintServiceFactory extends BasePrintServiceFactory {
* @implements {IPDFPrintServiceFactory}
*/
class PDFPrintServiceFactory {
static get supportsPrinting() { static get supportsPrinting() {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
return shadow(this, "supportsPrinting", "mozPrintCallback" in canvas); return shadow(this, "supportsPrinting", "mozPrintCallback" in canvas);

View File

@ -13,8 +13,9 @@
* limitations under the License. * limitations under the License.
*/ */
import { isPdfFile, MathClamp, PDFDataRangeTransport } from "pdfjs-lib"; import { MathClamp, PDFDataRangeTransport } from "pdfjs-lib";
import { AppOptions } from "./app_options.js"; import { AppOptions } from "./app_options.js";
import { BaseDownloadManager } from "./base_download_manager.js";
import { BaseExternalServices } from "./external_services.js"; import { BaseExternalServices } from "./external_services.js";
import { BasePreferences } from "./preferences.js"; import { BasePreferences } from "./preferences.js";
import { DEFAULT_SCALE_VALUE } from "./ui_utils.js"; import { DEFAULT_SCALE_VALUE } from "./ui_utils.js";
@ -80,69 +81,25 @@ class FirefoxCom {
} }
} }
class DownloadManager { class DownloadManager extends BaseDownloadManager {
#openBlobUrls = new WeakMap(); _triggerDownload(blobUrl, originalUrl, filename, isAttachment = false) {
downloadData(data, filename, contentType) {
const blobUrl = URL.createObjectURL(
new Blob([data], { type: contentType })
);
FirefoxCom.request("download", { FirefoxCom.request("download", {
blobUrl, blobUrl,
originalUrl: blobUrl, originalUrl,
filename, filename,
isAttachment: true, isAttachment,
}); });
} }
/** _getOpenDataUrl(blobUrl, filename, dest = null) {
* @returns {boolean} Indicating if the data was opened.
*/
openOrDownloadData(data, filename, dest = null) {
const isPdfData = isPdfFile(filename);
const contentType = isPdfData ? "application/pdf" : "";
if (isPdfData) {
let blobUrl = this.#openBlobUrls.get(data);
if (!blobUrl) {
blobUrl = URL.createObjectURL(new Blob([data], { type: contentType }));
this.#openBlobUrls.set(data, blobUrl);
}
// Let Firefox's content handler catch the URL and display the PDF. // Let Firefox's content handler catch the URL and display the PDF.
// NOTE: This cannot use a query string for the filename, see // NOTE: This cannot use a query string for the filename, see
// https://bugzilla.mozilla.org/show_bug.cgi?id=1632644#c5 // https://bugzilla.mozilla.org/show_bug.cgi?id=1632644#c5
let viewerUrl = blobUrl + "#filename=" + encodeURIComponent(filename); let url = blobUrl + "#filename=" + encodeURIComponent(filename);
if (dest) { if (dest) {
viewerUrl += `&filedest=${escape(dest)}`; url += `&filedest=${escape(dest)}`;
} }
return url;
try {
window.open(viewerUrl);
return true;
} catch (ex) {
console.error("openOrDownloadData:", ex);
// Release the `blobUrl`, since opening it failed, and fallback to
// downloading the PDF file.
URL.revokeObjectURL(blobUrl);
this.#openBlobUrls.delete(data);
}
}
this.downloadData(data, filename, contentType);
return false;
}
download(data, url, filename) {
const blobUrl = data
? URL.createObjectURL(new Blob([data], { type: "application/pdf" }))
: null;
FirefoxCom.request("download", {
blobUrl,
originalUrl: url,
filename,
});
} }
} }

View File

@ -13,8 +13,6 @@
* limitations under the License. * limitations under the License.
*/ */
/** @typedef {import("./interfaces").IL10n} IL10n */
import { FeatureTest, fetchData } from "pdfjs-lib"; import { FeatureTest, fetchData } from "pdfjs-lib";
import { FluentBundle, FluentResource } from "fluent-bundle"; import { FluentBundle, FluentResource } from "fluent-bundle";
import { DOMLocalization } from "fluent-dom"; import { DOMLocalization } from "fluent-dom";
@ -49,9 +47,6 @@ function createBundle(lang, text) {
return bundle; return bundle;
} }
/**
* @implements {IL10n}
*/
class GenericL10n extends L10n { class GenericL10n extends L10n {
constructor(lang) { constructor(lang) {
super({ lang }); super({ lang });

View File

@ -1,235 +0,0 @@
/* Copyright 2018 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable getter-return */
/** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */
// eslint-disable-next-line max-len
/** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
/** @typedef {import("./ui_utils").RenderingStates} RenderingStates */
/**
* @interface
*/
class IPDFLinkService {
/**
* @type {number}
*/
get pagesCount() {}
/**
* @type {number}
*/
get page() {}
/**
* @param {number} value
*/
set page(value) {}
/**
* @type {number}
*/
get rotation() {}
/**
* @param {number} value
*/
set rotation(value) {}
/**
* @type {boolean}
*/
get isInPresentationMode() {}
/**
* @type {boolean}
*/
get externalLinkEnabled() {}
/**
* @param {boolean} value
*/
set externalLinkEnabled(value) {}
/**
* @param {string|Array} dest - The named, or explicit, PDF destination.
*/
async goToDestination(dest) {}
/**
* @param {number|string} val - The page number, or page label.
*/
goToPage(val) {}
/**
* Scrolls to a specific location in the PDF document.
* @param {number} pageNumber - The page number to scroll to.
* @param {number} x - The x-coordinate to scroll to in page coordinates.
* @param {number} y - The y-coordinate to scroll to in page coordinates.
*/
goToXY(pageNumber, x, y) {}
/**
* @param {HTMLAnchorElement} link
* @param {string} url
* @param {boolean} [newWindow]
*/
addLinkAttributes(link, url, newWindow = false) {}
/**
* @param dest - The PDF destination object.
* @returns {string} The hyperlink to the PDF object.
*/
getDestinationHash(dest) {}
/**
* @param hash - The PDF parameters/hash.
* @returns {string} The hyperlink to the PDF object.
*/
getAnchorUrl(hash) {}
/**
* @param {string} hash
*/
setHash(hash) {}
/**
* @param {string} action
*/
executeNamedAction(action) {}
/**
* @param {Object} action
*/
executeSetOCGState(action) {}
}
/**
* @interface
*/
class IRenderableView {
constructor() {
/** @type {function | null} */
this.resume = null;
}
/**
* @type {string} - Unique ID for rendering queue.
*/
get renderingId() {}
/**
* @type {RenderingStates}
*/
get renderingState() {}
/**
* @returns {Promise} Resolved on draw completion.
*/
async draw() {}
}
/**
* @interface
*/
class IDownloadManager {
/**
* @param {Uint8Array} data
* @param {string} filename
* @param {string} [contentType]
*/
downloadData(data, filename, contentType) {}
/**
* @param {Uint8Array} data
* @param {string} filename
* @param {string | null} [dest]
* @returns {boolean} Indicating if the data was opened.
*/
openOrDownloadData(data, filename, dest = null) {}
/**
* @param {Uint8Array} data
* @param {string} url
* @param {string} filename
*/
download(data, url, filename) {}
}
/**
* @interface
*/
class IL10n {
/**
* @returns {string} - The current locale.
*/
getLanguage() {}
/**
* @returns {string} - 'rtl' or 'ltr'.
*/
getDirection() {}
/**
* Translates text identified by the key and adds/formats data using the args
* property bag. If the key was not found, translation falls back to the
* fallback text.
* @param {Array | string} ids
* @param {Object | null} [args]
* @param {string} [fallback]
* @returns {Promise<string>}
*/
async get(ids, args = null, fallback) {}
/**
* Translates HTML element.
* @param {HTMLElement} element
* @returns {Promise<void>}
*/
async translate(element) {}
/**
* Pause the localization.
*/
pause() {}
/**
* Resume the localization.
*/
resume() {}
}
/**
* @interface
*/
class IPDFPrintServiceFactory {
static initGlobals() {}
static get supportsPrinting() {
return false;
}
static createPrintService() {
throw new Error("Not implemented: createPrintService");
}
}
export {
IDownloadManager,
IL10n,
IPDFLinkService,
IPDFPrintServiceFactory,
IRenderableView,
};

View File

@ -13,12 +13,9 @@
* limitations under the License. * limitations under the License.
*/ */
/** @typedef {import("./interfaces").IL10n} IL10n */
/** /**
* NOTE: The L10n-implementations should use lowercase language-codes * NOTE: The L10n-implementations should use lowercase language-codes
* internally. * internally.
* @implements {IL10n}
*/ */
class L10n { class L10n {
#dir; #dir;

View File

@ -14,7 +14,6 @@
*/ */
/** @typedef {import("./event_utils.js").EventBus} EventBus */ /** @typedef {import("./event_utils.js").EventBus} EventBus */
/** @typedef {import("./interfaces.js").IL10n} IL10n */
/** @typedef {import("./overlay_manager.js").OverlayManager} OverlayManager */ /** @typedef {import("./overlay_manager.js").OverlayManager} OverlayManager */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/api.js").PDFDocumentProxy} PDFDocumentProxy */ /** @typedef {import("../src/display/api.js").PDFDocumentProxy} PDFDocumentProxy */
@ -58,7 +57,7 @@ class PDFDocumentProperties {
* @param {PDFDocumentPropertiesOptions} options * @param {PDFDocumentPropertiesOptions} options
* @param {OverlayManager} overlayManager - Manager for the viewer overlays. * @param {OverlayManager} overlayManager - Manager for the viewer overlays.
* @param {EventBus} eventBus - The application event bus. * @param {EventBus} eventBus - The application event bus.
* @param {IL10n} l10n - Localization service. * @param {L10n} l10n - Localization service.
* @param {function} fileNameLookup - The function that is used to lookup * @param {function} fileNameLookup - The function that is used to lookup
* the document fileName. * the document fileName.
*/ */

View File

@ -15,7 +15,6 @@
/** @typedef {import("../src/display/api").PDFDocumentProxy} PDFDocumentProxy */ /** @typedef {import("../src/display/api").PDFDocumentProxy} PDFDocumentProxy */
/** @typedef {import("./event_utils").EventBus} EventBus */ /** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
import { binarySearchFirstItem, scrollIntoView } from "./ui_utils.js"; import { binarySearchFirstItem, scrollIntoView } from "./ui_utils.js";
import { getCharacterType, getNormalizeWithNFKC } from "./pdf_find_utils.js"; import { getCharacterType, getNormalizeWithNFKC } from "./pdf_find_utils.js";
@ -405,7 +404,7 @@ function getOriginalIndex(diffs, pos, len) {
/** /**
* @typedef {Object} PDFFindControllerOptions * @typedef {Object} PDFFindControllerOptions
* @property {IPDFLinkService} linkService - The navigation/linking service. * @property {PDFLinkService} linkService - The navigation/linking service.
* @property {EventBus} eventBus - The application event bus. * @property {EventBus} eventBus - The application event bus.
* @property {boolean} [updateMatchesCountOnProgress] - True if the matches * @property {boolean} [updateMatchesCountOnProgress] - True if the matches
* count must be updated on progress or only when the last page is reached. * count must be updated on progress or only when the last page is reached.

View File

@ -14,7 +14,6 @@
*/ */
/** @typedef {import("./event_utils").EventBus} EventBus */ /** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
import { isValidRotation, parseQueryString } from "./ui_utils.js"; import { isValidRotation, parseQueryString } from "./ui_utils.js";
import { updateUrlHash } from "pdfjs-lib"; import { updateUrlHash } from "pdfjs-lib";
@ -29,7 +28,7 @@ const UPDATE_VIEWAREA_TIMEOUT = 1000; // milliseconds
/** /**
* @typedef {Object} PDFHistoryOptions * @typedef {Object} PDFHistoryOptions
* @property {IPDFLinkService} linkService - The navigation/linking service. * @property {PDFLinkService} linkService - The navigation/linking service.
* @property {EventBus} eventBus - The application event bus. * @property {EventBus} eventBus - The application event bus.
*/ */

View File

@ -14,7 +14,6 @@
*/ */
/** @typedef {import("./event_utils").EventBus} EventBus */ /** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
import { isValidExplicitDest } from "pdfjs-lib"; import { isValidExplicitDest } from "pdfjs-lib";
import { parseQueryString } from "./ui_utils.js"; import { parseQueryString } from "./ui_utils.js";
@ -45,7 +44,6 @@ const LinkTarget = {
/** /**
* Performs navigation functions inside PDF, such as opening specified page, * Performs navigation functions inside PDF, such as opening specified page,
* or destination. * or destination.
* @implements {IPDFLinkService}
*/ */
class PDFLinkService { class PDFLinkService {
externalLinkEnabled = true; externalLinkEnabled = true;
@ -425,7 +423,7 @@ class PDFLinkService {
} }
// Support opening of PDF attachments in the Firefox PDF Viewer, // Support opening of PDF attachments in the Firefox PDF Viewer,
// which uses a couple of non-standard hash parameters; refer to // which uses a couple of non-standard hash parameters; refer to
// `DownloadManager.openOrDownloadData` in the firefoxcom.js file. // `DownloadManager._getOpenDataUrl` in the firefoxcom.js file.
if (!params.has("filename") || !params.has("filedest")) { if (!params.has("filename") || !params.has("filedest")) {
return; return;
} }
@ -517,9 +515,6 @@ class PDFLinkService {
} }
} }
/**
* @implements {IPDFLinkService}
*/
class SimpleLinkService extends PDFLinkService { class SimpleLinkService extends PDFLinkService {
setDocument(pdfDocument, baseUrl = null) {} setDocument(pdfDocument, baseUrl = null) {}
} }

View File

@ -16,7 +16,6 @@
/** @typedef {import("./event_utils.js").EventBus} EventBus */ /** @typedef {import("./event_utils.js").EventBus} EventBus */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./download_manager.js").DownloadManager} DownloadManager */ /** @typedef {import("./download_manager.js").DownloadManager} DownloadManager */
/** @typedef {import("./interfaces.js").IPDFLinkService} IPDFLinkService */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/api.js").PDFDocumentProxy} PDFDocumentProxy */ /** @typedef {import("../src/display/api.js").PDFDocumentProxy} PDFDocumentProxy */
@ -27,7 +26,7 @@ import { SidebarView } from "./ui_utils.js";
* @typedef {Object} PDFOutlineViewerOptions * @typedef {Object} PDFOutlineViewerOptions
* @property {HTMLDivElement} container - The viewer element. * @property {HTMLDivElement} container - The viewer element.
* @property {EventBus} eventBus - The application event bus. * @property {EventBus} eventBus - The application event bus.
* @property {IPDFLinkService} linkService - The navigation/linking service. * @property {PDFLinkService} linkService - The navigation/linking service.
* @property {DownloadManager} downloadManager - The download manager. * @property {DownloadManager} downloadManager - The download manager.
*/ */

View File

@ -15,13 +15,8 @@
import { BasePDFPageView } from "./base_pdf_page_view.js"; import { BasePDFPageView } from "./base_pdf_page_view.js";
import { OutputScale } from "pdfjs-lib"; import { OutputScale } from "pdfjs-lib";
import { RenderingStates } from "./ui_utils.js"; import { RenderingStates } from "./renderable_view.js";
/** @typedef {import("./interfaces").IRenderableView} IRenderableView */
/**
* @implements {IRenderableView}
*/
class PDFPageDetailView extends BasePDFPageView { class PDFPageDetailView extends BasePDFPageView {
#detailArea = null; #detailArea = null;
@ -54,9 +49,9 @@ class PDFPageDetailView extends BasePDFPageView {
return super.renderingState; return super.renderingState;
} }
set renderingState(value) { set renderingState(state) {
this.renderingCancelled = false; this.renderingCancelled = false;
super.renderingState = value; super.renderingState = state;
} }
reset({ keepCanvas = false } = {}) { reset({ keepCanvas = false } = {}) {

View File

@ -18,8 +18,6 @@
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/optional_content_config").OptionalContentConfig} OptionalContentConfig */ /** @typedef {import("../src/display/optional_content_config").OptionalContentConfig} OptionalContentConfig */
/** @typedef {import("./event_utils").EventBus} EventBus */ /** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IL10n} IL10n */
/** @typedef {import("./interfaces").IRenderableView} IRenderableView */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */ /** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */
/** @typedef {import("./comment_manager.js").CommentManager} CommentManager */ /** @typedef {import("./comment_manager.js").CommentManager} CommentManager */
@ -37,7 +35,6 @@ import {
calcRound, calcRound,
DEFAULT_SCALE, DEFAULT_SCALE,
floorToDivide, floorToDivide,
RenderingStates,
TextLayerMode, TextLayerMode,
} from "./ui_utils.js"; } from "./ui_utils.js";
import { AnnotationEditorLayerBuilder } from "./annotation_editor_layer_builder.js"; import { AnnotationEditorLayerBuilder } from "./annotation_editor_layer_builder.js";
@ -48,6 +45,7 @@ import { BasePDFPageView } from "./base_pdf_page_view.js";
import { DrawLayerBuilder } from "./draw_layer_builder.js"; import { DrawLayerBuilder } from "./draw_layer_builder.js";
import { GenericL10n } from "web-null_l10n"; import { GenericL10n } from "web-null_l10n";
import { PDFPageDetailView } from "./pdf_page_detail_view.js"; import { PDFPageDetailView } from "./pdf_page_detail_view.js";
import { RenderingStates } from "./renderable_view.js";
import { SimpleLinkService } from "./pdf_link_service.js"; import { SimpleLinkService } from "./pdf_link_service.js";
import { StructTreeLayerBuilder } from "./struct_tree_layer_builder.js"; import { StructTreeLayerBuilder } from "./struct_tree_layer_builder.js";
import { TextAccessibilityManager } from "./text_accessibility.js"; import { TextAccessibilityManager } from "./text_accessibility.js";
@ -98,7 +96,7 @@ import { XfaLayerBuilder } from "./xfa_layer_builder.js";
* @property {Object} [pageColors] - Overwrites background and foreground colors * @property {Object} [pageColors] - Overwrites background and foreground colors
* with user defined ones in order to improve readability in high contrast * with user defined ones in order to improve readability in high contrast
* mode. * mode.
* @property {IL10n} [l10n] - Localization service. * @property {L10n} [l10n] - Localization service.
* @property {Object} [layerProperties] - The object that is used to lookup * @property {Object} [layerProperties] - The object that is used to lookup
* the necessary layer-properties. * the necessary layer-properties.
* @property {boolean} [enableAutoLinking] - Enable creation of hyperlinks from * @property {boolean} [enableAutoLinking] - Enable creation of hyperlinks from
@ -130,9 +128,6 @@ const LAYERS_ORDER = new Map([
["xfaLayer", 3], ["xfaLayer", 3],
]); ]);
/**
* @implements {IRenderableView}
*/
class PDFPageView extends BasePDFPageView { class PDFPageView extends BasePDFPageView {
#annotationMode = AnnotationMode.ENABLE_FORMS; #annotationMode = AnnotationMode.ENABLE_FORMS;

View File

@ -13,16 +13,16 @@
* limitations under the License. * limitations under the License.
*/ */
// eslint-disable-next-line max-len
/** @typedef {import("./interfaces.js").IPDFPrintServiceFactory} IPDFPrintServiceFactory */
import { import {
AnnotationMode, AnnotationMode,
PixelsPerInch, PixelsPerInch,
RenderingCancelledException, RenderingCancelledException,
shadow, shadow,
} from "pdfjs-lib"; } from "pdfjs-lib";
import { getXfaHtmlForPrinting } from "./print_utils.js"; import {
BasePrintServiceFactory,
getXfaHtmlForPrinting,
} from "./print_utils.js";
let activeService = null; let activeService = null;
let dialog = null; let dialog = null;
@ -371,10 +371,7 @@ function ensureOverlay() {
return overlayPromise; return overlayPromise;
} }
/** class PDFPrintServiceFactory extends BasePrintServiceFactory {
* @implements {IPDFPrintServiceFactory}
*/
class PDFPrintServiceFactory {
static initGlobals(app) { static initGlobals(app) {
viewerApp = app; viewerApp = app;
} }

View File

@ -13,13 +13,12 @@
* limitations under the License. * limitations under the License.
*/ */
/** @typedef {import("./interfaces").IRenderableView} IRenderableView */
/** @typedef {import("./pdf_viewer").PDFViewer} PDFViewer */ /** @typedef {import("./pdf_viewer").PDFViewer} PDFViewer */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./pdf_thumbnail_viewer").PDFThumbnailViewer} PDFThumbnailViewer */ /** @typedef {import("./pdf_thumbnail_viewer").PDFThumbnailViewer} PDFThumbnailViewer */
import { RenderingCancelledException } from "pdfjs-lib"; import { RenderingCancelledException } from "pdfjs-lib";
import { RenderingStates } from "./ui_utils.js"; import { RenderingStates } from "./renderable_view.js";
const CLEANUP_TIMEOUT = 30000; const CLEANUP_TIMEOUT = 30000;
@ -59,7 +58,7 @@ class PDFRenderingQueue {
} }
/** /**
* @param {IRenderableView} view * @param {RenderableView} view
* @returns {boolean} * @returns {boolean}
*/ */
isHighestPriority(view) { isHighestPriority(view) {
@ -183,7 +182,7 @@ class PDFRenderingQueue {
} }
/** /**
* @param {IRenderableView} view * @param {RenderableView} view
* @returns {boolean} * @returns {boolean}
*/ */
isViewFinished(view) { isViewFinished(view) {
@ -195,7 +194,7 @@ class PDFRenderingQueue {
* based on the views state. If the view is already rendered it will return * based on the views state. If the view is already rendered it will return
* `false`. * `false`.
* *
* @param {IRenderableView} view * @param {RenderableView} view
*/ */
renderView(view) { renderView(view) {
switch (view.renderingState) { switch (view.renderingState) {

View File

@ -15,7 +15,8 @@
/** @typedef {import("./event_utils").EventBus} EventBus */ /** @typedef {import("./event_utils").EventBus} EventBus */
import { apiPageLayoutToViewerModes, RenderingStates } from "./ui_utils.js"; import { apiPageLayoutToViewerModes } from "./ui_utils.js";
import { RenderingStates } from "./renderable_view.js";
import { shadow } from "pdfjs-lib"; import { shadow } from "pdfjs-lib";
/** /**

View File

@ -18,8 +18,6 @@
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */ /** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
/** @typedef {import("./event_utils").EventBus} EventBus */ /** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
/** @typedef {import("./interfaces").IRenderableView} IRenderableView */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */ /** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */
@ -28,8 +26,8 @@ import {
OutputScale, OutputScale,
RenderingCancelledException, RenderingCancelledException,
} from "pdfjs-lib"; } from "pdfjs-lib";
import { RenderableView, RenderingStates } from "./renderable_view.js";
import { AppOptions } from "./app_options.js"; import { AppOptions } from "./app_options.js";
import { RenderingStates } from "./ui_utils.js";
const DRAW_UPSCALE_FACTOR = 2; // See comment in `PDFThumbnailView.draw` below. const DRAW_UPSCALE_FACTOR = 2; // See comment in `PDFThumbnailView.draw` below.
const MAX_NUM_SCALING_STEPS = 3; const MAX_NUM_SCALING_STEPS = 3;
@ -44,7 +42,7 @@ const THUMBNAIL_WIDTH = 126; // px
* @property {Promise<OptionalContentConfig>} [optionalContentConfigPromise] - * @property {Promise<OptionalContentConfig>} [optionalContentConfigPromise] -
* A promise that is resolved with an {@link OptionalContentConfig} instance. * A promise that is resolved with an {@link OptionalContentConfig} instance.
* The default value is `null`. * The default value is `null`.
* @property {IPDFLinkService} linkService - The navigation/linking service. * @property {PDFLinkService} linkService - The navigation/linking service.
* @property {PDFRenderingQueue} renderingQueue - The rendering queue object. * @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
* @property {number} [maxCanvasPixels] - The maximum supported canvas size in * @property {number} [maxCanvasPixels] - The maximum supported canvas size in
* total pixels, i.e. width * height. Use `-1` for no limit, or `0` for * total pixels, i.e. width * height. Use `-1` for no limit, or `0` for
@ -79,10 +77,9 @@ class TempImageFactory {
} }
} }
/** class PDFThumbnailView extends RenderableView {
* @implements {IRenderableView} #renderingState = RenderingStates.INITIAL;
*/
class PDFThumbnailView {
/** /**
* @param {PDFThumbnailViewOptions} options * @param {PDFThumbnailViewOptions} options
*/ */
@ -99,6 +96,7 @@ class PDFThumbnailView {
pageColors, pageColors,
enableSplitMerge = false, enableSplitMerge = false,
}) { }) {
super();
this.id = id; this.id = id;
this.renderingId = `thumbnail${id}`; this.renderingId = `thumbnail${id}`;
this.pageLabel = null; this.pageLabel = null;
@ -116,9 +114,6 @@ class PDFThumbnailView {
this.linkService = linkService; this.linkService = linkService;
this.renderingQueue = renderingQueue; this.renderingQueue = renderingQueue;
this.renderTask = null;
this.renderingState = RenderingStates.INITIAL;
this.resume = null;
this.placeholder = null; this.placeholder = null;
const imageContainer = (this.div = document.createElement("div")); const imageContainer = (this.div = document.createElement("div"));
@ -163,6 +158,14 @@ class PDFThumbnailView {
this.image.style.height = `${canvasHeight}px`; this.image.style.height = `${canvasHeight}px`;
} }
get renderingState() {
return this.#renderingState;
}
set renderingState(state) {
this.#renderingState = state;
}
setPdfPage(pdfPage) { setPdfPage(pdfPage) {
this.pdfPage = pdfPage; this.pdfPage = pdfPage;
this.pdfPageRotate = pdfPage.rotate; this.pdfPageRotate = pdfPage.rotate;

View File

@ -16,7 +16,6 @@
/** @typedef {import("../src/display/api").PDFDocumentProxy} PDFDocumentProxy */ /** @typedef {import("../src/display/api").PDFDocumentProxy} PDFDocumentProxy */
/** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */ /** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */
/** @typedef {import("./event_utils").EventBus} EventBus */ /** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */ /** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */
@ -24,12 +23,12 @@ import {
binarySearchFirstItem, binarySearchFirstItem,
getVisibleElements, getVisibleElements,
isValidRotation, isValidRotation,
RenderingStates,
watchScroll, watchScroll,
} from "./ui_utils.js"; } from "./ui_utils.js";
import { MathClamp, noContextMenu, PagesMapper, stopEvent } from "pdfjs-lib"; import { MathClamp, noContextMenu, PagesMapper, stopEvent } from "pdfjs-lib";
import { Menu } from "./menu.js"; import { Menu } from "./menu.js";
import { PDFThumbnailView } from "./pdf_thumbnail_view.js"; import { PDFThumbnailView } from "./pdf_thumbnail_view.js";
import { RenderingStates } from "./renderable_view.js";
const SCROLL_OPTIONS = { const SCROLL_OPTIONS = {
behavior: "instant", behavior: "instant",
@ -51,7 +50,7 @@ const SPACE_FOR_DRAG_MARKER_WHEN_NO_NEXT_ELEMENT = 15;
* @property {HTMLDivElement} container - The container for the thumbnail * @property {HTMLDivElement} container - The container for the thumbnail
* elements. * elements.
* @property {EventBus} eventBus - The application event bus. * @property {EventBus} eventBus - The application event bus.
* @property {IPDFLinkService} linkService - The navigation/linking service. * @property {PDFLinkService} linkService - The navigation/linking service.
* @property {PDFRenderingQueue} renderingQueue - The rendering queue object. * @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
* @property {number} [maxCanvasPixels] - The maximum supported canvas size in * @property {number} [maxCanvasPixels] - The maximum supported canvas size in
* total pixels, i.e. width * height. Use `-1` for no limit, or `0` for * total pixels, i.e. width * height. Use `-1` for no limit, or `0` for

View File

@ -22,7 +22,6 @@ import {
import { import {
parseQueryString, parseQueryString,
ProgressBar, ProgressBar,
RenderingStates,
ScrollMode, ScrollMode,
SpreadMode, SpreadMode,
} from "./ui_utils.js"; } from "./ui_utils.js";
@ -35,6 +34,7 @@ import { PDFPageView } from "./pdf_page_view.js";
import { PDFScriptingManager } from "./pdf_scripting_manager.component.js"; import { PDFScriptingManager } from "./pdf_scripting_manager.component.js";
import { PDFSinglePageViewer } from "./pdf_single_page_viewer.js"; import { PDFSinglePageViewer } from "./pdf_single_page_viewer.js";
import { PDFViewer } from "./pdf_viewer.js"; import { PDFViewer } from "./pdf_viewer.js";
import { RenderingStates } from "./renderable_view.js";
import { StructTreeLayerBuilder } from "./struct_tree_layer_builder.js"; import { StructTreeLayerBuilder } from "./struct_tree_layer_builder.js";
import { TextLayerBuilder } from "./text_layer_builder.js"; import { TextLayerBuilder } from "./text_layer_builder.js";
import { XfaLayerBuilder } from "./xfa_layer_builder.js"; import { XfaLayerBuilder } from "./xfa_layer_builder.js";

View File

@ -20,9 +20,6 @@
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/optional_content_config").OptionalContentConfig} OptionalContentConfig */ /** @typedef {import("../src/display/optional_content_config").OptionalContentConfig} OptionalContentConfig */
/** @typedef {import("./event_utils").EventBus} EventBus */ /** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IDownloadManager} IDownloadManager */
/** @typedef {import("./interfaces").IL10n} IL10n */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("./pdf_find_controller").PDFFindController} PDFFindController */ /** @typedef {import("./pdf_find_controller").PDFFindController} PDFFindController */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
@ -55,7 +52,6 @@ import {
MIN_SCALE, MIN_SCALE,
PresentationModeState, PresentationModeState,
removeNullCharacters, removeNullCharacters,
RenderingStates,
SCROLLBAR_PADDING, SCROLLBAR_PADDING,
scrollIntoView, scrollIntoView,
ScrollMode, ScrollMode,
@ -68,6 +64,7 @@ import {
import { GenericL10n } from "web-null_l10n"; import { GenericL10n } from "web-null_l10n";
import { PDFPageView } from "./pdf_page_view.js"; import { PDFPageView } from "./pdf_page_view.js";
import { PDFRenderingQueue } from "./pdf_rendering_queue.js"; import { PDFRenderingQueue } from "./pdf_rendering_queue.js";
import { RenderingStates } from "./renderable_view.js";
import { SimpleLinkService } from "./pdf_link_service.js"; import { SimpleLinkService } from "./pdf_link_service.js";
const DEFAULT_CACHE_SIZE = 10; const DEFAULT_CACHE_SIZE = 10;
@ -90,8 +87,8 @@ function isValidAnnotationEditorMode(mode) {
* @property {HTMLDivElement} container - The container for the viewer element. * @property {HTMLDivElement} container - The container for the viewer element.
* @property {HTMLDivElement} [viewer] - The viewer element. * @property {HTMLDivElement} [viewer] - The viewer element.
* @property {EventBus} eventBus - The application event bus. * @property {EventBus} eventBus - The application event bus.
* @property {IPDFLinkService} [linkService] - The navigation/linking service. * @property {PDFLinkService} [linkService] - The navigation/linking service.
* @property {IDownloadManager} [downloadManager] - The download manager * @property {BaseDownloadManager} [downloadManager] - The download manager
* component. * component.
* @property {PDFFindController} [findController] - The find controller * @property {PDFFindController} [findController] - The find controller
* component. * component.
@ -135,7 +132,7 @@ function isValidAnnotationEditorMode(mode) {
* rendering will keep track of which areas of the page each PDF operation * rendering will keep track of which areas of the page each PDF operation
* affects. Then, when rendering a partial page (if `enableDetailCanvas` is * affects. Then, when rendering a partial page (if `enableDetailCanvas` is
* enabled), it will only run through the operations that affect that portion. * enabled), it will only run through the operations that affect that portion.
* @property {IL10n} [l10n] - Localization service. * @property {L10n} [l10n] - Localization service.
* @property {boolean} [enablePermissions] - Enables PDF document permissions, * @property {boolean} [enablePermissions] - Enables PDF document permissions,
* when they exist. The default value is `false`. * when they exist. The default value is `false`.
* @property {Object} [pageColors] - Overwrites background and foreground colors * @property {Object} [pageColors] - Overwrites background and foreground colors

View File

@ -17,6 +17,24 @@ import { getXfaPageViewport, PixelsPerInch } from "pdfjs-lib";
import { SimpleLinkService } from "./pdf_link_service.js"; import { SimpleLinkService } from "./pdf_link_service.js";
import { XfaLayerBuilder } from "./xfa_layer_builder.js"; import { XfaLayerBuilder } from "./xfa_layer_builder.js";
class BasePrintServiceFactory {
constructor() {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
throw new Error("Cannot initialize BasePrintServiceFactory.");
}
}
static initGlobals(app) {}
static get supportsPrinting() {
throw new Error("Not implemented: supportsPrinting");
}
static createPrintService(params) {
throw new Error("Not implemented: createPrintService");
}
}
function getXfaHtmlForPrinting(printContainer, pdfDocument) { function getXfaHtmlForPrinting(printContainer, pdfDocument) {
const xfaHtml = pdfDocument.allXfaHtml; const xfaHtml = pdfDocument.allXfaHtml;
const linkService = new SimpleLinkService(); const linkService = new SimpleLinkService();
@ -40,4 +58,4 @@ function getXfaHtmlForPrinting(printContainer, pdfDocument) {
} }
} }
export { getXfaHtmlForPrinting }; export { BasePrintServiceFactory, getXfaHtmlForPrinting };

71
web/renderable_view.js Normal file
View File

@ -0,0 +1,71 @@
/* Copyright 2018 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const RenderingStates = {
INITIAL: 0,
RUNNING: 1,
PAUSED: 2,
FINISHED: 3,
};
class RenderableView {
/**
* Unique ID for rendering queue.
* @type {string}
*/
renderingId = "";
/**
* @type {RenderTask | null}
*/
renderTask = null;
/**
* @type {function | null}
*/
resume = null;
constructor() {
if (
(typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) &&
this.constructor === RenderableView
) {
throw new Error("Cannot initialize RenderableView.");
}
}
/**
* @type {RenderingStates}
*/
get renderingState() {
throw new Error("Abstract getter `renderingState` accessed");
}
/**
* @param {RenderingStates}
*/
set renderingState(state) {
throw new Error("Abstract setter `renderingState` accessed");
}
/**
* @returns {Promise} Resolved on draw completion.
*/
async draw() {
throw new Error("Not implemented: draw");
}
}
export { RenderableView, RenderingStates };

View File

@ -25,13 +25,6 @@ const MAX_AUTO_SCALE = 1.25;
const SCROLLBAR_PADDING = 40; const SCROLLBAR_PADDING = 40;
const VERTICAL_PADDING = 5; const VERTICAL_PADDING = 5;
const RenderingStates = {
INITIAL: 0,
RUNNING: 1,
PAUSED: 2,
FINISHED: 3,
};
const PresentationModeState = { const PresentationModeState = {
UNKNOWN: 0, UNKNOWN: 0,
NORMAL: 1, NORMAL: 1,
@ -914,7 +907,6 @@ export {
PresentationModeState, PresentationModeState,
ProgressBar, ProgressBar,
removeNullCharacters, removeNullCharacters,
RenderingStates,
SCROLLBAR_PADDING, SCROLLBAR_PADDING,
scrollIntoView, scrollIntoView,
ScrollMode, ScrollMode,

View File

@ -13,10 +13,11 @@
* limitations under the License. * limitations under the License.
*/ */
import { RenderingStates, ScrollMode, SpreadMode } from "./ui_utils.js"; import { ScrollMode, SpreadMode } from "./ui_utils.js";
import { AppOptions } from "./app_options.js"; import { AppOptions } from "./app_options.js";
import { LinkTarget } from "./pdf_link_service.js"; import { LinkTarget } from "./pdf_link_service.js";
import { PDFViewerApplication } from "./app.js"; import { PDFViewerApplication } from "./app.js";
import { RenderingStates } from "./renderable_view.js";
const AppConstants = const AppConstants =
typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC") typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")

View File

@ -13,10 +13,11 @@
* limitations under the License. * limitations under the License.
*/ */
import { RenderingStates, ScrollMode, SpreadMode } from "./ui_utils.js"; import { ScrollMode, SpreadMode } from "./ui_utils.js";
import { AppOptions } from "./app_options.js"; import { AppOptions } from "./app_options.js";
import { LinkTarget } from "./pdf_link_service.js"; import { LinkTarget } from "./pdf_link_service.js";
import { PDFViewerApplication } from "./app.js"; import { PDFViewerApplication } from "./app.js";
import { RenderingStates } from "./renderable_view.js";
const AppConstants = const AppConstants =
typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC") typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")

View File

@ -14,7 +14,6 @@
*/ */
/** @typedef {import("./event_utils.js").EventBus} EventBus */ /** @typedef {import("./event_utils.js").EventBus} EventBus */
/** @typedef {import("./interfaces.js").IL10n} IL10n */
import { import {
docStyle, docStyle,
@ -34,7 +33,7 @@ const UI_NOTIFICATION_CLASS = "pdfSidebarNotification";
* @typedef {Object} PDFSidebarOptions * @typedef {Object} PDFSidebarOptions
* @property {PDFSidebarElements} elements - The DOM elements. * @property {PDFSidebarElements} elements - The DOM elements.
* @property {EventBus} eventBus - The application event bus. * @property {EventBus} eventBus - The application event bus.
* @property {IL10n} l10n - The localization service. * @property {L10n} l10n - The localization service.
*/ */
/** /**

View File

@ -18,7 +18,6 @@
/** @typedef {import("../src/display/annotation_storage").AnnotationStorage} AnnotationStorage */ /** @typedef {import("../src/display/annotation_storage").AnnotationStorage} AnnotationStorage */
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
/** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */ /** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
import { XfaLayer } from "pdfjs-lib"; import { XfaLayer } from "pdfjs-lib";
@ -26,7 +25,7 @@ import { XfaLayer } from "pdfjs-lib";
* @typedef {Object} XfaLayerBuilderOptions * @typedef {Object} XfaLayerBuilderOptions
* @property {PDFPageProxy} pdfPage * @property {PDFPageProxy} pdfPage
* @property {AnnotationStorage} [annotationStorage] * @property {AnnotationStorage} [annotationStorage]
* @property {IPDFLinkService} linkService * @property {PDFLinkService} linkService
* @property {Object} [xfaHtml] * @property {Object} [xfaHtml]
*/ */