From 5894bfa44936b5056767b8867a29c925004180a8 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 12:57:15 +0100 Subject: [PATCH 01/16] Move API specific compatibility options from `src/shared/compatibility.js` and into a separate file Unfortunately, as far as I can tell, we still need the ability to adjust certain API options depending on the browser environment in PDF.js version `2.0`. However, we should be able to separate this from the general compatibility code in the `src/shared/compatibility.js` file. --- src/display/api_compatibility.js | 50 ++++++++++++++++++++++++++++++++ src/pdf.js | 3 ++ src/shared/compatibility.js | 30 +------------------ 3 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 src/display/api_compatibility.js diff --git a/src/display/api_compatibility.js b/src/display/api_compatibility.js new file mode 100644 index 000000000..09e283e75 --- /dev/null +++ b/src/display/api_compatibility.js @@ -0,0 +1,50 @@ +/* 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. + */ + +let compatibilityParams = Object.create(null); +if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) { + const userAgent = + (typeof navigator !== 'undefined' && navigator.userAgent) || ''; + const isIE = /Trident/.test(userAgent); + const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent); + const isIOSChrome = /CriOS/.test(userAgent); + const isSafari = /Safari\//.test(userAgent) && + !/(Chrome\/|Android\s)/.test(userAgent); + + // Checks if possible to use URL.createObjectURL() + // Support: IE, Chrome on iOS + (function checkOnBlobSupport() { + // Sometimes IE and Chrome on iOS losing the data created with + // createObjectURL(), see issues #3977 and #8081. + if (isIE || isIOSChrome) { + compatibilityParams.disableCreateObjectURL = true; + } + })(); + + // Support: Safari 6.0+, iOS + (function checkRangeRequests() { + // Safari has issues with cached range requests, see issue #3260. + // Last tested with version 6.0.4. + if (isSafari || isIOS) { + compatibilityParams.disableRange = true; + compatibilityParams.disableStream = true; + } + })(); +} +const apiCompatibilityParams = Object.freeze(compatibilityParams); + +export { + apiCompatibilityParams, +}; diff --git a/src/pdf.js b/src/pdf.js index 48657fb95..63fa57b5c 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -29,6 +29,7 @@ var pdfjsDisplayAnnotationLayer = require('./display/annotation_layer.js'); var pdfjsDisplayDOMUtils = require('./display/dom_utils.js'); var pdfjsDisplaySVG = require('./display/svg.js'); let pdfjsDisplayWorkerOptions = require('./display/worker_options.js'); +let pdfjsDisplayAPICompatibility = require('./display/api_compatibility.js'); if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) { const isNodeJS = require('./shared/is_node.js'); @@ -96,3 +97,5 @@ exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl; exports.LinkTarget = pdfjsDisplayDOMUtils.LinkTarget; exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes; exports.GlobalWorkerOptions = pdfjsDisplayWorkerOptions.GlobalWorkerOptions; +exports.apiCompatibilityParams = + pdfjsDisplayAPICompatibility.apiCompatibilityParams; diff --git a/src/shared/compatibility.js b/src/shared/compatibility.js index 10f91958f..1cf763637 100644 --- a/src/shared/compatibility.js +++ b/src/shared/compatibility.js @@ -29,14 +29,7 @@ if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME')) { const globalScope = require('./global_scope'); const isNodeJS = require('./is_node'); -var userAgent = (typeof navigator !== 'undefined' && navigator.userAgent) || ''; -var isIOSChrome = userAgent.indexOf('CriOS') >= 0; -var isIE = userAgent.indexOf('Trident') >= 0; -var isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent); -var isSafari = /Safari\//.test(userAgent) && - !/(Chrome\/|Android\s)/.test(userAgent); - -var hasDOM = typeof window === 'object' && typeof document === 'object'; +const hasDOM = typeof window === 'object' && typeof document === 'object'; // Initializing PDFJS global object here, it case if we need to change/disable // some PDF.js features, e.g. range requests @@ -68,27 +61,6 @@ PDFJS.compatibilityChecked = true; }; })(); -// Checks if possible to use URL.createObjectURL() -// Support: IE, Chrome on iOS -(function checkOnBlobSupport() { - // sometimes IE and Chrome on iOS loosing the data created with - // createObjectURL(), see #3977 and #8081 - if (isIE || isIOSChrome) { - PDFJS.disableCreateObjectURL = true; - } -})(); - -// Support: Safari 6.0+, iOS -(function checkRangeRequests() { - // Safari has issues with cached range requests see: - // https://github.com/mozilla/pdf.js/issues/3260 - // Last tested with version 6.0.4. - if (isSafari || isIOS) { - PDFJS.disableRange = true; - PDFJS.disableStream = true; - } -})(); - // Provides document.currentScript support // Support: IE, Chrome<29. (function checkCurrentScript() { From 09da99b8a0fb908cde084c3359320cdea2ad6869 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 13:22:26 +0100 Subject: [PATCH 02/16] Introduce a `AppOptions` abstraction in preparation for a complete refactoring of the way that viewer options are handled The way that various options are handled in the default viewer is currently a bit of a mess (to say the least). Some viewer options reside in the global `PDFJS` object, while others reside in `Preferences`. To make matters worse, some options even exist in both of the two. Since the goal, with PDF.js version `2.0`, is to reduce our usage of the global `PDFJS` object, we'll instead want pass in the options when initializing the viewer components and when calling API methods (such as `getDocument`). However given the current state of things in the default viewer, this wouldn't be exactly easy to implement. Hence this patch, which attempts to consolidate the way that viewer (and later API) options are handled by introducing a `AppOptions` singleton that provides *one* centralized way of interacting with the various options in the default viewer. --- web/app_options.js | 70 ++++++++++++++++++++++++++++++++++++++++++++++ web/viewer.js | 8 ++++-- 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 web/app_options.js diff --git a/web/app_options.js b/web/app_options.js new file mode 100644 index 000000000..4325d22df --- /dev/null +++ b/web/app_options.js @@ -0,0 +1,70 @@ +/* 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 OptionKind = { + VIEWER: 'viewer', + API: 'api', + WORKER: 'worker', +}; + +/** + * PLEASE NOTE: To avoid introducing unnecessary dependencies, we specify the + * values below *explicitly* rather than relying on imported types; + * compare with the format of `default_preferences.json`. + */ +const defaultOptions = { +}; + +const userOptions = Object.create(null); + +class AppOptions { + constructor() { + throw new Error('Cannot initialize AppOptions.'); + } + + static get(name) { + let defaultOption = defaultOptions[name], userOption = userOptions[name]; + if (userOption !== undefined) { + return userOption; + } + return (defaultOption !== undefined ? defaultOption.value : undefined); + } + + static getAll(kind = null) { + let options = Object.create(null); + for (let name in defaultOptions) { + let defaultOption = defaultOptions[name], userOption = userOptions[name]; + if (kind && defaultOption.kind !== kind) { + continue; + } + options[name] = (userOption !== undefined ? + userOption : defaultOption.value); + } + return options; + } + + static set(name, value) { + userOptions[name] = value; + } + + static remove(name) { + delete userOptions[name]; + } +} + +export { + AppOptions, + OptionKind, +}; diff --git a/web/viewer.js b/web/viewer.js index ba680ec65..ecd7bc6cf 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -35,9 +35,10 @@ if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME')) { })(); } -let pdfjsWebApp; +let pdfjsWebApp, pdfjsWebAppOptions; if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('PRODUCTION')) { pdfjsWebApp = require('./app.js'); + pdfjsWebAppOptions = require('./app_options.js'); } if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) { @@ -180,14 +181,17 @@ function webViewerLoad() { if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) { Promise.all([ SystemJS.import('pdfjs-web/app'), + SystemJS.import('pdfjs-web/app_options'), SystemJS.import('pdfjs-web/genericcom'), SystemJS.import('pdfjs-web/pdf_print_service'), - ]).then(function([app, ...otherModules]) { + ]).then(function([app, appOptions, ...otherModules]) { window.PDFViewerApplication = app.PDFViewerApplication; + window.PDFViewerApplicationOptions = appOptions.AppOptions; app.PDFViewerApplication.run(config); }); } else { window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication; + window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions; pdfjsWebApp.PDFViewerApplication.run(config); } } From 81c550903fc7f31d33a45ad741207b194a6d00c2 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 15:08:28 +0100 Subject: [PATCH 03/16] Move various viewer components options from `PDFJS`/`PDFViewerApplication.viewerPrefs` and into `AppOptions` instead --- src/display/global.js | 23 +------- web/app.js | 116 +++++++++++++++++--------------------- web/app_options.js | 97 +++++++++++++++++++++++++++++++ web/genericcom.js | 4 +- web/pdf_outline_viewer.js | 4 +- web/ui_utils.js | 35 +----------- 6 files changed, 155 insertions(+), 124 deletions(-) diff --git a/src/display/global.js b/src/display/global.js index c4b329fdc..4c3a5f4fe 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -19,11 +19,11 @@ import { PasswordResponses, removeNullCharacters, shadow, UnexpectedResponseException, UnknownErrorException, UNSUPPORTED_FEATURES, Util } from '../shared/util'; -import { DEFAULT_LINK_REL, getFilenameFromUrl, LinkTarget } from './dom_utils'; import { getDocument, LoopbackPort, PDFDataRangeTransport, PDFWorker } from './api'; import { AnnotationLayer } from './annotation_layer'; +import { getFilenameFromUrl } from './dom_utils'; import globalScope from '../shared/global_scope'; import { GlobalWorkerOptions } from './worker_options'; import { Metadata } from './metadata'; @@ -137,27 +137,6 @@ PDFJS.pdfBug = (PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug); PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ? false : PDFJS.disableCreateObjectURL); -/** - * Specifies the |target| attribute for external links. - * The constants from {LinkTarget} should be used: - * - NONE [default] - * - SELF - * - BLANK - * - PARENT - * - TOP - * @var {number} - */ -PDFJS.externalLinkTarget = (PDFJS.externalLinkTarget === undefined ? - LinkTarget.NONE : PDFJS.externalLinkTarget); - -/** - * Specifies the |rel| attribute for external links. Defaults to stripping - * the referrer. - * @var {string} - */ -PDFJS.externalLinkRel = (PDFJS.externalLinkRel === undefined ? - DEFAULT_LINK_REL : PDFJS.externalLinkRel); - /** * Determines if we can eval strings as JS. Primarily used to improve * performance for font rendering. diff --git a/web/app.js b/web/app.js index 23f00ce8e..9d3ad5538 100644 --- a/web/app.js +++ b/web/app.js @@ -28,6 +28,7 @@ import { import { CursorTool, PDFCursorTools } from './pdf_cursor_tools'; import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue'; import { PDFSidebar, SidebarView } from './pdf_sidebar'; +import { AppOptions } from './app_options'; import { getGlobalEventBus } from './dom_events'; import { OverlayManager } from './overlay_manager'; import { PasswordPrompt } from './password_prompt'; @@ -44,14 +45,12 @@ import { PDFThumbnailViewer } from './pdf_thumbnail_viewer'; import { PDFViewer } from './pdf_viewer'; import { SecondaryToolbar } from './secondary_toolbar'; import { Toolbar } from './toolbar'; -import { viewerCompatibilityParams } from './viewer_compatibility'; import { ViewHistory } from './view_history'; const DEFAULT_SCALE_DELTA = 1.1; const DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000; function configure(PDFJS) { - PDFJS.imageResourcesPath = './images/'; if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL || GENERIC || CHROME')) { GlobalWorkerOptions.workerSrc = '../build/pdf.worker.js'; @@ -76,7 +75,7 @@ const DefaultExternalServices = { createPreferences() { throw new Error('Not implemented: createPreferences'); }, - createL10n() { + createL10n(options) { throw new Error('Not implemented: createL10n'); }, supportsIntegratedFind: false, @@ -138,19 +137,6 @@ let PDFViewerApplication = { l10n: null, isInitialViewSet: false, downloadComplete: false, - viewerPrefs: { - enableWebGL: false, - sidebarViewOnLoad: SidebarView.NONE, - pdfBugEnabled: false, - showPreviousViewOnLoad: true, - defaultZoomValue: '', - disablePageMode: false, - disablePageLabels: false, - renderer: 'canvas', - textLayerMode: TextLayerMode.ENABLE, - renderInteractiveForms: false, - enablePrintAutoRotate: false, - }, isViewerEmbedded: (window.parent !== window), url: '', baseUrl: '', @@ -186,10 +172,10 @@ let PDFViewerApplication = { }); if (this.isViewerEmbedded && - PDFJS.externalLinkTarget === LinkTarget.NONE) { + AppOptions.get('externalLinkTarget') === LinkTarget.NONE) { // Prevent external links from "replacing" the viewer, // when it's embedded in e.g. an iframe or an object. - PDFJS.externalLinkTarget = LinkTarget.TOP; + AppOptions.set('externalLinkTarget', LinkTarget.TOP); } this.initialized = true; @@ -200,29 +186,29 @@ let PDFViewerApplication = { * @private */ _readPreferences() { - let { preferences, viewerPrefs, } = this; + let { preferences, } = this; return Promise.all([ preferences.get('enableWebGL').then(function resolved(value) { - viewerPrefs['enableWebGL'] = value; + AppOptions.set('enableWebGL', value); }), preferences.get('sidebarViewOnLoad').then(function resolved(value) { - viewerPrefs['sidebarViewOnLoad'] = value; + AppOptions.set('sidebarViewOnLoad', value); }), preferences.get('pdfBugEnabled').then(function resolved(value) { - viewerPrefs['pdfBugEnabled'] = value; + AppOptions.set('pdfBugEnabled', value); }), preferences.get('showPreviousViewOnLoad').then(function resolved(value) { - viewerPrefs['showPreviousViewOnLoad'] = value; + AppOptions.set('showPreviousViewOnLoad', value); }), preferences.get('defaultZoomValue').then(function resolved(value) { - viewerPrefs['defaultZoomValue'] = value; + AppOptions.set('defaultZoomValue', value); }), preferences.get('textLayerMode').then(function resolved(value) { - if (viewerPrefs['textLayerMode'] === TextLayerMode.DISABLE) { + if (AppOptions.get('textLayerMode') === TextLayerMode.DISABLE) { return; } - viewerPrefs['textLayerMode'] = value; + AppOptions.set('textLayerMode', value); }), preferences.get('disableRange').then(function resolved(value) { if (PDFJS.disableRange === true) { @@ -246,28 +232,28 @@ let PDFViewerApplication = { PDFJS.disableFontFace = value; }), preferences.get('useOnlyCssZoom').then(function resolved(value) { - PDFJS.useOnlyCssZoom = value; + AppOptions.set('useOnlyCssZoom', value); }), preferences.get('externalLinkTarget').then(function resolved(value) { - if (PDFJS.externalLinkTarget !== LinkTarget.NONE) { + if (AppOptions.get('externalLinkTarget') !== LinkTarget.NONE) { return; } - PDFJS.externalLinkTarget = value; + AppOptions.set('externalLinkTarget', value); }), preferences.get('renderer').then(function resolved(value) { - viewerPrefs['renderer'] = value; + AppOptions.set('renderer', value); }), preferences.get('renderInteractiveForms').then(function resolved(value) { - viewerPrefs['renderInteractiveForms'] = value; + AppOptions.set('renderInteractiveForms', value); }), preferences.get('disablePageMode').then(function resolved(value) { - viewerPrefs['disablePageMode'] = value; + AppOptions.set('disablePageMode', value); }), preferences.get('disablePageLabels').then(function resolved(value) { - viewerPrefs['disablePageLabels'] = value; + AppOptions.set('disablePageLabels', value); }), preferences.get('enablePrintAutoRotate').then(function resolved(value) { - viewerPrefs['enablePrintAutoRotate'] = value; + AppOptions.set('enablePrintAutoRotate', value); }), ]).catch(function(reason) { }); }, @@ -276,11 +262,11 @@ let PDFViewerApplication = { * @private */ _parseHashParameters() { - let { appConfig, viewerPrefs, } = this; + let { appConfig, } = this; let waitOn = []; if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION') || - viewerPrefs['pdfBugEnabled']) { + AppOptions.get('pdfBugEnabled')) { // Special debugging flags in the hash section of the URL. let hash = document.location.hash.substring(1); let hashParams = parseQueryString(hash); @@ -302,13 +288,15 @@ let PDFViewerApplication = { PDFJS.disableFontFace = (hashParams['disablefontface'] === 'true'); } if ('disablehistory' in hashParams) { - PDFJS.disableHistory = (hashParams['disablehistory'] === 'true'); + AppOptions.set('disableHistory', + hashParams['disablehistory'] === 'true'); } if ('webgl' in hashParams) { - viewerPrefs['enableWebGL'] = (hashParams['webgl'] === 'true'); + AppOptions.set('enableWebGL', hashParams['webgl'] === 'true'); } if ('useonlycsszoom' in hashParams) { - PDFJS.useOnlyCssZoom = (hashParams['useonlycsszoom'] === 'true'); + AppOptions.set('useOnlyCssZoom', + hashParams['useonlycsszoom'] === 'true'); } if ('verbosity' in hashParams) { PDFJS.verbosity = hashParams['verbosity'] | 0; @@ -321,7 +309,7 @@ let PDFViewerApplication = { if ('textlayer' in hashParams) { switch (hashParams['textlayer']) { case 'off': - viewerPrefs['textLayerMode'] = TextLayerMode.DISABLE; + AppOptions.set('textLayerMode', TextLayerMode.DISABLE); break; case 'visible': case 'shadow': @@ -341,7 +329,7 @@ let PDFViewerApplication = { // It is not possible to change locale for Firefox extension builds. if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION') || !PDFJSDev.test('FIREFOX || MOZCENTRAL')) && 'locale' in hashParams) { - PDFJS.locale = hashParams['locale']; + AppOptions.set('locale', hashParams['locale']); } } @@ -353,7 +341,7 @@ let PDFViewerApplication = { */ _initializeL10n() { this.l10n = this.externalServices.createL10n({ - locale: PDFJS.locale, + locale: AppOptions.get('locale'), }); return this.l10n.getDirection().then((dir) => { document.getElementsByTagName('html')[0].dir = dir; @@ -364,7 +352,7 @@ let PDFViewerApplication = { * @private */ _initializeViewerComponents() { - let { appConfig, viewerPrefs, } = this; + let { appConfig, } = this; return new Promise((resolve, reject) => { this.overlayManager = new OverlayManager(); @@ -378,8 +366,8 @@ let PDFViewerApplication = { let pdfLinkService = new PDFLinkService({ eventBus, - externalLinkTarget: PDFJS.externalLinkTarget, - externalLinkRel: PDFJS.externalLinkRel, + externalLinkTarget: AppOptions.get('externalLinkTarget'), + externalLinkRel: AppOptions.get('externalLinkRel'), }); this.pdfLinkService = pdfLinkService; @@ -395,15 +383,15 @@ let PDFViewerApplication = { renderingQueue: pdfRenderingQueue, linkService: pdfLinkService, downloadManager, - renderer: viewerPrefs['renderer'], - enableWebGL: viewerPrefs['enableWebGL'], + renderer: AppOptions.get('renderer'), + enableWebGL: AppOptions.get('enableWebGL'), l10n: this.l10n, - textLayerMode: viewerPrefs['textLayerMode'], - imageResourcesPath: PDFJS.imageResourcesPath, - renderInteractiveForms: viewerPrefs['renderInteractiveForms'], - enablePrintAutoRotate: viewerPrefs['enablePrintAutoRotate'], - useOnlyCssZoom: PDFJS.useOnlyCssZoom, - maxCanvasPixels: PDFJS.maxCanvasPixels, + textLayerMode: AppOptions.get('textLayerMode'), + imageResourcesPath: AppOptions.get('imageResourcesPath'), + renderInteractiveForms: AppOptions.get('renderInteractiveForms'), + enablePrintAutoRotate: AppOptions.get('enablePrintAutoRotate'), + useOnlyCssZoom: AppOptions.get('useOnlyCssZoom'), + maxCanvasPixels: AppOptions.get('maxCanvasPixels'), }); pdfRenderingQueue.setViewer(this.pdfViewer); pdfLinkService.setViewer(this.pdfViewer); @@ -568,7 +556,7 @@ let PDFViewerApplication = { support = false; } } - if (support && viewerCompatibilityParams['disableFullscreen'] === true) { + if (support && AppOptions.get('disableFullscreen') === true) { support = false; } @@ -1013,10 +1001,10 @@ let PDFViewerApplication = { firstPagePromise.then((pdfPage) => { this.loadingBar.setWidth(this.appConfig.viewerContainer); - if (!PDFJS.disableHistory && !this.isViewerEmbedded) { + if (!AppOptions.get('disableHistory') && !this.isViewerEmbedded) { // The browsing history is only enabled when the viewer is standalone, // i.e. not when it is embedded in a web page. - let resetHistory = !this.viewerPrefs['showPreviousViewOnLoad']; + let resetHistory = !AppOptions.get('showPreviousViewOnLoad'); this.pdfHistory.initialize(id, resetHistory); if (this.pdfHistory.initialBookmark) { @@ -1043,19 +1031,19 @@ let PDFViewerApplication = { Promise.all([storePromise, pageModePromise]).then( ([values = {}, pageMode]) => { // Initialize the default values, from user preferences. - let hash = this.viewerPrefs['defaultZoomValue'] ? - ('zoom=' + this.viewerPrefs['defaultZoomValue']) : null; + let hash = AppOptions.get('defaultZoomValue') ? + ('zoom=' + AppOptions.get('defaultZoomValue')) : null; let rotation = null; - let sidebarView = this.viewerPrefs['sidebarViewOnLoad']; + let sidebarView = AppOptions.get('sidebarViewOnLoad'); - if (values.exists && this.viewerPrefs['showPreviousViewOnLoad']) { + if (values.exists && AppOptions.get('showPreviousViewOnLoad')) { hash = 'page=' + values.page + - '&zoom=' + (this.viewerPrefs['defaultZoomValue'] || values.zoom) + + '&zoom=' + (AppOptions.get('defaultZoomValue') || values.zoom) + ',' + values.scrollLeft + ',' + values.scrollTop; rotation = parseInt(values.rotation, 10); sidebarView = sidebarView || (values.sidebarView | 0); } - if (pageMode && !this.viewerPrefs['disablePageMode']) { + if (pageMode && !AppOptions.get('disablePageMode')) { // Always let the user preference/history take precedence. sidebarView = sidebarView || apiPageModeToSidebarView(pageMode); } @@ -1099,7 +1087,7 @@ let PDFViewerApplication = { }); pdfDocument.getPageLabels().then((labels) => { - if (!labels || this.viewerPrefs['disablePageLabels']) { + if (!labels || AppOptions.get('disablePageLabels')) { return; } let i = 0, numLabels = labels.length; @@ -1177,7 +1165,7 @@ let PDFViewerApplication = { info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() + ' / ' + (info.Creator || '-').trim() + ']' + ' (PDF.js: ' + (version || '-') + - (this.viewerPrefs['enableWebGL'] ? ' [WebGL]' : '') + ')'); + (AppOptions.get('enableWebGL') ? ' [WebGL]' : '') + ')'); let pdfTitle; if (metadata && metadata.has('dc:title')) { diff --git a/web/app_options.js b/web/app_options.js index 4325d22df..27f80d93c 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -13,6 +13,8 @@ * limitations under the License. */ +import { viewerCompatibilityParams } from './viewer_compatibility'; + const OptionKind = { VIEWER: 'viewer', API: 'api', @@ -25,6 +27,101 @@ const OptionKind = { * compare with the format of `default_preferences.json`. */ const defaultOptions = { + defaultZoomValue: { + /** @type {string} */ + value: '', + kind: OptionKind.VIEWER, + }, + disableFullscreen: { + /** @type {boolean} */ + value: viewerCompatibilityParams.disableFullscreen || false, + kind: OptionKind.VIEWER, + }, + disableHistory: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER, + }, + disablePageLabels: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER, + }, + disablePageMode: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER, + }, + enablePrintAutoRotate: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER, + }, + enableWebGL: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER, + }, + externalLinkRel: { + /** @type {string} */ + value: 'noopener noreferrer nofollow', + kind: OptionKind.VIEWER, + }, + externalLinkTarget: { + /** @type {number} */ + value: 0, + kind: OptionKind.VIEWER, + }, + imageResourcesPath: { + /** @type {string} */ + value: './images/', + kind: OptionKind.VIEWER, + }, + locale: { + /** @type {string} */ + value: (typeof navigator !== 'undefined' ? navigator.language : 'en-US'), + kind: OptionKind.VIEWER, + }, + maxCanvasPixels: { + /** @type {number} */ + value: viewerCompatibilityParams.maxCanvasPixels || 16777216, + kind: OptionKind.VIEWER, + }, + pdfBugEnabled: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER, + }, + renderer: { + /** @type {string} */ + value: 'canvas', + kind: OptionKind.VIEWER, + }, + renderInteractiveForms: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER, + }, + showPreviousViewOnLoad: { + /** @type {boolean} */ + value: true, + kind: OptionKind.VIEWER, + }, + sidebarViewOnLoad: { + /** @type {number} */ + value: 0, + kind: OptionKind.VIEWER, + }, + textLayerMode: { + /** @type {number} */ + value: 1, + kind: OptionKind.VIEWER, + }, + useOnlyCssZoom: { + /** @type {boolean} */ + value: false, + kind: OptionKind.VIEWER, + }, }; const userOptions = Object.create(null); diff --git a/web/genericcom.js b/web/genericcom.js index 36412a809..5a82df6a5 100644 --- a/web/genericcom.js +++ b/web/genericcom.js @@ -48,8 +48,8 @@ GenericExternalServices.createDownloadManager = function() { GenericExternalServices.createPreferences = function() { return new GenericPreferences(); }; -GenericExternalServices.createL10n = function(options) { - return new GenericL10n(options.locale); +GenericExternalServices.createL10n = function({ locale = 'en-US', }) { + return new GenericL10n(locale); }; PDFViewerApplication.externalServices = GenericExternalServices; diff --git a/web/pdf_outline_viewer.js b/web/pdf_outline_viewer.js index 05b94016c..6a30b1ebd 100644 --- a/web/pdf_outline_viewer.js +++ b/web/pdf_outline_viewer.js @@ -78,10 +78,10 @@ class PDFOutlineViewer { return; } - element.href = this.linkService.getDestinationHash(dest); + element.href = linkService.getDestinationHash(dest); element.onclick = () => { if (dest) { - this.linkService.navigateTo(dest); + linkService.navigateTo(dest); } return false; }; diff --git a/web/ui_utils.js b/web/ui_utils.js index ec45ac04c..b289ecd01 100644 --- a/web/ui_utils.js +++ b/web/ui_utils.js @@ -13,7 +13,7 @@ * limitations under the License. */ -import { createPromiseCapability, PDFJS } from 'pdfjs-lib'; +import { createPromiseCapability } from 'pdfjs-lib'; const CSS_UNITS = 96.0 / 72.0; const DEFAULT_SCALE_VALUE = 'auto'; @@ -71,39 +71,6 @@ let NullL10n = { }, }; -/** - * Enables CSS only zooming. - * @var {boolean} - */ -PDFJS.useOnlyCssZoom = (PDFJS.useOnlyCssZoom === undefined ? - false : PDFJS.useOnlyCssZoom); - -/** - * The maximum supported canvas size in total pixels e.g. width * height. - * The default value is 4096 * 4096. Use -1 for no limit. - * @var {number} - */ -PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ? - 16777216 : PDFJS.maxCanvasPixels); - -/** - * Disables saving of the last position of the viewed PDF. - * @var {boolean} - */ -PDFJS.disableHistory = (PDFJS.disableHistory === undefined ? - false : PDFJS.disableHistory); - -if (typeof PDFJSDev === 'undefined' || - !PDFJSDev.test('FIREFOX || MOZCENTRAL')) { - /** - * Interface locale settings. - * @var {string} - */ - PDFJS.locale = - (PDFJS.locale === undefined && typeof navigator !== 'undefined' ? - navigator.language : PDFJS.locale) || 'en-US'; -} - /** * Returns scale factor for the canvas. It makes sense for the HiDPI displays. * @return {Object} The object with horizontal (sx) and vertical (sy) From 57165afb08009179e6835bd971576b4d73f7186a Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 23:25:23 +0100 Subject: [PATCH 04/16] Move the `defaultUrl` parameter from the `appConfig` and into `AppOptions` instead The `appConfig` contains (mostly) references to various DOM elements, used when initializing the viewer components. Hence `defaultUrl` seem like a slightly better fit for the new `AppOptions` abstraction, not to mention that it should thus be easier to set/modify it for custom deployments of the default viewer. --- web/app.js | 4 ++-- web/app_options.js | 5 +++++ web/viewer.js | 13 ++++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/web/app.js b/web/app.js index 9d3ad5538..b02cf0c3a 100644 --- a/web/app.js +++ b/web/app.js @@ -1568,12 +1568,12 @@ function webViewerInitialized() { if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) { let queryString = document.location.search.substring(1); let params = parseQueryString(queryString); - file = 'file' in params ? params.file : appConfig.defaultUrl; + file = 'file' in params ? params.file : AppOptions.get('defaultUrl'); validateFileURL(file); } else if (PDFJSDev.test('FIREFOX || MOZCENTRAL')) { file = window.location.href.split('#')[0]; } else if (PDFJSDev.test('CHROME')) { - file = appConfig.defaultUrl; + file = AppOptions.get('defaultUrl'); } if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) { diff --git a/web/app_options.js b/web/app_options.js index 27f80d93c..49a214850 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -27,6 +27,11 @@ const OptionKind = { * compare with the format of `default_preferences.json`. */ const defaultOptions = { + defaultUrl: { + /** @type {string} */ + value: 'compressed.tracemonkey-pldi-09.pdf', + kind: OptionKind.VIEWER, + }, defaultZoomValue: { /** @type {string} */ value: '', diff --git a/web/viewer.js b/web/viewer.js index ecd7bc6cf..1c3fbb240 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -16,18 +16,18 @@ 'use strict'; -let DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf'; - if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME')) { + var defaultUrl; // eslint-disable-line no-var + (function rewriteUrlClosure() { // Run this code outside DOMContentLoaded to make sure that the URL // is rewritten as soon as possible. let queryString = document.location.search.slice(1); let m = /(^|&)file=([^&]*)/.exec(queryString); - DEFAULT_URL = m ? decodeURIComponent(m[2]) : ''; + defaultUrl = m ? decodeURIComponent(m[2]) : ''; // Example: chrome-extension://.../http://example.com/file.pdf - let humanReadableUrl = '/' + DEFAULT_URL + location.hash; + let humanReadableUrl = '/' + defaultUrl + location.hash; history.replaceState(history.state, '', humanReadableUrl); if (top === window) { chrome.runtime.sendMessage('showPageAction'); @@ -172,7 +172,6 @@ function getViewerConfiguration() { printContainer: document.getElementById('printContainer'), openFileInputName: 'fileInput', debuggerScriptPath: './debugger.js', - defaultUrl: DEFAULT_URL, }; } @@ -190,6 +189,10 @@ function webViewerLoad() { app.PDFViewerApplication.run(config); }); } else { + if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME')) { + pdfjsWebAppOptions.AppOptions.set('defaultUrl', defaultUrl); + } + window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication; window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions; pdfjsWebApp.PDFViewerApplication.run(config); From b0956a5d91946ee75729dbd8cedad3b86d9cfbc9 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 15:33:57 +0100 Subject: [PATCH 05/16] Refactor how the default viewer handles the worker options, by making use of `AppOptions` instead of the global `PDFJS` object --- web/app.js | 22 ++++++++++++++-------- web/app_options.js | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/web/app.js b/web/app.js index b02cf0c3a..05a3f5736 100644 --- a/web/app.js +++ b/web/app.js @@ -51,13 +51,8 @@ const DEFAULT_SCALE_DELTA = 1.1; const DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000; function configure(PDFJS) { - if (typeof PDFJSDev !== 'undefined' && - PDFJSDev.test('FIREFOX || MOZCENTRAL || GENERIC || CHROME')) { - GlobalWorkerOptions.workerSrc = '../build/pdf.worker.js'; - } if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) { PDFJS.cMapUrl = '../external/bcmaps/'; - GlobalWorkerOptions.workerSrc = '../src/worker_loader.js'; } else { PDFJS.cMapUrl = '../web/cmaps/'; } @@ -299,7 +294,7 @@ let PDFViewerApplication = { hashParams['useonlycsszoom'] === 'true'); } if ('verbosity' in hashParams) { - PDFJS.verbosity = hashParams['verbosity'] | 0; + AppOptions.set('verbosity', hashParams['verbosity'] | 0); } if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) && hashParams['disablebcmaps'] === 'true') { @@ -711,6 +706,11 @@ let PDFViewerApplication = { return this.open(file, args); }); } + // Set the necessary global worker parameters, using the available options. + const workerParameters = AppOptions.getAll('worker'); + for (let key in workerParameters) { + GlobalWorkerOptions[key] = workerParameters[key]; + } let parameters = Object.create(null); if (typeof file === 'string') { // URL @@ -728,8 +728,11 @@ let PDFViewerApplication = { PDFJSDev.test('FIREFOX || MOZCENTRAL || CHROME')) { parameters.docBaseUrl = this.baseUrl; } - // TODO: Remove this once all options are moved from the `PDFJS` object. - parameters.verbosity = PDFJS.verbosity; + // Set the necessary API parameters, using the available options. + const apiParameters = AppOptions.getAll('api'); + for (let key in apiParameters) { + parameters[key] = apiParameters[key]; + } if (args) { for (let prop in args) { @@ -1515,6 +1518,9 @@ if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) { function loadFakeWorker() { return new Promise(function(resolve, reject) { + if (!GlobalWorkerOptions.workerSrc) { + GlobalWorkerOptions.workerSrc = AppOptions.get('workerSrc'); + } if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) { if (typeof SystemJS === 'object') { SystemJS.import('pdfjs/core/worker').then((worker) => { diff --git a/web/app_options.js b/web/app_options.js index 49a214850..a2e53b7f0 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -127,6 +127,29 @@ const defaultOptions = { value: false, kind: OptionKind.VIEWER, }, + + postMessageTransfers: { + /** @type {boolean} */ + value: true, + kind: OptionKind.API, + }, + verbosity: { + /** @type {number} */ + value: 1, + kind: OptionKind.API, + }, + + workerPort: { + /** @type {Object} */ + value: null, + kind: OptionKind.WORKER, + }, + workerSrc: { + /** @type {string} */ + value: (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION') ? + '../src/worker_loader.js' : '../build/pdf.worker.js'), + kind: OptionKind.WORKER, + }, }; const userOptions = Object.create(null); From b674409397d722a3e1f916d68ee99d51983a1969 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 16:13:33 +0100 Subject: [PATCH 06/16] Move the `maxImageSize` option from the global `PDFJS` object and into `getDocument` instead --- examples/mobile-viewer/viewer.js | 7 +++++-- src/core/worker.js | 2 +- src/display/api.js | 14 ++++++++++---- src/display/dom_utils.js | 2 -- src/display/global.js | 8 -------- web/app_options.js | 5 +++++ 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/examples/mobile-viewer/viewer.js b/examples/mobile-viewer/viewer.js index 2501dbdfa..2b8f3854a 100644 --- a/examples/mobile-viewer/viewer.js +++ b/examples/mobile-viewer/viewer.js @@ -23,7 +23,7 @@ if (typeof PDFJS === 'undefined' || !PDFJS.PDFViewer || !PDFJS.getDocument) { var USE_ONLY_CSS_ZOOM = true; var TEXT_LAYER_MODE = 0; // DISABLE -PDFJS.maxImageSize = 1024 * 1024; +var MAX_IMAGE_SIZE = 1024 * 1024; PDFJS.cMapUrl = '../../node_modules/pdfjs-dist/cmaps/'; PDFJS.cMapPacked = true; @@ -62,7 +62,10 @@ var PDFViewerApplication = { this.setTitleUsingUrl(url); // Loading document. - var loadingTask = PDFJS.getDocument(url); + var loadingTask = PDFJS.getDocument({ + url: url, + maxImageSize: MAX_IMAGE_SIZE, + }); this.pdfLoadingTask = loadingTask; loadingTask.onProgress = function (progressData) { diff --git a/src/core/worker.js b/src/core/worker.js index 12a75df53..742718aad 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -614,7 +614,7 @@ var WorkerMessageHandler = { var evaluatorOptions = { forceDataSchema: data.disableCreateObjectURL, - maxImageSize: data.maxImageSize === undefined ? -1 : data.maxImageSize, + maxImageSize: data.maxImageSize, disableFontFace: data.disableFontFace, nativeImageDecoderSupport: data.nativeImageDecoderSupport, ignoreErrors: data.ignoreErrors, diff --git a/src/display/api.js b/src/display/api.js index bdec3bf94..545c6e1ee 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -150,6 +150,9 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * `getOperatorList`, `getTextContent`, and `RenderTask`, when the associated * PDF data cannot be successfully parsed, instead of attempting to recover * whatever possible of the data. The default value is `false`. + * @property {number} maxImageSize - (optional) The maximum allowed image size + * in total pixels, i.e. width * height. Images above this value will not be + * rendered. Use -1 for no limit, which is also the default value. */ /** @@ -195,7 +198,7 @@ function getDocument(src) { source = src; } - var params = {}; + let params = Object.create(null); var rangeTransport = null; let worker = null; var CMapReaderFactory = DOMCMapReaderFactory; @@ -237,11 +240,14 @@ function getDocument(src) { params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE; params.ignoreErrors = params.stopAtErrors !== true; - const nativeImageDecoderValues = Object.values(NativeImageDecoding); + const NativeImageDecoderValues = Object.values(NativeImageDecoding); if (params.nativeImageDecoderSupport === undefined || - !nativeImageDecoderValues.includes(params.nativeImageDecoderSupport)) { + !NativeImageDecoderValues.includes(params.nativeImageDecoderSupport)) { params.nativeImageDecoderSupport = NativeImageDecoding.DECODE; } + if (!Number.isInteger(params.maxImageSize)) { + params.maxImageSize = -1; + } // Set the main-thread verbosity level. setVerbosityLevel(params.verbosity); @@ -327,7 +333,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { rangeChunkSize: source.rangeChunkSize, length: source.length, }, - maxImageSize: getDefaultSetting('maxImageSize'), + maxImageSize: source.maxImageSize, disableFontFace: getDefaultSetting('disableFontFace'), disableCreateObjectURL: getDefaultSetting('disableCreateObjectURL'), postMessageTransfers: worker.postMessageTransfers, diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index 69a9e974c..776115cbd 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -349,8 +349,6 @@ function getDefaultSetting(id) { return globalSettings ? globalSettings.cMapUrl : null; case 'cMapPacked': return globalSettings ? globalSettings.cMapPacked : false; - case 'maxImageSize': - return globalSettings ? globalSettings.maxImageSize : -1; case 'isEvalSupported': return globalSettings ? globalSettings.isEvalSupported : true; default: diff --git a/src/display/global.js b/src/display/global.js index 4c3a5f4fe..24d36ccdc 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -65,14 +65,6 @@ PDFJS.Util = Util; PDFJS.PageViewport = PageViewport; PDFJS.createPromiseCapability = createPromiseCapability; -/** - * The maximum allowed image size in total pixels e.g. width * height. Images - * above this value will not be drawn. Use -1 for no limit. - * @var {number} - */ -PDFJS.maxImageSize = (PDFJS.maxImageSize === undefined ? - -1 : PDFJS.maxImageSize); - /** * The url of where the predefined Adobe CMaps are located. Include trailing * slash. diff --git a/web/app_options.js b/web/app_options.js index a2e53b7f0..638410303 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -128,6 +128,11 @@ const defaultOptions = { kind: OptionKind.VIEWER, }, + maxImageSize: { + /** @type {number} */ + value: -1, + kind: OptionKind.API, + }, postMessageTransfers: { /** @type {boolean} */ value: true, From 3c2fbdffe6e1d68d751cc0e0c125712094c8f5f8 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 16:57:24 +0100 Subject: [PATCH 07/16] Move the `cMapUrl` and `cMapPacked` options from the global `PDFJS` object and into `getDocument` instead --- examples/components/pageviewer.js | 12 ++++++++---- examples/components/simpleviewer.js | 10 +++++++--- examples/components/singlepageviewer.js | 10 +++++++--- examples/mobile-viewer/viewer.js | 6 ++++-- examples/svgviewer/viewer.js | 18 ++++++++++-------- src/display/api.js | 15 ++++++++++----- src/display/dom_utils.js | 9 +++------ src/display/global.js | 13 ------------- test/driver.js | 6 ++++-- test/unit/cmap_spec.js | 5 +++-- test/unit/test_utils.js | 5 +++-- web/app.js | 15 ++------------- web/app_options.js | 11 +++++++++++ 13 files changed, 72 insertions(+), 63 deletions(-) diff --git a/examples/components/pageviewer.js b/examples/components/pageviewer.js index 0d128ebc9..de33355e0 100644 --- a/examples/components/pageviewer.js +++ b/examples/components/pageviewer.js @@ -15,7 +15,7 @@ 'use strict'; -if (!PDFJS.PDFViewer || !PDFJS.getDocument) { +if (!PDFJS.PDFPageView || !PDFJS.getDocument) { alert('Please build the pdfjs-dist library using\n' + ' `gulp dist-install`'); } @@ -27,8 +27,8 @@ PDFJS.GlobalWorkerOptions.workerSrc = // Some PDFs need external cmaps. // -// PDFJS.cMapUrl = '../../node_modules/pdfjs-dist/cmaps/'; -// PDFJS.cMapPacked = true; +var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/'; +var CMAP_PACKED = true; var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf'; var PAGE_TO_VIEW = 1; @@ -37,7 +37,11 @@ var SCALE = 1.0; var container = document.getElementById('pageContainer'); // Loading document. -PDFJS.getDocument(DEFAULT_URL).then(function (pdfDocument) { +PDFJS.getDocument({ + url: DEFAULT_URL, + cMapUrl: CMAP_URL, + cMapPacked: CMAP_PACKED, +}).then(function(pdfDocument) { // Document loaded, retrieving the page. return pdfDocument.getPage(PAGE_TO_VIEW).then(function (pdfPage) { // Creating the page view with default parameters. diff --git a/examples/components/simpleviewer.js b/examples/components/simpleviewer.js index 5f9da0fcc..8d2e09fd2 100644 --- a/examples/components/simpleviewer.js +++ b/examples/components/simpleviewer.js @@ -27,8 +27,8 @@ PDFJS.GlobalWorkerOptions.workerSrc = // Some PDFs need external cmaps. // -// PDFJS.cMapUrl = '../../node_modules/pdfjs-dist/cmaps/'; -// PDFJS.cMapPacked = true; +var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/'; +var CMAP_PACKED = true; var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf'; var SEARCH_FOR = ''; // try 'Mozilla'; @@ -60,7 +60,11 @@ container.addEventListener('pagesinit', function () { }); // Loading document. -PDFJS.getDocument(DEFAULT_URL).then(function (pdfDocument) { +PDFJS.getDocument({ + url: DEFAULT_URL, + cMapUrl: CMAP_URL, + cMapPacked: CMAP_PACKED, +}).then(function(pdfDocument) { // Document loaded, specifying document for the viewer and // the (optional) linkService. pdfViewer.setDocument(pdfDocument); diff --git a/examples/components/singlepageviewer.js b/examples/components/singlepageviewer.js index 90900741e..b2b9d34be 100644 --- a/examples/components/singlepageviewer.js +++ b/examples/components/singlepageviewer.js @@ -27,8 +27,8 @@ PDFJS.GlobalWorkerOptions.workerSrc = // Some PDFs need external cmaps. // -// PDFJS.cMapUrl = '../../node_modules/pdfjs-dist/cmaps/'; -// PDFJS.cMapPacked = true; +var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/'; +var CMAP_PACKED = true; var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf'; var SEARCH_FOR = ''; // try 'Mozilla'; @@ -60,7 +60,11 @@ container.addEventListener('pagesinit', function () { }); // Loading document. -PDFJS.getDocument(DEFAULT_URL).then(function (pdfDocument) { +PDFJS.getDocument({ + url: DEFAULT_URL, + cMapUrl: CMAP_URL, + cMapPacked: CMAP_PACKED, +}).then(function(pdfDocument) { // Document loaded, specifying document for the viewer and // the (optional) linkService. pdfSinglePageViewer.setDocument(pdfDocument); diff --git a/examples/mobile-viewer/viewer.js b/examples/mobile-viewer/viewer.js index 2b8f3854a..52e152986 100644 --- a/examples/mobile-viewer/viewer.js +++ b/examples/mobile-viewer/viewer.js @@ -24,8 +24,8 @@ if (typeof PDFJS === 'undefined' || !PDFJS.PDFViewer || !PDFJS.getDocument) { var USE_ONLY_CSS_ZOOM = true; var TEXT_LAYER_MODE = 0; // DISABLE var MAX_IMAGE_SIZE = 1024 * 1024; -PDFJS.cMapUrl = '../../node_modules/pdfjs-dist/cmaps/'; -PDFJS.cMapPacked = true; +var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/'; +var CMAP_PACKED = true; PDFJS.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; @@ -65,6 +65,8 @@ var PDFViewerApplication = { var loadingTask = PDFJS.getDocument({ url: url, maxImageSize: MAX_IMAGE_SIZE, + cMapUrl: CMAP_URL, + cMapPacked: CMAP_PACKED, }); this.pdfLoadingTask = loadingTask; diff --git a/examples/svgviewer/viewer.js b/examples/svgviewer/viewer.js index 04f92f8a2..f29ab7907 100644 --- a/examples/svgviewer/viewer.js +++ b/examples/svgviewer/viewer.js @@ -38,29 +38,31 @@ function renderDocument(pdf, svgLib) { Promise.all([System.import('pdfjs/display/api'), System.import('pdfjs/display/svg'), - System.import('pdfjs/display/global'), System.import('pdfjs/display/worker_options'), System.import('pdfjs/display/network'), System.resolve('pdfjs/worker_loader')]) .then(function (modules) { var api = modules[0]; var svg = modules[1]; - var global = modules[2]; - var GlobalWorkerOptions = modules[3].GlobalWorkerOptions; - var network = modules[4]; + var GlobalWorkerOptions = modules[2].GlobalWorkerOptions; + var network = modules[3]; api.setPDFNetworkStreamFactory((params) => { return new network.PDFNetworkStream(params); }); // In production, change this to point to the built `pdf.worker.js` file. - GlobalWorkerOptions.workerSrc = modules[5]; + GlobalWorkerOptions.workerSrc = modules[4]; // In production, change this to point to where the cMaps are placed. - global.PDFJS.cMapUrl = '../../external/bcmaps/'; - global.PDFJS.cMapPacked = true; + var CMAP_URL = '../../external/bcmaps/'; + var CMAP_PACKED = true; // Fetch the PDF document from the URL using promises. - api.getDocument(url).then(function (doc) { + api.getDocument({ + url: url, + cMapUrl: CMAP_URL, + cMapPacked: CMAP_PACKED, + }).then(function(doc) { renderDocument(doc, svg); }); }); diff --git a/src/display/api.js b/src/display/api.js index 545c6e1ee..437312678 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -142,6 +142,10 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * with limited image support through stubs (useful for SVG conversion), * and 'none' where JPEG images will be decoded entirely by PDF.js. * The default value is 'decode'. + * @property {string} cMapUrl - (optional) The URL where the predefined + * Adobe CMaps are located. Include trailing slash. + * @property {boolean} cMapPacked - (optional) Specifies if the Adobe CMaps are + * binary packed. * @property {Object} CMapReaderFactory - (optional) The factory that will be * used when reading built-in CMap files. Providing a custom factory is useful * for environments without `XMLHttpRequest` support, such as e.g. Node.js. @@ -201,7 +205,7 @@ function getDocument(src) { let params = Object.create(null); var rangeTransport = null; let worker = null; - var CMapReaderFactory = DOMCMapReaderFactory; + let CMapReaderFactory = DOMCMapReaderFactory; for (var key in source) { if (key === 'url' && typeof window !== 'undefined') { @@ -289,7 +293,7 @@ function getDocument(src) { var messageHandler = new MessageHandler(docId, workerId, worker.port); messageHandler.postMessageTransfers = worker.postMessageTransfers; var transport = new WorkerTransport(messageHandler, task, networkStream, - CMapReaderFactory); + params, CMapReaderFactory); task._transport = transport; messageHandler.send('Ready', null); }); @@ -1550,14 +1554,15 @@ var PDFWorker = (function PDFWorkerClosure() { */ var WorkerTransport = (function WorkerTransportClosure() { function WorkerTransport(messageHandler, loadingTask, networkStream, - CMapReaderFactory) { + params, CMapReaderFactory) { this.messageHandler = messageHandler; this.loadingTask = loadingTask; this.commonObjs = new PDFObjects(); this.fontLoader = new FontLoader(loadingTask.docId); + this._params = params; this.CMapReaderFactory = new CMapReaderFactory({ - baseUrl: getDefaultSetting('cMapUrl'), - isCompressed: getDefaultSetting('cMapPacked'), + baseUrl: params.cMapUrl, + isCompressed: params.cMapPacked, }); this.destroyed = false; diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index 776115cbd..f1146f74b 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -69,8 +69,9 @@ class DOMCMapReaderFactory { fetch({ name, }) { if (!this.baseUrl) { - return Promise.reject(new Error('CMap baseUrl must be specified, ' + - 'see "PDFJS.cMapUrl" (and also "PDFJS.cMapPacked").')); + return Promise.reject(new Error( + 'The CMap "baseUrl" parameter must be specified, ensure that ' + + 'the "cMapUrl" and "cMapPacked" API parameters are provided.')); } if (!name) { return Promise.reject(new Error('CMap name must be specified.')); @@ -345,10 +346,6 @@ function getDefaultSetting(id) { return globalSettings ? globalSettings.disableFontFace : false; case 'disableCreateObjectURL': return globalSettings ? globalSettings.disableCreateObjectURL : false; - case 'cMapUrl': - return globalSettings ? globalSettings.cMapUrl : null; - case 'cMapPacked': - return globalSettings ? globalSettings.cMapPacked : false; case 'isEvalSupported': return globalSettings ? globalSettings.isEvalSupported : true; default: diff --git a/src/display/global.js b/src/display/global.js index 24d36ccdc..6fabc84df 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -65,19 +65,6 @@ PDFJS.Util = Util; PDFJS.PageViewport = PageViewport; PDFJS.createPromiseCapability = createPromiseCapability; -/** - * The url of where the predefined Adobe CMaps are located. Include trailing - * slash. - * @var {string} - */ -PDFJS.cMapUrl = (PDFJS.cMapUrl === undefined ? null : PDFJS.cMapUrl); - -/** - * Specifies if CMaps are binary packed. - * @var {boolean} - */ -PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked; - /** * By default fonts are converted to OpenType fonts and loaded via font face * rules. If disabled, the font will be rendered using a built in font diff --git a/test/driver.js b/test/driver.js index 91cd268a6..3a28cc55d 100644 --- a/test/driver.js +++ b/test/driver.js @@ -18,6 +18,8 @@ const WAITING_TIME = 100; // ms const PDF_TO_CSS_UNITS = 96.0 / 72.0; +const CMAP_URL = '../external/bcmaps/'; +const CMAP_PACKED = true; const IMAGE_RESOURCES_PATH = '/web/images/'; const WORKER_SRC = '../build/generic/build/pdf.worker.js'; @@ -271,8 +273,6 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars // Configure the global worker options. PDFJS.GlobalWorkerOptions.workerSrc = WORKER_SRC; - PDFJS.cMapPacked = true; - PDFJS.cMapUrl = '../external/bcmaps/'; PDFJS.pdfBug = true; // Set the passed options @@ -366,6 +366,8 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars url: absoluteUrl, password: task.password, nativeImageDecoderSupport: task.nativeImageDecoderSupport, + cMapUrl: CMAP_URL, + cMapPacked: CMAP_PACKED, }).then((doc) => { task.pdfDoc = doc; this._nextPage(task, failure); diff --git a/test/unit/cmap_spec.js b/test/unit/cmap_spec.js index 8c4c3f5b0..981f695a1 100644 --- a/test/unit/cmap_spec.js +++ b/test/unit/cmap_spec.js @@ -281,8 +281,9 @@ describe('cmap', function() { done.fail('No CMap should be loaded'); }, function (reason) { expect(reason instanceof Error).toEqual(true); - expect(reason.message).toEqual('CMap baseUrl must be specified, ' + - 'see "PDFJS.cMapUrl" (and also "PDFJS.cMapPacked").'); + expect(reason.message).toEqual( + 'The CMap "baseUrl" parameter must be specified, ensure that ' + + 'the "cMapUrl" and "cMapPacked" API parameters are provided.'); done(); }); }); diff --git a/test/unit/test_utils.js b/test/unit/test_utils.js index e57247c3c..c1e0337d4 100644 --- a/test/unit/test_utils.js +++ b/test/unit/test_utils.js @@ -51,8 +51,9 @@ class NodeCMapReaderFactory { fetch({ name, }) { if (!this.baseUrl) { - return Promise.reject(new Error('CMap baseUrl must be specified, ' + - 'see "PDFJS.cMapUrl" (and also "PDFJS.cMapPacked").')); + return Promise.reject(new Error( + 'The CMap "baseUrl" parameter must be specified, ensure that ' + + 'the "cMapUrl" and "cMapPacked" API parameters are provided.')); } if (!name) { return Promise.reject(new Error('CMap name must be specified.')); diff --git a/web/app.js b/web/app.js index 05a3f5736..cfcbdbaa7 100644 --- a/web/app.js +++ b/web/app.js @@ -50,15 +50,6 @@ import { ViewHistory } from './view_history'; const DEFAULT_SCALE_DELTA = 1.1; const DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000; -function configure(PDFJS) { - if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) { - PDFJS.cMapUrl = '../external/bcmaps/'; - } else { - PDFJS.cMapUrl = '../web/cmaps/'; - } - PDFJS.cMapPacked = true; -} - const DefaultExternalServices = { updateFindControlState(data) {}, initPassiveLoading(callbacks) {}, @@ -142,8 +133,6 @@ let PDFViewerApplication = { // Called once when the document is loaded. initialize(appConfig) { this.preferences = this.externalServices.createPreferences(); - - configure(PDFJS); this.appConfig = appConfig; return this._readPreferences().then(() => { @@ -298,8 +287,8 @@ let PDFViewerApplication = { } if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) && hashParams['disablebcmaps'] === 'true') { - PDFJS.cMapUrl = '../external/cmaps/'; - PDFJS.cMapPacked = false; + AppOptions.set('cMapUrl', '../external/cmaps/'); + AppOptions.set('cMapPacked', false); } if ('textlayer' in hashParams) { switch (hashParams['textlayer']) { diff --git a/web/app_options.js b/web/app_options.js index 638410303..f0c532bbb 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -128,6 +128,17 @@ const defaultOptions = { kind: OptionKind.VIEWER, }, + cMapPacked: { + /** @type {boolean} */ + value: true, + kind: OptionKind.API, + }, + cMapUrl: { + /** @type {string} */ + value: (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION') ? + '../external/bcmaps/' : '../web/cmaps/'), + kind: OptionKind.API, + }, maxImageSize: { /** @type {number} */ value: -1, From f3900c4e57accc3f326dab98153d15c8f844929f Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 21:49:14 +0100 Subject: [PATCH 08/16] Move the `isEvalSupported` option from the global `PDFJS` object and into `getDocument` instead --- src/display/api.js | 11 +++++++++-- src/display/dom_utils.js | 2 -- src/display/font_loader.js | 32 +++++++++++++------------------- src/display/global.js | 8 -------- web/app_options.js | 5 +++++ 5 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 437312678..7dc3cec67 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -157,6 +157,9 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * @property {number} maxImageSize - (optional) The maximum allowed image size * in total pixels, i.e. width * height. Images above this value will not be * rendered. Use -1 for no limit, which is also the default value. + * @property {boolean} isEvalSupported - (optional) Determines if we can eval + * strings as JS. Primarily used to improve performance of font rendering, + * and when parsing PDF functions. The default value is `true`. */ /** @@ -252,6 +255,9 @@ function getDocument(src) { if (!Number.isInteger(params.maxImageSize)) { params.maxImageSize = -1; } + if (typeof params.isEvalSupported !== 'boolean') { + params.isEvalSupported = true; + } // Set the main-thread verbosity level. setVerbosityLevel(params.verbosity); @@ -344,7 +350,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { docBaseUrl: source.docBaseUrl, nativeImageDecoderSupport: source.nativeImageDecoderSupport, ignoreErrors: source.ignoreErrors, - isEvalSupported: getDefaultSetting('isEvalSupported'), + isEvalSupported: source.isEvalSupported, }).then(function (workerId) { if (worker.destroyed) { throw new Error('Worker was destroyed'); @@ -1806,6 +1812,7 @@ var WorkerTransport = (function WorkerTransportClosure() { switch (type) { case 'Font': var exportedData = data[2]; + let params = this._params; if ('error' in exportedData) { var exportedError = exportedData.error; @@ -1823,7 +1830,7 @@ var WorkerTransport = (function WorkerTransportClosure() { }; } var font = new FontFaceObject(exportedData, { - isEvalSupported: getDefaultSetting('isEvalSupported'), + isEvalSupported: params.isEvalSupported, disableFontFace: getDefaultSetting('disableFontFace'), fontRegistry, }); diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index f1146f74b..ea88ad6f7 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -346,8 +346,6 @@ function getDefaultSetting(id) { return globalSettings ? globalSettings.disableFontFace : false; case 'disableCreateObjectURL': return globalSettings ? globalSettings.disableCreateObjectURL : false; - case 'isEvalSupported': - return globalSettings ? globalSettings.isEvalSupported : true; default: throw new Error('Unknown default setting: ' + id); } diff --git a/src/display/font_loader.js b/src/display/font_loader.js index 7e8ffcdd2..904712bf6 100644 --- a/src/display/font_loader.js +++ b/src/display/font_loader.js @@ -336,13 +336,17 @@ var IsEvalSupportedCached = { }; var FontFaceObject = (function FontFaceObjectClosure() { - function FontFaceObject(translatedData, options) { + function FontFaceObject(translatedData, { isEvalSupported = true, + disableFontFace = false, + fontRegistry = null, }) { this.compiledGlyphs = Object.create(null); // importing translated data for (var i in translatedData) { this[i] = translatedData[i]; } - this.options = options; + this.isEvalSupported = isEvalSupported !== false; + this.disableFontFace = disableFontFace === true; + this.fontRegistry = fontRegistry; } FontFaceObject.prototype = { createNativeFontFace: function FontFaceObject_createNativeFontFace() { @@ -350,30 +354,20 @@ var FontFaceObject = (function FontFaceObjectClosure() { throw new Error('Not implemented: createNativeFontFace'); } - if (!this.data) { - return null; - } - - if (this.options.disableFontFace) { - this.disableFontFace = true; + if (!this.data || this.disableFontFace) { return null; } var nativeFontFace = new FontFace(this.loadedName, this.data, {}); - if (this.options.fontRegistry) { - this.options.fontRegistry.registerFont(this); + if (this.fontRegistry) { + this.fontRegistry.registerFont(this); } return nativeFontFace; }, createFontFaceRule: function FontFaceObject_createFontFaceRule() { - if (!this.data) { - return null; - } - - if (this.options.disableFontFace) { - this.disableFontFace = true; + if (!this.data || this.disableFontFace) { return null; } @@ -384,8 +378,8 @@ var FontFaceObject = (function FontFaceObjectClosure() { var url = ('url(data:' + this.mimetype + ';base64,' + btoa(data) + ');'); var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}'; - if (this.options.fontRegistry) { - this.options.fontRegistry.registerFont(this, url); + if (this.fontRegistry) { + this.fontRegistry.registerFont(this, url); } return rule; @@ -398,7 +392,7 @@ var FontFaceObject = (function FontFaceObjectClosure() { var current, i, len; // If we can, compile cmds into JS for MAXIMUM SPEED - if (this.options.isEvalSupported && IsEvalSupportedCached.value) { + if (this.isEvalSupported && IsEvalSupportedCached.value) { var args, js = ''; for (i = 0, len = cmds.length; i < len; i++) { current = cmds[i]; diff --git a/src/display/global.js b/src/display/global.js index 6fabc84df..725ace290 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -116,14 +116,6 @@ PDFJS.pdfBug = (PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug); PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ? false : PDFJS.disableCreateObjectURL); -/** - * Determines if we can eval strings as JS. Primarily used to improve - * performance for font rendering. - * @var {boolean} - */ -PDFJS.isEvalSupported = (PDFJS.isEvalSupported === undefined ? - true : PDFJS.isEvalSupported); - PDFJS.getDocument = getDocument; PDFJS.LoopbackPort = LoopbackPort; PDFJS.PDFDataRangeTransport = PDFDataRangeTransport; diff --git a/web/app_options.js b/web/app_options.js index f0c532bbb..432e0c5e8 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -139,6 +139,11 @@ const defaultOptions = { '../external/bcmaps/' : '../web/cmaps/'), kind: OptionKind.API, }, + isEvalSupported: { + /** @type {boolean} */ + value: true, + kind: OptionKind.API, + }, maxImageSize: { /** @type {number} */ value: -1, From c7c583583bcd403da978508b90e9121801309cba Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 21:57:20 +0100 Subject: [PATCH 09/16] Move the `disableFontFace` option from the global `PDFJS` object and into `getDocument` instead --- src/display/api.js | 11 +++++++++-- src/display/dom_utils.js | 2 -- src/display/global.js | 9 --------- web/app.js | 9 +++++---- web/app_options.js | 5 +++++ 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 7dc3cec67..4a32bd7c7 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -160,6 +160,10 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * @property {boolean} isEvalSupported - (optional) Determines if we can eval * strings as JS. Primarily used to improve performance of font rendering, * and when parsing PDF functions. The default value is `true`. + * @property {boolean} disableFontFace - (optional) By default fonts are + * converted to OpenType fonts and loaded via font face rules. If disabled, + * fonts will be rendered using a built-in font renderer that constructs the + * glyphs with primitive path commands. The default value is `false`. */ /** @@ -258,6 +262,9 @@ function getDocument(src) { if (typeof params.isEvalSupported !== 'boolean') { params.isEvalSupported = true; } + if (typeof params.disableFontFace !== 'boolean') { + params.disableFontFace = false; + } // Set the main-thread verbosity level. setVerbosityLevel(params.verbosity); @@ -344,7 +351,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { length: source.length, }, maxImageSize: source.maxImageSize, - disableFontFace: getDefaultSetting('disableFontFace'), + disableFontFace: source.disableFontFace, disableCreateObjectURL: getDefaultSetting('disableCreateObjectURL'), postMessageTransfers: worker.postMessageTransfers, docBaseUrl: source.docBaseUrl, @@ -1831,7 +1838,7 @@ var WorkerTransport = (function WorkerTransportClosure() { } var font = new FontFaceObject(exportedData, { isEvalSupported: params.isEvalSupported, - disableFontFace: getDefaultSetting('disableFontFace'), + disableFontFace: params.disableFontFace, fontRegistry, }); var fontReady = (fontObjs) => { diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index ea88ad6f7..a2b9b6ebd 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -342,8 +342,6 @@ function getDefaultSetting(id) { return globalSettings ? globalSettings.disableStream : false; case 'disableRange': return globalSettings ? globalSettings.disableRange : false; - case 'disableFontFace': - return globalSettings ? globalSettings.disableFontFace : false; case 'disableCreateObjectURL': return globalSettings ? globalSettings.disableCreateObjectURL : false; default: diff --git a/src/display/global.js b/src/display/global.js index 725ace290..98b8b2dcf 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -65,15 +65,6 @@ PDFJS.Util = Util; PDFJS.PageViewport = PageViewport; PDFJS.createPromiseCapability = createPromiseCapability; -/** - * By default fonts are converted to OpenType fonts and loaded via font face - * rules. If disabled, the font will be rendered using a built in font - * renderer that constructs the glyphs with primitive path commands. - * @var {boolean} - */ -PDFJS.disableFontFace = (PDFJS.disableFontFace === undefined ? - false : PDFJS.disableFontFace); - /** * Disable range request loading of PDF files. When enabled and if the server * supports partial content requests then the PDF will be fetched in chunks. diff --git a/web/app.js b/web/app.js index cfcbdbaa7..88da0aaa9 100644 --- a/web/app.js +++ b/web/app.js @@ -210,10 +210,10 @@ let PDFViewerApplication = { PDFJS.disableAutoFetch = value; }), preferences.get('disableFontFace').then(function resolved(value) { - if (PDFJS.disableFontFace === true) { + if (AppOptions.get('disableFontFace') === true) { return; } - PDFJS.disableFontFace = value; + AppOptions.set('disableFontFace', value); }), preferences.get('useOnlyCssZoom').then(function resolved(value) { AppOptions.set('useOnlyCssZoom', value); @@ -269,7 +269,8 @@ let PDFViewerApplication = { PDFJS.disableAutoFetch = (hashParams['disableautofetch'] === 'true'); } if ('disablefontface' in hashParams) { - PDFJS.disableFontFace = (hashParams['disablefontface'] === 'true'); + AppOptions.set('disableFontFace', + hashParams['disablefontface'] === 'true'); } if ('disablehistory' in hashParams) { AppOptions.set('disableHistory', @@ -1604,7 +1605,7 @@ function webViewerInitialized() { if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL') && !PDFViewerApplication.supportsDocumentFonts) { - PDFJS.disableFontFace = true; + AppOptions.set('disableFontFace', true); PDFViewerApplication.l10n.get('web_fonts_disabled', null, 'Web fonts are disabled: unable to use embedded PDF fonts.'). then((msg) => { diff --git a/web/app_options.js b/web/app_options.js index 432e0c5e8..2e56a8b98 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -139,6 +139,11 @@ const defaultOptions = { '../external/bcmaps/' : '../web/cmaps/'), kind: OptionKind.API, }, + disableFontFace: { + /** @type {boolean} */ + value: false, + kind: OptionKind.API, + }, isEvalSupported: { /** @type {boolean} */ value: true, From 69d719103487339303e5883bff55aaffb9ce7da0 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 22:08:45 +0100 Subject: [PATCH 10/16] Move the `disableAutoFetch` option from the global `PDFJS` object and into `getDocument` instead One additional complication with removing this option from the global `PDFJS` object, is that the viewer currently needs to check `disableAutoFetch` in a couple of places. To address this I'm thus proposing adding a getter in `PDFDocumentProxy`, to allow checking the *actually* used values for a particular `getDocument` invocation. --- src/display/api.js | 24 ++++++++++++++++++++++-- src/display/dom_utils.js | 2 -- src/display/global.js | 12 ------------ test/driver.js | 2 +- web/app.js | 11 ++++++++--- web/app_options.js | 5 +++++ web/base_viewer.js | 4 ++-- 7 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 4a32bd7c7..d184717d3 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -18,7 +18,7 @@ import { assert, createPromiseCapability, getVerbosityLevel, info, InvalidPDFException, isArrayBuffer, isNum, isSameOrigin, MessageHandler, MissingPDFException, NativeImageDecoding, PageViewport, PasswordException, setVerbosityLevel, - stringToBytes, UnexpectedResponseException, UnknownErrorException, + shadow, stringToBytes, UnexpectedResponseException, UnknownErrorException, unreachable, Util, warn } from '../shared/util'; import { @@ -164,6 +164,12 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * converted to OpenType fonts and loaded via font face rules. If disabled, * fonts will be rendered using a built-in font renderer that constructs the * glyphs with primitive path commands. The default value is `false`. + * @property {boolean} disableAutoFetch - (optional) Disable pre-fetching of PDF + * file data. When range requests are enabled PDF.js will automatically keep + * fetching more data even if it isn't needed to display the current page. + * The default value is `false`. + * NOTE: It is also necessary to disable streaming, see above, + * in order for disabling of pre-fetching to work correctly. */ /** @@ -266,6 +272,10 @@ function getDocument(src) { params.disableFontFace = false; } + if (typeof params.disableAutoFetch !== 'boolean') { + params.disableAutoFetch = false; + } + // Set the main-thread verbosity level. setVerbosityLevel(params.verbosity); @@ -333,7 +343,6 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('BUNDLE_VERSION') : null; source.disableRange = getDefaultSetting('disableRange'); - source.disableAutoFetch = getDefaultSetting('disableAutoFetch'); source.disableStream = getDefaultSetting('disableStream'); if (pdfDataRangeTransport) { source.length = pdfDataRangeTransport.length; @@ -683,6 +692,10 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { destroy: function PDFDocumentProxy_destroy() { return this.loadingTask.destroy(); }, + + get loadingParams() { + return this.transport.loadingParams; + }, }; return PDFDocumentProxy; })(); @@ -2116,6 +2129,13 @@ var WorkerTransport = (function WorkerTransportClosure() { this.fontLoader.clear(); }); }, + + get loadingParams() { + let params = this._params; + return shadow(this, 'loadingParams', { + disableAutoFetch: params.disableAutoFetch, + }); + }, }; return WorkerTransport; diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index a2b9b6ebd..fa5b96be7 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -336,8 +336,6 @@ function getDefaultSetting(id) { switch (id) { case 'pdfBug': return globalSettings ? globalSettings.pdfBug : false; - case 'disableAutoFetch': - return globalSettings ? globalSettings.disableAutoFetch : false; case 'disableStream': return globalSettings ? globalSettings.disableStream : false; case 'disableRange': diff --git a/src/display/global.js b/src/display/global.js index 98b8b2dcf..d9cd5ae90 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -82,18 +82,6 @@ PDFJS.disableRange = (PDFJS.disableRange === undefined ? PDFJS.disableStream = (PDFJS.disableStream === undefined ? false : PDFJS.disableStream); -/** - * Disable pre-fetching of PDF file data. When range requests are enabled - * PDF.js will automatically keep fetching more data even if it isn't needed - * to display the current page. This default behavior can be disabled. - * - * NOTE: It is also necessary to disable streaming, see above, - * in order for disabling of pre-fetching to work correctly. - * @var {boolean} - */ -PDFJS.disableAutoFetch = (PDFJS.disableAutoFetch === undefined ? - false : PDFJS.disableAutoFetch); - /** * Enables special hooks for debugging PDF.js. * @var {boolean} diff --git a/test/driver.js b/test/driver.js index 3a28cc55d..bcbda8308 100644 --- a/test/driver.js +++ b/test/driver.js @@ -360,7 +360,6 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars let absoluteUrl = new URL(task.file, window.location).href; PDFJS.disableRange = task.disableRange; - PDFJS.disableAutoFetch = !task.enableAutoFetch; try { PDFJS.getDocument({ url: absoluteUrl, @@ -368,6 +367,7 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars nativeImageDecoderSupport: task.nativeImageDecoderSupport, cMapUrl: CMAP_URL, cMapPacked: CMAP_PACKED, + disableAutoFetch: !task.enableAutoFetch, }).then((doc) => { task.pdfDoc = doc; this._nextPage(task, failure); diff --git a/web/app.js b/web/app.js index 88da0aaa9..abeb7cc95 100644 --- a/web/app.js +++ b/web/app.js @@ -207,7 +207,7 @@ let PDFViewerApplication = { PDFJS.disableStream = value; }), preferences.get('disableAutoFetch').then(function resolved(value) { - PDFJS.disableAutoFetch = value; + AppOptions.set('disableAutoFetch', value); }), preferences.get('disableFontFace').then(function resolved(value) { if (AppOptions.get('disableFontFace') === true) { @@ -266,7 +266,8 @@ let PDFViewerApplication = { PDFJS.disableStream = (hashParams['disablestream'] === 'true'); } if ('disableautofetch' in hashParams) { - PDFJS.disableAutoFetch = (hashParams['disableautofetch'] === 'true'); + AppOptions.set('disableAutoFetch', + hashParams['disableautofetch'] === 'true'); } if ('disablefontface' in hashParams) { AppOptions.set('disableFontFace', @@ -933,7 +934,11 @@ let PDFViewerApplication = { // the loading bar will not be completely filled, nor will it be hidden. // To prevent displaying a partially filled loading bar permanently, we // hide it when no data has been loaded during a certain amount of time. - if (PDFJS.disableAutoFetch && percent) { + const disableAutoFetch = this.pdfDocument ? + this.pdfDocument.loadingParams['disableAutoFetch'] : + AppOptions.get('disableAutoFetch'); + + if (disableAutoFetch && percent) { if (this.disableAutoFetchLoadingBarTimeout) { clearTimeout(this.disableAutoFetchLoadingBarTimeout); this.disableAutoFetchLoadingBarTimeout = null; diff --git a/web/app_options.js b/web/app_options.js index 2e56a8b98..e0f90cdbe 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -139,6 +139,11 @@ const defaultOptions = { '../external/bcmaps/' : '../web/cmaps/'), kind: OptionKind.API, }, + disableAutoFetch: { + /** @type {boolean} */ + value: false, + kind: OptionKind.API, + }, disableFontFace: { /** @type {boolean} */ value: false, diff --git a/web/base_viewer.js b/web/base_viewer.js index 2b966379a..bc7955750 100644 --- a/web/base_viewer.js +++ b/web/base_viewer.js @@ -13,7 +13,6 @@ * limitations under the License. */ -import { createPromiseCapability, PDFJS } from 'pdfjs-lib'; import { CSS_UNITS, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, isValidRotation, MAX_AUTO_SCALE, NullL10n, PresentationModeState, RendererType, @@ -21,6 +20,7 @@ import { } from './ui_utils'; import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue'; import { AnnotationLayerBuilder } from './annotation_layer_builder'; +import { createPromiseCapability } from 'pdfjs-lib'; import { getGlobalEventBus } from './dom_events'; import { PDFPageView } from './pdf_page_view'; import { SimpleLinkService } from './pdf_link_service'; @@ -408,7 +408,7 @@ class BaseViewer { // starts to create the correct size canvas. Wait until one page is // rendered so we don't tie up too many resources early on. onePageRenderedCapability.promise.then(() => { - if (PDFJS.disableAutoFetch) { + if (pdfDocument.loadingParams['disableAutoFetch']) { // XXX: Printing is semi-broken with auto fetch disabled. pagesCapability.resolve(); return; From b69abf11115ffa67798d4cd6805465367f5bd1fa Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 22:22:10 +0100 Subject: [PATCH 11/16] Move the `disableRange` option from the global `PDFJS` object and into `getDocument` instead --- src/display/api.js | 10 +++++++++- src/display/dom_utils.js | 2 -- src/display/global.js | 9 --------- test/driver.js | 2 +- web/app.js | 6 +++--- web/app_options.js | 6 ++++++ 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index d184717d3..bd36c6efe 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -26,6 +26,7 @@ import { RenderingCancelledException, StatTimer } from './dom_utils'; import { FontFaceObject, FontLoader } from './font_loader'; +import { apiCompatibilityParams } from './api_compatibility'; import { CanvasGraphics } from './canvas'; import globalScope from '../shared/global_scope'; import { GlobalWorkerOptions } from './worker_options'; @@ -164,6 +165,10 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * converted to OpenType fonts and loaded via font face rules. If disabled, * fonts will be rendered using a built-in font renderer that constructs the * glyphs with primitive path commands. The default value is `false`. + * @property {boolean} disableRange - (optional) Disable range request loading + * of PDF files. When enabled, and if the server supports partial content + * requests, then the PDF will be fetched in chunks. + * The default value is `false`. * @property {boolean} disableAutoFetch - (optional) Disable pre-fetching of PDF * file data. When range requests are enabled PDF.js will automatically keep * fetching more data even if it isn't needed to display the current page. @@ -272,6 +277,9 @@ function getDocument(src) { params.disableFontFace = false; } + if (typeof params.disableRange !== 'boolean') { + params.disableRange = apiCompatibilityParams.disableRange || false; + } if (typeof params.disableAutoFetch !== 'boolean') { params.disableAutoFetch = false; } @@ -342,7 +350,6 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { let apiVersion = typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('BUNDLE_VERSION') : null; - source.disableRange = getDefaultSetting('disableRange'); source.disableStream = getDefaultSetting('disableStream'); if (pdfDataRangeTransport) { source.length = pdfDataRangeTransport.length; @@ -2133,6 +2140,7 @@ var WorkerTransport = (function WorkerTransportClosure() { get loadingParams() { let params = this._params; return shadow(this, 'loadingParams', { + disableRange: params.disableRange, disableAutoFetch: params.disableAutoFetch, }); }, diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index fa5b96be7..b364e7291 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -338,8 +338,6 @@ function getDefaultSetting(id) { return globalSettings ? globalSettings.pdfBug : false; case 'disableStream': return globalSettings ? globalSettings.disableStream : false; - case 'disableRange': - return globalSettings ? globalSettings.disableRange : false; case 'disableCreateObjectURL': return globalSettings ? globalSettings.disableCreateObjectURL : false; default: diff --git a/src/display/global.js b/src/display/global.js index d9cd5ae90..296955bdf 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -65,15 +65,6 @@ PDFJS.Util = Util; PDFJS.PageViewport = PageViewport; PDFJS.createPromiseCapability = createPromiseCapability; -/** - * Disable range request loading of PDF files. When enabled and if the server - * supports partial content requests then the PDF will be fetched in chunks. - * Enabled (false) by default. - * @var {boolean} - */ -PDFJS.disableRange = (PDFJS.disableRange === undefined ? - false : PDFJS.disableRange); - /** * Disable streaming of PDF file data. By default PDF.js attempts to load PDF * in chunks. This default behavior can be disabled. diff --git a/test/driver.js b/test/driver.js index bcbda8308..39bec1927 100644 --- a/test/driver.js +++ b/test/driver.js @@ -359,7 +359,6 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars this._log('Loading file "' + task.file + '"\n'); let absoluteUrl = new URL(task.file, window.location).href; - PDFJS.disableRange = task.disableRange; try { PDFJS.getDocument({ url: absoluteUrl, @@ -367,6 +366,7 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars nativeImageDecoderSupport: task.nativeImageDecoderSupport, cMapUrl: CMAP_URL, cMapPacked: CMAP_PACKED, + disableRange: task.disableRange, disableAutoFetch: !task.enableAutoFetch, }).then((doc) => { task.pdfDoc = doc; diff --git a/web/app.js b/web/app.js index abeb7cc95..e164e9518 100644 --- a/web/app.js +++ b/web/app.js @@ -195,10 +195,10 @@ let PDFViewerApplication = { AppOptions.set('textLayerMode', value); }), preferences.get('disableRange').then(function resolved(value) { - if (PDFJS.disableRange === true) { + if (AppOptions.get('disableRange') === true) { return; } - PDFJS.disableRange = value; + AppOptions.set('disableRange', value); }), preferences.get('disableStream').then(function resolved(value) { if (PDFJS.disableStream === true) { @@ -260,7 +260,7 @@ let PDFViewerApplication = { waitOn.push(loadFakeWorker()); } if ('disablerange' in hashParams) { - PDFJS.disableRange = (hashParams['disablerange'] === 'true'); + AppOptions.set('disableRange', hashParams['disablerange'] === 'true'); } if ('disablestream' in hashParams) { PDFJS.disableStream = (hashParams['disablestream'] === 'true'); diff --git a/web/app_options.js b/web/app_options.js index e0f90cdbe..b00a8b114 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -13,6 +13,7 @@ * limitations under the License. */ +import { apiCompatibilityParams } from 'pdfjs-lib'; import { viewerCompatibilityParams } from './viewer_compatibility'; const OptionKind = { @@ -149,6 +150,11 @@ const defaultOptions = { value: false, kind: OptionKind.API, }, + disableRange: { + /** @type {boolean} */ + value: apiCompatibilityParams.disableRange || false, + kind: OptionKind.API, + }, isEvalSupported: { /** @type {boolean} */ value: true, From 05c05bdef5ec5125ba6d5810140e2d50715e1958 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 22:28:08 +0100 Subject: [PATCH 12/16] Move the `disableStream` option from the global `PDFJS` object and into `getDocument` instead --- src/display/api.js | 8 +++++++- src/display/dom_utils.js | 2 -- src/display/global.js | 8 -------- web/app.js | 6 +++--- web/app_options.js | 5 +++++ 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index bd36c6efe..cc15f1444 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -169,6 +169,9 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * of PDF files. When enabled, and if the server supports partial content * requests, then the PDF will be fetched in chunks. * The default value is `false`. + * @property {boolean} disableStream - (optional) Disable streaming of PDF file + * data. By default PDF.js attempts to load PDFs in chunks. + * The default value is `false`. * @property {boolean} disableAutoFetch - (optional) Disable pre-fetching of PDF * file data. When range requests are enabled PDF.js will automatically keep * fetching more data even if it isn't needed to display the current page. @@ -280,6 +283,9 @@ function getDocument(src) { if (typeof params.disableRange !== 'boolean') { params.disableRange = apiCompatibilityParams.disableRange || false; } + if (typeof params.disableStream !== 'boolean') { + params.disableStream = apiCompatibilityParams.disableStream || false; + } if (typeof params.disableAutoFetch !== 'boolean') { params.disableAutoFetch = false; } @@ -350,7 +356,6 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { let apiVersion = typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('BUNDLE_VERSION') : null; - source.disableStream = getDefaultSetting('disableStream'); if (pdfDataRangeTransport) { source.length = pdfDataRangeTransport.length; source.initialData = pdfDataRangeTransport.initialData; @@ -2141,6 +2146,7 @@ var WorkerTransport = (function WorkerTransportClosure() { let params = this._params; return shadow(this, 'loadingParams', { disableRange: params.disableRange, + disableStream: params.disableStream, disableAutoFetch: params.disableAutoFetch, }); }, diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index b364e7291..e5d7e27d8 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -336,8 +336,6 @@ function getDefaultSetting(id) { switch (id) { case 'pdfBug': return globalSettings ? globalSettings.pdfBug : false; - case 'disableStream': - return globalSettings ? globalSettings.disableStream : false; case 'disableCreateObjectURL': return globalSettings ? globalSettings.disableCreateObjectURL : false; default: diff --git a/src/display/global.js b/src/display/global.js index 296955bdf..5c406407c 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -65,14 +65,6 @@ PDFJS.Util = Util; PDFJS.PageViewport = PageViewport; PDFJS.createPromiseCapability = createPromiseCapability; -/** - * Disable streaming of PDF file data. By default PDF.js attempts to load PDF - * in chunks. This default behavior can be disabled. - * @var {boolean} - */ -PDFJS.disableStream = (PDFJS.disableStream === undefined ? - false : PDFJS.disableStream); - /** * Enables special hooks for debugging PDF.js. * @var {boolean} diff --git a/web/app.js b/web/app.js index e164e9518..7cb21656a 100644 --- a/web/app.js +++ b/web/app.js @@ -201,10 +201,10 @@ let PDFViewerApplication = { AppOptions.set('disableRange', value); }), preferences.get('disableStream').then(function resolved(value) { - if (PDFJS.disableStream === true) { + if (AppOptions.get('disableStream') === true) { return; } - PDFJS.disableStream = value; + AppOptions.set('disableStream', value); }), preferences.get('disableAutoFetch').then(function resolved(value) { AppOptions.set('disableAutoFetch', value); @@ -263,7 +263,7 @@ let PDFViewerApplication = { AppOptions.set('disableRange', hashParams['disablerange'] === 'true'); } if ('disablestream' in hashParams) { - PDFJS.disableStream = (hashParams['disablestream'] === 'true'); + AppOptions.set('disableStream', hashParams['disablestream'] === 'true'); } if ('disableautofetch' in hashParams) { AppOptions.set('disableAutoFetch', diff --git a/web/app_options.js b/web/app_options.js index b00a8b114..49a63ac3d 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -155,6 +155,11 @@ const defaultOptions = { value: apiCompatibilityParams.disableRange || false, kind: OptionKind.API, }, + disableStream: { + /** @type {boolean} */ + value: apiCompatibilityParams.disableStream || false, + kind: OptionKind.API, + }, isEvalSupported: { /** @type {boolean} */ value: true, From 1d03ad006021cf9c039b22eb28249de0d60bb88a Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 22:51:03 +0100 Subject: [PATCH 13/16] Move the `disableCreateObjectURL` option from the global `PDFJS` object and into `getDocument` instead --- src/display/api.js | 10 +++++++++- src/display/dom_utils.js | 2 -- src/display/global.js | 16 +++------------- web/app.js | 8 +++++--- web/app_options.js | 5 +++++ web/chromecom.js | 4 ++-- web/download_manager.js | 15 ++++++++++++--- web/firefoxcom.js | 10 +++++++--- web/genericcom.js | 4 ++-- web/pdf_attachment_viewer.js | 11 ++++++----- web/pdf_print_service.js | 5 +++-- 11 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index cc15f1444..1b86bc7a3 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -178,6 +178,9 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * The default value is `false`. * NOTE: It is also necessary to disable streaming, see above, * in order for disabling of pre-fetching to work correctly. + * @property {boolean} disableCreateObjectURL - (optional) Disable the use of + * `URL.createObjectURL`, for compatibility with older browsers. + * The default value is `false`. */ /** @@ -289,6 +292,10 @@ function getDocument(src) { if (typeof params.disableAutoFetch !== 'boolean') { params.disableAutoFetch = false; } + if (typeof params.disableCreateObjectURL !== 'boolean') { + params.disableCreateObjectURL = + apiCompatibilityParams.disableCreateObjectURL || false; + } // Set the main-thread verbosity level. setVerbosityLevel(params.verbosity); @@ -373,7 +380,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { }, maxImageSize: source.maxImageSize, disableFontFace: source.disableFontFace, - disableCreateObjectURL: getDefaultSetting('disableCreateObjectURL'), + disableCreateObjectURL: source.disableCreateObjectURL, postMessageTransfers: worker.postMessageTransfers, docBaseUrl: source.docBaseUrl, nativeImageDecoderSupport: source.nativeImageDecoderSupport, @@ -2148,6 +2155,7 @@ var WorkerTransport = (function WorkerTransportClosure() { disableRange: params.disableRange, disableStream: params.disableStream, disableAutoFetch: params.disableAutoFetch, + disableCreateObjectURL: params.disableCreateObjectURL, }); }, }; diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index e5d7e27d8..3fa97f143 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -336,8 +336,6 @@ function getDefaultSetting(id) { switch (id) { case 'pdfBug': return globalSettings ? globalSettings.pdfBug : false; - case 'disableCreateObjectURL': - return globalSettings ? globalSettings.disableCreateObjectURL : false; default: throw new Error('Unknown default setting: ' + id); } diff --git a/src/display/global.js b/src/display/global.js index 5c406407c..92f69c1b1 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -14,9 +14,9 @@ */ import { - createBlob, createObjectURL, createPromiseCapability, InvalidPDFException, - isLittleEndian, MissingPDFException, OPS, PageViewport, PasswordException, - PasswordResponses, removeNullCharacters, shadow, UnexpectedResponseException, + createBlob, createPromiseCapability, InvalidPDFException, isLittleEndian, + MissingPDFException, OPS, PageViewport, PasswordException, PasswordResponses, + removeNullCharacters, shadow, UnexpectedResponseException, UnknownErrorException, UNSUPPORTED_FEATURES, Util } from '../shared/util'; import { @@ -45,9 +45,6 @@ PDFJS.OPS = OPS; PDFJS.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; PDFJS.shadow = shadow; PDFJS.createBlob = createBlob; -PDFJS.createObjectURL = function PDFJS_createObjectURL(data, contentType) { - return createObjectURL(data, contentType, PDFJS.disableCreateObjectURL); -}; Object.defineProperty(PDFJS, 'isLittleEndian', { configurable: true, get: function PDFJS_isLittleEndian() { @@ -71,13 +68,6 @@ PDFJS.createPromiseCapability = createPromiseCapability; */ PDFJS.pdfBug = (PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug); -/** - * Disables URL.createObjectURL usage. - * @var {boolean} - */ -PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ? - false : PDFJS.disableCreateObjectURL); - PDFJS.getDocument = getDocument; PDFJS.LoopbackPort = LoopbackPort; PDFJS.PDFDataRangeTransport = PDFDataRangeTransport; diff --git a/web/app.js b/web/app.js index 7cb21656a..912287cd7 100644 --- a/web/app.js +++ b/web/app.js @@ -55,7 +55,7 @@ const DefaultExternalServices = { initPassiveLoading(callbacks) {}, fallback(data, callback) {}, reportTelemetry(data) {}, - createDownloadManager() { + createDownloadManager(options) { throw new Error('Not implemented: createDownloadManager'); }, createPreferences() { @@ -357,7 +357,9 @@ let PDFViewerApplication = { }); this.pdfLinkService = pdfLinkService; - let downloadManager = this.externalServices.createDownloadManager(); + let downloadManager = this.externalServices.createDownloadManager({ + disableCreateObjectURL: AppOptions.get('disableCreateObjectURL'), + }); this.downloadManager = downloadManager; let container = appConfig.mainContainer; @@ -1873,7 +1875,7 @@ if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) { webViewerFileInputChange = function webViewerFileInputChange(evt) { let file = evt.fileInput.files[0]; - if (!PDFJS.disableCreateObjectURL && URL.createObjectURL) { + if (URL.createObjectURL && !AppOptions.get('disableCreateObjectURL')) { PDFViewerApplication.open(URL.createObjectURL(file)); } else { // Read the local file into a Uint8Array. diff --git a/web/app_options.js b/web/app_options.js index 49a63ac3d..70e11a850 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -145,6 +145,11 @@ const defaultOptions = { value: false, kind: OptionKind.API, }, + disableCreateObjectURL: { + /** @type {boolean} */ + value: apiCompatibilityParams.disableCreateObjectURL || false, + kind: OptionKind.API, + }, disableFontFace: { /** @type {boolean} */ value: false, diff --git a/web/chromecom.js b/web/chromecom.js index a4605b353..20429d8c1 100644 --- a/web/chromecom.js +++ b/web/chromecom.js @@ -363,8 +363,8 @@ ChromeExternalServices.initPassiveLoading = function(callbacks) { callbacks.onOpenWithURL(url, length, originalURL); }); }; -ChromeExternalServices.createDownloadManager = function() { - return new DownloadManager(); +ChromeExternalServices.createDownloadManager = function(options) { + return new DownloadManager(options); }; ChromeExternalServices.createPreferences = function() { return new ChromePreferences(); diff --git a/web/download_manager.js b/web/download_manager.js index 6db6f975c..f0809ae30 100644 --- a/web/download_manager.js +++ b/web/download_manager.js @@ -13,13 +13,18 @@ * limitations under the License. */ -import { createObjectURL, createValidAbsoluteUrl, PDFJS } from 'pdfjs-lib'; +import { + apiCompatibilityParams, createObjectURL, createValidAbsoluteUrl +} from 'pdfjs-lib'; if (typeof PDFJSDev !== 'undefined' && !PDFJSDev.test('CHROME || GENERIC')) { throw new Error('Module "pdfjs-web/download_manager" shall not be used ' + 'outside CHROME and GENERIC builds.'); } +const DISABLE_CREATE_OBJECT_URL = + apiCompatibilityParams.disableCreateObjectURL || false; + function download(blobUrl, filename) { let a = document.createElement('a'); if (!a.click) { @@ -40,6 +45,10 @@ function download(blobUrl, filename) { } class DownloadManager { + constructor({ disableCreateObjectURL = DISABLE_CREATE_OBJECT_URL, }) { + this.disableCreateObjectURL = disableCreateObjectURL; + } + downloadUrl(url, filename) { if (!createValidAbsoluteUrl(url, 'http://example.com')) { return; // restricted/invalid URL @@ -53,7 +62,7 @@ class DownloadManager { filename); } let blobUrl = createObjectURL(data, contentType, - PDFJS.disableCreateObjectURL); + this.disableCreateObjectURL); download(blobUrl, filename); } @@ -66,7 +75,7 @@ class DownloadManager { return; } - if (PDFJS.disableCreateObjectURL) { + if (this.disableCreateObjectURL) { // URL.createObjectURL is not supported this.downloadUrl(url, filename); return; diff --git a/web/firefoxcom.js b/web/firefoxcom.js index c5cb40640..5d7bc5997 100644 --- a/web/firefoxcom.js +++ b/web/firefoxcom.js @@ -84,6 +84,10 @@ let FirefoxCom = (function FirefoxComClosure() { })(); class DownloadManager { + constructor(options) { + this.disableCreateObjectURL = false; + } + downloadUrl(url, filename) { FirefoxCom.request('download', { originalUrl: url, @@ -92,7 +96,7 @@ class DownloadManager { } downloadData(data, filename, contentType) { - let blobUrl = createObjectURL(data, contentType, false); + let blobUrl = createObjectURL(data, contentType); FirefoxCom.request('download', { blobUrl, @@ -256,8 +260,8 @@ PDFViewerApplication.externalServices = { FirefoxCom.request('reportTelemetry', JSON.stringify(data)); }, - createDownloadManager() { - return new DownloadManager(); + createDownloadManager(options) { + return new DownloadManager(options); }, createPreferences() { diff --git a/web/genericcom.js b/web/genericcom.js index 5a82df6a5..89ffd90e3 100644 --- a/web/genericcom.js +++ b/web/genericcom.js @@ -42,8 +42,8 @@ class GenericPreferences extends BasePreferences { } let GenericExternalServices = Object.create(DefaultExternalServices); -GenericExternalServices.createDownloadManager = function() { - return new DownloadManager(); +GenericExternalServices.createDownloadManager = function(options) { + return new DownloadManager(options); }; GenericExternalServices.createPreferences = function() { return new GenericPreferences(); diff --git a/web/pdf_attachment_viewer.js b/web/pdf_attachment_viewer.js index 27d1b4eab..931b77f37 100644 --- a/web/pdf_attachment_viewer.js +++ b/web/pdf_attachment_viewer.js @@ -14,7 +14,7 @@ */ import { - createObjectURL, createPromiseCapability, getFilenameFromUrl, PDFJS, + createObjectURL, createPromiseCapability, getFilenameFromUrl, removeNullCharacters } from 'pdfjs-lib'; @@ -74,9 +74,9 @@ class PDFAttachmentViewer { * @private */ _bindPdfLink(button, content, filename) { - if (PDFJS.disableCreateObjectURL) { - throw new Error('bindPdfLink: ' + - 'Unsupported "PDFJS.disableCreateObjectURL" value.'); + if (this.downloadManager.disableCreateObjectURL) { + throw new Error( + 'bindPdfLink: Unsupported "disableCreateObjectURL" value.'); } let blobUrl; button.onclick = function() { @@ -141,7 +141,8 @@ class PDFAttachmentViewer { div.className = 'attachmentsItem'; let button = document.createElement('button'); button.textContent = filename; - if (/\.pdf$/i.test(filename) && !PDFJS.disableCreateObjectURL) { + if (/\.pdf$/i.test(filename) && + !this.downloadManager.disableCreateObjectURL) { this._bindPdfLink(button, item.content, filename); } else { this._bindLink(button, item.content, filename); diff --git a/web/pdf_print_service.js b/web/pdf_print_service.js index 3fc172cd6..f6470745d 100644 --- a/web/pdf_print_service.js +++ b/web/pdf_print_service.js @@ -15,7 +15,6 @@ import { CSS_UNITS, NullL10n } from './ui_utils'; import { PDFPrintServiceFactory, PDFViewerApplication } from './app'; -import { PDFJS } from 'pdfjs-lib'; let activeService = null; let overlayManager = null; @@ -62,6 +61,8 @@ function PDFPrintService(pdfDocument, pagesOverview, printContainer, l10n) { this.pagesOverview = pagesOverview; this.printContainer = printContainer; this.l10n = l10n || NullL10n; + this.disableCreateObjectURL = + pdfDocument.loadingParams['disableCreateObjectURL']; this.currentPage = -1; // The temporary canvas where renderPage paints one page at a time. this.scratchCanvas = document.createElement('canvas'); @@ -153,7 +154,7 @@ PDFPrintService.prototype = { img.style.height = printItem.height; let scratchCanvas = this.scratchCanvas; - if (('toBlob' in scratchCanvas) && !PDFJS.disableCreateObjectURL) { + if (('toBlob' in scratchCanvas) && !this.disableCreateObjectURL) { scratchCanvas.toBlob(function(blob) { img.src = URL.createObjectURL(blob); }); From 212553840f8b761461e11214239bf57fb1173c1d Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 23:13:49 +0100 Subject: [PATCH 14/16] Move the `pdfBug` option from the global `PDFJS` object and into `getDocument` instead Also removes the now unused `getDefaultSetting` helper function. --- src/display/api.js | 27 +++++++++++++++++---------- src/display/dom_utils.js | 14 -------------- src/display/global.js | 8 -------- src/display/text_layer.js | 12 ++++++------ test/driver.js | 3 +-- web/app.js | 8 ++++---- web/app_options.js | 5 +++++ 7 files changed, 33 insertions(+), 44 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 1b86bc7a3..781bc7021 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -22,7 +22,7 @@ import { unreachable, Util, warn } from '../shared/util'; import { - DOMCanvasFactory, DOMCMapReaderFactory, DummyStatTimer, getDefaultSetting, + DOMCanvasFactory, DOMCMapReaderFactory, DummyStatTimer, RenderingCancelledException, StatTimer } from './dom_utils'; import { FontFaceObject, FontLoader } from './font_loader'; @@ -181,6 +181,8 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { * @property {boolean} disableCreateObjectURL - (optional) Disable the use of * `URL.createObjectURL`, for compatibility with older browsers. * The default value is `false`. + * @property {boolean} pdfBug - (optional) Enables special hooks for debugging + * PDF.js (see `web/debugger.js`). The default value is `false`. */ /** @@ -267,6 +269,7 @@ function getDocument(src) { params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE; params.ignoreErrors = params.stopAtErrors !== true; + params.pdfBug = params.pdfBug === true; const NativeImageDecoderValues = Object.values(NativeImageDecoding); if (params.nativeImageDecoderSupport === undefined || @@ -812,12 +815,12 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { * @alias PDFPageProxy */ var PDFPageProxy = (function PDFPageProxyClosure() { - function PDFPageProxy(pageIndex, pageInfo, transport) { + function PDFPageProxy(pageIndex, pageInfo, transport, pdfBug = false) { this.pageIndex = pageIndex; this.pageInfo = pageInfo; this.transport = transport; - this._stats = (getDefaultSetting('pdfBug') ? - new StatTimer() : DummyStatTimer); + this._stats = (pdfBug ? new StatTimer() : DummyStatTimer); + this._pdfBug = pdfBug; this.commonObjs = transport.commonObjs; this.objs = new PDFObjects(); this.cleanupAfterRender = false; @@ -954,7 +957,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() { intentState.operatorList, this.pageNumber, canvasFactory, - webGLContext); + webGLContext, + this._pdfBug); internalRenderTask.useRequestAnimationFrame = renderingIntent !== 'print'; if (!intentState.renderTasks) { intentState.renderTasks = []; @@ -1860,8 +1864,8 @@ var WorkerTransport = (function WorkerTransportClosure() { break; } var fontRegistry = null; - if (getDefaultSetting('pdfBug') && globalScope.FontInspector && - globalScope['FontInspector'].enabled) { + if (params.pdfBug && globalScope.FontInspector && + globalScope.FontInspector.enabled) { fontRegistry = { registerFont(font, url) { globalScope['FontInspector'].fontAdded(font, url); @@ -2067,7 +2071,8 @@ var WorkerTransport = (function WorkerTransportClosure() { if (this.destroyed) { throw new Error('Transport destroyed'); } - var page = new PDFPageProxy(pageIndex, pageInfo, this); + let page = new PDFPageProxy(pageIndex, pageInfo, this, + this._params.pdfBug); this.pageCache[pageIndex] = page; return page; }); @@ -2327,7 +2332,8 @@ var InternalRenderTask = (function InternalRenderTaskClosure() { let canvasInRendering = new WeakMap(); function InternalRenderTask(callback, params, objs, commonObjs, operatorList, - pageNumber, canvasFactory, webGLContext) { + pageNumber, canvasFactory, webGLContext, + pdfBug = false) { this.callback = callback; this.params = params; this.objs = objs; @@ -2337,6 +2343,7 @@ var InternalRenderTask = (function InternalRenderTaskClosure() { this.pageNumber = pageNumber; this.canvasFactory = canvasFactory; this.webGLContext = webGLContext; + this._pdfBug = pdfBug; this.running = false; this.graphicsReadyCallback = null; @@ -2370,7 +2377,7 @@ var InternalRenderTask = (function InternalRenderTaskClosure() { if (this.cancelled) { return; } - if (getDefaultSetting('pdfBug') && globalScope.StepperManager && + if (this._pdfBug && globalScope.StepperManager && globalScope.StepperManager.enabled) { this.stepper = globalScope.StepperManager.create(this.pageNumber - 1); this.stepper.init(this.operatorList); diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index 3fa97f143..565c9836a 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -17,7 +17,6 @@ import { assert, CMapCompressionType, removeNullCharacters, stringToBytes, unreachable, warn } from '../shared/util'; -import globalScope from '../shared/global_scope'; const DEFAULT_LINK_REL = 'noopener noreferrer nofollow'; const SVG_NS = 'http://www.w3.org/2000/svg'; @@ -329,18 +328,6 @@ function getFilenameFromUrl(url) { return url.substring(url.lastIndexOf('/', end) + 1, end); } -function getDefaultSetting(id) { - // The list of the settings and their default is maintained for backward - // compatibility and shall not be extended or modified. See also global.js. - var globalSettings = globalScope.PDFJS; - switch (id) { - case 'pdfBug': - return globalSettings ? globalSettings.pdfBug : false; - default: - throw new Error('Unknown default setting: ' + id); - } -} - class StatTimer { constructor(enable = true) { this.enabled = !!enable; @@ -420,7 +407,6 @@ export { addLinkAttributes, getFilenameFromUrl, LinkTarget, - getDefaultSetting, DEFAULT_LINK_REL, DOMCanvasFactory, DOMCMapReaderFactory, diff --git a/src/display/global.js b/src/display/global.js index 92f69c1b1..0941c431d 100644 --- a/src/display/global.js +++ b/src/display/global.js @@ -39,8 +39,6 @@ if (!globalScope.PDFJS) { } var PDFJS = globalScope.PDFJS; -PDFJS.pdfBug = false; - PDFJS.OPS = OPS; PDFJS.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; PDFJS.shadow = shadow; @@ -62,12 +60,6 @@ PDFJS.Util = Util; PDFJS.PageViewport = PageViewport; PDFJS.createPromiseCapability = createPromiseCapability; -/** - * Enables special hooks for debugging PDF.js. - * @var {boolean} - */ -PDFJS.pdfBug = (PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug); - PDFJS.getDocument = getDocument; PDFJS.LoopbackPort = LoopbackPort; PDFJS.PDFDataRangeTransport = PDFDataRangeTransport; diff --git a/src/display/text_layer.js b/src/display/text_layer.js index 4362fa7b4..3bf75f584 100644 --- a/src/display/text_layer.js +++ b/src/display/text_layer.js @@ -14,7 +14,7 @@ */ import { AbortException, createPromiseCapability, Util } from '../shared/util'; -import { getDefaultSetting } from './dom_utils'; +import globalScope from '../shared/global_scope'; /** * Text layer render parameters. @@ -107,11 +107,9 @@ var renderTextLayer = (function renderTextLayerClosure() { textDiv.setAttribute('style', textDivProperties.style); textDiv.textContent = geom.str; - // |fontName| is only used by the Font Inspector. This test will succeed - // when e.g. the Font Inspector is off but the Stepper is on, but it's - // not worth the effort to do a more accurate test. We only use `dataset` - // here to make the font name available for the debugger. - if (getDefaultSetting('pdfBug')) { + // `fontName` is only used by the FontInspector, and we only use `dataset` + // here to make the font name available in the debugger. + if (task._fontInspectorEnabled) { textDiv.dataset.fontName = geom.fontName; } if (angle !== 0) { @@ -479,6 +477,8 @@ var renderTextLayer = (function renderTextLayerClosure() { this._textDivs = textDivs || []; this._textContentItemsStr = textContentItemsStr || []; this._enhanceTextSelection = !!enhanceTextSelection; + this._fontInspectorEnabled = !!(globalScope.FontInspector && + globalScope.FontInspector.enabled); this._reader = null; this._layoutTextLastFontSize = null; diff --git a/test/driver.js b/test/driver.js index 39bec1927..1206b912c 100644 --- a/test/driver.js +++ b/test/driver.js @@ -273,8 +273,6 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars // Configure the global worker options. PDFJS.GlobalWorkerOptions.workerSrc = WORKER_SRC; - PDFJS.pdfBug = true; - // Set the passed options this.inflight = options.inflight; this.disableScrolling = options.disableScrolling; @@ -368,6 +366,7 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars cMapPacked: CMAP_PACKED, disableRange: task.disableRange, disableAutoFetch: !task.enableAutoFetch, + pdfBug: true, }).then((doc) => { task.pdfDoc = doc; this._nextPage(task, failure); diff --git a/web/app.js b/web/app.js index 912287cd7..015723807 100644 --- a/web/app.js +++ b/web/app.js @@ -22,8 +22,8 @@ import { } from './ui_utils'; import { build, createBlob, getDocument, getFilenameFromUrl, GlobalWorkerOptions, - InvalidPDFException, LinkTarget, MissingPDFException, OPS, PDFJS, PDFWorker, - shadow, UnexpectedResponseException, UNSUPPORTED_FEATURES, version + InvalidPDFException, LinkTarget, MissingPDFException, OPS, PDFWorker, shadow, + UnexpectedResponseException, UNSUPPORTED_FEATURES, version } from 'pdfjs-lib'; import { CursorTool, PDFCursorTools } from './pdf_cursor_tools'; import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue'; @@ -306,7 +306,7 @@ let PDFViewerApplication = { } } if ('pdfbug' in hashParams) { - PDFJS.pdfBug = true; + AppOptions.set('pdfBug', true); let enabled = hashParams['pdfbug'].split(','); waitOn.push(loadAndEnablePDFBug(enabled)); } @@ -2005,7 +2005,7 @@ function webViewerPageChanging(evt) { PDFViewerApplication.pdfThumbnailViewer.scrollThumbnailIntoView(page); } - // we need to update stats + // We need to update stats. if (typeof Stats !== 'undefined' && Stats.enabled) { let pageView = PDFViewerApplication.pdfViewer.getPageView(page - 1); if (pageView && pageView.stats) { diff --git a/web/app_options.js b/web/app_options.js index 70e11a850..c851c9a76 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -175,6 +175,11 @@ const defaultOptions = { value: -1, kind: OptionKind.API, }, + pdfBug: { + /** @type {boolean} */ + value: false, + kind: OptionKind.API, + }, postMessageTransfers: { /** @type {boolean} */ value: true, From 4b4fcecf7027704fff5c242c39365fdbf57956ab Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 23:19:43 +0100 Subject: [PATCH 15/16] Ensure that we only pass in the necessary parameters when initializing `PDFDataTransportStream`/`PDFNetworkStream` in `src/display/api.js` With options being moved from the global `PDFJS` object and into `getDocument`, a side-effect is that we're now passing in a fair number of useless parameters to the various transport/network streams. Even though this doesn't *currently* cause any problems, it nonetheless seem like a good idea to explicitly provide the parameters that are actually necessary. --- src/display/api.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 781bc7021..163f257b2 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -332,9 +332,22 @@ function getDocument(src) { let networkStream; if (rangeTransport) { - networkStream = new PDFDataTransportStream(params, rangeTransport); + networkStream = new PDFDataTransportStream({ + length: params.length, + initialData: params.initialData, + disableRange: params.disableRange, + disableStream: params.disableStream, + }, rangeTransport); } else if (!params.data) { - networkStream = createPDFNetworkStream(params); + networkStream = createPDFNetworkStream({ + url: params.url, + length: params.length, + httpHeaders: params.httpHeaders, + withCredentials: params.withCredentials, + rangeChunkSize: params.rangeChunkSize, + disableRange: params.disableRange, + disableStream: params.disableStream, + }); } var messageHandler = new MessageHandler(docId, workerId, worker.port); @@ -363,8 +376,6 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { if (worker.destroyed) { return Promise.reject(new Error('Worker was destroyed')); } - let apiVersion = - typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('BUNDLE_VERSION') : null; if (pdfDataRangeTransport) { source.length = pdfDataRangeTransport.length; @@ -372,7 +383,8 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { } return worker.messageHandler.sendWithPromise('GetDocRequest', { docId, - apiVersion, + apiVersion: (typeof PDFJSDev !== 'undefined' ? + PDFJSDev.eval('BUNDLE_VERSION') : null), source: { data: source.data, url: source.url, From b8606abbc1448ffd26ad553b253e2fb72d7f2cb7 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 17 Feb 2018 23:51:24 +0100 Subject: [PATCH 16/16] [api-major] Completely remove the global `PDFJS` object --- examples/acroforms/acroforms.js | 8 +- examples/browserify/main.js | 6 +- examples/components/pageviewer.js | 12 +- examples/components/simpleviewer.js | 14 +- examples/components/singlepageviewer.js | 14 +- examples/learning/helloworld.html | 4 +- examples/learning/helloworld64.html | 4 +- examples/learning/prevnext.html | 6 +- examples/mobile-viewer/viewer.js | 37 +- examples/text-only/pdf2svg.js | 10 +- gulpfile.js | 1 - src/display/global.js | 82 ----- src/doc_helper.js | 9 - src/pdf.js | 3 +- src/shared/compatibility.js | 16 +- test/driver.js | 12 +- test/unit/api_spec.js | 471 ++++++++++++------------ web/pdf_viewer.component.js | 40 +- 18 files changed, 323 insertions(+), 426 deletions(-) delete mode 100644 src/display/global.js diff --git a/examples/acroforms/acroforms.js b/examples/acroforms/acroforms.js index 44932e796..a54494534 100644 --- a/examples/acroforms/acroforms.js +++ b/examples/acroforms/acroforms.js @@ -15,7 +15,7 @@ 'use strict'; -PDFJS.GlobalWorkerOptions.workerSrc = +pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; var DEFAULT_URL = '../../test/pdfs/f1040.pdf'; @@ -24,7 +24,7 @@ var DEFAULT_SCALE = 1.0; var container = document.getElementById('pageContainer'); // Fetch the PDF document from the URL using promises. -PDFJS.getDocument(DEFAULT_URL).then(function (doc) { +pdfjsDistBuildPdf.getDocument(DEFAULT_URL).then(function (doc) { // Use a promise to fetch and render the next page. var promise = Promise.resolve(); @@ -32,12 +32,12 @@ PDFJS.getDocument(DEFAULT_URL).then(function (doc) { promise = promise.then(function (pageNum) { return doc.getPage(pageNum).then(function (pdfPage) { // Create the page view. - var pdfPageView = new PDFJS.PDFPageView({ + var pdfPageView = new pdfjsDistWebPdfViewer.PDFPageView({ container: container, id: pageNum, scale: DEFAULT_SCALE, defaultViewport: pdfPage.getViewport(DEFAULT_SCALE), - annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory(), + annotationLayerFactory: new pdfjsDistWebPdfViewer.DefaultAnnotationLayerFactory(), renderInteractiveForms: true, }); diff --git a/examples/browserify/main.js b/examples/browserify/main.js index 5d20aa05b..218a8c0e5 100644 --- a/examples/browserify/main.js +++ b/examples/browserify/main.js @@ -3,16 +3,16 @@ // Hello world example for browserify. -require('pdfjs-dist'); +var pdfjsLib = require('pdfjs-dist'); var pdfPath = '../helloworld/helloworld.pdf'; // Setting worker path to worker bundle. -PDFJS.GlobalWorkerOptions.workerSrc = +pdfjsLib.GlobalWorkerOptions.workerSrc = '../../build/browserify/pdf.worker.bundle.js'; // Loading a document. -var loadingTask = PDFJS.getDocument(pdfPath); +var loadingTask = pdfjsLib.getDocument(pdfPath); loadingTask.promise.then(function (pdfDocument) { // Request a first page return pdfDocument.getPage(1).then(function (pdfPage) { diff --git a/examples/components/pageviewer.js b/examples/components/pageviewer.js index de33355e0..63d317560 100644 --- a/examples/components/pageviewer.js +++ b/examples/components/pageviewer.js @@ -15,14 +15,14 @@ 'use strict'; -if (!PDFJS.PDFPageView || !PDFJS.getDocument) { +if (!pdfjsDistBuildPdf.getDocument || !pdfjsDistWebPdfViewer.PDFPageView) { alert('Please build the pdfjs-dist library using\n' + ' `gulp dist-install`'); } // The workerSrc property shall be specified. // -PDFJS.GlobalWorkerOptions.workerSrc = +pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; // Some PDFs need external cmaps. @@ -37,7 +37,7 @@ var SCALE = 1.0; var container = document.getElementById('pageContainer'); // Loading document. -PDFJS.getDocument({ +pdfjsDistBuildPdf.getDocument({ url: DEFAULT_URL, cMapUrl: CMAP_URL, cMapPacked: CMAP_PACKED, @@ -45,14 +45,14 @@ PDFJS.getDocument({ // Document loaded, retrieving the page. return pdfDocument.getPage(PAGE_TO_VIEW).then(function (pdfPage) { // Creating the page view with default parameters. - var pdfPageView = new PDFJS.PDFPageView({ + var pdfPageView = new pdfjsDistWebPdfViewer.PDFPageView({ container: container, id: PAGE_TO_VIEW, scale: SCALE, defaultViewport: pdfPage.getViewport(SCALE), // We can enable text/annotations layers, if needed - textLayerFactory: new PDFJS.DefaultTextLayerFactory(), - annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory() + textLayerFactory: new pdfjsDistWebPdfViewer.DefaultTextLayerFactory(), + annotationLayerFactory: new pdfjsDistWebPdfViewer.DefaultAnnotationLayerFactory(), }); // Associates the actual page with the view, and drawing it pdfPageView.setPdfPage(pdfPage); diff --git a/examples/components/simpleviewer.js b/examples/components/simpleviewer.js index 8d2e09fd2..c987fd8c9 100644 --- a/examples/components/simpleviewer.js +++ b/examples/components/simpleviewer.js @@ -15,14 +15,14 @@ 'use strict'; -if (!PDFJS.PDFViewer || !PDFJS.getDocument) { +if (!pdfjsDistBuildPdf.getDocument || !pdfjsDistWebPdfViewer.PDFViewer) { alert('Please build the pdfjs-dist library using\n' + ' `gulp dist-install`'); } // The workerSrc property shall be specified. // -PDFJS.GlobalWorkerOptions.workerSrc = +pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; // Some PDFs need external cmaps. @@ -36,17 +36,17 @@ var SEARCH_FOR = ''; // try 'Mozilla'; var container = document.getElementById('viewerContainer'); // (Optionally) enable hyperlinks within PDF files. -var pdfLinkService = new PDFJS.PDFLinkService(); +var pdfLinkService = new pdfjsDistWebPdfViewer.PDFLinkService(); -var pdfViewer = new PDFJS.PDFViewer({ +var pdfViewer = new pdfjsDistWebPdfViewer.PDFViewer({ container: container, linkService: pdfLinkService, }); pdfLinkService.setViewer(pdfViewer); // (Optionally) enable find controller. -var pdfFindController = new PDFJS.PDFFindController({ - pdfViewer: pdfViewer +var pdfFindController = new pdfjsDistWebPdfViewer.PDFFindController({ + pdfViewer: pdfViewer, }); pdfViewer.setFindController(pdfFindController); @@ -60,7 +60,7 @@ container.addEventListener('pagesinit', function () { }); // Loading document. -PDFJS.getDocument({ +pdfjsDistBuildPdf.getDocument({ url: DEFAULT_URL, cMapUrl: CMAP_URL, cMapPacked: CMAP_PACKED, diff --git a/examples/components/singlepageviewer.js b/examples/components/singlepageviewer.js index b2b9d34be..e1d554e59 100644 --- a/examples/components/singlepageviewer.js +++ b/examples/components/singlepageviewer.js @@ -15,14 +15,14 @@ 'use strict'; -if (!PDFJS.PDFSinglePageViewer || !PDFJS.getDocument) { +if (!pdfjsDistBuildPdf.getDocument || !pdfjsDistWebPdfViewer.PDFSinglePageViewer) { alert('Please build the pdfjs-dist library using\n' + ' `gulp dist-install`'); } // The workerSrc property shall be specified. // -PDFJS.GlobalWorkerOptions.workerSrc = +pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; // Some PDFs need external cmaps. @@ -36,17 +36,17 @@ var SEARCH_FOR = ''; // try 'Mozilla'; var container = document.getElementById('viewerContainer'); // (Optionally) enable hyperlinks within PDF files. -var pdfLinkService = new PDFJS.PDFLinkService(); +var pdfLinkService = new pdfjsDistWebPdfViewer.PDFLinkService(); -var pdfSinglePageViewer = new PDFJS.PDFSinglePageViewer({ +var pdfSinglePageViewer = new pdfjsDistWebPdfViewer.PDFSinglePageViewer({ container: container, linkService: pdfLinkService, }); pdfLinkService.setViewer(pdfSinglePageViewer); // (Optionally) enable find controller. -var pdfFindController = new PDFJS.PDFFindController({ - pdfViewer: pdfSinglePageViewer +var pdfFindController = new pdfjsDistWebPdfViewer.PDFFindController({ + pdfViewer: pdfSinglePageViewer, }); pdfSinglePageViewer.setFindController(pdfFindController); @@ -60,7 +60,7 @@ container.addEventListener('pagesinit', function () { }); // Loading document. -PDFJS.getDocument({ +pdfjsDistBuildPdf.getDocument({ url: DEFAULT_URL, cMapUrl: CMAP_URL, cMapPacked: CMAP_PACKED, diff --git a/examples/learning/helloworld.html b/examples/learning/helloworld.html index 5657b73e0..aab3f84b0 100644 --- a/examples/learning/helloworld.html +++ b/examples/learning/helloworld.html @@ -22,13 +22,13 @@ // // The workerSrc property shall be specified. // - PDFJS.GlobalWorkerOptions.workerSrc = + pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; // // Asynchronous download PDF // - PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf) { + pdfjsDistBuildPdf.getDocument(url).then(function getPdfHelloWorld(pdf) { // // Fetch the first page // diff --git a/examples/learning/helloworld64.html b/examples/learning/helloworld64.html index 263ba905a..e24de3a2e 100644 --- a/examples/learning/helloworld64.html +++ b/examples/learning/helloworld64.html @@ -34,12 +34,12 @@ // // The workerSrc property shall be specified. // - PDFJS.GlobalWorkerOptions.workerSrc = + pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; // Opening PDF by passing its binary data as a string. It is still preferable // to use Uint8Array, but string or array-like structure will work too. - PDFJS.getDocument({data: pdfData}).then(function getPdfHelloWorld(pdf) { + pdfjsDistBuildPdf.getDocument({data: pdfData}).then(function getPdfHelloWorld(pdf) { // Fetch the first page. pdf.getPage(1).then(function getPageHelloWorld(page) { var scale = 1.5; diff --git a/examples/learning/prevnext.html b/examples/learning/prevnext.html index a315a2118..f02c40dbd 100644 --- a/examples/learning/prevnext.html +++ b/examples/learning/prevnext.html @@ -33,8 +33,8 @@ // pdf.js's one, or the pdf.js is executed via eval(), the workerSrc property // shall be specified. // - // PDFJS.GlobalWorkerOptions.workerSrc = - // '../../node_modules/pdfjs-dist/build/pdf.worker.js'; + pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = + '../../node_modules/pdfjs-dist/build/pdf.worker.js'; var pdfDoc = null, pageNum = 1, @@ -117,7 +117,7 @@ /** * Asynchronously downloads PDF. */ - PDFJS.getDocument(url).then(function (pdfDoc_) { + pdfjsDistBuildPdf.getDocument(url).then(function (pdfDoc_) { pdfDoc = pdfDoc_; document.getElementById('page_count').textContent = pdfDoc.numPages; diff --git a/examples/mobile-viewer/viewer.js b/examples/mobile-viewer/viewer.js index 52e152986..7b03cbcb5 100644 --- a/examples/mobile-viewer/viewer.js +++ b/examples/mobile-viewer/viewer.js @@ -12,13 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* globals PDFJS */ +/* globals pdfjsDistBuildPdf, pdfjsDistWebPdfViewer */ 'use strict'; -if (typeof PDFJS === 'undefined' || !PDFJS.PDFViewer || !PDFJS.getDocument) { - alert('Please build the pdfjs-dist library using\n' + - ' `gulp dist-install`'); +if (!pdfjsDistBuildPdf.getDocument || !pdfjsDistWebPdfViewer.PDFViewer) { + alert('Please build the pdfjs-dist library using\n `gulp dist-install`'); } var USE_ONLY_CSS_ZOOM = true; @@ -27,7 +26,7 @@ var MAX_IMAGE_SIZE = 1024 * 1024; var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/'; var CMAP_PACKED = true; -PDFJS.GlobalWorkerOptions.workerSrc = +pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf'; @@ -62,7 +61,7 @@ var PDFViewerApplication = { this.setTitleUsingUrl(url); // Loading document. - var loadingTask = PDFJS.getDocument({ + var loadingTask = pdfjsDistBuildPdf.getDocument({ url: url, maxImageSize: MAX_IMAGE_SIZE, cMapUrl: CMAP_URL, @@ -88,15 +87,15 @@ var PDFViewerApplication = { var l10n = self.l10n; var loadingErrorMessage; - if (exception instanceof PDFJS.InvalidPDFException) { + if (exception instanceof pdfjsDistBuildPdf.InvalidPDFException) { // change error message also for other builds loadingErrorMessage = l10n.get('invalid_file_error', null, 'Invalid or corrupted PDF file.'); - } else if (exception instanceof PDFJS.MissingPDFException) { + } else if (exception instanceof pdfjsDistBuildPdf.MissingPDFException) { // special message for missing PDFs loadingErrorMessage = l10n.get('missing_file_error', null, 'Missing PDF file.'); - } else if (exception instanceof PDFJS.UnexpectedResponseException) { + } else if (exception instanceof pdfjsDistBuildPdf.UnexpectedResponseException) { loadingErrorMessage = l10n.get('unexpected_response_error', null, 'Unexpected server response.'); } else { @@ -138,14 +137,14 @@ var PDFViewerApplication = { }, get loadingBar() { - var bar = new PDFJS.ProgressBar('#loadingBar', {}); + var bar = new pdfjsDistWebPdfViewer.ProgressBar('#loadingBar', {}); - return PDFJS.shadow(this, 'loadingBar', bar); + return pdfjsDistBuildPdf.shadow(this, 'loadingBar', bar); }, setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) { this.url = url; - var title = PDFJS.getFilenameFromUrl(url) || url; + var title = pdfjsDistBuildPdf.getFilenameFromUrl(url) || url; try { title = decodeURIComponent(title); } catch (e) { @@ -166,8 +165,7 @@ var PDFViewerApplication = { console.log('PDF ' + pdfDocument.fingerprint + ' [' + info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() + ' / ' + (info.Creator || '-').trim() + ']' + - ' (PDF.js: ' + (PDFJS.version || '-') + - (!PDFJS.disableWebGL ? ' [WebGL]' : '') + ')'); + ' (PDF.js: ' + (pdfjsDistBuildPdf.version || '-') + ')'); var pdfTitle; if (metadata && metadata.has('dc:title')) { @@ -197,7 +195,8 @@ var PDFViewerApplication = { error: function pdfViewError(message, moreInfo) { var l10n = this.l10n; var moreInfoText = [l10n.get('error_version_info', - {version: PDFJS.version || '?', build: PDFJS.build || '?'}, + { version: pdfjsDistBuildPdf.version || '?', + build: pdfjsDistBuildPdf.build || '?' }, 'PDF.js v{{version}} (build: {{build}})')]; if (moreInfo) { @@ -295,13 +294,13 @@ var PDFViewerApplication = { }, initUI: function pdfViewInitUI() { - var linkService = new PDFJS.PDFLinkService(); + var linkService = new pdfjsDistWebPdfViewer.PDFLinkService(); this.pdfLinkService = linkService; - this.l10n = PDFJS.NullL10n; + this.l10n = pdfjsDistWebPdfViewer.NullL10n; var container = document.getElementById('viewerContainer'); - var pdfViewer = new PDFJS.PDFViewer({ + var pdfViewer = new pdfjsDistWebPdfViewer.PDFViewer({ container: container, linkService: linkService, l10n: this.l10n, @@ -311,7 +310,7 @@ var PDFViewerApplication = { this.pdfViewer = pdfViewer; linkService.setViewer(pdfViewer); - this.pdfHistory = new PDFJS.PDFHistory({ + this.pdfHistory = new pdfjsDistWebPdfViewer.PDFHistory({ linkService: linkService }); linkService.setHistory(this.pdfHistory); diff --git a/examples/text-only/pdf2svg.js b/examples/text-only/pdf2svg.js index eeb53bfb6..328121a54 100644 --- a/examples/text-only/pdf2svg.js +++ b/examples/text-only/pdf2svg.js @@ -18,7 +18,7 @@ var PAGE_NUMBER = 1; var PAGE_SCALE = 1.5; var SVG_NS = 'http://www.w3.org/2000/svg'; -PDFJS.GlobalWorkerOptions.workerSrc = +pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = '../../node_modules/pdfjs-dist/build/pdf.worker.js'; function buildSVG(viewport, textContent) { @@ -33,8 +33,8 @@ function buildSVG(viewport, textContent) { textContent.items.forEach(function (textItem) { // we have to take in account viewport transform, which includes scale, // rotation and Y-axis flip, and not forgetting to flip text. - var tx = PDFJS.Util.transform( - PDFJS.Util.transform(viewport.transform, textItem.transform), + var tx = pdfjsDistBuildPdf.Util.transform( + pdfjsDistBuildPdf.Util.transform(viewport.transform, textItem.transform), [1, 0, 0, -1, 0, 0]); var style = textContent.styles[textItem.fontName]; // adding text element @@ -49,7 +49,7 @@ function buildSVG(viewport, textContent) { function pageLoaded() { // Loading document and page text content - PDFJS.getDocument({url: PDF_PATH}).then(function (pdfDocument) { + pdfjsDistBuildPdf.getDocument({url: PDF_PATH}).then(function (pdfDocument) { pdfDocument.getPage(PAGE_NUMBER).then(function (page) { var viewport = page.getViewport(PAGE_SCALE); page.getTextContent().then(function (textContent) { @@ -62,7 +62,7 @@ function pageLoaded() { } document.addEventListener('DOMContentLoaded', function () { - if (typeof PDFJS === 'undefined') { + if (typeof pdfjsDistBuildPdf === 'undefined') { alert('Built version of PDF.js was not found.\n' + 'Please run `gulp dist-install`.'); return; diff --git a/gulpfile.js b/gulpfile.js index 3568da316..54ef27640 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -934,7 +934,6 @@ gulp.task('jsdoc', function (done) { var JSDOC_FILES = [ 'src/doc_helper.js', 'src/display/api.js', - 'src/display/global.js', 'src/shared/util.js', 'src/core/annotation.js' ]; diff --git a/src/display/global.js b/src/display/global.js deleted file mode 100644 index 0941c431d..000000000 --- a/src/display/global.js +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright 2015 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 { - createBlob, createPromiseCapability, InvalidPDFException, isLittleEndian, - MissingPDFException, OPS, PageViewport, PasswordException, PasswordResponses, - removeNullCharacters, shadow, UnexpectedResponseException, - UnknownErrorException, UNSUPPORTED_FEATURES, Util -} from '../shared/util'; -import { - getDocument, LoopbackPort, PDFDataRangeTransport, PDFWorker -} from './api'; -import { AnnotationLayer } from './annotation_layer'; -import { getFilenameFromUrl } from './dom_utils'; -import globalScope from '../shared/global_scope'; -import { GlobalWorkerOptions } from './worker_options'; -import { Metadata } from './metadata'; -import { renderTextLayer } from './text_layer'; -import { SVGGraphics } from './svg'; - -// The global PDFJS object is now deprecated and will not be supported in -// the future. The members below are maintained for backward compatibility -// and shall not be extended or modified. If the global.js is included as -// a module, we will create a global PDFJS object instance or use existing. -if (!globalScope.PDFJS) { - globalScope.PDFJS = {}; -} -var PDFJS = globalScope.PDFJS; - -PDFJS.OPS = OPS; -PDFJS.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; -PDFJS.shadow = shadow; -PDFJS.createBlob = createBlob; -Object.defineProperty(PDFJS, 'isLittleEndian', { - configurable: true, - get: function PDFJS_isLittleEndian() { - return shadow(PDFJS, 'isLittleEndian', isLittleEndian()); - }, -}); -PDFJS.removeNullCharacters = removeNullCharacters; -PDFJS.PasswordResponses = PasswordResponses; -PDFJS.PasswordException = PasswordException; -PDFJS.UnknownErrorException = UnknownErrorException; -PDFJS.InvalidPDFException = InvalidPDFException; -PDFJS.MissingPDFException = MissingPDFException; -PDFJS.UnexpectedResponseException = UnexpectedResponseException; -PDFJS.Util = Util; -PDFJS.PageViewport = PageViewport; -PDFJS.createPromiseCapability = createPromiseCapability; - -PDFJS.getDocument = getDocument; -PDFJS.LoopbackPort = LoopbackPort; -PDFJS.PDFDataRangeTransport = PDFDataRangeTransport; -PDFJS.PDFWorker = PDFWorker; -PDFJS.GlobalWorkerOptions = GlobalWorkerOptions; - -PDFJS.getFilenameFromUrl = getFilenameFromUrl; - -PDFJS.AnnotationLayer = AnnotationLayer; - -PDFJS.renderTextLayer = renderTextLayer; - -PDFJS.Metadata = Metadata; - -PDFJS.SVGGraphics = SVGGraphics; - -export { - globalScope, - PDFJS, -}; diff --git a/src/doc_helper.js b/src/doc_helper.js index 69b055144..fd640b786 100644 --- a/src/doc_helper.js +++ b/src/doc_helper.js @@ -18,15 +18,6 @@ It is not for use in the executable code. */ -/** - * PDFJS scope object that contains all functions, objects and variables related - * to the PDF.js. - * @constructor - */ -function PDFJS() { // eslint-disable-line no-unused-vars - // Mock class constructor. See src/display/api.js. -} - /** * Represents the eventual result of an asynchronous operation. * @external Promise diff --git a/src/pdf.js b/src/pdf.js index 63fa57b5c..ea3a3cd83 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -22,7 +22,6 @@ var pdfjsBuild = typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('BUNDLE_BUILD') : void 0; var pdfjsSharedUtil = require('./shared/util.js'); -var pdfjsDisplayGlobal = require('./display/global.js'); var pdfjsDisplayAPI = require('./display/api.js'); var pdfjsDisplayTextLayer = require('./display/text_layer.js'); var pdfjsDisplayAnnotationLayer = require('./display/annotation_layer.js'); @@ -66,7 +65,6 @@ if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) { }); } -exports.PDFJS = pdfjsDisplayGlobal.PDFJS; exports.build = pdfjsDisplayAPI.build; exports.version = pdfjsDisplayAPI.version; exports.getDocument = pdfjsDisplayAPI.getDocument; @@ -91,6 +89,7 @@ exports.createObjectURL = pdfjsSharedUtil.createObjectURL; exports.removeNullCharacters = pdfjsSharedUtil.removeNullCharacters; exports.shadow = pdfjsSharedUtil.shadow; exports.createBlob = pdfjsSharedUtil.createBlob; +exports.Util = pdfjsSharedUtil.Util; exports.RenderingCancelledException = pdfjsDisplayDOMUtils.RenderingCancelledException; exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl; diff --git a/src/shared/compatibility.js b/src/shared/compatibility.js index 1cf763637..5a4911357 100644 --- a/src/shared/compatibility.js +++ b/src/shared/compatibility.js @@ -13,32 +13,26 @@ * limitations under the License. */ /* eslint-disable mozilla/use-includes-instead-of-indexOf */ -/* globals PDFJS */ + +const globalScope = require('./global_scope'); // Skip compatibility checks for the extensions and if we already ran // this module. if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('FIREFOX || MOZCENTRAL')) && - (typeof PDFJS === 'undefined' || !PDFJS.compatibilityChecked)) { + !globalScope._pdfjsCompatibilityChecked) { + +globalScope._pdfjsCompatibilityChecked = true; // In the Chrome extension, most of the polyfills are unnecessary. // We support down to Chrome 49, because it's still commonly used by Windows XP // users - https://github.com/mozilla/pdf.js/issues/9397 if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME')) { -const globalScope = require('./global_scope'); const isNodeJS = require('./is_node'); const hasDOM = typeof window === 'object' && typeof document === 'object'; -// Initializing PDFJS global object here, it case if we need to change/disable -// some PDF.js features, e.g. range requests -if (typeof PDFJS === 'undefined') { - globalScope.PDFJS = {}; -} - -PDFJS.compatibilityChecked = true; - // Support: Node.js (function checkNodeBtoa() { if (globalScope.btoa || !isNodeJS()) { diff --git a/test/driver.js b/test/driver.js index 1206b912c..ac7d804ef 100644 --- a/test/driver.js +++ b/test/driver.js @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* globals PDFJS, pdfjsDistBuildPdf */ +/* globals pdfjsDistBuildPdf, pdfjsDistWebPdfViewer */ 'use strict'; @@ -69,7 +69,7 @@ var rasterizeTextLayer = (function rasterizeTextLayerClosure() { foreignObject.appendChild(div); // Rendering text layer as HTML. - var task = PDFJS.renderTextLayer({ + var task = pdfjsDistBuildPdf.renderTextLayer({ textContent, container: div, viewport, @@ -204,11 +204,11 @@ var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() { div, annotations, page, - linkService: new PDFJS.SimpleLinkService(), + linkService: new pdfjsDistWebPdfViewer.SimpleLinkService(), imageResourcesPath, renderInteractiveForms, }; - PDFJS.AnnotationLayer.render(parameters); + pdfjsDistBuildPdf.AnnotationLayer.render(parameters); // Inline SVG images from text annotations. var images = div.getElementsByTagName('img'); @@ -271,7 +271,7 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars */ function Driver(options) { // Configure the global worker options. - PDFJS.GlobalWorkerOptions.workerSrc = WORKER_SRC; + pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = WORKER_SRC; // Set the passed options this.inflight = options.inflight; @@ -358,7 +358,7 @@ var Driver = (function DriverClosure() { // eslint-disable-line no-unused-vars let absoluteUrl = new URL(task.file, window.location).href; try { - PDFJS.getDocument({ + pdfjsDistBuildPdf.getDocument({ url: absoluteUrl, password: task.password, nativeImageDecoderSupport: task.nativeImageDecoderSupport, diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index f879ba7c3..35e729283 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -58,266 +58,265 @@ describe('api', function() { }, WAIT_TIMEOUT); } - describe('PDFJS', function() { - describe('getDocument', function() { - it('creates pdf doc from URL', function(done) { - var loadingTask = getDocument(basicApiGetDocumentParams); + describe('getDocument', function() { + it('creates pdf doc from URL', function(done) { + var loadingTask = getDocument(basicApiGetDocumentParams); - var isProgressReportedResolved = false; - var progressReportedCapability = createPromiseCapability(); + var isProgressReportedResolved = false; + var progressReportedCapability = createPromiseCapability(); - // Attach the callback that is used to report loading progress; - // similarly to how viewer.js works. - loadingTask.onProgress = function (progressData) { - if (!isProgressReportedResolved) { - isProgressReportedResolved = true; - progressReportedCapability.resolve(progressData); - } - }; + // Attach the callback that is used to report loading progress; + // similarly to how viewer.js works. + loadingTask.onProgress = function (progressData) { + if (!isProgressReportedResolved) { + isProgressReportedResolved = true; + progressReportedCapability.resolve(progressData); + } + }; - var promises = [ - progressReportedCapability.promise, - loadingTask.promise - ]; - Promise.all(promises).then(function (data) { - expect((data[0].loaded / data[0].total) > 0).toEqual(true); - expect(data[1] instanceof PDFDocumentProxy).toEqual(true); - expect(loadingTask).toEqual(data[1].loadingTask); - loadingTask.destroy().then(done); - }).catch(function (reason) { - done.fail(reason); - }); + var promises = [ + progressReportedCapability.promise, + loadingTask.promise + ]; + Promise.all(promises).then(function (data) { + expect((data[0].loaded / data[0].total) > 0).toEqual(true); + expect(data[1] instanceof PDFDocumentProxy).toEqual(true); + expect(loadingTask).toEqual(data[1].loadingTask); + loadingTask.destroy().then(done); + }).catch(function (reason) { + done.fail(reason); }); - it('creates pdf doc from URL and aborts before worker initialized', - function(done) { - var loadingTask = getDocument(basicApiGetDocumentParams); - let destroyed = loadingTask.destroy(); + }); + it('creates pdf doc from URL and aborts before worker initialized', + function(done) { + var loadingTask = getDocument(basicApiGetDocumentParams); + let destroyed = loadingTask.destroy(); - loadingTask.promise.then(function(reason) { - done.fail('shall fail loading'); - }).catch(function (reason) { - expect(true).toEqual(true); - destroyed.then(done); - }); + loadingTask.promise.then(function(reason) { + done.fail('shall fail loading'); + }).catch(function (reason) { + expect(true).toEqual(true); + destroyed.then(done); }); - it('creates pdf doc from URL and aborts loading after worker initialized', - function(done) { - var loadingTask = getDocument(basicApiGetDocumentParams); - // This can be somewhat random -- we cannot guarantee perfect - // 'Terminate' message to the worker before/after setting up pdfManager. - var destroyed = loadingTask._worker.promise.then(function () { - return loadingTask.destroy(); - }); - destroyed.then(function (data) { - expect(true).toEqual(true); - done(); - }).catch(function (reason) { - done.fail(reason); - }); + }); + it('creates pdf doc from URL and aborts loading after worker initialized', + function(done) { + var loadingTask = getDocument(basicApiGetDocumentParams); + // This can be somewhat random -- we cannot guarantee perfect + // 'Terminate' message to the worker before/after setting up pdfManager. + var destroyed = loadingTask._worker.promise.then(function () { + return loadingTask.destroy(); }); - it('creates pdf doc from typed array', function(done) { - var typedArrayPdf; - if (isNodeJS()) { - typedArrayPdf = NodeFileReaderFactory.fetch({ - path: TEST_PDFS_PATH.node + basicApiFileName, - }); + destroyed.then(function (data) { + expect(true).toEqual(true); + done(); + }).catch(function (reason) { + done.fail(reason); + }); + }); + it('creates pdf doc from typed array', function(done) { + var typedArrayPdf; + if (isNodeJS()) { + typedArrayPdf = NodeFileReaderFactory.fetch({ + path: TEST_PDFS_PATH.node + basicApiFileName, + }); + } else { + let nonBinaryRequest = false; + let request = new XMLHttpRequest(); + request.open('GET', TEST_PDFS_PATH.dom + basicApiFileName, false); + try { + request.responseType = 'arraybuffer'; + nonBinaryRequest = request.responseType !== 'arraybuffer'; + } catch (e) { + nonBinaryRequest = true; + } + if (nonBinaryRequest && request.overrideMimeType) { + request.overrideMimeType('text/plain; charset=x-user-defined'); + } + request.send(null); + + if (nonBinaryRequest) { + typedArrayPdf = stringToBytes(request.responseText); } else { - let nonBinaryRequest = false; - let request = new XMLHttpRequest(); - request.open('GET', TEST_PDFS_PATH.dom + basicApiFileName, false); - try { - request.responseType = 'arraybuffer'; - nonBinaryRequest = request.responseType !== 'arraybuffer'; - } catch (e) { - nonBinaryRequest = true; - } - if (nonBinaryRequest && request.overrideMimeType) { - request.overrideMimeType('text/plain; charset=x-user-defined'); - } - request.send(null); - - if (nonBinaryRequest) { - typedArrayPdf = stringToBytes(request.responseText); - } else { - typedArrayPdf = new Uint8Array(request.response); - } + typedArrayPdf = new Uint8Array(request.response); } - // Sanity check to make sure that we fetched the entire PDF file. - expect(typedArrayPdf.length).toEqual(basicApiFileLength); + } + // Sanity check to make sure that we fetched the entire PDF file. + expect(typedArrayPdf.length).toEqual(basicApiFileLength); - var loadingTask = getDocument(typedArrayPdf); - loadingTask.promise.then(function(data) { - expect(data instanceof PDFDocumentProxy).toEqual(true); - loadingTask.destroy().then(done); - }).catch(function (reason) { - done.fail(reason); - }); + var loadingTask = getDocument(typedArrayPdf); + loadingTask.promise.then(function(data) { + expect(data instanceof PDFDocumentProxy).toEqual(true); + loadingTask.destroy().then(done); + }).catch(function (reason) { + done.fail(reason); }); - it('creates pdf doc from invalid PDF file', function(done) { - // A severely corrupt PDF file (even Adobe Reader fails to open it). - var loadingTask = getDocument(buildGetDocumentParams('bug1020226.pdf')); - loadingTask.promise.then(function () { - done.fail('shall fail loading'); - }).catch(function (error) { - expect(error instanceof InvalidPDFException).toEqual(true); - loadingTask.destroy().then(done); - }); + }); + it('creates pdf doc from invalid PDF file', function(done) { + // A severely corrupt PDF file (even Adobe Reader fails to open it). + var loadingTask = getDocument(buildGetDocumentParams('bug1020226.pdf')); + loadingTask.promise.then(function () { + done.fail('shall fail loading'); + }).catch(function (error) { + expect(error instanceof InvalidPDFException).toEqual(true); + loadingTask.destroy().then(done); }); - it('creates pdf doc from non-existent URL', function(done) { - if (isNodeJS()) { - pending('XMLHttpRequest is not supported in Node.js.'); + }); + it('creates pdf doc from non-existent URL', function(done) { + if (isNodeJS()) { + pending('XMLHttpRequest is not supported in Node.js.'); + } + var loadingTask = getDocument( + buildGetDocumentParams('non-existent.pdf')); + loadingTask.promise.then(function(error) { + done.fail('shall fail loading'); + }).catch(function (error) { + expect(error instanceof MissingPDFException).toEqual(true); + loadingTask.destroy().then(done); + }); + }); + it('creates pdf doc from PDF file protected with user and owner password', + function (done) { + var loadingTask = getDocument(buildGetDocumentParams('pr6531_1.pdf')); + + var isPasswordNeededResolved = false; + var passwordNeededCapability = createPromiseCapability(); + var isPasswordIncorrectResolved = false; + var passwordIncorrectCapability = createPromiseCapability(); + + // Attach the callback that is used to request a password; + // similarly to how viewer.js handles passwords. + loadingTask.onPassword = function (updatePassword, reason) { + if (reason === PasswordResponses.NEED_PASSWORD && + !isPasswordNeededResolved) { + isPasswordNeededResolved = true; + passwordNeededCapability.resolve(); + + updatePassword('qwerty'); // Provide an incorrect password. + return; } - var loadingTask = getDocument( - buildGetDocumentParams('non-existent.pdf')); - loadingTask.promise.then(function(error) { - done.fail('shall fail loading'); - }).catch(function (error) { - expect(error instanceof MissingPDFException).toEqual(true); - loadingTask.destroy().then(done); - }); + if (reason === PasswordResponses.INCORRECT_PASSWORD && + !isPasswordIncorrectResolved) { + isPasswordIncorrectResolved = true; + passwordIncorrectCapability.resolve(); + + updatePassword('asdfasdf'); // Provide the correct password. + return; + } + // Shouldn't get here. + expect(false).toEqual(true); + }; + + var promises = [ + passwordNeededCapability.promise, + passwordIncorrectCapability.promise, + loadingTask.promise + ]; + Promise.all(promises).then(function (data) { + expect(data[2] instanceof PDFDocumentProxy).toEqual(true); + loadingTask.destroy().then(done); + }).catch(function (reason) { + done.fail(reason); }); - it('creates pdf doc from PDF file protected with user and owner password', - function (done) { - var loadingTask = getDocument(buildGetDocumentParams('pr6531_1.pdf')); + }); + it('creates pdf doc from PDF file protected with only a user password', + function (done) { + var filename = 'pr6531_2.pdf'; - var isPasswordNeededResolved = false; - var passwordNeededCapability = createPromiseCapability(); - var isPasswordIncorrectResolved = false; - var passwordIncorrectCapability = createPromiseCapability(); - - // Attach the callback that is used to request a password; - // similarly to how viewer.js handles passwords. - loadingTask.onPassword = function (updatePassword, reason) { - if (reason === PasswordResponses.NEED_PASSWORD && - !isPasswordNeededResolved) { - isPasswordNeededResolved = true; - passwordNeededCapability.resolve(); - - updatePassword('qwerty'); // Provide an incorrect password. - return; - } - if (reason === PasswordResponses.INCORRECT_PASSWORD && - !isPasswordIncorrectResolved) { - isPasswordIncorrectResolved = true; - passwordIncorrectCapability.resolve(); - - updatePassword('asdfasdf'); // Provide the correct password. - return; - } - // Shouldn't get here. - expect(false).toEqual(true); - }; - - var promises = [ - passwordNeededCapability.promise, - passwordIncorrectCapability.promise, - loadingTask.promise - ]; - Promise.all(promises).then(function (data) { - expect(data[2] instanceof PDFDocumentProxy).toEqual(true); - loadingTask.destroy().then(done); - }).catch(function (reason) { - done.fail(reason); - }); - }); - it('creates pdf doc from PDF file protected with only a user password', - function (done) { - var filename = 'pr6531_2.pdf'; - - var passwordNeededLoadingTask = getDocument( - buildGetDocumentParams(filename, { - password: '', - })); - var result1 = passwordNeededLoadingTask.promise.then(function () { - done.fail('shall fail with no password'); - return Promise.reject(new Error('loadingTask should be rejected')); - }, function (data) { - expect(data instanceof PasswordException).toEqual(true); - expect(data.code).toEqual(PasswordResponses.NEED_PASSWORD); - return passwordNeededLoadingTask.destroy(); - }); - - var passwordIncorrectLoadingTask = getDocument( - buildGetDocumentParams(filename, { - password: 'qwerty', - })); - var result2 = passwordIncorrectLoadingTask.promise.then(function () { - done.fail('shall fail with wrong password'); - return Promise.reject(new Error('loadingTask should be rejected')); - }, function (data) { - expect(data instanceof PasswordException).toEqual(true); - expect(data.code).toEqual(PasswordResponses.INCORRECT_PASSWORD); - return passwordIncorrectLoadingTask.destroy(); - }); - - var passwordAcceptedLoadingTask = getDocument( - buildGetDocumentParams(filename, { - password: 'asdfasdf', - })); - var result3 = passwordAcceptedLoadingTask.promise.then(function (data) { - expect(data instanceof PDFDocumentProxy).toEqual(true); - return passwordAcceptedLoadingTask.destroy(); - }); - Promise.all([result1, result2, result3]).then(function () { - done(); - }).catch(function (reason) { - done.fail(reason); - }); + var passwordNeededLoadingTask = getDocument( + buildGetDocumentParams(filename, { + password: '', + })); + var result1 = passwordNeededLoadingTask.promise.then(function () { + done.fail('shall fail with no password'); + return Promise.reject(new Error('loadingTask should be rejected')); + }, function (data) { + expect(data instanceof PasswordException).toEqual(true); + expect(data.code).toEqual(PasswordResponses.NEED_PASSWORD); + return passwordNeededLoadingTask.destroy(); }); - it('creates pdf doc from password protected PDF file and aborts/throws ' + - 'in the onPassword callback (issue 7806)', function (done) { - var filename = 'issue3371.pdf'; + var passwordIncorrectLoadingTask = getDocument( + buildGetDocumentParams(filename, { + password: 'qwerty', + })); + var result2 = passwordIncorrectLoadingTask.promise.then(function () { + done.fail('shall fail with wrong password'); + return Promise.reject(new Error('loadingTask should be rejected')); + }, function (data) { + expect(data instanceof PasswordException).toEqual(true); + expect(data.code).toEqual(PasswordResponses.INCORRECT_PASSWORD); + return passwordIncorrectLoadingTask.destroy(); + }); - var passwordNeededLoadingTask = getDocument( - buildGetDocumentParams(filename)); - var passwordIncorrectLoadingTask = getDocument( - buildGetDocumentParams(filename, { - password: 'qwerty', - })); + var passwordAcceptedLoadingTask = getDocument( + buildGetDocumentParams(filename, { + password: 'asdfasdf', + })); + var result3 = passwordAcceptedLoadingTask.promise.then(function (data) { + expect(data instanceof PDFDocumentProxy).toEqual(true); + return passwordAcceptedLoadingTask.destroy(); + }); + Promise.all([result1, result2, result3]).then(function () { + done(); + }).catch(function (reason) { + done.fail(reason); + }); + }); - let passwordNeededDestroyed; - passwordNeededLoadingTask.onPassword = function (callback, reason) { - if (reason === PasswordResponses.NEED_PASSWORD) { - passwordNeededDestroyed = passwordNeededLoadingTask.destroy(); - return; - } - // Shouldn't get here. - expect(false).toEqual(true); - }; - var result1 = passwordNeededLoadingTask.promise.then(function () { - done.fail('shall fail since the loadingTask should be destroyed'); - return Promise.reject(new Error('loadingTask should be rejected')); - }, function (reason) { - expect(reason instanceof PasswordException).toEqual(true); - expect(reason.code).toEqual(PasswordResponses.NEED_PASSWORD); - return passwordNeededDestroyed; - }); + it('creates pdf doc from password protected PDF file and aborts/throws ' + + 'in the onPassword callback (issue 7806)', function (done) { + var filename = 'issue3371.pdf'; - passwordIncorrectLoadingTask.onPassword = function (callback, reason) { - if (reason === PasswordResponses.INCORRECT_PASSWORD) { - throw new Error('Incorrect password'); - } - // Shouldn't get here. - expect(false).toEqual(true); - }; - var result2 = passwordIncorrectLoadingTask.promise.then(function () { - done.fail('shall fail since the onPassword callback should throw'); - return Promise.reject(new Error('loadingTask should be rejected')); - }, function (reason) { - expect(reason instanceof PasswordException).toEqual(true); - expect(reason.code).toEqual(PasswordResponses.INCORRECT_PASSWORD); - return passwordIncorrectLoadingTask.destroy(); - }); + var passwordNeededLoadingTask = getDocument( + buildGetDocumentParams(filename)); + var passwordIncorrectLoadingTask = getDocument( + buildGetDocumentParams(filename, { + password: 'qwerty', + })); - Promise.all([result1, result2]).then(function () { - done(); - }).catch(function (reason) { - done.fail(reason); - }); + let passwordNeededDestroyed; + passwordNeededLoadingTask.onPassword = function (callback, reason) { + if (reason === PasswordResponses.NEED_PASSWORD) { + passwordNeededDestroyed = passwordNeededLoadingTask.destroy(); + return; + } + // Shouldn't get here. + expect(false).toEqual(true); + }; + var result1 = passwordNeededLoadingTask.promise.then(function () { + done.fail('shall fail since the loadingTask should be destroyed'); + return Promise.reject(new Error('loadingTask should be rejected')); + }, function (reason) { + expect(reason instanceof PasswordException).toEqual(true); + expect(reason.code).toEqual(PasswordResponses.NEED_PASSWORD); + return passwordNeededDestroyed; + }); + + passwordIncorrectLoadingTask.onPassword = function (callback, reason) { + if (reason === PasswordResponses.INCORRECT_PASSWORD) { + throw new Error('Incorrect password'); + } + // Shouldn't get here. + expect(false).toEqual(true); + }; + var result2 = passwordIncorrectLoadingTask.promise.then(function () { + done.fail('shall fail since the onPassword callback should throw'); + return Promise.reject(new Error('loadingTask should be rejected')); + }, function (reason) { + expect(reason instanceof PasswordException).toEqual(true); + expect(reason.code).toEqual(PasswordResponses.INCORRECT_PASSWORD); + return passwordIncorrectLoadingTask.destroy(); + }); + + Promise.all([result1, result2]).then(function () { + done(); + }).catch(function (reason) { + done.fail(reason); }); }); }); + describe('PDFWorker', function() { if (isNodeJS()) { pending('Worker is not supported in Node.js.'); diff --git a/web/pdf_viewer.component.js b/web/pdf_viewer.component.js index de940eaed..34dc65251 100644 --- a/web/pdf_viewer.component.js +++ b/web/pdf_viewer.component.js @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* eslint-disable no-unused-vars */ import { AnnotationLayerBuilder, DefaultAnnotationLayerFactory @@ -25,31 +26,28 @@ import { DownloadManager } from './download_manager.js'; import { GenericL10n } from './genericl10n.js'; import { PDFFindController } from './pdf_find_controller.js'; import { PDFHistory } from './pdf_history.js'; -import pdfjsLib from './pdfjs.js'; import { PDFPageView } from './pdf_page_view.js'; import { PDFSinglePageViewer } from './pdf_single_page_viewer'; import { PDFViewer } from './pdf_viewer.js'; -let { PDFJS, } = pdfjsLib; - -PDFJS.PDFViewer = PDFViewer; -PDFJS.PDFSinglePageViewer = PDFSinglePageViewer; -PDFJS.PDFPageView = PDFPageView; -PDFJS.PDFLinkService = PDFLinkService; -PDFJS.SimpleLinkService = SimpleLinkService; -PDFJS.TextLayerBuilder = TextLayerBuilder; -PDFJS.DefaultTextLayerFactory = DefaultTextLayerFactory; -PDFJS.AnnotationLayerBuilder = AnnotationLayerBuilder; -PDFJS.DefaultAnnotationLayerFactory = DefaultAnnotationLayerFactory; -PDFJS.PDFHistory = PDFHistory; -PDFJS.PDFFindController = PDFFindController; -PDFJS.EventBus = EventBus; - -PDFJS.DownloadManager = DownloadManager; -PDFJS.ProgressBar = ProgressBar; -PDFJS.GenericL10n = GenericL10n; -PDFJS.NullL10n = NullL10n; +const pdfjsVersion = PDFJSDev.eval('BUNDLE_VERSION'); +const pdfjsBuild = PDFJSDev.eval('BUNDLE_BUILD'); export { - PDFJS, + PDFViewer, + PDFSinglePageViewer, + PDFPageView, + PDFLinkService, + SimpleLinkService, + TextLayerBuilder, + DefaultTextLayerFactory, + AnnotationLayerBuilder, + DefaultAnnotationLayerFactory, + PDFHistory, + PDFFindController, + EventBus, + DownloadManager, + ProgressBar, + GenericL10n, + NullL10n, };