Commit 52a0e927 authored by Alexandre Poirot's avatar Alexandre Poirot
Browse files

Bug 1565263 - Support target switching for the console. r=nchevobbe,yulia,jdescottes

Differential Revision: https://phabricator.services.mozilla.com/D40016

--HG--
extra : moz-landing-system : lando
parent 995d069a
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1960,6 +1960,15 @@ pref("devtools.toolbox.tabsOrder", "");
// ⚠ This is a work in progress. Expect weirdness when the pref is enabled. ⚠
pref("devtools.browsertoolbox.fission", false);

// This pref is also related to fission, but not only. It allows the toolbox
// to stay open even if the debugged tab switches to another process.
// It can happen between two documents, one running in the parent process like
// about:sessionrestore and another one running in the content process like
// any web page. Or between two distinct domain when running with fission turned
// on. See bug 1565263.
// ⚠ This is a work in progress. Expect weirdness when the pref is flipped on ⚠
pref("devtools.target-switching.enabled", false);

// Toolbox Button preferences
pref("devtools.command-button-pick.enabled", true);
pref("devtools.command-button-frames.enabled", true);
+7 −0
Original line number Diff line number Diff line
@@ -634,6 +634,13 @@ DevTools.prototype = {
      this._toolboxes.delete(target);
      this.emit("toolbox-destroyed", target);
    });
    // If the document navigates to another process, the current target will be
    // destroyed in favor of a new one. So acknowledge this swap here.
    toolbox.on("switch-target", newTarget => {
      this._toolboxes.delete(target);
      this._toolboxes.set(newTarget, toolbox);
      target = newTarget;
    });

    await toolbox.open();
    this.emit("toolbox-ready", toolbox);
+6 −2
Original line number Diff line number Diff line
@@ -19,7 +19,11 @@ const SOURCE_MAP_PREF = "devtools.source-map.client-service.enabled";
 */
function SourceMapURLService(toolbox, sourceMapService) {
  this._toolbox = toolbox;
  this._target = toolbox.target;
  Object.defineProperty(this, "_target", {
    get() {
      return toolbox.target;
    },
  });
  this._sourceMapService = sourceMapService;
  // Map from content URLs to descriptors.  Descriptors are later
  // passed to the source map worker.
@@ -120,7 +124,7 @@ SourceMapURLService.prototype.destroy = function() {
    this._stylesheetsFront.off("stylesheet-added", this._onNewStyleSheet);
  }
  Services.prefs.removeObserver(SOURCE_MAP_PREF, this._onPrefChanged);
  this._target = this._urls = this._subscriptions = this._idMap = null;
  this._urls = this._subscriptions = this._idMap = null;
};

/**
+15 −9
Original line number Diff line number Diff line
@@ -29,15 +29,17 @@ exports.TargetFactory = {
   *
   * @param {XULTab} tab
   *        The tab to use in creating a new target.
   * @param {DebuggerClient} client
   *        Optional client to fetch the target actor from.
   *
   * @return A target object
   */
  forTab: async function(tab) {
  forTab: async function(tab, client) {
    let target = targets.get(tab);
    if (target) {
      return target;
    }
    const promise = this.createTargetForTab(tab);
    const promise = this.createTargetForTab(tab, client);
    // Immediately set the target's promise in cache to prevent race
    targets.set(tab, promise);
    target = await promise;
@@ -53,17 +55,19 @@ exports.TargetFactory = {
   * Instantiate a target for the given tab.
   *
   * This will automatically:
   * - spawn a DebuggerServer in the parent process,
   * - create a DebuggerClient and connect it to this local DebuggerServer,
   * - if no client is passed, spawn a DebuggerServer in the parent process,
   *   and create a DebuggerClient and connect it to this local DebuggerServer,
   * - call RootActor's `getTab` request to retrieve the FrameTargetActor's form,
   * - instantiate a Target instance.
   *
   * @param {XULTab} tab
   *        The tab to use in creating a new target.
   * @param {DebuggerClient} client
   *        Optional client to fetch the target actor from.
   *
   * @return A target object
   */
  async createTargetForTab(tab) {
  async createTargetForTab(tab, client) {
    function createLocalServer() {
      // Since a remote protocol connection will be made, let's start the
      // DebuggerServer here, once and for all tools.
@@ -81,14 +85,16 @@ exports.TargetFactory = {
    }

    function createLocalClient() {
      createLocalServer();
      return new DebuggerClient(DebuggerServer.connectPipe());
    }

    createLocalServer();
    const client = createLocalClient();
    if (!client) {
      client = createLocalClient();

      // Connect the local client to the local server
      await client.connect();
    }

    // Fetch the FrameTargetActor's Front which is a BrowsingContextTargetFront
    return client.mainRoot.getTab({ tab });
+32 −7
Original line number Diff line number Diff line
@@ -7,6 +7,21 @@ const URL_2 =
  encodeURIComponent('<div id="remote-page">foo</div>');

add_task(async function() {
  // Test twice.
  // Once without target switching, where the toolbox closes and reopens
  // And a second time, with target switching, where the toolbox stays open
  await navigateBetweenProcesses(false);
  await navigateBetweenProcesses(true);
});

async function navigateBetweenProcesses(enableTargetSwitching) {
  info(
    `Testing navigation between processes ${
      enableTargetSwitching ? "with" : "without"
    } target switching`
  );
  await pushPref("devtools.target-switching.enabled", enableTargetSwitching);

  info("Open a tab on a URL supporting only running in parent process");
  const tab = await addTab(URL_1);
  is(
@@ -24,6 +39,7 @@ add_task(async function() {

  const onToolboxDestroyed = toolbox.once("destroyed");
  const onToolboxCreated = gDevTools.once("toolbox-created");
  const onToolboxSwitchedToTarget = toolbox.once("switched-target");

  info("Navigate to a URL supporting remote process");
  const onLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
@@ -36,6 +52,10 @@ add_task(async function() {
    "Navigated to a data: URI and switching to remote"
  );

  if (enableTargetSwitching) {
    info("Waiting for the toolbox to be switched to the new target");
    await onToolboxSwitchedToTarget;
  } else {
    info("Waiting for the toolbox to be destroyed");
    await onToolboxDestroyed;

@@ -44,6 +64,7 @@ add_task(async function() {

    info("Waiting for the new toolbox to be ready");
    await toolbox.once("ready");
  }

  info("Veryify we are inspecting the new document");
  const console = await toolbox.selectTool("webconsole");
@@ -56,4 +77,8 @@ add_task(async function() {
    url.textContent.includes(URL_2),
    "The console inspects the second document"
  );
});

  const { client } = toolbox.target;
  await toolbox.destroy();
  ok(client._closed, "The client is closed after closing the toolbox");
}
Loading