Bug 862341 Part 4: Start recording network requests when the toolbox opens. r=vporof
authorPanos Astithas <past@mozilla.com>
Mon, 04 May 2015 13:58:25 +0300
changeset 274307 6db74fd5b4474861726f4673bc233d8b1c19ec2c
parent 274306 f5f7375211fc791ec36154f837e2a4127d31b826
child 274308 2bda9fb3b5d66a32ba9ed090caa2113a7d9de48e
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvporof
bugs862341
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 862341 Part 4: Start recording network requests when the toolbox opens. r=vporof
browser/devtools/framework/target.js
browser/devtools/framework/toolbox.js
browser/devtools/netmonitor/netmonitor-controller.js
browser/devtools/netmonitor/test/browser_net_reload-button.js
browser/devtools/netmonitor/test/head.js
--- a/browser/devtools/framework/target.js
+++ b/browser/devtools/framework/target.js
@@ -160,16 +160,17 @@ Object.defineProperty(Target.prototype, 
  * be web pages served over http(s), but they don't have to be.
  */
 function TabTarget(tab) {
   EventEmitter.decorate(this);
   this.destroy = this.destroy.bind(this);
   this._handleThreadState = this._handleThreadState.bind(this);
   this.on("thread-resumed", this._handleThreadState);
   this.on("thread-paused", this._handleThreadState);
+  this.activeTab = this.activeConsole = null;
   // Only real tabs need initialization here. Placeholder objects for remote
   // targets will be initialized after a makeRemote method call.
   if (tab && !["client", "form", "chrome"].every(tab.hasOwnProperty, tab)) {
     this._tab = tab;
     this._setupListeners();
   } else {
     this._form = tab.form;
     this._client = tab.client;
@@ -415,16 +416,29 @@ TabTarget.prototype = {
     let attachTab = () => {
       this._client.attachTab(this._form.actor, (aResponse, aTabClient) => {
         if (!aTabClient) {
           this._remote.reject("Unable to attach to the tab");
           return;
         }
         this.activeTab = aTabClient;
         this.threadActor = aResponse.threadActor;
+        attachConsole();
+      });
+    };
+
+    let attachConsole = () => {
+      this._client.attachConsole(this._form.consoleActor,
+                                 [ "NetworkActivity" ],
+                                 (aResponse, aWebConsoleClient) => {
+        if (!aWebConsoleClient) {
+          this._remote.reject("Unable to attach to the console");
+          return;
+        }
+        this.activeConsole = aWebConsoleClient;
         this._remote.resolve(null);
       });
     };
 
     if (this.isLocalTab) {
       this._client.connect((aType, aTraits) => {
         this._client.getTab({ tab: this.tab })
             .then(aResponse => {
@@ -434,17 +448,17 @@ TabTarget.prototype = {
       });
     } else if (this.isTabActor) {
       // In the remote debugging case, the protocol connection will have been
       // already initialized in the connection screen code.
       attachTab();
     } else {
       // AddonActor and chrome debugging on RootActor doesn't inherits from TabActor and
       // doesn't need to be attached.
-      this._remote.resolve(null);
+      attachConsole();
     }
 
     return this._remote.promise;
   },
 
   /**
    * Listen to the different events.
    */
@@ -588,43 +602,42 @@ TabTarget.prototype = {
       // If, on the other hand, this target was remoted, the promise will be
       // resolved after the remote connection is closed.
       this._teardownRemoteListeners();
 
       if (this.isLocalTab) {
         // We started with a local tab and created the client ourselves, so we
         // should close it.
         this._client.close(cleanupAndResolve);
-      } else {
+      } else if (this.activeTab) {
         // The client was handed to us, so we are not responsible for closing
         // it. We just need to detach from the tab, if already attached.
-        if (this.activeTab) {
-          // |detach| may fail if the connection is already dead, so proceed
-          // cleanup directly after this.
-          this.activeTab.detach();
-          cleanupAndResolve();
-        } else {
-          cleanupAndResolve();
-        }
+        // |detach| may fail if the connection is already dead, so proceed with
+        // cleanup directly after this.
+        this.activeTab.detach();
+        cleanupAndResolve();
+      } else {
+        cleanupAndResolve();
       }
     }
 
     return this._destroyer.promise;
   },
 
   /**
    * Clean up references to what this target points to.
    */
   _cleanup: function TabTarget__cleanup() {
     if (this._tab) {
       targets.delete(this._tab);
     } else {
       promiseTargets.delete(this._form);
     }
     this.activeTab = null;
+    this.activeConsole = null;
     this._client = null;
     this._tab = null;
     this._form = null;
     this._remote = null;
   },
 
   toString: function() {
     return 'TabTarget:' + (this._tab ? this._tab : (this._form && this._form.actor));
--- a/browser/devtools/framework/toolbox.js
+++ b/browser/devtools/framework/toolbox.js
@@ -105,16 +105,19 @@ const ToolboxButtons = exports.ToolboxBu
  * @param {object} hostOptions
  *        Options for host specifically
  */
 function Toolbox(target, selectedTool, hostType, hostOptions) {
   this._target = target;
   this._toolPanels = new Map();
   this._telemetry = new Telemetry();
 
+  this._initInspector = null;
+  this._inspector = null;
+
   this._toolRegistered = this._toolRegistered.bind(this);
   this._toolUnregistered = this._toolUnregistered.bind(this);
   this._refreshHostTitle = this._refreshHostTitle.bind(this);
   this.selectFrame = this.selectFrame.bind(this);
   this._updateFrames = this._updateFrames.bind(this);
   this._splitConsoleOnKeypress = this._splitConsoleOnKeypress.bind(this);
   this.destroy = this.destroy.bind(this);
   this.highlighterUtils = getHighlighterUtils(this);
@@ -362,17 +365,17 @@ Toolbox.prototype = {
       this.webconsolePanel = this.doc.querySelector("#toolbox-panel-webconsole");
       this.webconsolePanel.height = Services.prefs.getIntPref(SPLITCONSOLE_HEIGHT_PREF);
       this.webconsolePanel.addEventListener("resize", this._saveSplitConsoleHeight);
 
       let buttonsPromise = this._buildButtons();
 
       this._pingTelemetry();
 
-      let panel = yield this.selectTool(this._defaultToolId);
+      yield this.selectTool(this._defaultToolId);
 
       // Wait until the original tool is selected so that the split
       // console input will receive focus.
       let splitConsolePromise = promise.resolve();
       if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) {
         splitConsolePromise = this.openSplitConsole();
       }
 
--- a/browser/devtools/netmonitor/netmonitor-controller.js
+++ b/browser/devtools/netmonitor/netmonitor-controller.js
@@ -191,38 +191,43 @@ let NetMonitorController = {
     this.disconnect();
 
     // Shutdown is synchronous, for now.
     return this._shutdown = promise.resolve();
   },
 
   /**
    * Initiates remote or chrome network monitoring based on the current target,
-   * wiring event handlers as necessary.
+   * wiring event handlers as necessary. Since the TabTarget will have already
+   * started listening to network requests by now, this is largely
+   * netmonitor-specific initialization.
    *
    * @return object
    *         A promise that is resolved when the monitor finishes connecting.
    */
   connect: Task.async(function*() {
     if (this._connection) {
       return this._connection;
     }
 
     let deferred = promise.defer();
     this._connection = deferred.promise;
 
-    let target = this._target;
-    let { client, form } = target;
+    this.client = this._target.client;
     // Some actors like AddonActor or RootActor for chrome debugging
-    // do not support attach/detach and can be used directly
-    if (!target.isTabActor) {
-      this._startChromeMonitoring(client, form.consoleActor, deferred.resolve);
-    } else {
-      this._startMonitoringTab(client, form, deferred.resolve);
+    // aren't actual tabs.
+    if (this._target.isTabActor) {
+      this.tabClient = this._target.activeTab;
     }
+    this.webConsoleClient = this._target.activeConsole;
+    this.webConsoleClient.setPreferences(NET_PREFS, () => {
+      this.TargetEventsHandler.connect();
+      this.NetworkEventsHandler.connect();
+      deferred.resolve();
+    });
 
     yield deferred.promise;
     window.emit(EVENTS.CONNECTED);
   }),
 
   /**
    * Disconnects the debugger client and removes event handlers as necessary.
    */
@@ -239,92 +244,16 @@ let NetMonitorController = {
    * Checks whether the netmonitor connection is active.
    * @return boolean
    */
   isConnected: function() {
     return !!this.client;
   },
 
   /**
-   * Sets up a monitoring session.
-   *
-   * @param DebuggerClient aClient
-   *        The debugger client.
-   * @param object aTabGrip
-   *        The remote protocol grip of the tab.
-   * @param function aCallback
-   *        A function to invoke once the client attached to the console client.
-   */
-  _startMonitoringTab: function(aClient, aTabGrip, aCallback) {
-    if (!aClient) {
-      Cu.reportError("No client found!");
-      return;
-    }
-    this.client = aClient;
-
-    aClient.attachTab(aTabGrip.actor, (aResponse, aTabClient) => {
-      if (!aTabClient) {
-        Cu.reportError("No tab client found!");
-        return;
-      }
-      this.tabClient = aTabClient;
-
-      aClient.attachConsole(aTabGrip.consoleActor, LISTENERS, (aResponse, aWebConsoleClient) => {
-        if (!aWebConsoleClient) {
-          Cu.reportError("Couldn't attach to console: " + aResponse.error);
-          return;
-        }
-        this.webConsoleClient = aWebConsoleClient;
-        this.webConsoleClient.setPreferences(NET_PREFS, () => {
-          this.TargetEventsHandler.connect();
-          this.NetworkEventsHandler.connect();
-
-          if (aCallback) {
-            aCallback();
-          }
-        });
-      });
-    });
-  },
-
-  /**
-   * Sets up a chrome monitoring session.
-   *
-   * @param DebuggerClient aClient
-   *        The debugger client.
-   * @param object aConsoleActor
-   *        The remote protocol grip of the chrome debugger.
-   * @param function aCallback
-   *        A function to invoke once the client attached to the console client.
-   */
-  _startChromeMonitoring: function(aClient, aConsoleActor, aCallback) {
-    if (!aClient) {
-      Cu.reportError("No client found!");
-      return;
-    }
-    this.client = aClient;
-
-    aClient.attachConsole(aConsoleActor, LISTENERS, (aResponse, aWebConsoleClient) => {
-      if (!aWebConsoleClient) {
-        Cu.reportError("Couldn't attach to console: " + aResponse.error);
-        return;
-      }
-      this.webConsoleClient = aWebConsoleClient;
-      this.webConsoleClient.setPreferences(NET_PREFS, () => {
-        this.TargetEventsHandler.connect();
-        this.NetworkEventsHandler.connect();
-
-        if (aCallback) {
-          aCallback();
-        }
-      });
-    });
-  },
-
-  /**
    * Gets the activity currently performed by the frontend.
    * @return number
    */
   getCurrentActivity: function() {
     return this._currentActivity || ACTIVITY_TYPE.NONE;
   },
 
   /**
--- a/browser/devtools/netmonitor/test/browser_net_reload-button.js
+++ b/browser/devtools/netmonitor/test/browser_net_reload-button.js
@@ -10,19 +10,16 @@ function test() {
   initNetMonitor(SINGLE_GET_URL).then(([aTab, aDebuggee, aMonitor]) => {
     info("Starting test... ");
 
     monitor = aMonitor;
     let { document, NetMonitorView } = aMonitor.panelWin;
     let { RequestsMenu } = NetMonitorView;
     reqMenu = RequestsMenu;
 
-    is(reqMenu.itemCount, 0,
-      "The request menu should empty before reloading");
-
     let button = document.querySelector("#requests-menu-reload-notice-button");
     button.click();
   })
   .then(() => {
     return waitForNetworkEvents(monitor, 2);
   })
   .then(() => {
     is(reqMenu.itemCount, 2,
--- a/browser/devtools/netmonitor/test/head.js
+++ b/browser/devtools/netmonitor/test/head.js
@@ -142,16 +142,21 @@ function initNetMonitor(aUrl, aWindow, a
     let target = TargetFactory.forTab(tab);
 
     yield target.makeRemote();
     info("Target remoted.");
 
     if(!aEnableCache) {
       yield toggleCache(target, true);
       info("Cache disabled when the current and all future toolboxes are open.");
+      // Remove any requests generated by the reload while toggling the cache to
+      // avoid interfering with the test.
+      isnot([...target.activeConsole.getNetworkEvents()].length, 0,
+         "Request to reconfigure the tab was recorded.");
+      target.activeConsole.clearNetworkRequests();
     }
 
     let toolbox = yield gDevTools.showToolbox(target, "netmonitor");
     info("Netork monitor pane shown successfully.");
 
     let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
     let monitor = toolbox.getCurrentPanel();
     return [tab, debuggee, monitor];