/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; var subscriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"] .getService(Ci.mozIJSSubScriptLoader); /** * Start a new RIL worker. * * @param custom_ns * Namespace with symbols to be injected into the new worker * namespace. * * @return an object that represents the worker's namespace. * * @note that this does not start an actual worker thread. The worker * is executed on the main thread, within a separate namespace object. */ function newWorker(custom_ns) { let worker_ns = { importScripts: function() { Array.slice(arguments).forEach(function(script) { if (!script.startsWith("resource:")) { script = "resource://gre/modules/" + script; } subscriptLoader.loadSubScript(script, this); }, this); }, postRILMessage: function(message) { }, postMessage: function(message) { }, // Define these variables inside the worker scope so ES5 strict mode // doesn't flip out. onmessage: undefined, onerror: undefined, DEBUG: true }; // The 'self' variable in a worker points to the worker's own namespace. worker_ns.self = worker_ns; // Copy the custom definitions over. for (let key in custom_ns) { worker_ns[key] = custom_ns[key]; } // fake require() for toolkit/components/workerloader/require.js let require = (function() { return function require(script) { worker_ns.module = {}; worker_ns.importScripts(script); return worker_ns; } })(); Object.freeze(require); Object.defineProperty(worker_ns, "require", { value: require, enumerable: true, configurable: false }); // Load the RIL worker itself. worker_ns.importScripts("ril_worker.js"); // Register at least one client. worker_ns.ContextPool.registerClient({ clientId: 0 }); return worker_ns; } /** * Create a buffered RIL worker. * * @return A worker object that stores sending octets in a internal buffer. */ function newUint8Worker() { let worker = newWorker(); let index = 0; // index for read let buf = []; let context = worker.ContextPool._contexts[0]; context.Buf.writeUint8 = function(value) { buf.push(value); }; context.Buf.readUint8 = function() { return buf[index++]; }; context.Buf.seekIncoming = function(offset) { index += offset; }; context.Buf.getReadAvailable = function() { return buf.length - index; }; worker.debug = do_print; return worker; } /** * Create a worker that keeps posted chrome message. */ function newInterceptWorker() { let postedMessage; let worker = newWorker({ postRILMessage: function(data) { }, postMessage: function(message) { postedMessage = message; } }); return { get postedMessage() { return postedMessage; }, get worker() { return worker; } }; } /** * Create a parcel suitable for postRILMessage(). * * @param fakeParcelSize * Value to be written to parcel size field for testing * incorrect/incomplete parcel reading. Replaced with correct * one determined length of data if negative. * @param response * Response code of the incoming parcel. * @param request * Request code of the incoming parcel. * @param data * Extra data to be appended. * * @return an Uint8Array carrying all parcel data. */ function newIncomingParcel(fakeParcelSize, response, request, data) { const UINT32_SIZE = 4; const PARCEL_SIZE_SIZE = 4; let realParcelSize = data.length + 2 * UINT32_SIZE; let buffer = new ArrayBuffer(realParcelSize + PARCEL_SIZE_SIZE); let bytes = new Uint8Array(buffer); let writeIndex = 0; function writeUint8(value) { bytes[writeIndex] = value; ++writeIndex; } function writeInt32(value) { writeUint8(value & 0xff); writeUint8((value >> 8) & 0xff); writeUint8((value >> 16) & 0xff); writeUint8((value >> 24) & 0xff); } function writeParcelSize(value) { writeUint8((value >> 24) & 0xff); writeUint8((value >> 16) & 0xff); writeUint8((value >> 8) & 0xff); writeUint8(value & 0xff); } if (fakeParcelSize < 0) { fakeParcelSize = realParcelSize; } writeParcelSize(fakeParcelSize); writeInt32(response); writeInt32(request); // write parcel data for (let ii = 0; ii < data.length; ++ii) { writeUint8(data[ii]); } return bytes; } /** * Create a parcel buffer which represents the hex string. * * @param hexString * The HEX string to be converted. * * @return an Uint8Array carrying all parcel data. */ function hexStringToParcelByteArrayData(hexString) { let length = Math.ceil((hexString.length / 2)); let bytes = new Uint8Array(4 + length); bytes[0] = length & 0xFF; bytes[1] = (length >> 8) & 0xFF; bytes[2] = (length >> 16) & 0xFF; bytes[3] = (length >> 24) & 0xFF; for (let i = 0; i < length; i ++) { bytes[i + 4] = Number.parseInt(hexString.substr(i * 2, 2), 16); } return bytes; }