Bug 1223726 - Customize response body interception; r=ochameau draft
authorJan Odvarko <odvarko@gmail.com>
Mon, 12 Mar 2018 08:10:39 +0100
changeset 770512 86117d796357defad79afac890655c28f4d44587
parent 769726 bfb7edfd0436db388bb9e103b8ad817fc50bfdcf
child 770513 cf0a0bcd1f09cb61541109e4387d9f72d7775b72
push id103420
push userjodvarko@mozilla.com
push dateWed, 21 Mar 2018 12:55:49 +0000
reviewersochameau
bugs1223726
milestone61.0a1
Bug 1223726 - Customize response body interception; r=ochameau * Introduce pref for custom response body limit * Introduce pref for saving request/response bodies MozReview-Commit-ID: 7DrAU1did1a
devtools/client/netmonitor/test/browser_net_truncate.js
devtools/client/preferences/devtools.js
devtools/client/webconsole/webconsole-connection-proxy.js
devtools/shared/webconsole/network-monitor.js
modules/libpref/init/all.js
--- a/devtools/client/netmonitor/test/browser_net_truncate.js
+++ b/devtools/client/netmonitor/test/browser_net_truncate.js
@@ -1,20 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 /**
  * Verifies that truncated response bodies still have the correct reported size.
  */
-
 add_task(async function() {
-  let { RESPONSE_BODY_LIMIT } = require("devtools/shared/webconsole/network-monitor");
-  let URL = EXAMPLE_URL + "sjs_truncate-test-server.sjs?limit=" + RESPONSE_BODY_LIMIT;
+  let limit = Services.prefs.getIntPref("devtools.netmonitor.responseBodyLimit");
+  let URL = EXAMPLE_URL + "sjs_truncate-test-server.sjs?limit=" + limit;
   let { monitor, tab } = await initNetMonitor(URL);
 
   info("Starting test... ");
 
   let { L10N } = require("devtools/client/netmonitor/src/utils/l10n");
 
   let { document } = monitor.panelWin;
 
--- a/devtools/client/preferences/devtools.js
+++ b/devtools/client/preferences/devtools.js
@@ -158,16 +158,19 @@ pref("devtools.netmonitor.enabled", true
 // The default Network Monitor UI settings
 pref("devtools.netmonitor.panes-network-details-width", 550);
 pref("devtools.netmonitor.panes-network-details-height", 450);
 pref("devtools.netmonitor.filters", "[\"all\"]");
 pref("devtools.netmonitor.visibleColumns",
   "[\"status\",\"method\",\"file\",\"domain\",\"cause\",\"type\",\"transferred\",\"contentSize\",\"waterfall\"]"
 );
 
+// Save request/response bodies yes/no.
+pref("devtools.netmonitor.saveRequestAndResponseBodies", true);
+
 // The default Network monitor HAR export setting
 pref("devtools.netmonitor.har.defaultLogDir", "");
 pref("devtools.netmonitor.har.defaultFileName", "Archive %date");
 pref("devtools.netmonitor.har.jsonp", false);
 pref("devtools.netmonitor.har.jsonpCallback", "");
 pref("devtools.netmonitor.har.includeResponseBodies", true);
 pref("devtools.netmonitor.har.compress", false);
 pref("devtools.netmonitor.har.forceExport", false);
--- a/devtools/client/webconsole/webconsole-connection-proxy.js
+++ b/devtools/client/webconsole/webconsole-connection-proxy.js
@@ -201,19 +201,25 @@ WebConsoleConnectionProxy.prototype = {
                     response.message);
       this._connectDefer.reject(response);
       return;
     }
 
     this.webConsoleClient = webConsoleClient;
     this._hasNativeConsoleAPI = response.nativeConsoleAPI;
 
+    let saveBodies = Services.prefs.getBoolPref(
+      "devtools.netmonitor.saveRequestAndResponseBodies");
+
     // There is no way to view response bodies from the Browser Console, so do
     // not waste the memory.
-    let saveBodies = !this.webConsoleFrame.isBrowserConsole;
+    if (this.webConsoleFrame.isBrowserConsole) {
+      saveBodies = false;
+    }
+
     this.webConsoleFrame.setSaveRequestAndResponseBodies(saveBodies);
 
     this.webConsoleClient.on("networkEvent", this._onNetworkEvent);
     this.webConsoleClient.on("networkEventUpdate", this._onNetworkEventUpdate);
 
     let msgs = ["PageError", "ConsoleAPI"];
     this.webConsoleClient.getCachedMessages(msgs, this._onCachedMessages);
 
--- a/devtools/shared/webconsole/network-monitor.js
+++ b/devtools/shared/webconsole/network-monitor.js
@@ -30,21 +30,16 @@ const {NetworkThrottleManager} = require
 const PR_UINT32_MAX = 4294967295;
 
 // HTTP status codes.
 const HTTP_MOVED_PERMANENTLY = 301;
 const HTTP_FOUND = 302;
 const HTTP_SEE_OTHER = 303;
 const HTTP_TEMPORARY_REDIRECT = 307;
 
-// The maximum number of bytes a NetworkResponseListener can hold: 1 MB
-const RESPONSE_BODY_LIMIT = 1048576;
-// Exported for testing.
-exports.RESPONSE_BODY_LIMIT = RESPONSE_BODY_LIMIT;
-
 /**
  * Check if a given network request should be logged by a network monitor
  * based on the specified filters.
  *
  * @param nsIHttpChannel channel
  *        Request to check.
  * @param filters
  *        NetworkMonitor filters to match against.
@@ -274,17 +269,17 @@ exports.StackTraceCollector = StackTrace
  *        HttpActivity object associated with this request. See NetworkMonitor
  *        for more information.
  */
 function NetworkResponseListener(owner, httpActivity) {
   this.owner = owner;
   this.receivedData = "";
   this.httpActivity = httpActivity;
   this.bodySize = 0;
-  // Indicates if the response had a size greater than RESPONSE_BODY_LIMIT.
+  // Indicates if the response had a size greater than response body limit.
   this.truncated = false;
   // Note that this is really only needed for the non-e10s case.
   // See bug 1309523.
   let channel = this.httpActivity.channel;
   this._wrappedNotificationCallbacks = channel.notificationCallbacks;
   channel.notificationCallbacks = this;
 }
 
@@ -392,17 +387,17 @@ NetworkResponseListener.prototype = {
   setAsyncListener: function(stream, listener) {
     // Asynchronously wait for the stream to be readable or closed.
     stream.asyncWait(listener, 0, 0, Services.tm.mainThread);
   },
 
   /**
    * Stores the received data, if request/response body logging is enabled. It
    * also does limit the number of stored bytes, based on the
-   * RESPONSE_BODY_LIMIT constant.
+   * `devtools.netmonitor.responseBodyLimit` pref.
    *
    * Learn more about nsIStreamListener at:
    * https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIStreamListener
    *
    * @param nsIRequest request
    * @param nsISupports context
    * @param nsIInputStream inputStream
    * @param unsigned long offset
@@ -410,20 +405,23 @@ NetworkResponseListener.prototype = {
    */
   onDataAvailable: function(request, context, inputStream, offset, count) {
     this._findOpenResponse();
     let data = NetUtil.readInputStreamToString(inputStream, count);
 
     this.bodySize += count;
 
     if (!this.httpActivity.discardResponseBody) {
-      if (this.receivedData.length < RESPONSE_BODY_LIMIT) {
+      let limit = Services.prefs.getIntPref("devtools.netmonitor.responseBodyLimit");
+      if (this.receivedData.length <= limit || limit == 0) {
         this.receivedData +=
           NetworkHelper.convertToUnicode(data, request.contentCharset);
-      } else {
+      }
+      if (this.receivedData.length > limit && limit > 0) {
+        this.receivedData = this.receivedData.substr(0, limit);
         this.truncated = true;
       }
     }
   },
 
   /**
    * See documentation at
    * https://developer.mozilla.org/En/NsIRequestObserver
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1109,16 +1109,22 @@ pref("devtools.debugger.log.verbose", fa
 
 pref("devtools.debugger.remote-port", 6000);
 pref("devtools.debugger.remote-websocket", false);
 // Force debugger server binding on the loopback interface
 pref("devtools.debugger.force-local", true);
 // Block tools from seeing / interacting with certified apps
 pref("devtools.debugger.forbid-certified-apps", true);
 
+// Limit for intercepted response bodies (1 MB)
+// Possible values:
+// 0 => the response body has no limit
+// n => represents max number of bytes stored
+pref("devtools.netmonitor.responseBodyLimit", 1048576);
+
 // DevTools default color unit
 pref("devtools.defaultColorUnit", "authored");
 
 // Used for devtools debugging
 pref("devtools.dump.emit", false);
 
 // Controls whether EventEmitter module throws dump message on each emit
 pref("toolkit.dump.emit", false);