/* Copyright 2012 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. */ /** @typedef {import("./interfaces.js").IL10n} IL10n */ // eslint-disable-next-line max-len /** @typedef {import("../src/display/api.js").PDFDocumentProxy} PDFDocumentProxy */ // eslint-disable-next-line max-len /** @typedef {import("../src/display/api.js").PDFDocumentLoadingTask} PDFDocumentLoadingTask */ import { animationStarted, apiPageLayoutToViewerModes, apiPageModeToSidebarView, AutoPrintRegExp, CursorTool, DEFAULT_SCALE_VALUE, getActiveOrFocusedElement, isValidRotation, isValidScrollMode, isValidSpreadMode, normalizeWheelEventDirection, parseQueryString, ProgressBar, RenderingStates, ScrollMode, SidebarView, SpreadMode, TextLayerMode, } from "./ui_utils.js"; import { AnnotationEditorType, build, FeatureTest, getDocument, getFilenameFromUrl, getPdfFilenameFromUrl, GlobalWorkerOptions, InvalidPDFException, isDataScheme, isPdfFile, MissingPDFException, PDFWorker, shadow, UnexpectedResponseException, version, } from "./pdfjs"; import {AppOptions, OptionKind} from "./app_options.js"; import {EventBus, FirefoxEventBus} from "./event_utils.js"; import {ExternalServices, initCom, MLManager} from "./genericcom.js"; import { ImageAltTextSettings, NewAltTextManager, } from "./new_alt_text_manager"; import {LinkTarget, PDFLinkService} from "./pdf_link_service.js"; import {AnnotationEditorParams} from "./annotation_editor_params"; import {CaretBrowsingMode} from "./caret_browsing.js"; import {DownloadManager} from "./download_manager"; import {OverlayManager} from "./overlay_manager.js"; import {PasswordPrompt} from "./password_prompt.js"; import {PDFAttachmentViewer} from "./pdf_attachment_viewer"; import {PDFCursorTools} from "./pdf_cursor_tools"; import {PDFDocumentProperties} from "./pdf_document_properties"; import {PDFFindBar} from "./pdf_find_bar"; import {PDFFindController} from "./pdf_find_controller.js"; import {PDFHistory} from "./pdf_history.js"; import {PDFLayerViewer} from "./pdf_layer_viewer"; import {PDFOutlineViewer} from "./pdf_outline_viewer"; import {PDFPresentationMode} from "./pdf_presentation_mode"; import {PDFPrintServiceFactory} from "./pdf_print_service.js"; import {PDFRenderingQueue} from "./pdf_rendering_queue.js"; import {PDFScriptingManager} from "./pdf_scripting_manager.js"; import {PDFSidebar} from "./pdf_sidebar"; import {PDFThumbnailViewer} from "./pdf_thumbnail_viewer"; import {PDFViewer} from "./pdf_viewer.js"; import {Preferences} from "./genericcom.js"; import {SecondaryToolbar} from "./secondary_toolbar"; import {Toolbar} from "./toolbar"; import {ViewHistory} from "./view_history.js"; import {hasClosestByClassName} from "../../protyle/util/hasClosest"; import {Constants} from "../../constants"; import {getPdfInstance, hlPDFRect} from "../anno"; const FORCE_PAGES_LOADED_TIMEOUT = 10000; // ms const ViewOnLoad = { UNKNOWN: -1, PREVIOUS: 0, // Default value. INITIAL: 1, }; // NOTE class PDFViewerApplication { constructor(pdfId) { this.pdfId = pdfId this.initialBookmark = document.location.hash.substring(1); this._initializedCapability = { ...Promise.withResolvers(), settled: false, } this.appConfig = null /** @type {PDFDocumentProxy} */ this.pdfDocument = null /** @type {PDFDocumentLoadingTask} */ this.pdfLoadingTask = null this.printService = null /** @type {PDFViewer} */ this.pdfViewer = null /** @type {PDFThumbnailViewer} */ this.pdfThumbnailViewer = null /** @type {PDFRenderingQueue} */ this.pdfRenderingQueue = null /** @type {PDFPresentationMode} */ this.pdfPresentationMode = null /** @type {PDFDocumentProperties} */ this.pdfDocumentProperties = null /** @type {PDFLinkService} */ this.pdfLinkService = null /** @type {PDFHistory} */ this.pdfHistory = null /** @type {PDFSidebar} */ this.pdfSidebar = null /** @type {PDFOutlineViewer} */ this.pdfOutlineViewer = null /** @type {PDFAttachmentViewer} */ this.pdfAttachmentViewer = null /** @type {PDFLayerViewer} */ this.pdfLayerViewer = null /** @type {PDFCursorTools} */ this.pdfCursorTools = null /** @type {PDFScriptingManager} */ this.pdfScriptingManager = null /** @type {ViewHistory} */ this.store = null /** @type {DownloadManager} */ this.downloadManager = null /** @type {OverlayManager} */ this.overlayManager = null /** @type {Preferences} */ this.preferences = new Preferences() /** @type {Toolbar} */ this.toolbar = null /** @type {SecondaryToolbar} */ this.secondaryToolbar = null /** @type {EventBus} */ this.eventBus = null /** @type {IL10n} */ this.l10n = null /** @type {AnnotationEditorParams} */ this.annotationEditorParams = null /** @type {ImageAltTextSettings} */ this.imageAltTextSettings = null this.isInitialViewSet = false // NOTE 不使用 initialBookmark this.isViewerEmbedded = true this.url = "" this.baseUrl = "" this.mlManager = null this._downloadUrl = "" this._eventBusAbortController = null this._windowAbortController = null this._globalAbortController = new AbortController() this.documentInfo = null this.metadata = null this._contentDispositionFilename = null this._contentLength = null this._saveInProgress = false this._wheelUnusedTicks = 0 this._wheelUnusedFactor = 1 this._touchUnusedTicks = 0 this._touchUnusedFactor = 1 this._PDFBug = null this._hasAnnotationEditors = false this._title = document.title this._printAnnotationStoragePromise = null this._touchInfo = null this._isCtrlKeyDown = false this._caretBrowsing = null this._isScrolling = false } // Called once when the document is loaded. async initialize(appConfig) { this.appConfig = appConfig; // Ensure that `Preferences`, and indirectly `AppOptions`, have initialized // before creating e.g. the various viewer components. try { await this.preferences.initializedPromise; } catch (ex) { console.error(`initialize: "${ex.message}".`); } if (AppOptions.get("pdfBugEnabled")) { await this._parseHashParams(); } if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) { let mode; switch (AppOptions.get("viewerCssTheme")) { case 1: mode = "is-light"; break; case 2: mode = "is-dark"; break; } if (mode) { document.documentElement.classList.add(mode); } if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) { if (AppOptions.get("enableFakeMLManager")) { this.mlManager = MLManager.getFakeMLManager?.({ enableGuessAltText: AppOptions.get("enableGuessAltText"), enableAltTextModelDownload: AppOptions.get( "enableAltTextModelDownload" ), }) || null; } } } else if (AppOptions.get("enableAltText")) { // We want to load the image-to-text AI engine as soon as possible. this.mlManager = new MLManager({ enableGuessAltText: AppOptions.get("enableGuessAltText"), enableAltTextModelDownload: AppOptions.get( "enableAltTextModelDownload" ), altTextLearnMoreUrl: AppOptions.get("altTextLearnMoreUrl"), }); } // Ensure that the `L10n`-instance has been initialized before creating // e.g. the various viewer components. this.l10n = await this.externalServices.createL10n(); document.getElementsByTagName("html")[0].dir = this.l10n.getDirection(); // Connect Fluent, when necessary, and translate what we already have. if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) { this.l10n.translate(appConfig.appContainer || document.documentElement); } if ( this.isViewerEmbedded && AppOptions.get("externalLinkTarget") === LinkTarget.NONE ) { // Prevent external links from "replacing" the viewer, // when it's embedded in e.g. an