michael@0: /* Any copyright is dedicated to the Public Domain.
michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0:
michael@0: "use strict";
michael@0:
michael@0: const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
michael@0:
michael@0:
michael@0: let subscriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
michael@0: .getService(Ci.mozIJSSubScriptLoader);
michael@0:
michael@0: /**
michael@0: * Start a new RIL worker.
michael@0: *
michael@0: * @param custom_ns
michael@0: * Namespace with symbols to be injected into the new worker
michael@0: * namespace.
michael@0: *
michael@0: * @return an object that represents the worker's namespace.
michael@0: *
michael@0: * @note that this does not start an actual worker thread. The worker
michael@0: * is executed on the main thread, within a separate namespace object.
michael@0: */
michael@0: function newWorker(custom_ns) {
michael@0: let worker_ns = {
michael@0: importScripts: function() {
michael@0: Array.slice(arguments).forEach(function(script) {
michael@0: if (!script.startsWith("resource:")) {
michael@0: script = "resource://gre/modules/" + script;
michael@0: }
michael@0: subscriptLoader.loadSubScript(script, this);
michael@0: }, this);
michael@0: },
michael@0:
michael@0: postRILMessage: function(message) {
michael@0: },
michael@0:
michael@0: postMessage: function(message) {
michael@0: },
michael@0:
michael@0: // Define these variables inside the worker scope so ES5 strict mode
michael@0: // doesn't flip out.
michael@0: onmessage: undefined,
michael@0: onerror: undefined,
michael@0:
michael@0: DEBUG: true
michael@0: };
michael@0: // The 'self' variable in a worker points to the worker's own namespace.
michael@0: worker_ns.self = worker_ns;
michael@0:
michael@0: // Copy the custom definitions over.
michael@0: for (let key in custom_ns) {
michael@0: worker_ns[key] = custom_ns[key];
michael@0: }
michael@0:
michael@0: // fake require() for toolkit/components/workerloader/require.js
michael@0: let require = (function() {
michael@0: return function require(script) {
michael@0: worker_ns.module = {};
michael@0: worker_ns.importScripts(script);
michael@0: return worker_ns;
michael@0: }
michael@0: })();
michael@0:
michael@0: Object.freeze(require);
michael@0: Object.defineProperty(worker_ns, "require", {
michael@0: value: require,
michael@0: enumerable: true,
michael@0: configurable: false
michael@0: });
michael@0:
michael@0: // Load the RIL worker itself.
michael@0: worker_ns.importScripts("ril_worker.js");
michael@0:
michael@0: // Register at least one client.
michael@0: worker_ns.ContextPool.registerClient({ clientId: 0 });
michael@0:
michael@0: return worker_ns;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Create a parcel suitable for postRILMessage().
michael@0: *
michael@0: * @param fakeParcelSize
michael@0: * Value to be written to parcel size field for testing
michael@0: * incorrect/incomplete parcel reading. Replaced with correct
michael@0: * one determined length of data if negative.
michael@0: * @param response
michael@0: * Response code of the incoming parcel.
michael@0: * @param request
michael@0: * Request code of the incoming parcel.
michael@0: * @param data
michael@0: * Extra data to be appended.
michael@0: *
michael@0: * @return an Uint8Array carrying all parcel data.
michael@0: */
michael@0: function newIncomingParcel(fakeParcelSize, response, request, data) {
michael@0: const UINT32_SIZE = 4;
michael@0: const PARCEL_SIZE_SIZE = 4;
michael@0:
michael@0: let realParcelSize = data.length + 2 * UINT32_SIZE;
michael@0: let buffer = new ArrayBuffer(realParcelSize + PARCEL_SIZE_SIZE);
michael@0: let bytes = new Uint8Array(buffer);
michael@0:
michael@0: let writeIndex = 0;
michael@0: function writeUint8(value) {
michael@0: bytes[writeIndex] = value;
michael@0: ++writeIndex;
michael@0: }
michael@0:
michael@0: function writeInt32(value) {
michael@0: writeUint8(value & 0xff);
michael@0: writeUint8((value >> 8) & 0xff);
michael@0: writeUint8((value >> 16) & 0xff);
michael@0: writeUint8((value >> 24) & 0xff);
michael@0: }
michael@0:
michael@0: function writeParcelSize(value) {
michael@0: writeUint8((value >> 24) & 0xff);
michael@0: writeUint8((value >> 16) & 0xff);
michael@0: writeUint8((value >> 8) & 0xff);
michael@0: writeUint8(value & 0xff);
michael@0: }
michael@0:
michael@0: if (fakeParcelSize < 0) {
michael@0: fakeParcelSize = realParcelSize;
michael@0: }
michael@0: writeParcelSize(fakeParcelSize);
michael@0:
michael@0: writeInt32(response);
michael@0: writeInt32(request);
michael@0:
michael@0: // write parcel data
michael@0: for (let ii = 0; ii < data.length; ++ii) {
michael@0: writeUint8(data[ii]);
michael@0: }
michael@0:
michael@0: return bytes;
michael@0: }
michael@0:
michael@0: /**
michael@0: *
michael@0: */
michael@0: let ril_ns;
michael@0: function newRadioInterface() {
michael@0: if (!ril_ns) {
michael@0: ril_ns = {};
michael@0: subscriptLoader.loadSubScript("resource://gre/components/RadioInterfaceLayer.js", ril_ns);
michael@0: }
michael@0:
michael@0: return {
michael@0: __proto__: ril_ns.RadioInterface.prototype,
michael@0: };
michael@0: }
michael@0:
michael@0: /**
michael@0: * Test whether specified function throws exception with expected
michael@0: * result.
michael@0: *
michael@0: * @param func
michael@0: * Function to be tested.
michael@0: * @param message
michael@0: * Message of expected exception. null
for no throws.
michael@0: * @param stack
michael@0: * Optional stack object to be printed. null
for
michael@0: * Components#stack#caller.
michael@0: */
michael@0: function do_check_throws(func, message, stack)
michael@0: {
michael@0: if (!stack)
michael@0: stack = Components.stack.caller;
michael@0:
michael@0: try {
michael@0: func();
michael@0: } catch (exc) {
michael@0: if (exc.message === message) {
michael@0: return;
michael@0: }
michael@0: do_throw("expecting exception '" + message
michael@0: + "', caught '" + exc.message + "'", stack);
michael@0: }
michael@0:
michael@0: if (message) {
michael@0: do_throw("expecting exception '" + message + "', none thrown", stack);
michael@0: }
michael@0: }
michael@0: