tor-browser

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

browser_resources_target_resources_race.js (2497B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 /**
      7 * Test initial target resources are correctly retrieved even when several calls
      8 * to watchResources are made simultaneously.
      9 *
     10 * This checks a race condition which occurred when calling watchResources
     11 * simultaneously. This made the "second" call to watchResources miss existing
     12 * resources (in case those are emitted from the target instead of the watcher).
     13 * See Bug 1663896.
     14 */
     15 add_task(async function () {
     16  // Disable the preloaded process as it creates processes intermittently
     17  // which forces the emission of RDP requests we aren't correctly waiting for.
     18  await pushPref("dom.ipc.processPrelaunch.enabled", false);
     19 
     20  const { client, resourceCommand, targetCommand } =
     21    await initMultiProcessResourceCommand();
     22 
     23  const expectedPlatformMessage = "expectedMessage";
     24 
     25  info("Log a message *before* calling ResourceCommand.watchResources");
     26  Services.console.logStringMessage(expectedPlatformMessage);
     27 
     28  info("Call watchResources from 2 separate call sites consecutively");
     29 
     30  // Empty onAvailable callback for CSS MESSAGES, we only want to check that
     31  // the second resource we watch correctly provides existing resources.
     32  const onCssMessageAvailable = () => {};
     33 
     34  // First call to watchResources.
     35  // We do not await on `watchPromise1` here, in order to simulate simultaneous
     36  // calls to watchResources (which could come from 2 separate modules in a real
     37  // scenario).
     38  const initialWatchPromise = resourceCommand.watchResources(
     39    [resourceCommand.TYPES.CSS_MESSAGE],
     40    {
     41      onAvailable: onCssMessageAvailable,
     42    }
     43  );
     44 
     45  // `waitForNextResource` will trigger another call to `watchResources`.
     46  const { onResource: onMessageReceived } =
     47    await resourceCommand.waitForNextResource(
     48      resourceCommand.TYPES.PLATFORM_MESSAGE,
     49      {
     50        ignoreExistingResources: false,
     51        predicate: r => r.message === expectedPlatformMessage,
     52      }
     53    );
     54 
     55  info("Waiting for the expected message to be received");
     56  await onMessageReceived;
     57  ok(true, "All the expected messages were received");
     58 
     59  info("Wait for the other watchResources promise to finish");
     60  await initialWatchPromise;
     61 
     62  // Unwatch all resources.
     63  resourceCommand.unwatchResources([resourceCommand.TYPES.CSS_MESSAGE], {
     64    onAvailable: onCssMessageAvailable,
     65  });
     66 
     67  Services.console.reset();
     68  targetCommand.destroy();
     69  await client.close();
     70 });