tor-browser

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

browser_dbg-backgroundtask-debugging.js (5997B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
      4 
      5 /**
      6 * Tests that `--backgroundtask` debugging works.
      7 *
      8 * This test is subtle.  We launch a `--backgroundtask` with `--jsdebugger` and
      9 * `--wait-for-jsdebugger` within the test.  The background task infrastructure
     10 * launches a browser toolbox, and the test connects to that browser toolbox
     11 * instance.  The test drives the instance, verifying that the automatically
     12 * placed breakpoint paused execution.  It then closes the browser toolbox,
     13 * which resumes the execution and the task exits.
     14 *
     15 * In the future, it would be nice to change the task's running environment, for
     16 * example by redefining a failing exit code to exit code 0.  Attempts to do
     17 * this have so far not been robust in automation.
     18 */
     19 
     20 "use strict";
     21 
     22 requestLongerTimeout(4);
     23 
     24 Services.scriptloader.loadSubScript(
     25  "chrome://mochitests/content/browser/devtools/client/framework/browser-toolbox/test/helpers-browser-toolbox.js",
     26  this
     27 );
     28 
     29 const { BackgroundTasksTestUtils } = ChromeUtils.importESModule(
     30  "resource://testing-common/BackgroundTasksTestUtils.sys.mjs"
     31 );
     32 BackgroundTasksTestUtils.init(this);
     33 const do_backgroundtask = BackgroundTasksTestUtils.do_backgroundtask.bind(
     34  BackgroundTasksTestUtils
     35 );
     36 
     37 add_task(async function test_backgroundtask_debugger() {
     38  // In this test, the background task infrastructure launches the browser
     39  // toolbox.  The browser toolbox profile prefs are taken from the default
     40  // profile (which is the standard place for background tasks to look for
     41  // task-specific configuration).  The current test profile will be
     42  // considered the default profile by the background task apparatus, so this
     43  // is how we configure the browser toolbox profile prefs.
     44  //
     45  // These prefs are not set for the background task under test directly: the
     46  // relevant prefs are set in the background task defaults.
     47  await pushPref("devtools.chrome.enabled", true);
     48  await pushPref("devtools.debugger.remote-enabled", true);
     49  await pushPref("devtools.browsertoolbox.enable-test-server", true);
     50  await pushPref("devtools.debugger.prompt-connection", false);
     51 
     52  // Before we start the background task, the preference file must be flushed to disk.
     53  Services.prefs.savePrefFile(null);
     54 
     55  // This invokes the test-only background task `BackgroundTask_jsdebugger.jsm`.
     56  const p = do_backgroundtask("jsdebugger", {
     57    extraArgs: [`--jsdebugger`, "--wait-for-jsdebugger"],
     58    extraEnv: {
     59      // Force the current test profile to be considered the default profile.
     60      MOZ_BACKGROUNDTASKS_DEFAULT_PROFILE_PATH: Services.dirsvc.get(
     61        "ProfD",
     62        Ci.nsIFile
     63      ).path,
     64    },
     65  });
     66 
     67  ok(true, "Launched background task");
     68 
     69  const existingProcessClose = async () => {
     70    const exitCode = await p;
     71    return { exitCode };
     72  };
     73  const ToolboxTask = await initBrowserToolboxTask({ existingProcessClose });
     74 
     75  await ToolboxTask.spawn(selectors, () => {
     76    const {
     77      LocalizationHelper,
     78    } = require("resource://devtools/shared/l10n.js");
     79    // We have to expose this symbol as global for waitForSelectedSource
     80    this.DEBUGGER_L10N = new LocalizationHelper(
     81      "devtools/client/locales/debugger.properties"
     82    );
     83  });
     84 
     85  await ToolboxTask.importFunctions({
     86    checkEvaluateInTopFrame,
     87    evaluateInTopFrame,
     88    createDebuggerContext,
     89    expandAllScopes,
     90    findElement,
     91    findElementWithSelector,
     92    getSelector,
     93    getVisibleSelectedFrameLine,
     94    isPaused,
     95    resume,
     96    stepOver,
     97    toggleObjectInspectorNode,
     98    toggleScopeNode,
     99    waitForElement,
    100    waitForLoadedScopes,
    101    waitForPaused,
    102    waitForResumed,
    103    waitForSelectedSource,
    104    //waitForElementWithSelector,
    105    waitForInlinePreviews,
    106    waitForState,
    107    waitUntil,
    108    createLocation,
    109    getEditorContent,
    110    getCMEditor,
    111    log: (msg, data) =>
    112      console.log(`${msg} ${!data ? "" : JSON.stringify(data)}`),
    113    info: (msg, data) =>
    114      console.info(`${msg} ${!data ? "" : JSON.stringify(data)}`),
    115  });
    116 
    117  // ToolboxTask.spawn passes input arguments by stringify-ing them via string
    118  // concatenation.  But functions do not survive this process, so we manually
    119  // recreate (in the toolbox process) the single function the `expandAllScopes`
    120  // invocation in this test needs.
    121  await ToolboxTask.spawn(selectors, async _selectors => {
    122    this.selectors = _selectors;
    123    this.selectors.scopeNode = i =>
    124      `.scopes-list .tree-node:nth-child(${i}) .object-label`;
    125  });
    126 
    127  // The debugger should automatically be selected.
    128  await ToolboxTask.spawn(null, async () => {
    129    await waitUntil(() => gToolbox.currentToolId == "jsdebugger");
    130  });
    131  ok(true, "Debugger selected");
    132 
    133  // The debugger should automatically pause.
    134  await ToolboxTask.spawn(null, async () => {
    135    try {
    136      /* global gToolbox */
    137      // Wait for the debugger to finish loading.
    138      await gToolbox.getPanelWhenReady("jsdebugger");
    139 
    140      const dbg = createDebuggerContext(gToolbox);
    141 
    142      // Scopes are supposed to be automatically expanded, but with
    143      // `setBreakpointOnLoad` that doesn't seem to be happening.  Explicitly
    144      // expand scopes so that they are expanded for `waitForPaused`.
    145      await expandAllScopes(dbg);
    146 
    147      await waitForPaused(dbg);
    148 
    149      if (!gToolbox.isHighlighted("jsdebugger")) {
    150        throw new Error("Debugger not highlighted");
    151      }
    152    } catch (e) {
    153      console.log("Caught exception in spawn", e);
    154      throw e;
    155    }
    156  });
    157  ok(true, "Paused in backgroundtask script");
    158 
    159  // If we `resume`, then the task completes and the Browser Toolbox exits,
    160  // which isn't handled cleanly by `spawn`, resulting in a test time out.  This
    161  // closes the toolbox "from the inside", which continues execution.  The test
    162  // then waits for the background task to terminate with exit code 0.
    163  await ToolboxTask.destroy();
    164 });