Bug 859133 - Add a plain request/response headers view. r=vporof
authorRaphaël Lustin <raphael@lustin.fr>
Wed, 01 Oct 2014 08:09:00 -0400
changeset 231933 d1244379f050e03782e72416c9f2511f05a067c2
parent 231932 4339077e7826b456717a0a2a115812914b55a85f
child 231934 f467df2147976456be9426ceb15d27bbd490dc21
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvporof
bugs859133
milestone35.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 859133 - Add a plain request/response headers view. r=vporof
browser/devtools/netmonitor/netmonitor-view.js
browser/devtools/netmonitor/netmonitor.xul
browser/devtools/netmonitor/test/browser.ini
browser/devtools/netmonitor/test/browser_net_raw_headers.js
browser/locales/en-US/chrome/browser/devtools/netmonitor.dtd
browser/themes/linux/devtools/netmonitor.css
browser/themes/shared/devtools/netmonitor.inc.css
--- a/browser/devtools/netmonitor/netmonitor-view.js
+++ b/browser/devtools/netmonitor/netmonitor-view.js
@@ -365,30 +365,33 @@ RequestsMenuView.prototype = Heritage.ex
     this.requestsMenuSortEvent = getKeyWithEvent(this.sortBy.bind(this));
     this.requestsMenuFilterEvent = getKeyWithEvent(this.filterOn.bind(this));
     this.reqeustsMenuClearEvent = this.clear.bind(this);
     this._onContextShowing = this._onContextShowing.bind(this);
     this._onContextNewTabCommand = this.openRequestInTab.bind(this);
     this._onContextCopyUrlCommand = this.copyUrl.bind(this);
     this._onContextCopyImageAsDataUriCommand = this.copyImageAsDataUri.bind(this);
     this._onContextResendCommand = this.cloneSelectedRequest.bind(this);
+    this._onContextToggleRawHeadersCommand = this.toggleRawHeaders.bind(this);
     this._onContextPerfCommand = () => NetMonitorView.toggleFrontendMode();
     this._onReloadCommand = () => NetMonitorView.reloadPage();
 
     this.sendCustomRequestEvent = this.sendCustomRequest.bind(this);
     this.closeCustomRequestEvent = this.closeCustomRequest.bind(this);
     this.cloneSelectedRequestEvent = this.cloneSelectedRequest.bind(this);
+    this.toggleRawHeadersEvent = this.toggleRawHeaders.bind(this);
 
     $("#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);
+    $("#toggle-raw-headers").addEventListener("click", this.toggleRawHeadersEvent, false);
 
     window.once("connected", this._onConnect.bind(this));
   },
 
   _onConnect: function() {
     $("#requests-menu-reload-notice-button").addEventListener("command", this._onReloadCommand, false);
 
     if (NetMonitorController.supportsCustomRequest) {
@@ -442,16 +445,17 @@ RequestsMenuView.prototype = Heritage.ex
     $("#requests-menu-perf-notice-button").removeEventListener("command", this._onContextPerfCommand, false);
     $("#requests-menu-network-summary-button").removeEventListener("command", this._onContextPerfCommand, false);
     $("#requests-menu-network-summary-label").removeEventListener("click", this._onContextPerfCommand, false);
     $("#network-statistics-back-button").removeEventListener("command", this._onContextPerfCommand, false);
 
     $("#custom-request-send-button").removeEventListener("click", this.sendCustomRequestEvent, false);
     $("#custom-request-close-button").removeEventListener("click", this.closeCustomRequestEvent, false);
     $("#headers-summary-resend").removeEventListener("click", this.cloneSelectedRequestEvent, false);
+    $("#toggle-raw-headers").removeEventListener("click", this.toggleRawHeadersEvent, false);
   },
 
   /**
    * Resets this container (removes all the networking information).
    */
   reset: function() {
     this.empty();
     this._firstRequestStartedMillis = -1;
@@ -634,16 +638,38 @@ RequestsMenuView.prototype = Heritage.ex
    * Remove the currently selected custom request.
    */
   closeCustomRequest: function() {
     this.remove(this.selectedItem);
     NetMonitorView.Sidebar.toggle(false);
   },
 
   /**
+   * Shows raw request/response headers in textboxes.
+   */
+  toggleRawHeaders: function() {
+    let requestTextarea = $("#raw-request-headers-textarea");
+    let responseTextare = $("#raw-response-headers-textarea");
+    let rawHeadersHidden = $("#raw-headers").getAttribute("hidden");
+
+    if (rawHeadersHidden) {
+      let selected = this.selectedItem.attachment;
+      let selectedRequestHeaders = selected.requestHeaders.headers;
+      let selectedResponseHeaders = selected.responseHeaders.headers;
+      requestTextarea.value = writeHeaderText(selectedRequestHeaders);
+      responseTextare.value = writeHeaderText(selectedResponseHeaders);
+      $("#raw-headers").hidden = false;
+    } else {
+      requestTextarea.value = null;
+      responseTextare.value = null;
+      $("#raw-headers").hidden = true;
+    }
+  },
+
+  /**
    * Filters all network requests in this container by a specified type.
    *
    * @param string aType
    *        Either "all", "html", "css", "js", "xhr", "fonts", "images", "media"
    *        "flash" or "other".
    */
   filterOn: function(aType = "all") {
     if (aType === "all") {
@@ -2008,16 +2034,17 @@ NetworkDetailsView.prototype = {
    */
   populate: function(aData) {
     $("#request-params-box").setAttribute("flex", "1");
     $("#request-params-box").hidden = false;
     $("#request-post-data-textarea-box").hidden = true;
     $("#response-content-info-header").hidden = true;
     $("#response-content-json-box").hidden = true;
     $("#response-content-textarea-box").hidden = true;
+    $("#raw-headers").hidden = true;
     $("#response-content-image-box").hidden = true;
 
     let isHtml = RequestsMenuView.prototype.isHtml({ attachment: aData });
 
     // Show the "Preview" tabpanel only for plain HTML responses.
     $("#preview-tab").hidden = !isHtml;
     $("#preview-tabpanel").hidden = !isHtml;
 
--- a/browser/devtools/netmonitor/netmonitor.xul
+++ b/browser/devtools/netmonitor/netmonitor.xul
@@ -302,27 +302,49 @@
                          class="requests-menu-status"/>
                     <label id="headers-summary-status-value"
                            class="plain tabpanel-summary-value devtools-monospace"
                            crop="end"
                            flex="1"/>
                     <button id="headers-summary-resend"
                             class="devtools-toolbarbutton"
                             label="&netmonitorUI.summary.editAndResend;"/>
+                    <button id="toggle-raw-headers"
+                            class="devtools-toolbarbutton"
+                            label="&netmonitorUI.summary.rawHeaders;"/>
                   </hbox>
                   <hbox id="headers-summary-version"
                         class="tabpanel-summary-container"
                         align="center">
                     <label class="plain tabpanel-summary-label"
                            value="&netmonitorUI.summary.version;"/>
                     <label id="headers-summary-version-value"
                            class="plain tabpanel-summary-value devtools-monospace"
                            crop="end"
                            flex="1"/>
                   </hbox>
+                  <hbox id="raw-headers"
+                        class="tabpanel-summary-container"
+                        align="center"
+                        hidden="true">
+                    <vbox id="raw-request-headers-textarea-box" flex="1" hidden="false">
+                      <label class="plain tabpanel-summary-label"
+                        value="&netmonitorUI.summary.rawHeaders.requestHeaders;"/>
+                      <textbox id="raw-request-headers-textarea"
+                        class="raw-response-textarea"
+                        flex="1" multiline="true" readonly="true"/>
+                    </vbox>
+                    <vbox id="raw-response-headers-textarea-box" flex="1" hidden="false">
+                      <label class="plain tabpanel-summary-label"
+                        value="&netmonitorUI.summary.rawHeaders.responseHeaders;"/>
+                      <textbox id="raw-response-headers-textarea"
+                        class="raw-response-textarea"
+                        flex="1" multiline="true" readonly="true"/>
+                    </vbox>
+                  </hbox>
                   <vbox id="all-headers" flex="1"/>
                 </vbox>
               </tabpanel>
               <tabpanel id="cookies-tabpanel"
                         class="tabpanel-content">
                 <vbox flex="1">
                   <vbox id="all-cookies" flex="1"/>
                 </vbox>
--- a/browser/devtools/netmonitor/test/browser.ini
+++ b/browser/devtools/netmonitor/test/browser.ini
@@ -72,16 +72,17 @@ skip-if= buildapp == 'mulet'
 [browser_net_page-nav.js]
 [browser_net_pane-collapse.js]
 [browser_net_pane-toggle.js]
 [browser_net_post-data-01.js]
 [browser_net_post-data-02.js]
 [browser_net_post-data-03.js]
 [browser_net_prefs-and-l10n.js]
 [browser_net_prefs-reload.js]
+[browser_net_raw_headers.js]
 [browser_net_reload-button.js]
 [browser_net_req-resp-bodies.js]
 [browser_net_resend.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]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/netmonitor/test/browser_net_raw_headers.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let gPanelWin;
+let gPanelDoc;
+
+/**
+ * Tests if showing raw headers works.
+ */
+
+function test() {
+  initNetMonitor(POST_DATA_URL).then(([aTab, aDebuggee, aMonitor]) => {
+    info("Starting test... ");
+
+    gPanelWin = aMonitor.panelWin;
+    gPanelDoc = gPanelWin.document;
+
+    let { document, Editor, NetMonitorView } = gPanelWin;
+    let { RequestsMenu } = NetMonitorView;
+    let TAB_UPDATED = gPanelWin.EVENTS.TAB_UPDATED;
+
+    RequestsMenu.lazyUpdate = false;
+
+    waitForNetworkEvents(aMonitor, 0, 2).then(() => {
+      let origItem = RequestsMenu.getItemAtIndex(0);
+      RequestsMenu.selectedItem = origItem;
+
+      waitFor(aMonitor.panelWin, TAB_UPDATED).then(() => {
+        EventUtils.sendMouseEvent({ type: "click" }, document.getElementById("toggle-raw-headers"));
+        testShowRawHeaders(origItem.attachment);
+        EventUtils.sendMouseEvent({ type: "click" }, document.getElementById("toggle-raw-headers"));
+        testHideRawHeaders(document);
+        finishUp(aMonitor);
+      });
+    });
+
+    aDebuggee.performRequests();
+  });
+}
+
+/*
+ * Tests that raw headers were displayed correctly
+ */
+function testShowRawHeaders(aData) {
+  let requestHeaders = gPanelDoc.getElementById("raw-request-headers-textarea").value;
+  for (let header of aData.requestHeaders.headers) {
+    ok(requestHeaders.indexOf(header.name + ": " + header.value) >= 0, "textarea contains request headers");
+  }
+  let responseHeaders = gPanelDoc.getElementById("raw-response-headers-textarea").value;
+  for (let header of aData.responseHeaders.headers) {
+    ok(responseHeaders.indexOf(header.name + ": " + header.value) >= 0, "textarea contains response headers");
+  }
+}
+
+/*
+ * Tests that raw headers textareas are hidden and empty
+ */
+function testHideRawHeaders(document) {
+  let rawHeadersHidden = document.getElementById("raw-headers").getAttribute("hidden");
+  let requestTextarea = document.getElementById("raw-request-headers-textarea");
+  let responseTextare = document.getElementById("raw-response-headers-textarea");
+  ok(rawHeadersHidden, "raw headers textareas are hidden");
+  ok(requestTextarea.value == '', "raw request headers textarea is empty");
+  ok(responseTextare.value == '', "raw response headers textarea is empty");
+}
+
+function finishUp(aMonitor) {
+  gPanelWin = null;
+  gPanelDoc = null;
+
+  teardown(aMonitor).then(finish);
+}
--- a/browser/locales/en-US/chrome/browser/devtools/netmonitor.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/netmonitor.dtd
@@ -226,16 +226,29 @@
   -  on the button in the headers tab that opens a form to edit and resend the currently
      displayed request -->
 <!ENTITY netmonitorUI.summary.editAndResend "Edit and Resend">
 
 <!-- LOCALIZATION NOTE (debuggerUI.summary.editAndResend.accesskey): This is the access key
   -  for the "Edit and Resend" menu item displayed in the context menu for a request -->
 <!ENTITY netmonitorUI.summary.editAndResend.accesskey "R">
 
+<!-- LOCALIZATION NOTE (debuggerUI.summary.rawHeaders): This is the label displayed
+  -  on the button in the headers tab that toggle view for raw request/response headers
+     from the currently displayed request -->
+<!ENTITY netmonitorUI.summary.rawHeaders "Raw headers">
+
+<!-- LOCALIZATION NOTE (debuggerUI.summary.rawHeaders.requestHeaders): This is the label displayed
+  -  in the network details headers tab identifying the raw request headers textarea -->
+<!ENTITY netmonitorUI.summary.rawHeaders.requestHeaders "Request headers:">
+
+<!-- LOCALIZATION NOTE (debuggerUI.summary.rawHeaders.responseHeaders): This is the label displayed
+  -  in the network details headers tab identifying the raw response headers textarea -->
+<!ENTITY netmonitorUI.summary.rawHeaders.responseHeaders "Response headers:">
+
 <!-- LOCALIZATION NOTE (netmonitorUI.context.newTab):  This is the label
   -  for the Open in New Tab menu item displayed in the context menu of the
   -  network container  -->
 <!ENTITY netmonitorUI.context.newTab      "Open in New Tab">
 
 <!-- LOCALIZATION NOTE (netmonitorUI.context.newTab.accesskey): This is the access key
   -  for the Open in New Tab menu item displayed in the context menu of the
   -  network container -->
--- a/browser/themes/linux/devtools/netmonitor.css
+++ b/browser/themes/linux/devtools/netmonitor.css
@@ -3,16 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 %include ../../shared/devtools/netmonitor.inc.css
 
 #headers-summary-resend {
   padding: 4px;
 }
 
+#toggle-raw-headers {
+  padding: 4px;
+}
+
 .requests-menu-status-and-method {
   width: 9em;
 }
 
 .requests-menu-domain {
   width: 16vw;
 }
 
--- a/browser/themes/shared/devtools/netmonitor.inc.css
+++ b/browser/themes/shared/devtools/netmonitor.inc.css
@@ -480,16 +480,25 @@ label.requests-menu-status-code {
   padding-top: 2px;
 }
 
 #headers-summary-resend {
   margin-top: -10px;
   -moz-margin-end: 6px;
 }
 
+#toggle-raw-headers {
+  margin-top: -10px;
+  -moz-margin-end: 6px;
+}
+
+.raw-response-textarea {
+  height: 50vh;
+}
+
 /* Response tabpanel */
 
 #response-content-info-header {
   margin: 0;
   padding: 3px 8px;
 }
 
 .theme-dark  #response-content-info-header {