tor-browser

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

browser_object.js (4306B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // Test the ObjectCommand
      7 
      8 add_task(async function testObjectRelease() {
      9  const tab = await addTab("data:text/html;charset=utf-8,Test page<script>var foo = { bar: 42 };</script>");
     10 
     11  const commands = await CommandsFactory.forTab(tab);
     12  await commands.targetCommand.startListening();
     13 
     14  const evaluationResponse = await commands.scriptCommand.execute(
     15    "window.foo"
     16  );
     17 
     18  // Execute a second time so that the WebConsoleActor set this._lastConsoleInputEvaluation to another value
     19  // and so we prevent freeing `window.foo` 
     20  await commands.scriptCommand.execute("");
     21 
     22  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () {
     23    is(content.wrappedJSObject.foo.bar, 42);
     24    const weakRef = Cu.getWeakReference(content.wrappedJSObject.foo);
     25 
     26    // Hold off the weak reference on SpecialPowsers so that it can be accessed in the next SpecialPowers.spawn
     27    SpecialPowers.weakRef = weakRef;
     28 
     29    // Nullify this variable so that it should be freed
     30    // unless the DevTools inspection still hold it in memory
     31    content.wrappedJSObject.foo = null;
     32 
     33    Cu.forceGC();
     34    Cu.forceCC();
     35 
     36    ok(SpecialPowers.weakRef.get(), "The 'foo' object can't be freed because of DevTools keeping a reference on it");
     37  });
     38 
     39  info("Release the server side actors which are keeping the object in memory");
     40  const objectFront = evaluationResponse.result;
     41  await commands.objectCommand.releaseObjects([objectFront]);
     42 
     43  ok(objectFront.isDestroyed(), "The passed object front has been destroyed");
     44 
     45  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
     46    await ContentTaskUtils.waitForCondition(() => {
     47      Cu.forceGC();
     48      Cu.forceCC();
     49      return !SpecialPowers.weakRef.get();
     50    }, "Wait for JS object to be freed", 500);
     51 
     52    ok(!SpecialPowers.weakRef.get(), "The 'foo' object has been freed");
     53  });
     54 
     55  await commands.destroy();
     56  BrowserTestUtils.removeTab(tab);
     57 });
     58 
     59 add_task(async function testMultiTargetObjectRelease() {
     60  const tab = await addTab(`data:text/html;charset=utf-8,Test page<iframe src="data:text/html,bar">/iframe>`);
     61 
     62  const commands = await CommandsFactory.forTab(tab);
     63  await commands.targetCommand.startListening();
     64 
     65  const [,iframeTarget] = commands.targetCommand.getAllTargets(commands.targetCommand.ALL_TYPES);
     66  is(iframeTarget.url, "data:text/html,bar");
     67 
     68  const evaluationResponse1 = await commands.scriptCommand.execute(
     69    "window"
     70  );
     71  const evaluationResponse2 = await commands.scriptCommand.execute(
     72    "window", {
     73      selectedTargetFront: iframeTarget,
     74    }
     75  );
     76  const object1 = evaluationResponse1.result;
     77  const object2 = evaluationResponse2.result;
     78  isnot(object1, object2, "The two window object fronts are different");
     79  isnot(object1.targetFront, object2.targetFront, "The two window object fronts relates to two distinct targets");
     80  is(object2.targetFront, iframeTarget, "The second object relates to the iframe target");
     81 
     82  await commands.objectCommand.releaseObjects([object1, object2]);
     83  ok(object1.isDestroyed(), "The first object front is destroyed");
     84  ok(object2.isDestroyed(), "The second object front is destroyed");
     85 
     86  await commands.destroy();
     87  BrowserTestUtils.removeTab(tab);
     88 });
     89 
     90 add_task(async function testWorkerObjectRelease() {
     91  const workerUrl = `data:text/javascript,const foo = {}`;
     92  const tab = await addTab(`data:text/html;charset=utf-8,Test page<script>const worker = new Worker("${workerUrl}")</script>`);
     93 
     94  const commands = await CommandsFactory.forTab(tab);
     95  commands.targetCommand.listenForWorkers = true;
     96  await commands.targetCommand.startListening();
     97 
     98  const [,workerTarget] = commands.targetCommand.getAllTargets(commands.targetCommand.ALL_TYPES);
     99  is(workerTarget.url, workerUrl);
    100 
    101  const evaluationResponse = await commands.scriptCommand.execute(
    102    "foo", {
    103      selectedTargetFront: workerTarget,
    104    }
    105  );
    106  const object = evaluationResponse.result;
    107  is(object.targetFront, workerTarget, "The 'foo' object relates to the worker target");
    108 
    109  await commands.objectCommand.releaseObjects([object]);
    110  ok(object.isDestroyed(), "The object front is destroyed");
    111 
    112  await commands.destroy();
    113  BrowserTestUtils.removeTab(tab);
    114 });