summaryrefslogtreecommitdiff
path: root/data/extensions/jsr@javascriptrestrictor/code_builders.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/jsr@javascriptrestrictor/code_builders.js')
-rw-r--r--data/extensions/jsr@javascriptrestrictor/code_builders.js759
1 files changed, 0 insertions, 759 deletions
diff --git a/data/extensions/jsr@javascriptrestrictor/code_builders.js b/data/extensions/jsr@javascriptrestrictor/code_builders.js
deleted file mode 100644
index 1d17849..0000000
--- a/data/extensions/jsr@javascriptrestrictor/code_builders.js
+++ /dev/null
@@ -1,759 +0,0 @@
-/** \file
- * \brief Functions that build code that modifies JS evironment provided to page scripts
- *
- * \author Copyright (C) 2019 Libor Polcak
- * \author Copyright (C) 2021 Giorgio Maone
- * \author Copyright (C) 2022 Marek Salon
- * \author Copyright (C) 2023 Martin Zmitko
- *
- * \license SPDX-License-Identifier: GPL-3.0-or-later
- */
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-//
-
-/**
- * Create IIFE to wrap the code in closure
- */
-function enclose_wrapping(code, ...args) {
- return `try{(function(...args) {${code}})(${args});} catch (e) {console.error(e)}`;
-}
-
-/**
- * Create wrapping that might be IIFE or a function that is immediately called and also available
- * for future.
- */
-function enclose_wrapping2(code, name, params, call_with_window) {
- if (name === undefined) {
- return enclose_wrapping(code);
- }
- return `function ${name}(${params}) {${code}}
- ${name}(${call_with_window ? "window" : ""});`
-}
-
-/**
- * Create code containing call of API counting function.
- */
-function create_counter_call(wrapper, type) {
- let {parent_object, parent_object_property} = wrapper;
- let resource = `${parent_object}.${parent_object_property}`;
- let args = wrapper.report_args ? "args.map(x => JSON.stringify(x))" : "[]"
- return `if (fp_enabled && fp_${type}_count < 1000) {
- var stack = undefined;
- if (fpdTrackCallers) {
- try {
- throw new Error("FPDCallerTracker");
- } catch (e) {
- stack = e.stack.toString();
- }
- }
- updateCount(${JSON.stringify(resource)}, "${type}", ${args}, stack);
- fp_${type}_count += 1;
- }`;
-}
-
-/**
- * This function create code (as string) that creates code that can be used to inject (or overwrite)
- * a function in the page context.
- */
-function define_page_context_function(wrapper) {
- let {parent_object, parent_object_property, original_function, replace_original_function} = wrapper;
- if (replace_original_function) {
- let lastDot = original_function.lastIndexOf(".");
- parent_object = original_function.substring(0, lastDot);
- parent_object_property = original_function.substring(lastDot + 1);
- }
- let originalF = original_function || `${parent_object}.${parent_object_property}`;
- let code = `
- let originalF = ${originalF};
- var fp_call_count = 0;
- let replacementF = function(${wrapper.wrapping_function_args}) {
- try {
- ${create_counter_call(wrapper, "call")}
- }
- catch (e) { /* No action: let the wrapper continue uninterupted. TODO: let the user decide? */ }`
-
- // if apply_if condition is present, we need to wrap for FPD anyhow
- if (wrapper.apply_if !== undefined) {
- code += `
- if (${wrapper.apply_if}) {
- ${wrapper.wrapping_function_body}
- }
- else {
- return originalF.call(this, ${wrapper.wrapping_function_args});
- }`
- }
- else {
- code += `${wrapper.wrapping_function_body}`
- }
- code += `
- };
- `;
-
- if (typeof browser_polyfill_used === "undefined") {
- code += `
- let innerF = replacementF;
- replacementF = function(...args) {
-
- // prepare callbacks
- args = args.map(a => typeof a === "function" ? WrapHelper.pageAPI(a) : a);
-
- let ret = WrapHelper.forPage(innerF.call(this, ...args));
- if (ret) {
- if (ret instanceof xrayWindow.Promise || ret instanceof WrapHelper.unX(xrayWindow).Promise) {
- ret = Promise.resolve(ret);
- }
- try {
- ret = WrapHelper.unX(ret);
- } catch (e) {}
- }
- return ret;
- };
- `;
- }
- code += `
- exportFunction(replacementF, ${parent_object}, {defineAs: '${parent_object_property}'});
- ${wrapper.post_replacement_code || ''}
- `;
-
- return enclose_wrapping2(code, wrapper.wrapping_code_function_name, wrapper.wrapping_code_function_params, wrapper.wrapping_code_function_call_window);
-}
-
-/**
- * This function creates code that assigns an already defined function to given property.
- */
-function generate_assign_function_code(code_spec_obj) {
- return `exportFunction(${code_spec_obj.export_function_name},
- ${code_spec_obj.parent_object},
- {defineAs: '${code_spec_obj.parent_object_property}'});
- `;
-}
-
-/**
- * This function wraps object properties using WrapHelper.defineProperties().
- */
-function generate_object_properties(code_spec_obj, fpd_only) {
- var code = `
- if (!("${code_spec_obj.parent_object_property}" in ${code_spec_obj.parent_object})) {
- // Do not wrap an object that is not defined, e.g. because it is experimental feature.
- // This should reduce fingerprintability.
- return;
- }
- `;
- for (let assign of code_spec_obj.wrapped_objects || []) {
- code += `var ${assign.wrapped_name} = window.${assign.original_name};`;
- }
- code += `
- {
- let descriptor = WrapHelper.getDescriptor(${code_spec_obj.parent_object}, "${code_spec_obj.parent_object_property}");
- `
- for (let wrap_spec of code_spec_obj.wrapped_properties) {
- // variable name used for distinguishing between different original properties of the same wrapper
- var original_property = `originalP_${wrap_spec.property_name}`;
-
- var counting_wrapper = `
- function(...args) {
- ${create_counter_call(code_spec_obj, wrap_spec.property_name)}
-
- // checks type of underlying wrapper/definition and returns it (no changes to semantics)
- if (typeof (${fpd_only ? original_property : wrap_spec.property_value}) === 'function') {
- return (${fpd_only ? original_property : wrap_spec.property_value}).bind(this)(...args);
- }
- else {
- return (${fpd_only ? original_property : wrap_spec.property_value});
- }
- }
- `;
-
- if (fpd_only) {
- code += `var ${original_property} = descriptor["${wrap_spec.property_name}"];`;
- }
-
- code += `
- originalPDF = descriptor["${wrap_spec.property_name}"];
- var fp_${wrap_spec.property_name}_count = 0;
- replacementPD = ${counting_wrapper};
- descriptor["${wrap_spec.property_name}"] = replacementPD;
- `;
- }
- code += `WrapHelper.defineProperty(${code_spec_obj.parent_object},
- "${code_spec_obj.parent_object_property}", descriptor);
- }`;
- return code;
-}
-
-/**
- * This function removes a property.
- */
-function generate_delete_properties(code_spec_obj) {
- var code = `
- `;
- for (prop of code_spec_obj.delete_properties) {
- code += `
- if ("${prop}" in ${code_spec_obj.parent_object}) {
- // Delete only properties that are available.
- // The if should be safe to be deleted but it can possibly reduce fingerprintability
- WrapHelper.defineProperty(
- ${code_spec_obj.parent_object},
- "${prop}", {get: undefined, set: undefined, configurable: false, enumerable: false}
- );
- }
- `
- }
- return code;
-}
-
-/**
- * This function generates code that makes an assignment.
- */
-function generate_assignement(code_spec_obj) {
- return `${code_spec_obj.parent_object}.${code_spec_obj.parent_object_property} = ${code_spec_obj.value};`
-}
-
-/**
- * This function builds the wrapping code.
- */
-var build_code = function(wrapper, ...args) {
- let post_wrapping_functions = {
- function_define: define_page_context_function,
- function_export: generate_assign_function_code,
- object_properties: generate_object_properties,
- delete_properties: generate_delete_properties,
- assign: generate_assignement,
- };
-
- let target = `${wrapper.parent_object}.${wrapper.parent_object_property}`;
- let code = "";
-
- {
- // Do not wrap an object that is not defined, e.g. because it is experimental feature.
- // This should reduce fingerprintability.
- let objPath = [], undefChecks = [];
- for (leaf of target.split('.')) {
- undefChecks.push(
- objPath.length ? `!("${leaf}" in ${objPath.join('.')})` // avoids e.g. Event.prototype.timeStamp from throwing "Illegal invocation"
- : `typeof ${leaf} === "undefined"`
- );
- objPath.push(leaf);
- }
-
- code += `
- try {
- if (${undefChecks.join(" || ")}) return;
- } catch (e) {
- return;
- }`;
- }
-
- for (let {original_name = target, wrapped_name, callable_name} of wrapper.wrapped_objects || []) {
- if (original_name !== target) {
- code += `
- if (typeof ${original_name} === undefined) return;
- `;
- }
- if (wrapped_name) {
- code += `var ${wrapped_name} = window.${original_name};`;
- }
- if (callable_name) {
- code += `var ${callable_name} = WrapHelper.pageAPI(window.${original_name});`;
- }
- }
- code += `
- ${wrapper.helping_code || ''}`;
-
- if (wrapper.wrapping_function_body){
- code += `${define_page_context_function(wrapper)}`;
- }
-
- let build_post_normal = () => {
- if (wrapper["post_wrapping_code"] !== undefined) {
- for (code_spec of wrapper["post_wrapping_code"]) {
- if (code_spec.apply_if !== undefined) {
- code += `if (${code_spec.apply_if}) {`
- }
- code += post_wrapping_functions[code_spec.code_type](code_spec);
- if (code_spec.apply_if !== undefined) {
- code += "}";
- }
- // if not wrapped because of apply_if condition in post wrapping object, still needs to be wrapped for FPD
- if (code_spec.apply_if !== undefined && code_spec.code_type == "object_properties") {
- code += "else {" + generate_object_properties(code_spec, true) + "}";
- }
- }
- }
- }
-
- let build_post_fpd = () => {
- if (wrapper["post_wrapping_code"] !== undefined) {
- for (code_spec of wrapper["post_wrapping_code"]) {
- // if not wrapped because of apply_if condition in post wrapping object, still needs to be wrapped for FPD
- if (code_spec.apply_if !== undefined && code_spec.code_type == "object_properties") {
- code += generate_object_properties(code_spec, true);
- }
- }
- }
- }
-
- // if apply_if is present in main wrapper object and contains post wrapping code -> wrap for FPD only if condition is FALSE
- if (wrapper.apply_if !== undefined) {
- code += `if (${wrapper.apply_if}) {`
- build_post_normal();
- code += `} else {`
- build_post_fpd();
- code += `}`
- }
- else {
- build_post_normal();
- }
-
- if (wrapper["wrapper_prototype"] !== undefined) {
- let source = wrapper.wrapper_prototype;
- code += `if (${target.prototype} !== ${source.prototype}) { // prevent cyclic __proto__ errors on Proxy
- Object.setPrototypeOf(${target}, ${source});
- }`;
- }
- if (wrapper.freeze !== undefined) {
- code += `
- if (${wrapper.freeze}) {
- Object.freeze(${wrapper.parent_object}.${wrapper.parent_object_property});
- }
- `;
- }
-
- return enclose_wrapping(code, ...args);
-};
-
-/**
- * Transform wrapping arrays into injectable code.
- */
-function wrap_code(wrappers) {
- if (wrappers.length === 0) {
- return; // Nothing to wrap
- }
-
- let build = (wrapper) => {
- try {
- return build_code(build_wrapping_code[wrapper[0]], wrapper.slice(1));
- } catch (e) {
- console.error(e);
- return "";
- }
- };
-
- let fpd_placeholder = "\n\n// FPD_S\n\n// FPD_E"
- return generate_code(joinWrappingCode(wrappers.map(x => build(x))) + fpd_placeholder);
-}
-
-/**
- * Join array of wrapping codes into single string.
- */
-let joinWrappingCode = code => {
- return code.join("\n").replace(/\bObject\.(create|definePropert)/g, "WrapHelper.$1");
-}
-
-/**
- * Insert WebAssembly initialization code into wrapped injection code.
- */
-function insert_wasm_code(code) {
- let wasm_code = (() => {
- const wasm_memory = new WebAssembly.Memory({initial: 1});
- // Memory layout:
- // +-----------------+--------------+----------+---------------------------------------- - -
- // | CRC table | Xoring table | Reserved | Data
- // | 256 * u16 | 8 * u32 | |
- // +-----------------+--------------+----------+---------------------------------------- - -
- // 0 512 544 1024
- const crc_offset = 0;
- const xoring_offset = 512;
- const reserved_offset = 544;
- const data_offset = 1024;
-
- WebAssembly.instantiateStreaming(fetch("/* WASM_URL */"), {env: {memory: wasm_memory}}).then(result => {
- new Uint16Array(wasm_memory.buffer, crc_offset, crc16_table.length).set(crc16_table);
- const xoring = new Uint32Array(wasm_memory.buffer, xoring_offset, 8);
- for (let i = 0; i < 64; i += 8) {
- xoring[i / 8] = parseInt(domainHash.slice(i, i + 8), 16) >>> 0;
- }
-
- wasm = {
- // Getter and setter for data in WASM memory. Because we need access from page context,
- // we can't just get a memory view and use it directly. The view needs to be exported to be
- // usable in the page context on Firefox.
- // This means that views returned by wasm.get() aren't actually views of the WASM memory,
- // but rather copies of the data and modifying them won't affect the underlying memory.
- // We can't export the wasm memory directly either, it is bound to the WASM instance and
- // it's not possible to export the instance as well.
- // For constructing views of the correct type, we can't use constructors passed from page context,
- // a content script constructor must be used. For now, we use just 2 types, so passing a bool
- // to differentiate is enough.
- get(length, offset = 0, float = false) {
- if (float) {
- return WrapHelper.forPage(new Float32Array(wasm_memory.buffer, data_offset + offset, length));
- } else {
- return WrapHelper.forPage(new Uint8Array(wasm_memory.buffer, data_offset + offset, length));
- }
- },
- set(data, offset = 0, float = false) {
- if (float) {
- new Float32Array(wasm_memory.buffer, data_offset + offset, data.length).set(data);
- } else {
- new Uint8Array(wasm_memory.buffer, data_offset + offset, data.length).set(data);
- }
- },
- // Grow the WASM memory if needed.
- grow(needed_bytes) {
- const memory_size = wasm_memory.buffer.byteLength;
- needed_bytes += data_offset;
- if (memory_size < needed_bytes) {
- try {
- wasm_memory.grow(Math.ceil((needed_bytes - memory_size) / 65536));
- } catch (e) {
- console.warn("Failed to grow WASM memory, falling back to JS implementation", e);
- return false;
- }
- }
- return true;
- },
- // Make WASM exported functions available to wrappers.
- ...result.instance.exports,
- ready: true
- }
- Object.freeze(wasm);
- }).catch(e => {
- console.warn("Failed to instantiate WASM farbling module, falling back to JS implementation", e);
- });
- }).toString().replace("/* WASM_URL */", browser.runtime.getURL("farble.wasm"));
-
- return code.replace("// WASM_CODE //", `(${wasm_code})()`);
-}
-
-/**
- * Append wrapped codes to NSCL helpers and create injectable code.
- */
-function generate_code(wrapped_code) {
- let code = (w => {
-
- // cross-wrapper globals
- let xrayWindow = window; // the "privileged" xray window wrapper in Firefox
- let WrapHelper; // xray boundary helper
- {
- const XRAY = (xrayWindow.top !== unwrappedWindow.top && typeof XPCNativeWrapper !== "undefined");
- let privilegedToPage = new WeakMap();
- let pageReady = new WeakSet();
-
- let promise = obj => obj.then(r => forPage(r));
-
- forPage = obj => {
- if (typeof obj !== "object" && typeof obj !== "function" || obj === null
- || pageReady.has(obj)) return obj;
- if (privilegedToPage.has(obj)) return privilegedToPage.get(obj); // keep clone identity
- let ret = obj; // fallback
- if (XRAY) {
- if (obj instanceof xrayWindow.Promise) {
- return promise(obj);
- }
- if (obj instanceof unX(xrayWindow).Promise) {
- return new xrayWindow.Promise((resolve, reject) => {
- unX(xrayWindow).Promise.prototype.then.call(obj,
- forPage(r => {
- if (r.wrappedJSObject && r.wrappedJSObject === unX(r)) {
- r = unX(r)
- } else r = forPage(r);
- resolve(r);
- }
- ), forPage(e => reject(e)))
- });
- }
- try {
- if (obj.wrappedJSObject && obj.wrappedJSObject === unX(obj)) {
- return obj;
- }
- } catch (e) {}
- try {
- ret = cloneInto(obj, unX(xrayWindow), {cloneFunctions: true, wrapReflectors: true});
- } catch (e) {
- // can't be cloned: must be a Proxy
- }
- } else {
- // Chromium: just use patchWindow's exportFunction() to make our wrappers look like native functions
- if (typeof obj === "function") {
- ret = exportFunction(obj, unX(xrayWindow));
- }
- }
- pageReady.add(ret);
- privilegedToPage.set(obj, ret);
- return ret;
- }
-
- let fixProp = (d, prop, obj) => {
- for (let accessor of ["set", "get"]) {
- if (typeof d[accessor] === "function") {
- let f = d[accessor];
- d[accessor] = exportFunction(d[accessor], obj, {defineAs: `${accessor} ${prop}`});
- }
- }
- if (typeof d.value === "object") d.value = forPage(d.value);
- return d;
- };
- let OriginalProxy = unwrappedWindow.Proxy;
- let Proxy = OriginalProxy;
- let pageAPI, unX;
- if (XRAY) {
-
- unX = o => XPCNativeWrapper.unwrap(o);
-
- // automatically export Proxy constructor parameters
- let proxyConstructorHandler = forPage({
- construct(targetConstructor, args) {
- let [target, handler] = unX(args);
- let selfProxy = !!(target === WrapHelper.Proxy && handler.construct);
- if (selfProxy) {
- let {construct} = handler;
- handler.construct = (target, args) => {
- let proxy = construct(target, unX(args));
- pageReady.add(proxy);
- return proxy;
- }
- }
-
- target = forPage(target);
- handler = forPage(handler);
- let proxy = new targetConstructor(target, handler);
- pageReady.add(proxy);
- return proxy;
- },
- });
- Proxy = new OriginalProxy(OriginalProxy, proxyConstructorHandler);
- let then;
- let apiHandler = {
- apply(target, thisArg, args) {
- let pa = unX(args);
- for (let j = pa.length; j-- > 0;) {
- let a = pa[j];
- if (a && unX(a) === a) {
- pa[j] = forPage(a);
- } else if (typeof a === "function") {
- pa[j] = new Proxy(a, apiHandler);
- }
- }
- let ret = target.apply(thisArg, pa);
- if (ret) {
- if (ret instanceof xrayWindow.Promise) {
- then = then || (then = new Proxy(xrayWindow.Promise.prototype.then, apiHandler));
- if (ret.wrappedJSObject) {
- let p = unX(ret);
- if (p === ret.wrappedJSObject) {
- p.then = then
- ret = p;
- }
- }
- } else {
- ret = forPage(ret);
- }
- }
- return ret;
- }
- };
-
-
-
- pageAPI = f => {
- if (typeof f !== "function") return f;
- return new Proxy(f, apiHandler);
- }
- } else {
- pageAPI = unX = f => f;
- }
-
- let overlay;
- {
- let overlayProtos = new WeakMap();
- let overlayObjects = new WeakMap();
- overlay = (obj, data) => {
- obj = unX(obj);
- let proto = obj.__proto__;
- let proxiedProps = overlayProtos.get(proto);
- if (!proxiedProps) overlayProtos.set(proto, proxiedProps = {});
- let props = Object.getOwnPropertyDescriptors(data);
- for (let p in props) {
- if (p in proxiedProps) continue;
- for (let rootProto = proto; ;) {
- let protoProps = Object.getOwnPropertyDescriptors(rootProto);
- let protoProp = protoProps[p];
- if (!protoProp) {
- rootProto = rootProto.__proto__;
- if (rootProto) continue;
- }
- if (protoProp) {
- let original;
- if (protoProp.get) {
- let getterHandler = forPage({
- apply(target, thisArg, args) {
- let obj = unX(thisArg);
- if (overlayObjects.has(obj)) {
- let data = overlayObjects.get(obj);
- return forPage(data[p]);
- }
- return target.apply(thisArg, args);
- }
- });
- let original = protoProp.get;
- protoProp.get = new Proxy(protoProp.get, getterHandler);
- } else if (typeof protoProp.value === "function") {
- original = protoProp.value;
- let methodHandler = forPage({
- apply(target, thisArg, args) {
- let obj = unX(thisArg);
- if (overlayObjects.has(obj)) {
- let data = overlayObjects.get(obj);
- return forPage(data[p].apply(thisArg, args));
- }
- return target.apply(thisArg, args);
- }
- });
- protoProp.value = new Proxy(protoProp.value, methodHandler);
- } else {
- protoProp = null;
- }
- if (protoProp) {
- Reflect.defineProperty(rootProto, p, protoProp);
- proxiedProps[p] = {rootProto, original, protoProp};
- break;
- }
- }
- Reflect.defineProperty(obj, p, forPage(props[p]));
- break;
- }
- }
- overlayObjects.set(obj, data);
- return obj;
- }
- }
- let createObj = unX(xrayWindow).Object.create;
- WrapHelper = {
- XRAY, // boolean, are we in a xray environment (i.e. on Firefox)?
- shared: {}, // shared storage object for in inter-wrapper coordination
-
- // WrapHelper.forPage() can be used by "complex" proxies to explicitly
- // prepare an object/function created in Firefox's sandboxed content script environment
- // to be consumed/called from the page context, and to make replacements for native
- // objects and functions provided by the wrappers look as much native as possible.
- // in most cases, however, this gets automated by the code builders replacing
- // Object methods found in the wrapper sources with their WrapHelper counterparts
- // and by proxying "callable_name" functions through WrapHelper.pageAPI().
- forPage,
- _forPage: x => x, // dummy for easily testing out the preparation
- isForPage: obj => pageReady.has(obj),
- unX, // safely waives xray wrappers
- // xray-aware Object creation helpers, mostly used transparently by the code builders
- defineProperty(obj, prop, descriptor, ...args) {
- obj = unX(obj);
- return Object.defineProperty(obj, prop, fixProp(descriptor, prop, obj), ...args);
- },
- defineProperties(obj, descriptors, ...args) {
- obj = unX(obj);
- for (let [prop, d] of Object.entries(descriptors)) {
- descriptors[prop] = fixProp(d, prop, obj);
- }
- return Object.defineProperties(obj, descriptors, ...args);
- },
- create(proto, descriptors) {
- let unwrappedProto = unX(proto);
- let obj = unX(createObj(unwrappedProto));
- try {
- if (proto && !obj.__proto__) {
- obj = Object.create(XPCNativeWrapper(proto));
- }
- } catch (e) {
- // access denied to obj.__proto__, wrappers mismatch
- obj = forPage(Object.create(proto));
- }
- return descriptors ? this.defineProperties(obj, descriptors) && obj : obj;
- },
- getDescriptor(obj, prop) {
- let descriptor = Object.getOwnPropertyDescriptor(obj, prop);
- if (!descriptor) {
- // let's traverse the prototype chain in search of this property
- for (let proto = Object.getPrototypeOf(obj); proto; proto = Object.getPrototypeOf(obj)) {
- if (descriptor = Object.getOwnPropertyDescriptor(proto, prop)) {
- obj = unX(obj);
- break;
- }
- }
- if (!descriptor) descriptor = {
- // Originally not a descriptor, fallback
- enumerable: true,
- configurable: true,
- };
- }
- return descriptor;
- },
-
- // WrapHelper.overlay(obj, data)
- // Proxies the prototype of the obj object in order to return the properties of the data object
- // as if they were native properties (e.g. as if they were returned by getters on the prototype chain,
- // rather than defined on the instance).
- // This allows spoofing some native objects data in a less detectable / fingerprintable way than using
- // Object.defineProperty(). See wrappingS-MCS.js for an example.
- overlay,
- // WrapHelper.pageAPI(f)
- // Proxies the function/method f so that arguments and return values, and especially callbacks and
- // Promise objects, are recursively managed in order to transparently marshal objects back
- // and forth Firefox's sandbox for extensions and the page scripts.
- pageAPI,
- // the original Proxy constructor
- OriginalProxy,
- // our xray-aware proxied Proxy constructor
- Proxy,
- };
- Object.freeze(WrapHelper);
- }
-
- // The object available to wrappers later containing farbling WASM optmitimized functions if enabled
- let wasm = Object.freeze({ready: false});
-
- // Farbling WebAssembly module initialization placeholder
- // WASM_CODE //
-
- with(unwrappedWindow) {
- let window = unwrappedWindow;
- let {Proxy} = WrapHelper;
- let {Promise, Object, Array, JSON} = xrayWindow;
-
- // add flag variable that determines whether messages should be sent
- let fp_enabled = false;
-
- (function () {
- let {port} = env;
- function updateCount(wrapperName, wrapperType, wrapperArgs, stack) {
- port.postMessage({
- wrapperName,
- wrapperType,
- wrapperArgs,
- stack
- });
- }
- try {
- // WRAPPERS //
- } finally {
- // cleanup environment if necessary
- }
- })();
-
- // after injection code completed, allow messages (calls from wrappers won't be counted)
- fp_enabled = true;
- }
- }).toString().replace('// WRAPPERS //', wrapped_code)
-
- return `(${code})();`;
-}