diff --git a/src/scripting_api/constants.js b/src/scripting_api/constants.js new file mode 100644 index 0000000000000..683e37324a163 --- /dev/null +++ b/src/scripting_api/constants.js @@ -0,0 +1,26 @@ +/* Copyright 2020 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 ZoomType = Object.freeze({ + none: "NoVary", + fitP: "FitPage", + fitW: "FitWidth", + fitH: "FitHeight", + fitV: "FitVisibleWidth", + pref: "Preferred", + refW: "ReflowWidth", +}); + +export { ZoomType }; diff --git a/src/scripting_api/doc.js b/src/scripting_api/doc.js index 3eff51931e266..0a7e1f4ef17d2 100644 --- a/src/scripting_api/doc.js +++ b/src/scripting_api/doc.js @@ -14,28 +14,678 @@ */ import { PDFObject } from "./pdf_object.js"; +import { PrintParams } from "./print_params.js"; +import { ZoomType } from "./constants.js"; + +class InfoProxyHandler { + static get(obj, prop) { + return obj[prop.toLowerCase()]; + } + + static set(obj, prop, value) { + throw new Error(`doc.info.${prop} is read-only`); + } +} class Doc extends PDFObject { constructor(data) { super(data); + this.baseURL = data.baseURL || ""; + this.calculate = true; + this.delay = false; + this.dirty = false; + this.disclosed = false; + this.media = undefined; + this.metadata = data.metadata; + this.noautocomplete = undefined; + this.nocache = undefined; + this.spellDictionaryOrder = []; + this.spellLanguageOrder = []; + this._printParams = null; - this._fields = Object.create(null); + this._fields = new Map(); + this._fieldNames = []; this._event = null; + + this._author = data.Author || ""; + this._creator = data.Creator || ""; + this._creationDate = this._getDate(data.CreationDate) || null; + this._docID = data.docID || ["", ""]; + this._documentFileName = data.filename || ""; + this._filesize = data.filesize || 0; + this._keywords = data.Keywords || ""; + this._layout = data.layout || ""; + this._modDate = this._getDate(data.ModDate) || null; + this._numFields = 0; + this._numPages = data.numPages || 1; + this._pageNum = data.pageNum || 0; + this._producer = data.Producer || ""; + this._subject = data.Subject || ""; + this._title = data.Title || ""; + this._URL = data.URL || ""; + + // info has case insensitive properties + // and they're are read-only. + this._info = new Proxy( + { + title: this.title, + author: this.author, + subject: this.subject, + keywords: this.keywords, + creator: this.creator, + producer: this.producer, + creationdate: this._creationDate, + moddate: this._modDate, + trapped: data.Trapped || "Unknown", + }, + InfoProxyHandler + ); + + this._zoomType = ZoomType.none; + this._zoom = data.zoom || 100; + } + + _addField(name, field) { + this._fields.set(name, field); + this._fieldNames.push(name); + this._numFields++; + } + + _getDate(date) { + // date format is D:YYYYMMDDHHmmSS[OHH'mm'] + if (!date || date.length < 15 || !date.startsWith("D:")) { + return date; + } + + date = date.substring(2); + const year = date.substring(0, 4); + const month = date.substring(4, 6); + const day = date.substring(6, 8); + const hour = date.substring(8, 10); + const minute = date.substring(10, 12); + const o = date.charAt(12); + let second, offsetPos; + if (o === "Z" || o === "+" || o === "-") { + second = "00"; + offsetPos = 12; + } else { + second = date.substring(12, 14); + offsetPos = 14; + } + const offset = date.substring(offsetPos).replaceAll("'", ""); + return new Date( + `${year}-${month}-${day}T${hour}:${minute}:${second}${offset}` + ); + } + + get author() { + return this._author; + } + + set author(_) { + throw new Error("doc.author is read-only"); + } + + get bookmarkRoot() { + return undefined; + } + + set bookmarkRoot(_) { + throw new Error("doc.bookmarkRoot is read-only"); + } + + get creator() { + return this._creator; + } + + set creator(_) { + throw new Error("doc.creator is read-only"); + } + + get dataObjects() { + return []; + } + + set dataObjects(_) { + throw new Error("doc.dataObjects is read-only"); + } + + get docID() { + return this._docID; + } + + set docID(_) { + throw new Error("doc.docID is read-only"); + } + + get documentFileName() { + return this._documentFileName; + } + + set documentFileName(_) { + throw new Error("doc.documentFileName is read-only"); + } + + get dynamicXFAForm() { + return false; + } + + set dynamicXFAForm(_) { + throw new Error("doc.dynamicXFAForm is read-only"); + } + + get external() { + return true; + } + + set external(_) { + throw new Error("doc.external is read-only"); + } + + get filesize() { + return this._filesize; + } + + set filesize(_) { + throw new Error("doc.filesize is read-only"); + } + + get hidden() { + return false; + } + + set hidden(_) { + throw new Error("doc.hidden is read-only"); + } + + get hostContainer() { + return undefined; + } + + set hostContainer(_) { + throw new Error("doc.hostContainer is read-only"); + } + + get icons() { + return undefined; + } + + set icons(_) { + throw new Error("doc.icons is read-only"); + } + + get info() { + return this._info; + } + + set info(_) { + throw new Error("doc.info is read-only"); + } + + get innerAppWindowRect() { + return [0, 0, 0, 0]; + } + + set innerAppWindowRect(_) { + throw new Error("doc.innerAppWindowRect is read-only"); + } + + get innerDocWindowRect() { + return [0, 0, 0, 0]; + } + + set innerDocWindowRect(_) { + throw new Error("doc.innerDocWindowRect is read-only"); + } + + get isModal() { + return false; + } + + set isModal(_) { + throw new Error("doc.isModal is read-only"); + } + + get keywords() { + return this._keywords; + } + + set keywords(_) { + throw new Error("doc.keywords is read-only"); + } + + get layout() { + return this._layout; + } + + set layout(value) { + if (typeof value !== "string") { + return; + } + + if ( + value !== "SinglePage" && + value !== "OneColumn" && + value !== "TwoColumnLeft" && + value !== "TwoPageLeft" && + value !== "TwoColumnRight" && + value !== "TwoPageRight" + ) { + value = "SinglePage"; + } + this._send({ command: "layout", value }); + this._layout = value; + } + + get modDate() { + return this._modDate; + } + + set modDate(_) { + throw new Error("doc.modDate is read-only"); + } + + get mouseX() { + return 0; + } + + set mouseX(_) { + throw new Error("doc.mouseX is read-only"); + } + + get mouseY() { + return 0; + } + + set mouseY(_) { + throw new Error("doc.mouseY is read-only"); + } + + get numFields() { + return this._numFields; + } + + set numFields(_) { + throw new Error("doc.numFields is read-only"); + } + + get numPages() { + return this._numPages; + } + + set numPages(_) { + throw new Error("doc.numPages is read-only"); + } + + get numTemplates() { + return 0; + } + + set numTemplates(_) { + throw new Error("doc.numTemplates is read-only"); + } + + get outerAppWindowRect() { + return [0, 0, 0, 0]; + } + + set outerAppWindowRect(_) { + throw new Error("doc.outerAppWindowRect is read-only"); + } + + get outerDocWindowRect() { + return [0, 0, 0, 0]; + } + + set outerDocWindowRect(_) { + throw new Error("doc.outerDocWindowRect is read-only"); + } + + get pageNum() { + return this._pageNum; + } + + set pageNum(value) { + if (typeof value !== "number" || value < 0 || value >= this._numPages) { + return; + } + this._send({ command: "page-num", value }); + this._pageNum = value; + } + + get pageWindowRect() { + return [0, 0, 0, 0]; + } + + set pageWindowRect(_) { + throw new Error("doc.pageWindowRect is read-only"); + } + + get path() { + return ""; + } + + set path(_) { + throw new Error("doc.path is read-only"); + } + + get permStatusReady() { + return true; + } + + set permStatusReady(_) { + throw new Error("doc.permStatusReady is read-only"); + } + + get producer() { + return this._producer; + } + + set producer(_) { + throw new Error("doc.producer is read-only"); + } + + get requiresFullSave() { + return false; + } + + set requiresFullSave(_) { + throw new Error("doc.requiresFullSave is read-only"); + } + + get securityHandler() { + return null; + } + + set securityHandler(_) { + throw new Error("doc.securityHandler is read-only"); + } + + get selectedAnnots() { + return []; + } + + set selectedAnnots(_) { + throw new Error("doc.selectedAnnots is read-only"); + } + + get sounds() { + return []; + } + + set sounds(_) { + throw new Error("doc.sounds is read-only"); + } + + get subject() { + return this._subject; + } + + set subject(_) { + throw new Error("doc.subject is read-only"); + } + + get templates() { + return []; + } + + set templates(_) { + throw new Error("doc.templates is read-only"); + } + + get title() { + return this._title; + } + + set title(_) { + throw new Error("doc.title is read-only"); + } + + get URL() { + return this._URL; + } + + set URL(_) { + throw new Error("doc.URL is read-only"); + } + + get viewState() { + return undefined; + } + + set viewState(_) { + throw new Error("doc.viewState is read-only"); + } + + get xfa() { + return this._xfa; + } + + set xfa(_) { + throw new Error("doc.xfa is read-only"); + } + + get XFAForeground() { + return false; + } + + set XFAForeground(_) { + throw new Error("doc.XFAForeground is read-only"); + } + + get zoomType() { + return this._zoomType; + } + + set zoomType(type) { + if (typeof type !== "string") { + return; + } + switch (type) { + case ZoomType.none: + this._send({ command: "zoom", value: 1 }); + break; + case ZoomType.fitP: + this._send({ command: "zoom", value: "page-fit" }); + break; + case ZoomType.fitW: + this._send({ command: "zoom", value: "page-width" }); + break; + case ZoomType.fitH: + this._send({ command: "zoom", value: "page-height" }); + break; + case ZoomType.fitV: + this._send({ command: "zoom", value: "auto" }); + break; + case ZoomType.pref: + case ZoomType.refW: + break; + default: + return; + } + + this._zoomType = type; + } + + get zoom() { + return this._zoom; + } + + set zoom(value) { + if (typeof value !== "number" || value < 8.33 || value > 6400) { + return; + } + + this._send({ command: "zoom", value: value / 100 }); + } + + addAnnot() { + /* Not implemented */ + } + + addField() { + /* Not implemented */ + } + + addIcon() { + /* Not implemented */ + } + + addLink() { + /* Not implemented */ + } + + addRecipientListCryptFilter() { + /* Not implemented */ + } + + addRequirement() { + /* Not implemented */ + } + + addScript() { + /* Not implemented */ + } + + addThumbnails() { + /* Not implemented */ + } + + addWatermarkFromFile() { + /* Not implemented */ + } + + addWatermarkFromText() { + /* Not implemented */ + } + + addWeblinks() { + /* Not implemented */ + } + + bringToFront() { + /* Not implemented */ } calculateNow() { this._eventDispatcher.calculateNow(); } + closeDoc() { + /* Not implemented */ + } + + colorConvertPage() { + /* Not implemented */ + } + + createDataObject() { + /* Not implemented */ + } + + createTemplate() { + /* Not implemented */ + } + + deletePages() { + /* Not implemented */ + } + + deleteSound() { + /* Not implemented */ + } + + embedDocAsDataObject() { + /* Not implemented */ + } + + embedOutputIntent() { + /* Not implemented */ + } + + encryptForRecipients() { + /* Not implemented */ + } + + encryptUsingPolicy() { + /* Not implemented */ + } + + exportAsFDF() { + /* Not implemented */ + } + + exportAsFDFStr() { + /* Not implemented */ + } + + exportAsText() { + /* Not implemented */ + } + + exportAsXFDF() { + /* Not implemented */ + } + + exportAsXFDFStr() { + /* Not implemented */ + } + + exportDataObject() { + /* Not implemented */ + } + + exportXFAData() { + /* Not implemented */ + } + + extractPages() { + /* Not implemented */ + } + + flattenPages() { + /* Not implemented */ + } + + getAnnot() { + /* TODO */ + } + + getAnnots() { + /* TODO */ + } + + getAnnot3D() { + /* Not implemented */ + } + + getAnnots3D() { + /* Not implemented */ + } + + getColorConvertAction() { + /* Not implemented */ + } + + getDataObject() { + /* Not implemented */ + } + + getDataObjectContents() { + /* Not implemented */ + } + getField(cName) { if (typeof cName !== "string") { throw new TypeError("Invalid field name: must be a string"); } - if (cName in this._fields) { - return this._fields[cName]; + const searchedField = this._fields.get(cName); + if (searchedField) { + return searchedField; } - for (const [name, field] of Object.entries(this._fields)) { + + for (const [name, field] of this._fields.entries()) { if (name.includes(cName)) { return field; } @@ -43,6 +693,298 @@ class Doc extends PDFObject { return undefined; } + + getIcon() { + /* Not implemented */ + } + + getLegalWarnings() { + /* Not implemented */ + } + + getLinks() { + /* Not implemented */ + } + + getNthFieldName(nIndex) { + if (typeof nIndex !== "number") { + throw new TypeError("Invalid field index: must be a number"); + } + if (0 <= nIndex && nIndex < this.numFields) { + return this._fieldNames[Math.trunc(nIndex)]; + } + return null; + } + + getNthTemplate() { + return null; + } + + getOCGs() { + /* Not implemented */ + } + + getOCGOrder() { + /* Not implemented */ + } + + getPageBox() { + /* TODO */ + } + + getPageLabel() { + /* TODO */ + } + + getPageNthWord() { + /* TODO or not */ + } + + getPageNthWordQuads() { + /* TODO or not */ + } + + getPageNumWords() { + /* TODO or not */ + } + + getPageRotation() { + /* TODO */ + } + + getPageTransition() { + /* Not implemented */ + } + + getPrintParams() { + if (!this._printParams) { + this._printParams = new PrintParams({ lastPage: this._numPages - 1 }); + } + return this._printParams; + } + + getSound() { + /* Not implemented */ + } + + getTemplate() { + /* Not implemented */ + } + + getURL() { + /* Not implemented because unsafe */ + } + + gotoNamedDest() { + /* TODO */ + } + + importAnFDF() { + /* Not implemented */ + } + + importAnXFDF() { + /* Not implemented */ + } + + importDataObject() { + /* Not implemented */ + } + + importIcon() { + /* Not implemented */ + } + + importSound() { + /* Not implemented */ + } + + importTextData() { + /* Not implemented */ + } + + importXFAData() { + /* Not implemented */ + } + + insertPages() { + /* Not implemented */ + } + + mailDoc() { + /* TODO or not */ + } + + mailForm() { + /* TODO or not */ + } + + movePage() { + /* Not implemented */ + } + + newPage() { + /* Not implemented */ + } + + openDataObject() { + /* Not implemented */ + } + + print( + bUI = true, + nStart = 0, + nEnd = -1, + bSilent = false, + bShrinkToFit = false, + bPrintAsImage = false, + bReverse = false, + bAnnotations = true, + printParams = null + ) { + // TODO: for now just use nStart and nEnd + // so need to see how to deal with the other params + // (if possible) + if (printParams) { + nStart = printParams.firstPage; + nEnd = printParams.lastPage; + } + + if (typeof nStart === "number") { + nStart = Math.max(0, Math.trunc(nStart)); + } else { + nStart = 0; + } + + if (typeof nEnd === "number") { + nEnd = Math.max(0, Math.trunc(nEnd)); + } else { + nEnd = -1; + } + + this._send({ id: "print", start: nStart, end: nEnd }); + } + + removeDataObject() { + /* Not implemented */ + } + + removeField() { + /* TODO or not */ + } + + removeIcon() { + /* Not implemented */ + } + + removeLinks() { + /* Not implemented */ + } + + removeRequirement() { + /* Not implemented */ + } + + removeScript() { + /* Not implemented */ + } + + removeTemplate() { + /* Not implemented */ + } + + removeThumbnails() { + /* Not implemented */ + } + + removeWeblinks() { + /* Not implemented */ + } + + replacePages() { + /* Not implemented */ + } + + resetForm(aFields = null) { + let mustCalculate = false; + if (aFields) { + for (const fieldName of aFields) { + const field = this.getField(fieldName); + if (field) { + field.value = field.defaultValue; + mustCalculate = true; + } + } + } else { + mustCalculate = this._fields.size !== 0; + for (const field of this._fields.values()) { + field.value = field.defaultValue; + } + } + if (mustCalculate) { + this.calculateNow(); + } + } + + saveAs() { + /* Not implemented */ + } + + scroll() { + /* TODO */ + } + + selectPageNthWord() { + /* TODO */ + } + + setAction() { + /* TODO */ + } + + setDataObjectContents() { + /* Not implemented */ + } + + setOCGOrder() { + /* Not implemented */ + } + + setPageAction() { + /* TODO */ + } + + setPageBoxes() { + /* Not implemented */ + } + + setPageLabels() { + /* Not implemented */ + } + + setPageRotations() { + /* TODO */ + } + + setPageTabOrder() { + /* Not implemented */ + } + + setPageTransitions() { + /* Not implemented */ + } + + spawnPageFromTemplate() { + /* Not implemented */ + } + + submitForm() { + /* TODO or not */ + } + + syncAnnotScan() { + /* Not implemented */ + } } export { Doc }; diff --git a/src/scripting_api/initialization.js b/src/scripting_api/initialization.js index cf44d4058ce62..55e8054131f16 100644 --- a/src/scripting_api/initialization.js +++ b/src/scripting_api/initialization.js @@ -20,11 +20,15 @@ import { Doc } from "./doc.js"; import { Field } from "./field.js"; import { ProxyHandler } from "./proxy.js"; import { Util } from "./util.js"; +import { ZoomType } from "./constants.js"; function initSandbox(data, extra, out) { const proxyHandler = new ProxyHandler(data.dispatchEventName); const { send, crackURL } = extra; - const doc = new Doc({ send }); + const doc = new Doc({ + send, + ...data.docInfo, + }); const _document = { obj: doc, wrapped: new Proxy(doc, proxyHandler) }; const app = new App({ send, @@ -39,7 +43,8 @@ function initSandbox(data, extra, out) { obj.send = send; obj.doc = _document.wrapped; const field = new Field(obj); - const wrapped = (doc._fields[name] = new Proxy(field, proxyHandler)); + const wrapped = new Proxy(field, proxyHandler); + doc._addField(name, wrapped); app._objects[obj.id] = { obj: field, wrapped }; } @@ -47,6 +52,7 @@ function initSandbox(data, extra, out) { out.app = new Proxy(app, proxyHandler); out.console = new Proxy(new Console({ send }), proxyHandler); out.util = new Proxy(util, proxyHandler); + out.zoomtype = ZoomType; for (const name of Object.getOwnPropertyNames(AForm.prototype)) { if (name.startsWith("AF")) { out[name] = aform[name].bind(aform); diff --git a/src/scripting_api/print_params.js b/src/scripting_api/print_params.js new file mode 100644 index 0000000000000..f465ec8a24b55 --- /dev/null +++ b/src/scripting_api/print_params.js @@ -0,0 +1,146 @@ +/* Copyright 2020 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. + */ + +class PrintParams { + constructor(data) { + this.binaryOk = true; + this.bitmapDPI = 150; + this.booklet = { + binding: 0, + duplexMode: 0, + subsetFrom: 0, + subsetTo: -1, + }; + this.colorOverride = 0; + this.colorProfile = ""; + this.constants = Object.freeze({ + bookletBindings: Object.freeze({ + Left: 0, + Right: 1, + LeftTall: 2, + RightTall: 3, + }), + bookletDuplexMode: Object.freeze({ + BothSides: 0, + FrontSideOnly: 1, + BasicSideOnly: 2, + }), + colorOverrides: Object.freeze({ + auto: 0, + gray: 1, + mono: 2, + }), + fontPolicies: Object.freeze({ + everyPage: 0, + jobStart: 1, + pageRange: 2, + }), + handling: Object.freeze({ + none: 0, + fit: 1, + shrink: 2, + tileAll: 3, + tileLarge: 4, + nUp: 5, + booklet: 6, + }), + interactionLevel: Object.freeze({ + automatic: 0, + full: 1, + silent: 2, + }), + nUpPageOrders: Object.freeze({ + Horizontal: 0, + HorizontalReversed: 1, + Vertical: 2, + }), + printContents: Object.freeze({ + doc: 0, + docAndComments: 1, + formFieldsOnly: 2, + }), + flagValues: Object.freeze({ + applyOverPrint: 1, + applySoftProofSettings: 1 << 1, + applyWorkingColorSpaces: 1 << 2, + emitHalftones: 1 << 3, + emitPostScriptXObjects: 1 << 4, + emitFormsAsPSForms: 1 << 5, + maxJP2KRes: 1 << 6, + setPageSize: 1 << 7, + suppressBG: 1 << 8, + suppressCenter: 1 << 9, + suppressCJKFontSubst: 1 << 10, + suppressCropClip: 1 << 1, + suppressRotate: 1 << 12, + suppressTransfer: 1 << 13, + suppressUCR: 1 << 14, + useTrapAnnots: 1 << 15, + usePrintersMarks: 1 << 16, + }), + rasterFlagValues: Object.freeze({ + textToOutline: 1, + strokesToOutline: 1 << 1, + allowComplexClip: 1 << 2, + preserveOverprint: 1 << 3, + }), + subsets: Object.freeze({ + all: 0, + even: 1, + odd: 2, + }), + tileMarks: Object.freeze({ + none: 0, + west: 1, + east: 2, + }), + usages: Object.freeze({ + auto: 0, + use: 1, + noUse: 2, + }), + }); + this.downloadFarEastFonts = false; + this.fileName = ""; + this.firstPage = 0; + this.flags = 0; + this.fontPolicy = 0; + this.gradientDPI = 150; + this.interactive = 1; + this.lastPage = data.lastPage; + this.npUpAutoRotate = false; + this.npUpNumPagesH = 2; + this.npUpNumPagesV = 2; + this.npUpPageBorder = false; + this.npUpPageOrder = 0; + this.pageHandling = 0; + this.pageSubset = 0; + this.printAsImage = false; + this.printContent = 0; + this.printerName = ""; + this.psLevel = 0; + this.rasterFlags = 0; + this.reversePages = false; + this.tileLabel = false; + this.tileMark = 0; + this.tileOverlap = 0; + this.tileScale = 1.0; + this.transparencyLevel = 75; + this.usePrinterCRD = 0; + this.useT1Conversion = 0; + } +} + +export { PrintParams }; diff --git a/web/app.js b/web/app.js index fbc495507c381..0a2fa253207cb 100644 --- a/web/app.js +++ b/web/app.js @@ -1350,11 +1350,11 @@ const PDFViewerApplication = { ); this._idleCallbacks.add(callback); } + this._initializeJavaScript(pdfDocument); }); this._initializePageLabels(pdfDocument); this._initializeMetadata(pdfDocument); - this._initializeJavaScript(pdfDocument); }, /** @@ -1370,25 +1370,46 @@ const PDFViewerApplication = { return; } const scripting = this.externalServices.scripting; + const { + info, + metadata, + contentDispositionFilename, + } = await pdfDocument.getMetadata(); - window.addEventListener("updateFromSandbox", function (event) { + window.addEventListener("updateFromSandbox", event => { const detail = event.detail; const id = detail.id; if (!id) { switch (detail.command) { - case "println": - console.log(detail.value); - break; - case "clear": - console.clear(); - break; case "alert": // eslint-disable-next-line no-alert window.alert(detail.value); break; + case "clear": + console.clear(); + break; case "error": console.error(detail.value); break; + case "layout": + this.pdfViewer.spreadMode = apiPageLayoutToSpreadMode(detail.value); + return; + case "page-num": + this.pdfViewer.currentPageNumber = detail.value + 1; + return; + case "print": + this.triggerPrinting(); + return; + case "println": + console.log(detail.value); + break; + case "zoom": + if (typeof detail.value === "string") { + this.pdfViewer.currentScaleValue = detail.value; + } else { + this.pdfViewer.currentScale = detail.value; + } + return; } return; } @@ -1411,7 +1432,23 @@ const PDFViewerApplication = { const dispatchEventName = generateRandomStringForSandbox(objects); const calculationOrder = []; - scripting.createSandbox({ objects, dispatchEventName, calculationOrder }); + const { length } = await pdfDocument.getDownloadInfo(); + const filename = + contentDispositionFilename || getPDFFileNameFromURL(this.url); + scripting.createSandbox({ + objects, + dispatchEventName, + calculationOrder, + docInfo: { + ...info, + baseURL: this.baseUrl, + filesize: length, + filename, + metadata, + numPages: pdfDocument.numPages, + URL: this.url, + }, + }); }, /**