2020-10-01 20:57:23 +09:00
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
|
2020-11-16 22:27:27 +09:00
|
|
|
import {
|
|
|
|
Border,
|
|
|
|
Cursor,
|
|
|
|
Display,
|
|
|
|
Font,
|
2021-01-12 01:19:24 +09:00
|
|
|
GlobalConstants,
|
2020-11-16 22:27:27 +09:00
|
|
|
Highlight,
|
|
|
|
Position,
|
|
|
|
ScaleHow,
|
|
|
|
ScaleWhen,
|
|
|
|
Style,
|
|
|
|
Trans,
|
|
|
|
ZoomType,
|
|
|
|
} from "./constants.js";
|
2020-11-19 02:54:26 +09:00
|
|
|
import { CheckboxField, Field, RadioButtonField } from "./field.js";
|
2020-10-01 20:57:23 +09:00
|
|
|
import { AForm } from "./aform.js";
|
|
|
|
import { App } from "./app.js";
|
2020-11-16 22:27:27 +09:00
|
|
|
import { Color } from "./color.js";
|
2020-10-01 20:57:23 +09:00
|
|
|
import { Console } from "./console.js";
|
|
|
|
import { Doc } from "./doc.js";
|
|
|
|
import { ProxyHandler } from "./proxy.js";
|
|
|
|
import { Util } from "./util.js";
|
|
|
|
|
2020-12-04 08:39:50 +09:00
|
|
|
function initSandbox(params) {
|
|
|
|
delete globalThis.pdfjsScripting;
|
|
|
|
|
|
|
|
// externalCall is a function to call a function defined
|
|
|
|
// outside the sandbox.
|
|
|
|
// (see src/pdf.sandbox.external.js).
|
|
|
|
const externalCall = globalThis.callExternalFunction;
|
|
|
|
delete globalThis.callExternalFunction;
|
|
|
|
|
|
|
|
// eslint-disable-next-line no-eval
|
|
|
|
const globalEval = code => globalThis.eval(code);
|
|
|
|
const send = data => externalCall("send", [data]);
|
|
|
|
const proxyHandler = new ProxyHandler();
|
|
|
|
const { data } = params;
|
2020-11-05 21:22:35 +09:00
|
|
|
const doc = new Doc({
|
|
|
|
send,
|
2020-12-08 03:22:14 +09:00
|
|
|
globalEval,
|
2020-11-05 21:22:35 +09:00
|
|
|
...data.docInfo,
|
|
|
|
});
|
2020-10-01 20:57:23 +09:00
|
|
|
const _document = { obj: doc, wrapped: new Proxy(doc, proxyHandler) };
|
|
|
|
const app = new App({
|
|
|
|
send,
|
2020-12-04 08:39:50 +09:00
|
|
|
globalEval,
|
|
|
|
externalCall,
|
2020-10-01 20:57:23 +09:00
|
|
|
_document,
|
|
|
|
calculationOrder: data.calculationOrder,
|
2020-11-16 22:27:27 +09:00
|
|
|
proxyHandler,
|
|
|
|
...data.appInfo,
|
2020-10-01 20:57:23 +09:00
|
|
|
});
|
2020-12-04 08:39:50 +09:00
|
|
|
|
|
|
|
const util = new Util({ externalCall });
|
2020-10-01 20:57:23 +09:00
|
|
|
|
2020-12-08 03:22:14 +09:00
|
|
|
if (data.objects) {
|
|
|
|
for (const [name, objs] of Object.entries(data.objects)) {
|
|
|
|
const obj = objs[0];
|
|
|
|
obj.send = send;
|
|
|
|
obj.globalEval = globalEval;
|
2021-01-08 03:22:37 +09:00
|
|
|
obj.doc = _document;
|
|
|
|
obj.fieldPath = name;
|
2020-11-19 02:54:26 +09:00
|
|
|
let field;
|
|
|
|
if (obj.type === "radiobutton") {
|
|
|
|
const otherButtons = objs.slice(1);
|
|
|
|
field = new RadioButtonField(otherButtons, obj);
|
|
|
|
} else if (obj.type === "checkbox") {
|
|
|
|
const otherButtons = objs.slice(1);
|
|
|
|
field = new CheckboxField(otherButtons, obj);
|
|
|
|
} else {
|
|
|
|
field = new Field(obj);
|
|
|
|
}
|
|
|
|
|
2020-12-08 03:22:14 +09:00
|
|
|
const wrapped = new Proxy(field, proxyHandler);
|
|
|
|
doc._addField(name, wrapped);
|
2020-11-19 02:54:26 +09:00
|
|
|
const _object = { obj: field, wrapped };
|
|
|
|
for (const object of objs) {
|
|
|
|
app._objects[object.id] = _object;
|
|
|
|
}
|
2020-12-08 03:22:14 +09:00
|
|
|
}
|
2020-10-01 20:57:23 +09:00
|
|
|
}
|
|
|
|
|
2021-01-12 01:19:24 +09:00
|
|
|
const color = new Color();
|
|
|
|
|
2020-12-04 08:39:50 +09:00
|
|
|
globalThis.event = null;
|
|
|
|
globalThis.global = Object.create(null);
|
|
|
|
globalThis.app = new Proxy(app, proxyHandler);
|
2021-01-12 01:19:24 +09:00
|
|
|
globalThis.color = new Proxy(color, proxyHandler);
|
2020-12-04 08:39:50 +09:00
|
|
|
globalThis.console = new Proxy(new Console({ send }), proxyHandler);
|
|
|
|
globalThis.util = new Proxy(util, proxyHandler);
|
|
|
|
globalThis.border = Border;
|
|
|
|
globalThis.cursor = Cursor;
|
|
|
|
globalThis.display = Display;
|
|
|
|
globalThis.font = Font;
|
|
|
|
globalThis.highlight = Highlight;
|
|
|
|
globalThis.position = Position;
|
|
|
|
globalThis.scaleHow = ScaleHow;
|
|
|
|
globalThis.scaleWhen = ScaleWhen;
|
|
|
|
globalThis.style = Style;
|
|
|
|
globalThis.trans = Trans;
|
|
|
|
globalThis.zoomtype = ZoomType;
|
2020-11-16 22:27:27 +09:00
|
|
|
|
2021-02-24 23:46:03 +09:00
|
|
|
// Avoid to have a popup asking to update Acrobat.
|
|
|
|
globalThis.ADBE = {
|
|
|
|
Reader_Value_Asked: true,
|
|
|
|
Viewer_Value_Asked: true,
|
|
|
|
};
|
|
|
|
|
2021-01-12 01:19:24 +09:00
|
|
|
// AF... functions
|
|
|
|
const aform = new AForm(doc, app, util, color);
|
2020-10-01 20:57:23 +09:00
|
|
|
for (const name of Object.getOwnPropertyNames(AForm.prototype)) {
|
2020-12-10 23:38:31 +09:00
|
|
|
if (name !== "constructor" && !name.startsWith("_")) {
|
2020-12-04 08:39:50 +09:00
|
|
|
globalThis[name] = aform[name].bind(aform);
|
2020-10-01 20:57:23 +09:00
|
|
|
}
|
|
|
|
}
|
2020-12-04 08:39:50 +09:00
|
|
|
|
2021-01-12 01:19:24 +09:00
|
|
|
// Add global constants such as IDS_GREATER_THAN or RE_NUMBER_ENTRY_DOT_SEP
|
|
|
|
for (const [name, value] of Object.entries(GlobalConstants)) {
|
|
|
|
Object.defineProperty(globalThis, name, {
|
|
|
|
value,
|
|
|
|
writable: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Color functions
|
|
|
|
Object.defineProperties(globalThis, {
|
|
|
|
ColorConvert: {
|
|
|
|
value: color.convert.bind(color),
|
|
|
|
writable: true,
|
|
|
|
},
|
|
|
|
ColorEqual: {
|
|
|
|
value: color.equal.bind(color),
|
|
|
|
writable: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2020-12-16 22:04:22 +09:00
|
|
|
// The doc properties must live in the global scope too
|
|
|
|
const properties = Object.create(null);
|
|
|
|
for (const name of Object.getOwnPropertyNames(Doc.prototype)) {
|
|
|
|
if (name === "constructor" || name.startsWith("_")) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const descriptor = Object.getOwnPropertyDescriptor(Doc.prototype, name);
|
|
|
|
if (descriptor.get) {
|
|
|
|
properties[name] = {
|
|
|
|
get: descriptor.get.bind(doc),
|
|
|
|
set: descriptor.set.bind(doc),
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
properties[name] = {
|
|
|
|
value: Doc.prototype[name].bind(doc),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Object.defineProperties(globalThis, properties);
|
|
|
|
|
2020-12-04 08:39:50 +09:00
|
|
|
const functions = {
|
|
|
|
dispatchEvent: app._dispatchEvent.bind(app),
|
|
|
|
timeoutCb: app._evalCallback.bind(app),
|
|
|
|
};
|
|
|
|
|
|
|
|
return (name, args) => {
|
|
|
|
try {
|
|
|
|
functions[name](args);
|
|
|
|
} catch (error) {
|
|
|
|
const value = `${error.toString()}\n${error.stack}`;
|
|
|
|
send({ command: "error", value });
|
|
|
|
}
|
|
|
|
};
|
2020-10-01 20:57:23 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
export { initSandbox };
|