tor-browser

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

ContentTask.sys.mjs (4067B)


      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 const FRAME_SCRIPT = "resource://testing-common/content-task.js";
      8 
      9 /**
     10 * Keeps track of whether the frame script was already loaded.
     11 */
     12 var gFrameScriptLoaded = false;
     13 
     14 /**
     15 * Mapping from message id to associated promise.
     16 */
     17 var gPromises = new Map();
     18 
     19 /**
     20 * Incrementing integer to generate unique message id.
     21 */
     22 var gMessageID = 1;
     23 
     24 /**
     25 * This object provides the public module functions.
     26 */
     27 export var ContentTask = {
     28  /**
     29   * _testScope saves the current testScope from
     30   * browser-test.js. This is used to implement SimpleTest functions
     31   * like ok() and is() in the content process. The scope is only
     32   * valid for tasks spawned in the current test, so we keep track of
     33   * the ID of the first task spawned in this test (_scopeValidId).
     34   */
     35  _testScope: null,
     36  _scopeValidId: 0,
     37 
     38  /**
     39   * Creates and starts a new task in a browser's content.
     40   *
     41   * @param browser A xul:browser
     42   * @param arg A single serializable argument that will be passed to the
     43   *             task when executed on the content process.
     44   * @param task
     45   *        - A generator or function which will be serialized and sent to
     46   *          the remote browser to be executed. Unlike Task.spawn, this
     47   *          argument may not be an iterator as it will be serialized and
     48   *          sent to the remote browser.
     49   * @return {Promise}
     50   *   Resolves when the task finishes without errors.
     51   * @rejects An error message if execution fails.
     52   */
     53  spawn: function ContentTask_spawn(browser, arg, task) {
     54    // Load the frame script if needed.
     55    if (!gFrameScriptLoaded) {
     56      Services.mm.loadFrameScript(FRAME_SCRIPT, true);
     57      gFrameScriptLoaded = true;
     58    }
     59 
     60    let deferred = {};
     61    deferred.promise = new Promise((resolve, reject) => {
     62      deferred.resolve = resolve;
     63      deferred.reject = reject;
     64    });
     65 
     66    let id = gMessageID++;
     67    gPromises.set(id, deferred);
     68 
     69    browser.messageManager.sendAsyncMessage("content-task:spawn", {
     70      id,
     71      runnable: task.toString(),
     72      arg,
     73    });
     74 
     75    return deferred.promise;
     76  },
     77 
     78  setTestScope(scope) {
     79    this._testScope = scope;
     80    this._scopeValidId = gMessageID;
     81  },
     82 };
     83 
     84 var ContentMessageListener = {
     85  receiveMessage(aMessage) {
     86    let id = aMessage.data.id;
     87 
     88    if (id < ContentTask._scopeValidId) {
     89      throw new Error("test result returned after test finished");
     90    }
     91 
     92    if (aMessage.name == "content-task:complete") {
     93      let deferred = gPromises.get(id);
     94      gPromises.delete(id);
     95 
     96      if (aMessage.data.error) {
     97        deferred.reject(aMessage.data.error);
     98      } else {
     99        deferred.resolve(aMessage.data.result);
    100      }
    101    } else if (aMessage.name == "content-task:test-result") {
    102      let data = aMessage.data;
    103      ContentTask._testScope.record(
    104        data.condition,
    105        data.name,
    106        null,
    107        data.stack
    108      );
    109    } else if (aMessage.name == "content-task:test-info") {
    110      ContentTask._testScope.info(aMessage.data.name);
    111    } else if (aMessage.name == "content-task:test-todo") {
    112      ContentTask._testScope.todo(aMessage.data.expr, aMessage.data.name);
    113    } else if (aMessage.name == "content-task:test-todo_is") {
    114      ContentTask._testScope.todo_is(
    115        aMessage.data.a,
    116        aMessage.data.b,
    117        aMessage.data.name
    118      );
    119    }
    120  },
    121 };
    122 
    123 Services.mm.addMessageListener("content-task:complete", ContentMessageListener);
    124 Services.mm.addMessageListener(
    125  "content-task:test-result",
    126  ContentMessageListener
    127 );
    128 Services.mm.addMessageListener(
    129  "content-task:test-info",
    130  ContentMessageListener
    131 );
    132 Services.mm.addMessageListener(
    133  "content-task:test-todo",
    134  ContentMessageListener
    135 );
    136 Services.mm.addMessageListener(
    137  "content-task:test-todo_is",
    138  ContentMessageListener
    139 );