The network panel should only record beacons from the monitored page (bug 1160837). r=ochameau
☠☠ backed out by 9f6666bd7a9b ☠ ☠
authorPanos Astithas <past@mozilla.com>
Tue, 19 May 2015 12:28:18 +0300
changeset 248114 fd60bc4207c6939c3677b3b50e3eb4f96a591ebc
parent 248113 ea7e872d6e4c5803ea9070990201732f232361ce
child 248115 f0c15d17566f5639ed85954ca24a64352407e6d9
push id60888
push userkwierso@gmail.com
push dateThu, 11 Jun 2015 01:38:38 +0000
treeherdermozilla-inbound@39e638ed06bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1160837
milestone41.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
The network panel should only record beacons from the monitored page (bug 1160837). r=ochameau
browser/devtools/netmonitor/netmonitor-view.js
browser/devtools/netmonitor/test/browser.ini
browser/devtools/netmonitor/test/browser_net_send-beacon-other-tab.js
browser/devtools/netmonitor/test/browser_net_send-beacon.js
browser/devtools/netmonitor/test/head.js
browser/devtools/netmonitor/test/html_send-beacon.html
toolkit/devtools/webconsole/network-monitor.js
--- a/browser/devtools/netmonitor/netmonitor-view.js
+++ b/browser/devtools/netmonitor/netmonitor-view.js
@@ -188,16 +188,20 @@ let NetMonitorView = {
     }
   },
 
   /**
    * Gets the current mode for this tool.
    * @return string (e.g, "network-inspector-view" or "network-statistics-view")
    */
   get currentFrontendMode() {
+    // The getter may be called from a timeout after the panel is destroyed.
+    if (!this._body.selectedPanel) {
+      return null;
+    }
     return this._body.selectedPanel.id;
   },
 
   /**
    * Toggles between the frontend view modes ("Inspector" vs. "Statistics").
    */
   toggleFrontendMode: function() {
     if (this.currentFrontendMode != "network-inspector-view") {
--- a/browser/devtools/netmonitor/test/browser.ini
+++ b/browser/devtools/netmonitor/test/browser.ini
@@ -16,16 +16,17 @@ support-files =
   html_json-text-mime-test-page.html
   html_jsonp-test-page.html
   html_navigate-test-page.html
   html_params-test-page.html
   html_post-data-test-page.html
   html_post-raw-test-page.html
   html_post-raw-with-headers-test-page.html
   html_simple-test-page.html
+  html_send-beacon.html
   html_sorting-test-page.html
   html_statistics-test-page.html
   html_status-codes-test-page.html
   html_api-calls-test-page.html
   html_copy-as-curl.html
   html_curl-utils.html
   sjs_content-type-test-server.sjs
   sjs_cors-test-server.sjs
@@ -94,16 +95,18 @@ skip-if = e10s # Bug 1091612
 [browser_net_security-details.js]
 [browser_net_security-error.js]
 [browser_net_security-icon-click.js]
 [browser_net_security-redirect.js]
 [browser_net_security-state.js]
 [browser_net_security-tab-deselect.js]
 [browser_net_security-tab-visibility.js]
 [browser_net_security-warnings.js]
+[browser_net_send-beacon.js]
+[browser_net_send-beacon-other-tab.js]
 [browser_net_simple-init.js]
 [browser_net_simple-request-data.js]
 [browser_net_simple-request-details.js]
 [browser_net_simple-request.js]
 [browser_net_sort-01.js]
 [browser_net_sort-02.js]
 [browser_net_sort-03.js]
 [browser_net_statistics-01.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/netmonitor/test/browser_net_send-beacon-other-tab.js
@@ -0,0 +1,31 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests if beacons from other tabs are properly ignored.
+ */
+
+let test = Task.async(function*() {
+  let [, debuggee, monitor] = yield initNetMonitor(SIMPLE_URL);
+  let { RequestsMenu } = monitor.panelWin.NetMonitorView;
+  RequestsMenu.lazyUpdate = false;
+
+  let tab = yield addTab(SEND_BEACON_URL);
+  let beaconDebuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
+  info("Beacon tab added successfully.");
+
+  is(RequestsMenu.itemCount, 0, "The requests menu should be empty.");
+
+  beaconDebuggee.performRequest();
+  debuggee.location.reload();
+
+  yield waitForNetworkEvents(monitor, 1);
+  is(RequestsMenu.itemCount, 1, "Only the reload should be recorded.");
+  let request = RequestsMenu.getItemAtIndex(0);
+  is(request.attachment.method, "GET", "The method is correct.");
+  is(request.attachment.status, "200", "The status is correct.");
+
+  yield teardown(monitor);
+  removeTab(tab);
+  finish();
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/netmonitor/test/browser_net_send-beacon.js
@@ -0,0 +1,27 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests if beacons are handled correctly.
+ */
+
+let test = Task.async(function*() {
+  let [, debuggee, monitor] = yield initNetMonitor(SEND_BEACON_URL);
+  let { RequestsMenu } = monitor.panelWin.NetMonitorView;
+
+  RequestsMenu.lazyUpdate = false;
+
+  is(RequestsMenu.itemCount, 0, "The requests menu should be empty.");
+
+  debuggee.performRequest();
+
+  yield waitForNetworkEvents(monitor, 1);
+  is(RequestsMenu.itemCount, 1, "The beacon should be recorded.");
+  let request = RequestsMenu.getItemAtIndex(0);
+  is(request.attachment.method, "POST", "The method is correct.");
+  ok(request.attachment.url.endsWith("beacon_request"), "The URL is correct.");
+  is(request.attachment.status, "404", "The status is correct.");
+
+  yield teardown(monitor);
+  finish();
+});
--- a/browser/devtools/netmonitor/test/head.js
+++ b/browser/devtools/netmonitor/test/head.js
@@ -35,16 +35,17 @@ const JSON_TEXT_MIME_URL = EXAMPLE_URL +
 const SORTING_URL = EXAMPLE_URL + "html_sorting-test-page.html";
 const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html";
 const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html";
 const CUSTOM_GET_URL = EXAMPLE_URL + "html_custom-get-page.html";
 const SINGLE_GET_URL = EXAMPLE_URL + "html_single-get-page.html";
 const STATISTICS_URL = EXAMPLE_URL + "html_statistics-test-page.html";
 const CURL_URL = EXAMPLE_URL + "html_copy-as-curl.html";
 const CURL_UTILS_URL = EXAMPLE_URL + "html_curl-utils.html";
+const SEND_BEACON_URL = EXAMPLE_URL + "html_send-beacon.html";
 
 const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs";
 const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs";
 const STATUS_CODES_SJS = EXAMPLE_URL + "sjs_status-codes-test-server.sjs";
 const SORTING_SJS = EXAMPLE_URL + "sjs_sorting-test-server.sjs";
 const HTTPS_REDIRECT_SJS = EXAMPLE_URL + "sjs_https-redirect-test-server.sjs";
 const CORS_SJS_PATH = "/browser/browser/devtools/netmonitor/test/sjs_cors-test-server.sjs";
 
new file mode 100644
--- /dev/null
+++ b/browser/devtools/netmonitor/test/html_send-beacon.html
@@ -0,0 +1,23 @@
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<!doctype html>
+
+<html>
+  <head>
+    <meta charset="utf-8"/>
+    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
+    <meta http-equiv="Pragma" content="no-cache" />
+    <meta http-equiv="Expires" content="0" />
+    <title>Network Monitor test page</title>
+  </head>
+
+  <body>
+    <p>Send beacon test</p>
+
+    <script type="text/javascript">
+    function performRequest() {
+      navigator.sendBeacon("beacon_request");
+    }
+    </script>
+  </body>
+</html>
--- a/toolkit/devtools/webconsole/network-monitor.js
+++ b/toolkit/devtools/webconsole/network-monitor.js
@@ -10,17 +10,26 @@ Cu.import("resource://gre/modules/XPCOMU
 
 loader.lazyGetter(this, "NetworkHelper", () => require("devtools/toolkit/webconsole/network-helper"));
 loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
 loader.lazyImporter(this, "DevToolsUtils", "resource://gre/modules/devtools/DevToolsUtils.jsm");
 loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
 loader.lazyServiceGetter(this, "gActivityDistributor",
                          "@mozilla.org/network/http-activity-distributor;1",
                          "nsIHttpActivityDistributor");
-loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
+loader.lazyGetter(this, "gTesting", () => {
+  let testing = false;
+  try {
+    const { gDevTools } = require("resource:///modules/devtools/gDevTools.jsm");
+    testing = gDevTools.testing;
+  } catch (e) {
+    // gDevTools is not present on B2G.
+  }
+  return testing;
+});
 
 ///////////////////////////////////////////////////////////////////////////////
 // Network logging
 ///////////////////////////////////////////////////////////////////////////////
 
 // The maximum uint32 value.
 const PR_UINT32_MAX = 4294967295;
 
@@ -742,17 +751,17 @@ NetworkMonitor.prototype = {
       return true;
     }
 
     // Ignore requests from chrome or add-on code when we are monitoring
     // content.
     // TODO: one particular test (browser_styleeditor_fetch-from-cache.js) needs
     // the gDevTools.testing check. We will move to a better way to serve its
     // needs in bug 1167188, where this check should be removed.
-    if (!gDevTools.testing && aChannel.loadInfo &&
+    if (!gTesting && aChannel.loadInfo &&
         aChannel.loadInfo.loadingDocument === null &&
         aChannel.loadInfo.loadingPrincipal === Services.scriptSecurityManager.getSystemPrincipal()) {
       return false;
     }
 
     if (this.window) {
       // Since frames support, this.window may not be the top level content
       // frame, so that we can't only compare with win.top.
@@ -763,36 +772,48 @@ NetworkMonitor.prototype = {
         }
         if (win.parent == win) {
           break;
         }
         win = win.parent;
       }
     }
 
-    if (aChannel.loadInfo) {
-      if (aChannel.loadInfo.contentPolicyType == Ci.nsIContentPolicy.TYPE_BEACON) {
-        return true;
-      }
-    }
-
     if (this.topFrame) {
       let topFrame = NetworkHelper.getTopFrameForRequest(aChannel);
       if (topFrame && topFrame === this.topFrame) {
         return true;
       }
     }
 
     if (this.appId) {
       let appId = NetworkHelper.getAppIdForRequest(aChannel);
       if (appId && appId == this.appId) {
         return true;
       }
     }
 
+    // The following check is necessary because beacon channels don't come
+    // associated with a load group. Bug 1160837 will hopefully introduce a
+    // platform fix that will render the following code entirely useless.
+    if (aChannel.loadInfo &&
+        aChannel.loadInfo.contentPolicyType == Ci.nsIContentPolicy.TYPE_BEACON) {
+      let nonE10sMatch = this.window &&
+                         aChannel.loadInfo.loadingDocument === this.window.document;
+      let e10sMatch = this.topFrame &&
+                      this.topFrame.contentPrincipal &&
+                      this.topFrame.contentPrincipal.equals(aChannel.loadInfo.loadingPrincipal) &&
+                      this.topFrame.contentPrincipal.URI.spec == aChannel.referrer.spec;
+      let b2gMatch = this.appId &&
+                     aChannel.loadInfo.loadingPrincipal.appId === this.appId;
+      if (nonE10sMatch || e10sMatch || b2gMatch) {
+        return true;
+      }
+    }
+
     return false;
   },
 
   /**
    *
    */
   _createNetworkEvent: function(aChannel, { timestamp, extraStringData, fromCache }) {
     let win = NetworkHelper.getWindowForRequest(aChannel);