Bug 917227 - Part 1: network monitor client changes; r=ochameau
authorMihai Sucan <mihai.sucan@gmail.com>
Fri, 07 Mar 2014 14:14:53 +0200
changeset 190185 731be5361993d488ac76cc4d1e2e30c8aad57086
parent 190184 09ba2ea97c87bc09d6bee6a495b087886f97566b
child 190186 493f2ddd14ba57a7d832a8ae467df348d9251770
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs917227
milestone30.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 917227 - Part 1: network monitor client changes; r=ochameau
browser/devtools/framework/test/browser_toolbox_tabsswitch_shortcuts.js
browser/devtools/framework/test/browser_toolbox_tool_ready.js
browser/devtools/framework/toolbox.js
browser/devtools/main.js
browser/devtools/netmonitor/netmonitor-controller.js
browser/devtools/netmonitor/netmonitor-view.js
toolkit/devtools/webconsole/client.js
--- a/browser/devtools/framework/test/browser_toolbox_tabsswitch_shortcuts.js
+++ b/browser/devtools/framework/test/browser_toolbox_tabsswitch_shortcuts.js
@@ -6,22 +6,25 @@ let Toolbox = devtools.Toolbox;
 let toolbox, toolIDs, idIndex, secondTime = false,
     reverse = false, nextKey = null, prevKey = null;
 
 function test() {
   waitForExplicitFinish();
 
   addTab("about:blank", function() {
     let target = TargetFactory.forTab(gBrowser.selectedTab);
-    toolIDs = gDevTools.getToolDefinitionArray()
-                .filter(def => def.isTargetSupported(target))
-                .map(def => def.id);
     idIndex = 0;
-    gDevTools.showToolbox(target, toolIDs[0], Toolbox.HostType.BOTTOM)
-             .then(testShortcuts);
+
+    target.makeRemote().then(() => {
+      toolIDs = gDevTools.getToolDefinitionArray()
+                  .filter(def => def.isTargetSupported(target))
+                  .map(def => def.id);
+      gDevTools.showToolbox(target, toolIDs[0], Toolbox.HostType.BOTTOM)
+               .then(testShortcuts);
+    });
   });
 }
 
 function testShortcuts(aToolbox, aIndex) {
   if (aIndex == toolIDs.length) {
     aIndex = 0;
     if (secondTime) {
       secondTime = false;
--- a/browser/devtools/framework/test/browser_toolbox_tool_ready.js
+++ b/browser/devtools/framework/test/browser_toolbox_tool_ready.js
@@ -1,13 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   addTab().then(function(data) {
+    data.target.makeRemote().then(performChecks.bind(null, data));
+  }).then(null, console.error);
+
+  function performChecks(data) {
     let toolIds = gDevTools.getToolDefinitionArray()
                     .filter(def => def.isTargetSupported(data.target))
                     .map(def => def.id);
 
     let open = function(index) {
       let toolId = toolIds[index];
 
       info("About to open " + index + "/" + toolId);
@@ -27,10 +31,10 @@ function test() {
         }
         else {
           open(nextIndex);
         }
       }, console.error);
     };
 
     open(0);
-  }).then(null, console.error);
+  }
 }
--- a/browser/devtools/framework/toolbox.js
+++ b/browser/devtools/framework/toolbox.js
@@ -248,31 +248,30 @@ Toolbox.prototype = {
         this._buildOptions();
         this._buildTabs();
         this._buildButtons();
         this._addKeysToWindow();
         this._addToolSwitchingKeys();
         this._addZoomKeys();
         this._loadInitialZoom();
 
-        // Load the toolbox-level actor fronts and utilities now
-        this._target.makeRemote().then(() => {
-          this._telemetry.toolOpened("toolbox");
+        this._telemetry.toolOpened("toolbox");
 
-          this.selectTool(this._defaultToolId).then(panel => {
-            this.emit("ready");
-            deferred.resolve();
-          });
+        this.selectTool(this._defaultToolId).then(panel => {
+          this.emit("ready");
+          deferred.resolve();
         });
       };
 
-      iframe.setAttribute("src", this._URL);
-
-      let domHelper = new DOMHelpers(iframe.contentWindow);
-      domHelper.onceDOMReady(domReady);
+      // Load the toolbox-level actor fronts and utilities now
+      this._target.makeRemote().then(() => {
+        iframe.setAttribute("src", this._URL);
+        let domHelper = new DOMHelpers(iframe.contentWindow);
+        domHelper.onceDOMReady(domReady);
+      });
 
       return deferred.promise;
     });
   },
 
   _buildOptions: function() {
     let key = this.doc.getElementById("toolbox-options-key");
     key.addEventListener("command", () => {
--- a/browser/devtools/main.js
+++ b/browser/devtools/main.js
@@ -234,17 +234,18 @@ Tools.netMonitor = {
   icon: "chrome://browser/skin/devtools/tool-network.svg",
   invertIconForLightTheme: true,
   url: "chrome://browser/content/devtools/netmonitor.xul",
   label: l10n("netmonitor.label", netMonitorStrings),
   tooltip: l10n("netmonitor.tooltip", netMonitorStrings),
   inMenu: true,
 
   isTargetSupported: function(target) {
-    return !target.isApp;
+    let root = target.client.mainRoot;
+    return root.traits.networkMonitor || !target.isApp;
   },
 
   build: function(iframeWindow, toolbox) {
     let panel = new NetMonitorPanel(iframeWindow, toolbox);
     return panel.open();
   }
 };
 
--- a/browser/devtools/netmonitor/netmonitor-controller.js
+++ b/browser/devtools/netmonitor/netmonitor-controller.js
@@ -73,17 +73,21 @@ const EVENTS = {
   NETWORKDETAILSVIEW_POPULATED: "NetMonitor:NetworkDetailsViewPopulated",
 
   // Fired when CustomRequestView has finished being populated.
   CUSTOMREQUESTVIEW_POPULATED: "NetMonitor:CustomRequestViewPopulated",
 
   // Fired when charts have been displayed in the PerformanceStatisticsView.
   PLACEHOLDER_CHARTS_DISPLAYED: "NetMonitor:PlaceholderChartsDisplayed",
   PRIMED_CACHE_CHART_DISPLAYED: "NetMonitor:PrimedChartsDisplayed",
-  EMPTY_CACHE_CHART_DISPLAYED: "NetMonitor:EmptyChartsDisplayed"
+  EMPTY_CACHE_CHART_DISPLAYED: "NetMonitor:EmptyChartsDisplayed",
+
+  // Fired once the NetMonitorController establishes a connection to the debug
+  // target.
+  CONNECTED: "connected",
 };
 
 // Descriptions for what this frontend is currently doing.
 const ACTIVITY_TYPE = {
   // Standing by and handling requests normally.
   NONE: 0,
 
   // Forcing the target to reload with cache enabled or disabled.
@@ -195,17 +199,20 @@ let NetMonitorController = {
     let target = this._target;
     let { client, form } = target;
     if (target.chrome) {
       this._startChromeMonitoring(client, form.consoleActor, deferred.resolve);
     } else {
       this._startMonitoringTab(client, form, deferred.resolve);
     }
 
-    return deferred.promise;
+    return deferred.promise.then((result) => {
+      window.emit(EVENTS.CONNECTED);
+      return result;
+    });
   },
 
   /**
    * Disconnects the debugger client and removes event handlers as necessary.
    */
   disconnect: function() {
     // When debugging local or a remote instance, the connection is closed by
     // the RemoteTarget.
@@ -357,16 +364,35 @@ let NetMonitorController = {
     if (aType == ACTIVITY_TYPE.DISABLE_CACHE) {
       this._currentActivity = aType;
       return reconfigureTab({ cacheEnabled: false, performReload: false }).then(standBy);
     }
     this._currentActivity = ACTIVITY_TYPE.NONE;
     return promise.reject(new Error("Invalid activity type"));
   },
 
+  /**
+   * Getter that tells if the server supports sending custom network requests.
+   * @type boolean
+   */
+  get supportsCustomRequest() {
+    return this.webConsoleClient &&
+           (this.webConsoleClient.traits.customNetworkRequest ||
+            !this._target.isApp);
+  },
+
+  /**
+   * Getter that tells if the server can do network performance statistics.
+   * @type boolean
+   */
+  get supportsPerfStats() {
+    return this.tabClient &&
+           (this.tabClient.traits.reconfigure || !this._target.isApp);
+  },
+
   _startup: null,
   _shutdown: null,
   _connection: null,
   _currentActivity: null,
   client: null,
   tabClient: null,
   webConsoleClient: null
 };
@@ -488,31 +514,40 @@ NetworkEventsHandler.prototype = {
    * The "networkEvent" message type handler.
    *
    * @param string aType
    *        Message type.
    * @param object aPacket
    *        The message received from the server.
    */
   _onNetworkEvent: function(aType, aPacket) {
+    if (aPacket.from != this.webConsoleClient.actor) {
+      // Skip events from different console actors.
+      return;
+    }
+
     let { actor, startedDateTime, method, url, isXHR } = aPacket.eventActor;
     NetMonitorView.RequestsMenu.addRequest(actor, startedDateTime, method, url, isXHR);
     window.emit(EVENTS.NETWORK_EVENT);
   },
 
   /**
    * The "networkEventUpdate" message type handler.
    *
    * @param string aType
    *        Message type.
    * @param object aPacket
    *        The message received from the server.
    */
   _onNetworkEventUpdate: function(aType, aPacket) {
     let actor = aPacket.from;
+    if (!NetMonitorView.RequestsMenu.getItemByValue(actor)) {
+      // Skip events from unknown actors.
+      return;
+    }
 
     switch (aPacket.updateType) {
       case "requestHeaders":
         this.webConsoleClient.getRequestHeaders(actor, this._onRequestHeaders);
         window.emit(EVENTS.UPDATING_REQUEST_HEADERS);
         break;
       case "requestCookies":
         this.webConsoleClient.getRequestCookies(actor, this._onRequestCookies);
--- a/browser/devtools/netmonitor/netmonitor-view.js
+++ b/browser/devtools/netmonitor/netmonitor-view.js
@@ -369,26 +369,42 @@ RequestsMenuView.prototype = Heritage.ex
 
     $("#toolbar-labels").addEventListener("click", this.requestsMenuSortEvent, false);
     $("#requests-menu-footer").addEventListener("click", this.requestsMenuFilterEvent, false);
     $("#requests-menu-clear-button").addEventListener("click", this.reqeustsMenuClearEvent, false);
     $("#network-request-popup").addEventListener("popupshowing", this._onContextShowing, false);
     $("#request-menu-context-newtab").addEventListener("command", this._onContextNewTabCommand, false);
     $("#request-menu-context-copy-url").addEventListener("command", this._onContextCopyUrlCommand, false);
     $("#request-menu-context-copy-image-as-data-uri").addEventListener("command", this._onContextCopyImageAsDataUriCommand, false);
-    $("#request-menu-context-resend").addEventListener("command", this._onContextResendCommand, false);
-    $("#request-menu-context-perf").addEventListener("command", this._onContextPerfCommand, false);
+
+    window.once("connected", this._onConnect.bind(this));
+  },
 
-    $("#requests-menu-perf-notice-button").addEventListener("command", this._onContextPerfCommand, false);
-    $("#requests-menu-network-summary-button").addEventListener("command", this._onContextPerfCommand, false);
-    $("#requests-menu-network-summary-label").addEventListener("click", this._onContextPerfCommand, false);
+  _onConnect: function() {
+    if (NetMonitorController.supportsCustomRequest) {
+      $("#request-menu-context-resend").addEventListener("command", this._onContextResendCommand, false);
+      $("#custom-request-send-button").addEventListener("click", this.sendCustomRequestEvent, false);
+      $("#custom-request-close-button").addEventListener("click", this.closeCustomRequestEvent, false);
+      $("#headers-summary-resend").addEventListener("click", this.cloneSelectedRequestEvent, false);
+    } else {
+      $("#request-menu-context-resend").hidden = true;
+      $("#headers-summary-resend").hidden = true;
+    }
 
-    $("#custom-request-send-button").addEventListener("click", this.sendCustomRequestEvent, false);
-    $("#custom-request-close-button").addEventListener("click", this.closeCustomRequestEvent, false);
-    $("#headers-summary-resend").addEventListener("click", this.cloneSelectedRequestEvent, false);
+    if (NetMonitorController.supportsPerfStats) {
+      $("#request-menu-context-perf").addEventListener("command", this._onContextPerfCommand, false);
+      $("#requests-menu-perf-notice-button").addEventListener("command", this._onContextPerfCommand, false);
+      $("#requests-menu-network-summary-button").addEventListener("command", this._onContextPerfCommand, false);
+      $("#requests-menu-network-summary-label").addEventListener("click", this._onContextPerfCommand, false);
+    } else {
+      $("#notice-perf-message").hidden = true;
+      $("#request-menu-context-perf").hidden = true;
+      $("#requests-menu-network-summary-button").hidden = true;
+      $("#requests-menu-network-summary-label").hidden = true;
+    }
   },
 
   /**
    * Destruction function, called when the network monitor is closed.
    */
   destroy: function() {
     dumpn("Destroying the SourcesView");
 
@@ -541,18 +557,22 @@ RequestsMenuView.prototype = Heritage.ex
     this.selectedItem = newItem;
   },
 
   /**
    * Send a new HTTP request using the data in the custom request form.
    */
   sendCustomRequest: function() {
     let selected = this.selectedItem.attachment;
-    let data = Object.create(selected);
 
+    let data = {
+      method: selected.method,
+      url: selected.url,
+      httpVersion: selected.httpVersion,
+    };
     if (selected.requestHeaders) {
       data.headers = selected.requestHeaders.headers;
     }
     if (selected.requestPostData) {
       data.body = selected.requestPostData.postData.text;
     }
 
     NetMonitorController.webConsoleClient.sendHTTPRequest(data, aResponse => {
@@ -1529,17 +1549,18 @@ RequestsMenuView.prototype = Heritage.ex
 
   /**
    * Handle the context menu opening. Hide items if no request is selected.
    */
   _onContextShowing: function() {
     let selectedItem = this.selectedItem;
 
     let resendElement = $("#request-menu-context-resend");
-    resendElement.hidden = !selectedItem || selectedItem.attachment.isCustom;
+    resendElement.hidden = !NetMonitorController.supportsCustomRequest ||
+                           !selectedItem || selectedItem.attachment.isCustom;
 
     let copyUrlElement = $("#request-menu-context-copy-url");
     copyUrlElement.hidden = !selectedItem;
 
     let copyImageAsDataUriElement = $("#request-menu-context-copy-image-as-data-uri");
     copyImageAsDataUriElement.hidden = !selectedItem ||
       !selectedItem.attachment.responseContent ||
       !selectedItem.attachment.responseContent.content.mimeType.contains("image/");
--- a/toolkit/devtools/webconsole/client.js
+++ b/toolkit/devtools/webconsole/client.js
@@ -25,16 +25,18 @@ function WebConsoleClient(aDebuggerClien
   this._client = aDebuggerClient;
   this._longStrings = {};
 }
 exports.WebConsoleClient = WebConsoleClient;
 
 WebConsoleClient.prototype = {
   _longStrings: null,
 
+  get actor() { return this._actor; },
+
   /**
    * Retrieve the cached messages from the server.
    *
    * @see this.CACHED_MESSAGES
    * @param array aTypes
    *        The array of message types you want from the server. See
    *        this.CACHED_MESSAGES for known types.
    * @param function aOnResponse