tor-browser

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

common_postMessages.js (10066B)


      1 /* eslint-disable mozilla/no-comparison-or-assignment-inside-ok */
      2 
      3 function getType(a) {
      4  if (a === null || a === undefined) {
      5    return "null";
      6  }
      7 
      8  if (Array.isArray(a)) {
      9    return "array";
     10  }
     11 
     12  if (typeof a == "object") {
     13    return "object";
     14  }
     15 
     16  if (
     17    SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported() &&
     18    a instanceof WebAssembly.Module
     19  ) {
     20    return "wasm";
     21  }
     22 
     23  return "primitive";
     24 }
     25 
     26 function compare(a, b) {
     27  is(getType(a), getType(b), "Type matches");
     28 
     29  var type = getType(a);
     30  if (type == "array") {
     31    is(a.length, b.length, "Array.length matches");
     32    for (var i = 0; i < a.length; ++i) {
     33      compare(a[i], b[i]);
     34    }
     35 
     36    return;
     37  }
     38 
     39  if (type == "object") {
     40    ok(a !== b, "They should not match");
     41 
     42    var aProps = [];
     43    for (var p in a) {
     44      aProps.push(p);
     45    }
     46 
     47    var bProps = [];
     48    for (var p in b) {
     49      bProps.push(p);
     50    }
     51 
     52    is(aProps.length, bProps.length, "Props match");
     53    is(aProps.sort().toString(), bProps.sort().toString(), "Props names match");
     54 
     55    for (var p in a) {
     56      compare(a[p], b[p]);
     57    }
     58 
     59    return;
     60  }
     61 
     62  if (type == "wasm") {
     63    var wasmA = new WebAssembly.Instance(a);
     64    ok(wasmA instanceof WebAssembly.Instance, "got an instance");
     65 
     66    var wasmB = new WebAssembly.Instance(b);
     67    ok(wasmB instanceof WebAssembly.Instance, "got an instance");
     68 
     69    ok(wasmA.exports.foo() === wasmB.exports.foo(), "Same result!");
     70    ok(wasmB.exports.foo() === 42, "We want 42");
     71  }
     72 
     73  if (type != "null") {
     74    is(a, b, "Same value");
     75  }
     76 }
     77 
     78 var clonableObjects = [
     79  { target: "all", data: "hello world" },
     80  { target: "all", data: 123 },
     81  { target: "all", data: null },
     82  { target: "all", data: true },
     83  { target: "all", data: new Date() },
     84  { target: "all", data: [1, "test", true, new Date()] },
     85  {
     86    target: "all",
     87    data: { a: true, b: null, c: new Date(), d: [true, false, {}] },
     88  },
     89  { target: "all", data: new Blob([123], { type: "plain/text" }) },
     90  { target: "all", data: new ImageData(2, 2) },
     91 ];
     92 
     93 function create_fileList() {
     94  var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js");
     95  var script = SpecialPowers.loadChromeScript(url);
     96 
     97  function onOpened(message) {
     98    var fileList = document.getElementById("fileList");
     99    SpecialPowers.wrap(fileList).mozSetFileArray([message.file]);
    100 
    101    // Just a simple test
    102    var domFile = fileList.files[0];
    103    is(domFile.name, "prefs.js", "fileName should be prefs.js");
    104 
    105    clonableObjects.push({ target: "all", data: fileList.files });
    106    script.destroy();
    107    next();
    108  }
    109 
    110  script.addMessageListener("file.opened", onOpened);
    111  script.sendAsyncMessage("file.open");
    112 }
    113 
    114 function create_directory() {
    115  if (navigator.userAgent.toLowerCase().includes("Android")) {
    116    next();
    117    return;
    118  }
    119 
    120  var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js");
    121  var script = SpecialPowers.loadChromeScript(url);
    122 
    123  function onOpened(message) {
    124    var fileList = document.getElementById("fileList");
    125    SpecialPowers.wrap(fileList).mozSetDirectory(message.dir);
    126 
    127    SpecialPowers.wrap(fileList)
    128      .getFilesAndDirectories()
    129      .then(function (list) {
    130        list = SpecialPowers.unwrap(list);
    131        // Just a simple test
    132        is(list.length, 1, "This list has 1 element");
    133        ok(list[0] instanceof Directory, "We have a directory.");
    134 
    135        clonableObjects.push({ target: "all", data: list[0] });
    136        script.destroy();
    137        next();
    138      });
    139  }
    140 
    141  script.addMessageListener("dir.opened", onOpened);
    142  script.sendAsyncMessage("dir.open");
    143 }
    144 
    145 function create_wasmModule() {
    146  info("Checking if we can play with WebAssembly...");
    147 
    148  if (!SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported()) {
    149    next();
    150    return;
    151  }
    152 
    153  ok(WebAssembly, "WebAssembly object should exist");
    154  ok(WebAssembly.compile, "WebAssembly.compile function should exist");
    155 
    156  /*
    157    js -e '
    158      t = wasmTextToBinary(`
    159        (module
    160          (func $foo (result i32) (i32.const 42))
    161          (export "foo" (func $foo))
    162        )
    163      `);
    164      print(t)
    165    '
    166  */
    167  // prettier-ignore
    168  const fooModuleCode = new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,127,3,2,1,0,7,7,1,3,102,111,111,0,0,10,6,1,4,0,65,42,11,0,13,4,110,97,109,101,1,6,1,0,3,102,111,111]);
    169 
    170  WebAssembly.compile(fooModuleCode).then(
    171    m => {
    172      ok(m instanceof WebAssembly.Module, "The WasmModule has been compiled.");
    173      clonableObjects.push({ target: "sameProcess", data: m });
    174      next();
    175    },
    176    () => {
    177      ok(false, "The compilation of the wasmModule failed.");
    178    }
    179  );
    180 }
    181 
    182 function runTests(obj) {
    183  ok(
    184    "clonableObjectsEveryWhere" in obj &&
    185      "clonableObjectsSameProcess" in obj &&
    186      "transferableObjects" in obj &&
    187      (obj.clonableObjectsEveryWhere ||
    188        obj.clonableObjectsSameProcess ||
    189        obj.transferableObjects),
    190    "We must run some test!"
    191  );
    192 
    193  // cloning tests - everyWhere
    194  new Promise(function (resolve, reject) {
    195    var clonableObjectsId = 0;
    196    function runClonableTest() {
    197      if (clonableObjectsId >= clonableObjects.length) {
    198        resolve();
    199        return;
    200      }
    201 
    202      var object = clonableObjects[clonableObjectsId++];
    203 
    204      if (object.target != "all") {
    205        runClonableTest();
    206        return;
    207      }
    208 
    209      obj
    210        .send(object.data, [])
    211        .catch(() => {
    212          return { error: true };
    213        })
    214        .then(received => {
    215          if (!obj.clonableObjectsEveryWhere) {
    216            ok(received.error, "Error expected");
    217          } else {
    218            ok(!received.error, "Error not expected");
    219            compare(received.data, object.data);
    220          }
    221          runClonableTest();
    222        });
    223    }
    224 
    225    runClonableTest();
    226  })
    227 
    228    // clonable same process
    229    .then(function () {
    230      return new Promise(function (resolve, reject) {
    231        var clonableObjectsId = 0;
    232        function runClonableTest() {
    233          if (clonableObjectsId >= clonableObjects.length) {
    234            resolve();
    235            return;
    236          }
    237 
    238          var object = clonableObjects[clonableObjectsId++];
    239 
    240          if (object.target != "sameProcess") {
    241            runClonableTest();
    242            return;
    243          }
    244 
    245          obj
    246            .send(object.data, [])
    247            .catch(() => {
    248              return { error: true };
    249            })
    250            .then(received => {
    251              if (!obj.clonableObjectsSameProcess) {
    252                ok(received.error, "Error expected");
    253              } else {
    254                ok(!received.error, "Error not expected");
    255                compare(received.data, object.data);
    256              }
    257              runClonableTest();
    258            });
    259        }
    260 
    261        runClonableTest();
    262      });
    263    })
    264 
    265    // transfering tests
    266    .then(function () {
    267      if (!obj.transferableObjects) {
    268        return Promise.resolve();
    269      }
    270 
    271      // MessagePort
    272      return new Promise(function (r, rr) {
    273        var mc = new MessageChannel();
    274        obj.send(42, [mc.port1]).then(function (received) {
    275          is(received.ports.length, 1, "MessagePort has been transferred");
    276          mc.port2.postMessage("hello world");
    277          received.ports[0].onmessage = function (e) {
    278            is(e.data, "hello world", "Ports are connected!");
    279            r();
    280          };
    281        });
    282      });
    283    })
    284 
    285    // no dup transfering
    286    .then(function () {
    287      if (!obj.transferableObjects) {
    288        return Promise.resolve();
    289      }
    290 
    291      // MessagePort
    292      return new Promise(function (r, rr) {
    293        var mc = new MessageChannel();
    294        obj
    295          .send(42, [mc.port1, mc.port1])
    296          .then(
    297            function (received) {
    298              ok(false, "Duplicate ports should throw!");
    299            },
    300            function () {
    301              ok(true, "Duplicate ports should throw!");
    302            }
    303          )
    304          .then(r);
    305      });
    306    })
    307 
    308    // maintaining order of transferred ports
    309    .then(function () {
    310      if (!obj.transferableObjects) {
    311        return Promise.resolve();
    312      }
    313 
    314      // MessagePort
    315      return new Promise(function (r, rr) {
    316        var mcs = [];
    317        const NPORTS = 50;
    318        for (let i = 0; i < NPORTS; i++) {
    319          mcs.push(new MessageChannel());
    320        }
    321        obj
    322          .send(
    323            42,
    324            mcs.map(channel => channel.port1)
    325          )
    326          .then(function (received) {
    327            is(
    328              received.ports.length,
    329              NPORTS,
    330              `all ${NPORTS} ports transferred`
    331            );
    332            const promises = Array(NPORTS)
    333              .fill()
    334              .map(
    335                (_, i) =>
    336                  new Promise(function (subr, subrr) {
    337                    mcs[i].port2.postMessage(i);
    338                    received.ports[i].onmessage = e => subr(e.data == i);
    339                  })
    340              );
    341            return Promise.all(promises);
    342          })
    343          .then(function (result) {
    344            let in_order = 0;
    345            for (const correct of result) {
    346              if (correct) {
    347                in_order++;
    348              }
    349            }
    350            is(in_order, NPORTS, "All transferred ports are in order");
    351          })
    352          .then(r);
    353      });
    354    })
    355 
    356    // non transfering tests
    357    .then(function () {
    358      if (obj.transferableObjects) {
    359        return Promise.resolve();
    360      }
    361 
    362      // MessagePort
    363      return new Promise(function (r, rr) {
    364        var mc = new MessageChannel();
    365        obj
    366          .send(42, [mc.port1])
    367          .then(
    368            function (received) {
    369              ok(false, "This object should not support port transferring");
    370            },
    371            function () {
    372              ok(true, "This object should not support port transferring");
    373            }
    374          )
    375          .then(r);
    376      });
    377    })
    378 
    379    // done.
    380    .then(function () {
    381      obj.finished();
    382    });
    383 }
    384 
    385 function next() {
    386  if (!tests.length) {
    387    SimpleTest.finish();
    388    return;
    389  }
    390 
    391  var test = tests.shift();
    392  test();
    393 }
    394 
    395 var tests = [create_fileList, create_directory, create_wasmModule];