Bug 1160837 - The network panel should only record beacons from the monitored page. r=ochameau a=sledru
authorPanos Astithas <past@mozilla.com>
Tue, 16 Jun 2015 04:05:00 +0200
changeset 275069 d5061d388ddc1977ae9f9e5c6dc70fb553f5f326
parent 275068 47d4d88efa1d1ebaa80b1218218bec3c1029d664
child 275070 0af869625d14ccda1696e214f7e8224cc06f2f50
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)
reviewersochameau, sledru
bugs1160837
milestone40.0a2
Bug 1160837 - The network panel should only record beacons from the monitored page. r=ochameau a=sledru
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
@@ -175,16 +175,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
@@ -745,36 +745,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);