Adds the Request and Response headers to the Resource view.
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 May 2008 03:31:50 +0000 (03:31 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 May 2008 03:31:50 +0000 (03:31 +0000)
<rdar://problem/5940782> REGRESSION: Resource Request and Response
headers aren't shown (18451)

Reviewed by Adam Roben.

* English.lproj/localizedStrings.js: Added new strings.
* css/view-source.css: Add comments to make sure a couple of
style rules stay in sync with inspector.css.
* page/inspector/Resource.js:
(WebInspector.Resource.prototype.set url): Dispatch an event when
this property changes.
(WebInspector.Resource.prototype.set requestHeaders): Ditto.
(WebInspector.Resource.prototype.set responseHeaders): Ditto.
* page/inspector/ResourceView.js:
(WebInspector.ResourceView): Add new elements for the headers
and a headers TreeOutline. Add event listeners for resource
property changes. Calls the three new refresh functions.
(WebInspector.ResourceView.prototype.set headersVisible): Implemented.
Toggles the headers-visible class name.
(WebInspector.ResourceView.prototype._refreshURL): Update the URL
tree element.
(WebInspector.ResourceView.prototype._refreshRequestHeaders): Call _refreshHeaders.
(WebInspector.ResourceView.prototype._refreshResponseHeaders): Ditto.
(WebInspector.ResourceView.prototype._refreshHeaders): Remove the previous
headers fromm the tree element. Loop throuh the headers and create new
tree elements and append them.
* page/inspector/ResourcesPanel.js:
(WebInspector.ResourcesPanel.prototype._updateSidebarWidth): Call resize
on the visible view if it is implemented.
* page/inspector/SourceFrame.js:
(WebInspector.SourceFrame.prototype.get autoSizeToFitContentHeight):
(WebInspector.SourceFrame.prototype.set autoSizeToFitContentHeight):
(WebInspector.SourceFrame.prototype.sizeToFitContentHeight):
(WebInspector.SourceFrame.prototype._loaded):
(WebInspector.SourceFrame.prototype._windowResized):
* page/inspector/SourceView.js:
(WebInspector.SourceView): Move the SourceFrame creation so it is
available when headersVisible is set. Add a gutter element to fill
the vertical space no covered by the SourceFrame now.
(WebInspector.SourceView.prototype.set headersVisible): Set the
SourceFrame.autoSizeToFitContentHeight when this property changes.
(WebInspector.SourceView.prototype.resize): Call SourceFrame.sizeToFitContentHeight
when autoSizeToFitContentHeight is true. This happens when resizing the
Resources sidebar.
* page/inspector/inspector.css: Add a copy of webkit-line-gutter-backdrop
and a comment to keep in sync with view-source.css. Adds other styles
for the headers area of resource-view.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@33991 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/English.lproj/localizedStrings.js
WebCore/css/view-source.css
WebCore/page/inspector/Resource.js
WebCore/page/inspector/ResourceView.js
WebCore/page/inspector/ResourcesPanel.js
WebCore/page/inspector/SourceFrame.js
WebCore/page/inspector/SourceView.js
WebCore/page/inspector/inspector.css

index 80a9ccd..0c4cbfa 100644 (file)
@@ -1,3 +1,55 @@
+2008-05-21  Timothy Hatcher  <timothy@apple.com>
+
+        Adds the Request and Response headers to the Resource view.
+
+        <rdar://problem/5940782> REGRESSION: Resource Request and Response
+        headers aren't shown (18451)
+
+        Reviewed by Adam Roben.
+
+        * English.lproj/localizedStrings.js: Added new strings.
+        * css/view-source.css: Add comments to make sure a couple of
+        style rules stay in sync with inspector.css.
+        * page/inspector/Resource.js:
+        (WebInspector.Resource.prototype.set url): Dispatch an event when
+        this property changes.
+        (WebInspector.Resource.prototype.set requestHeaders): Ditto.
+        (WebInspector.Resource.prototype.set responseHeaders): Ditto.
+        * page/inspector/ResourceView.js:
+        (WebInspector.ResourceView): Add new elements for the headers
+        and a headers TreeOutline. Add event listeners for resource
+        property changes. Calls the three new refresh functions.
+        (WebInspector.ResourceView.prototype.set headersVisible): Implemented.
+        Toggles the headers-visible class name.
+        (WebInspector.ResourceView.prototype._refreshURL): Update the URL
+        tree element.
+        (WebInspector.ResourceView.prototype._refreshRequestHeaders): Call _refreshHeaders.
+        (WebInspector.ResourceView.prototype._refreshResponseHeaders): Ditto.
+        (WebInspector.ResourceView.prototype._refreshHeaders): Remove the previous
+        headers fromm the tree element. Loop throuh the headers and create new
+        tree elements and append them.
+        * page/inspector/ResourcesPanel.js:
+        (WebInspector.ResourcesPanel.prototype._updateSidebarWidth): Call resize
+        on the visible view if it is implemented.
+        * page/inspector/SourceFrame.js:
+        (WebInspector.SourceFrame.prototype.get autoSizesToFitContentHeight):
+        (WebInspector.SourceFrame.prototype.set autoSizesToFitContentHeight):
+        (WebInspector.SourceFrame.prototype.sizeToFitContentHeight):
+        (WebInspector.SourceFrame.prototype._loaded): 
+        (WebInspector.SourceFrame.prototype._windowResized): 
+        * page/inspector/SourceView.js:
+        (WebInspector.SourceView): Move the SourceFrame creation so it is
+        available when headersVisible is set. Add a gutter element to fill
+        the vertical space no covered by the SourceFrame now.
+        (WebInspector.SourceView.prototype.set headersVisible): Set the
+        SourceFrame.autoSizesToFitContentHeight when this property changes.
+        (WebInspector.SourceView.prototype.resize): Call SourceFrame.sizeToFitContentHeight
+        when autoSizesToFitContentHeight is true. This happens when resizing the 
+        Resources sidebar.
+        * page/inspector/inspector.css: Add a copy of webkit-line-gutter-backdrop
+        and a comment to keep in sync with view-source.css. Adds other styles
+        for the headers area of resource-view.
+
 2008-05-21  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Anders Carlsson.
index a73eb86..d308338 100644 (file)
Binary files a/WebCore/English.lproj/localizedStrings.js and b/WebCore/English.lproj/localizedStrings.js differ
index 11fd9ec..20722ee 100644 (file)
@@ -43,6 +43,7 @@ td {
 }
 
 .webkit-line-gutter-backdrop, .webkit-line-number {
+    /* Keep this in sync with inspector.css (.webkit-line-gutter-backdrop) */
     -webkit-box-sizing: border-box;
     padding: 0 4px !important;
     width: 31px;
@@ -52,6 +53,7 @@ td {
 }
 
 .webkit-line-gutter-backdrop {
+    /* Keep this in sync with inspector.css (.webkit-line-gutter-backdrop) */
     position: absolute;
     z-index: -1;
     left: 0;
index 3f2e260..0fa6df4 100644 (file)
@@ -93,7 +93,12 @@ WebInspector.Resource.prototype = {
 
         var oldURL = this._url;
         this._url = x;
+
+        // FIXME: We should make the WebInspector object listen for the "url changed" event.
+        // Then resourceURLChanged can be removed.
         WebInspector.resourceURLChanged(this, oldURL);
+
+        this.dispatchEventToListeners("url changed");
     },
 
     get domain()
@@ -341,8 +346,7 @@ WebInspector.Resource.prototype = {
         this._requestHeaders = x;
         delete this._sortedRequestHeaders;
 
-        if (WebInspector.panels.resources)
-            WebInspector.panels.resources.refreshResource(this);
+        this.dispatchEventToListeners("requestHeaders changed");
     },
 
     get sortedRequestHeaders()
@@ -373,8 +377,7 @@ WebInspector.Resource.prototype = {
         this._responseHeaders = x;
         delete this._sortedResponseHeaders;
 
-        if (WebInspector.panels.resources)
-            WebInspector.panels.resources.refreshResource(this);
+        this.dispatchEventToListeners("responseHeaders changed");
     },
 
     get sortedResponseHeaders()
index 5372efc..7a4efd6 100644 (file)
@@ -34,11 +34,44 @@ WebInspector.ResourceView = function(resource)
 
     this.resource = resource;
 
-    // FIXME: Implement the setter for headersVisible when the header element is added.
+    this.headersElement = document.createElement("div");
+    this.headersElement.className = "resource-view-headers";
+    this.element.appendChild(this.headersElement);
 
     this.contentElement = document.createElement("div");
     this.contentElement.className = "resource-view-content";
     this.element.appendChild(this.contentElement);
+
+    this.headersListElement = document.createElement("ol");
+    this.headersListElement.className = "outline-disclosure";
+    this.headersElement.appendChild(this.headersListElement);
+
+    this.headersTreeOutline = new TreeOutline(this.headersListElement);
+    this.headersTreeOutline.expandTreeElementsWhenArrowing = true;
+
+    this.urlTreeElement = new TreeElement("", null, false);
+    this.urlTreeElement.selectable = false;
+    this.headersTreeOutline.appendChild(this.urlTreeElement);
+
+    this.requestHeadersTreeElement = new TreeElement("", null, true);
+    this.requestHeadersTreeElement.expanded = false;
+    this.requestHeadersTreeElement.selectable = false;
+    this.headersTreeOutline.appendChild(this.requestHeadersTreeElement);
+
+    this.responseHeadersTreeElement = new TreeElement("", null, true);
+    this.responseHeadersTreeElement.expanded = false;
+    this.responseHeadersTreeElement.selectable = false;
+    this.headersTreeOutline.appendChild(this.responseHeadersTreeElement);
+
+    this.headersVisible = true;
+
+    resource.addEventListener("url changed", this._refreshURL, this);
+    resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this);
+    resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this);
+
+    this._refreshURL();
+    this._refreshRequestHeaders();
+    this._refreshResponseHeaders();
 }
 
 WebInspector.ResourceView.prototype = {
@@ -54,17 +87,50 @@ WebInspector.ResourceView.prototype = {
 
         this._headersVisible = x;
 
-        if (x) {
-            // FIXME: Implement this when headers are added.
-        } else {
-            // FIXME: Implement this when headers are added.
-        }
+        if (x)
+            this.element.addStyleClass("headers-visible");
+        else
+            this.element.removeStyleClass("headers-visible");
     },
 
     attach: function()
     {
         if (!this.element.parentNode)
             document.getElementById("resource-views").appendChild(this.element);
+    },
+
+    _refreshURL: function()
+    {
+        this.urlTreeElement.title = this.resource.url.escapeHTML();
+    },
+
+    _refreshRequestHeaders: function()
+    {
+        this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, this.requestHeadersTreeElement);
+    },
+
+    _refreshResponseHeaders: function()
+    {
+        this._refreshHeaders(WebInspector.UIString("Response Headers"), this.resource.sortedResponseHeaders, this.responseHeadersTreeElement);
+    },
+
+    _refreshHeaders: function(title, headers, headersTreeElement)
+    {
+        headersTreeElement.removeChildren();
+
+        var length = headers.length;
+        headersTreeElement.title = title.escapeHTML() + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", length) + "</span>";
+        headersTreeElement.hidden = !length;
+
+        var length = headers.length;
+        for (var i = 0; i < length; ++i) {
+            var title = "<div class=\"header-name\">" + headers[i].header.escapeHTML() + ":</div>";
+            title += "<div class=\"header-value\">" + headers[i].value.escapeHTML() + "</div>"
+
+            var headerTreeElement = new TreeElement(title, null, false);
+            headerTreeElement.selectable = false;
+            headersTreeElement.appendChild(headerTreeElement);
+        }
     }
 }
 
index b3aa950..ae7cc55 100644 (file)
@@ -1053,6 +1053,10 @@ WebInspector.ResourcesPanel.prototype = {
 
         this._updateGraphBars();
         this._updateGraphDividersIfNeeded();
+
+        var visibleResourceView = this.visibleResourceView;
+        if (visibleResourceView && "resize" in visibleResourceView)
+            visibleResourceView.resize();
     }
 }
 
index b2f2278..f32b942 100644 (file)
@@ -54,6 +54,31 @@ WebInspector.SourceFrame.prototype = {
         this._updateExecutionLine(previousLine);
     },
 
+    get autoSizesToFitContentHeight()
+    {
+        return this._autoSizesToFitContentHeight;
+    },
+
+    set autoSizesToFitContentHeight(x)
+    {
+        if (this._autoSizesToFitContentHeight === x)
+            return;
+
+        this._autoSizesToFitContentHeight = x;
+
+        if (this._autoSizesToFitContentHeight) {
+            this._windowResizeListener = this._windowResized.bind(this);
+            window.addEventListener("resize", this._windowResizeListener, false);
+            this.sizeToFitContentHeight();
+        } else {
+            this.element.style.removeProperty("height");
+            if (this.element.contentDocument)
+                this.element.contentDocument.body.addStyleClass("webkit-height-sized-to-fit");
+            window.removeEventListener("resize", this._windowResizeListener, false);
+            delete this._windowResizeListener;
+        }
+    },
+
     sourceRow: function(lineNumber)
     {
         if (!lineNumber || !this.element.contentDocument)
@@ -131,6 +156,14 @@ WebInspector.SourceFrame.prototype = {
         }
     },
 
+    sizeToFitContentHeight: function()
+    {
+        if (this.element.contentDocument) {
+            this.element.style.setProperty("height", this.element.contentDocument.body.offsetHeight + "px");
+            this.element.contentDocument.body.addStyleClass("webkit-height-sized-to-fit");
+        }
+    },
+
     _loaded: function()
     {
         WebInspector.addMainEventListeners(this.element.contentDocument);
@@ -154,6 +187,7 @@ WebInspector.SourceFrame.prototype = {
         styleText += ".webkit-breakpoint.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-program-counter); }\n";
         styleText += ".webkit-breakpoint-disabled.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-program-counter); }\n";
         styleText += ".webkit-execution-line .webkit-line-content { background-color: rgb(171, 191, 254); outline: 1px solid rgb(64, 115, 244); }\n";
+        styleText += ".webkit-height-sized-to-fit { overflow-y: hidden }\n";
 
         styleElement.textContent = styleText;
 
@@ -168,6 +202,16 @@ WebInspector.SourceFrame.prototype = {
         this._addExistingMessagesToSource();
         this._addExistingBreakpointsToSource();
         this._updateExecutionLine();
+
+        if (this.autoSizesToFitContentHeight)
+            this.sizeToFitContentHeight();
+    },
+
+    _windowResized: function(event)
+    {
+        if (!this._autoSizesToFitContentHeight)
+            return;
+        this.sizeToFitContentHeight();
     },
 
     _documentMouseDown: function(event)
index d052f51..acb2a1e 100644 (file)
 
 WebInspector.SourceView = function(resource)
 {
+    // Set the sourceFrame first since WebInspector.ResourceView will set headersVisible
+    // and our override of headersVisible needs the sourceFrame.
+    this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
+
     WebInspector.ResourceView.call(this, resource);
 
     resource.addEventListener("finished", this._resourceLoadingFinished, this);
@@ -36,18 +40,38 @@ WebInspector.SourceView = function(resource)
 
     this._frameNeedsSetup = true;
 
-    this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
-
     this.contentElement.appendChild(this.sourceFrame.element);
+
+    var gutterElement = document.createElement("div");
+    gutterElement.className = "webkit-line-gutter-backdrop";
+    this.element.appendChild(gutterElement);
 }
 
 WebInspector.SourceView.prototype = {
+    set headersVisible(x)
+    {
+        if (x === this._headersVisible)
+            return;
+
+        var superSetter = WebInspector.ResourceView.prototype.__lookupSetter__("headersVisible");
+        if (superSetter)
+            superSetter.call(this, x);
+
+        this.sourceFrame.autoSizesToFitContentHeight = x;
+    },
+
     show: function(parentElement)
     {
         WebInspector.ResourceView.prototype.show.call(this, parentElement);
         this.setupSourceFrameIfNeeded();
     },
 
+    resize: function()
+    {
+        if (this.sourceFrame.autoSizesToFitContentHeight)
+            this.sourceFrame.sizeToFitContentHeight();
+    },
+
     setupSourceFrameIfNeeded: function()
     {
         if (this.resource.finished && !this.resource.failed && this._frameNeedsSetup) {
index 5833f8f..85bec79 100644 (file)
@@ -528,12 +528,63 @@ body.console-visible #console {
     left: 0;
     right: 0;
     bottom: 0;
+    overflow: hidden;
 }
 
 .resource-view.visible {
     display: block;
 }
 
+.resource-view.headers-visible {
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+.resource-view-headers {
+    display: none;
+    padding: 6px;
+    border-bottom: 1px solid rgb(64%, 64%, 64%);
+    background-color: white;
+    -webkit-user-select: text;
+}
+
+.resource-view-headers .outline-disclosure .parent {
+    -webkit-user-select: none;
+    font-weight: bold;
+}
+
+.resource-view.headers-visible .resource-view-headers {
+    display: block;
+}
+
+.resource-view-headers .outline-disclosure .children li {
+    white-space: nowrap;
+}
+
+.resource-view-headers .outline-disclosure li.expanded .header-count {
+    display: none;
+}
+
+.resource-view-headers .outline-disclosure .header-name {
+    color: rgb(33%, 33%, 33%);
+    display: inline-block;
+    width: 105px;
+    text-align: right;
+    margin-right: 0.5em;
+    font-weight: bold;
+    vertical-align: top;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.resource-view-headers .outline-disclosure .header-value {
+    display: inline-block;
+    white-space: normal;
+    word-break: break-word;
+    vertical-align: top;
+    margin-right: 100px;
+}
+
 .resource-view .resource-view-content {
     position: absolute;
     top: 0;
@@ -542,6 +593,30 @@ body.console-visible #console {
     bottom: 0;
 }
 
+.resource-view.headers-visible .resource-view-content {
+    position: relative;
+    top: auto;
+    right: auto;
+    left: auto;
+    bottom: auto;
+}
+
+.resource-view.headers-visible .source-view-frame {
+    height: auto;
+}
+
+.webkit-line-gutter-backdrop {
+    /* Keep this in sync with view-source.css (.webkit-line-gutter-backdrop) */
+    width: 31px;
+    background-color: rgb(240, 240, 240);
+    border-right: 1px solid rgb(187, 187, 187);
+    position: absolute;
+    z-index: -1;
+    left: 0;
+    top: 0;
+    height: 100%
+}
+
 .resource-view.font {
     font-size: 60px;
     white-space: pre-wrap;