tor-browser

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

browser_messagemanager_loadprocessscript.js (5966B)


      1 function getBaseNumberOfProcesses() {
      2  // We should have three processes for this test, the parent process and two
      3  // content processes for the tabs craeted by this test.
      4  let processCount = 3;
      5 
      6  // If we run WebExtensions out-of-process (see bug 1190679), there might be
      7  // additional processes for those, so let's add these to the base count to
      8  // not have system WebExtensions cause test failures.
      9  for (let i = 0; i < Services.ppmm.childCount; i++) {
     10    if (
     11      Services.ppmm.getChildAt(i).remoteType === E10SUtils.EXTENSION_REMOTE_TYPE
     12    ) {
     13      processCount += 1;
     14    }
     15  }
     16 
     17  return processCount;
     18 }
     19 
     20 function checkBaseProcessCount(description) {
     21  const baseProcessCount = getBaseNumberOfProcesses();
     22  const { childCount } = Services.ppmm;
     23  // With preloaded activity-stream, process count is a bit undeterministic, so
     24  // allow for some variation
     25  const extraCount = baseProcessCount + 1;
     26  ok(
     27    childCount === baseProcessCount || childCount === extraCount,
     28    `${description} (${baseProcessCount} or ${extraCount})`
     29  );
     30 }
     31 
     32 function processScript() {
     33  /* eslint-env mozilla/process-script */
     34  if (Services.cpmm !== this) {
     35    dump("Test failed: wrong global object\n");
     36    return;
     37  }
     38 
     39  this.cpmm = Services.cpmm;
     40 
     41  addMessageListener("ProcessTest:Reply", function listener(msg) {
     42    removeMessageListener("ProcessTest:Reply", listener);
     43    sendAsyncMessage("ProcessTest:Finished");
     44  });
     45  sendSyncMessage("ProcessTest:Loaded");
     46 }
     47 var processScriptURL = "data:,(" + processScript.toString() + ").call(this)";
     48 
     49 function initTestScript() {
     50  /* eslint-env mozilla/process-script */
     51  let init = initialProcessData;
     52  if (init.test123 != "hello") {
     53    dump("Initial data incorrect\n");
     54    return;
     55  }
     56 
     57  sendAsyncMessage("ProcessTest:InitGood", init.test456.get("hi"));
     58 }
     59 var initTestScriptURL = "data:,(" + initTestScript.toString() + ")()";
     60 
     61 var checkProcess = async function (mm) {
     62  let { target } = await promiseMessage(mm, "ProcessTest:Loaded");
     63  target.sendAsyncMessage("ProcessTest:Reply");
     64  await promiseMessage(target, "ProcessTest:Finished");
     65  ok(true, "Saw process finished");
     66 };
     67 
     68 function promiseMessage(messageManager, message) {
     69  return new Promise(resolve => {
     70    let listener = msg => {
     71      messageManager.removeMessageListener(message, listener);
     72      resolve(msg);
     73    };
     74 
     75    messageManager.addMessageListener(message, listener);
     76  });
     77 }
     78 
     79 add_task(async function () {
     80  // We want to count processes in this test, so let's disable the pre-allocated process manager.
     81  await SpecialPowers.pushPrefEnv({
     82    set: [["dom.ipc.processPrelaunch.enabled", false]],
     83  });
     84 });
     85 
     86 add_task(async function () {
     87  // This test is only relevant in e10s.
     88  if (!gMultiProcessBrowser) {
     89    return;
     90  }
     91 
     92  Services.ppmm.releaseCachedProcesses();
     93 
     94  await SpecialPowers.pushPrefEnv({ set: [["dom.ipc.processCount", 5]] });
     95  await SpecialPowers.pushPrefEnv({
     96    set: [["dom.ipc.keepProcessesAlive.web", 5]],
     97  });
     98 
     99  let tabs = [];
    100  for (let i = 0; i < 3; i++) {
    101    tabs[i] = await BrowserTestUtils.openNewForegroundTab(
    102      gBrowser,
    103      "about:blank"
    104    );
    105  }
    106 
    107  for (let i = 0; i < 3; i++) {
    108    // FIXME: This should wait for the tab removal gets reflected to the
    109    //        process count (bug 1446726).
    110    let sessionStorePromise = BrowserTestUtils.waitForSessionStoreUpdate(
    111      tabs[i]
    112    );
    113    BrowserTestUtils.removeTab(tabs[i]);
    114    await sessionStorePromise;
    115  }
    116 
    117  Services.ppmm.releaseCachedProcesses();
    118  checkBaseProcessCount(
    119    "Should get back to the base number of processes at this point"
    120  );
    121 });
    122 
    123 // Test that loading a process script loads in all existing processes
    124 add_task(async function () {
    125  let checks = [];
    126  for (let i = 0; i < Services.ppmm.childCount; i++) {
    127    checks.push(checkProcess(Services.ppmm.getChildAt(i)));
    128  }
    129 
    130  Services.ppmm.loadProcessScript(processScriptURL, false);
    131  await Promise.all(checks);
    132 });
    133 
    134 // Test that loading a process script loads in new processes
    135 add_task(async function () {
    136  // This test is only relevant in e10s
    137  if (!gMultiProcessBrowser) {
    138    return;
    139  }
    140 
    141  checkBaseProcessCount(
    142    "Should still be at the base number of processes at this point"
    143  );
    144 
    145  // Load something in the main process
    146  BrowserTestUtils.startLoadingURIString(
    147    gBrowser.selectedBrowser,
    148    "about:mozilla"
    149  );
    150  await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
    151 
    152  let init = Services.ppmm.initialProcessData;
    153  init.test123 = "hello";
    154  init.test456 = new Map();
    155  init.test456.set("hi", "bye");
    156 
    157  // With no remote frames left we should be down to one process.
    158  // However, stuff like remote thumbnails can cause a content
    159  // process to exist nonetheless. This should be rare, though,
    160  // so the test is useful most of the time.
    161  if (Services.ppmm.childCount == 2) {
    162    let mainMM = Services.ppmm.getChildAt(0);
    163 
    164    let check = checkProcess(Services.ppmm);
    165    Services.ppmm.loadProcessScript(processScriptURL, true);
    166 
    167    // The main process should respond
    168    await check;
    169 
    170    check = checkProcess(Services.ppmm);
    171    // Reset the default browser to start a new child process
    172    gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, {
    173      remoteType: E10SUtils.DEFAULT_REMOTE_TYPE,
    174    });
    175    BrowserTestUtils.startLoadingURIString(
    176      gBrowser.selectedBrowser,
    177      "about:blank"
    178    );
    179    await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
    180 
    181    checkBaseProcessCount(
    182      "Should be back to the base number of processes at this point"
    183    );
    184 
    185    // The new process should have responded
    186    await check;
    187 
    188    Services.ppmm.removeDelayedProcessScript(processScriptURL);
    189 
    190    let childMM;
    191    childMM = Services.ppmm.getChildAt(2);
    192 
    193    childMM.loadProcessScript(initTestScriptURL, false);
    194    let msg = await promiseMessage(childMM, "ProcessTest:InitGood");
    195    is(msg.data, "bye", "initial process data was correct");
    196  } else {
    197    info("Unable to finish test entirely");
    198  }
    199 });