tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ChromeTask.js (4909B)


      1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 "use strict";
      8 
      9 function ChromeTask_ChromeScript() {
     10  /* eslint-env mozilla/chrome-script */
     11 
     12  "use strict";
     13 
     14  const { Assert: AssertCls } = ChromeUtils.importESModule(
     15    "resource://testing-common/Assert.sys.mjs"
     16  );
     17 
     18  addMessageListener("chrome-task:spawn", async function (aData) {
     19    let id = aData.id;
     20    let source = aData.runnable || "()=>{}";
     21 
     22    function getStack(aStack) {
     23      let frames = [];
     24      for (let frame = aStack; frame; frame = frame.caller) {
     25        frames.push(frame.filename + ":" + frame.name + ":" + frame.lineNumber);
     26      }
     27      return frames.join("\n");
     28    }
     29 
     30    /* eslint-disable no-unused-vars */
     31    var Assert = new AssertCls((err, message, stack) => {
     32      sendAsyncMessage("chrome-task:test-result", {
     33        id,
     34        condition: !err,
     35        name: err ? err.message : message,
     36        stack: getStack(err ? err.stack : stack),
     37      });
     38    });
     39 
     40    var ok = Assert.ok.bind(Assert);
     41    var is = Assert.equal.bind(Assert);
     42    var isnot = Assert.notEqual.bind(Assert);
     43 
     44    function todo(expr, name) {
     45      sendAsyncMessage("chrome-task:test-todo", { id, expr, name });
     46    }
     47 
     48    function todo_is(a, b, name) {
     49      sendAsyncMessage("chrome-task:test-todo_is", { id, a, b, name });
     50    }
     51 
     52    function info(name) {
     53      sendAsyncMessage("chrome-task:test-info", { id, name });
     54    }
     55    /* eslint-enable no-unused-vars */
     56 
     57    try {
     58      let sb = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal(), {
     59        sandboxPrototype: {
     60          __proto__: globalThis,
     61          Assert,
     62          ok,
     63          is,
     64          isnot,
     65          todo,
     66          todo_is,
     67          info,
     68        },
     69      });
     70      let runnable = Cu.evalInSandbox(`(() => (${source}))()`, sb);
     71      let result = await runnable.call(this, aData.arg);
     72      sendAsyncMessage("chrome-task:complete", {
     73        id,
     74        result,
     75      });
     76    } catch (ex) {
     77      sendAsyncMessage("chrome-task:complete", {
     78        id,
     79        error: ex.toString(),
     80      });
     81    }
     82  });
     83 }
     84 
     85 /**
     86 * This object provides the public module functions.
     87 */
     88 var ChromeTask = {
     89  /**
     90   * the ChromeScript if it has already been loaded.
     91   */
     92  _chromeScript: null,
     93 
     94  /**
     95   * Mapping from message id to associated promise.
     96   */
     97  _promises: new Map(),
     98 
     99  /**
    100   * Incrementing integer to generate unique message id.
    101   */
    102  _messageID: 1,
    103 
    104  /**
    105   * Creates and starts a new task in the chrome process.
    106   *
    107   * @param arg A single serializable argument that will be passed to the
    108   *             task when executed on the content process.
    109   * @param task
    110   *        - A generator or function which will be serialized and sent to
    111   *          the remote browser to be executed. Unlike Task.spawn, this
    112   *          argument may not be an iterator as it will be serialized and
    113   *          sent to the remote browser.
    114   * @return {Promise}
    115   *   Resolves when the task finishes without errors.
    116   * @rejects An error message if execution fails.
    117   */
    118  spawn: function ChromeTask_spawn(arg, task) {
    119    // Load the frame script if needed.
    120    let handle = ChromeTask._chromeScript;
    121    if (!handle) {
    122      handle = SpecialPowers.loadChromeScript(ChromeTask_ChromeScript);
    123      handle.addMessageListener("chrome-task:complete", ChromeTask.onComplete);
    124      handle.addMessageListener("chrome-task:test-result", ChromeTask.onResult);
    125      handle.addMessageListener("chrome-task:test-info", ChromeTask.onInfo);
    126      handle.addMessageListener("chrome-task:test-todo", ChromeTask.onTodo);
    127      handle.addMessageListener(
    128        "chrome-task:test-todo_is",
    129        ChromeTask.onTodoIs
    130      );
    131      ChromeTask._chromeScript = handle;
    132    }
    133 
    134    let deferred = {};
    135    deferred.promise = new Promise((resolve, reject) => {
    136      deferred.resolve = resolve;
    137      deferred.reject = reject;
    138    });
    139 
    140    let id = ChromeTask._messageID++;
    141    ChromeTask._promises.set(id, deferred);
    142 
    143    handle.sendAsyncMessage("chrome-task:spawn", {
    144      id,
    145      runnable: task.toString(),
    146      arg,
    147    });
    148 
    149    return deferred.promise;
    150  },
    151 
    152  onComplete(aData) {
    153    let deferred = ChromeTask._promises.get(aData.id);
    154    ChromeTask._promises.delete(aData.id);
    155 
    156    if (aData.error) {
    157      deferred.reject(aData.error);
    158    } else {
    159      deferred.resolve(aData.result);
    160    }
    161  },
    162 
    163  onResult(aData) {
    164    SimpleTest.record(aData.condition, aData.name);
    165  },
    166 
    167  onInfo(aData) {
    168    SimpleTest.info(aData.name);
    169  },
    170 
    171  onTodo(aData) {
    172    SimpleTest.todo(aData.expr, aData.name);
    173  },
    174 
    175  onTodoIs(aData) {
    176    SimpleTest.todo_is(aData.a, aData.b, aData.name);
    177  },
    178 };