OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. |
| 3 * Copyright (C) IBM Corp. 2009 All rights reserved. |
| 4 * |
| 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions |
| 7 * are met: |
| 8 * |
| 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. |
| 11 * 2. Redistributions in binary form must reproduce the above copyright |
| 12 * notice, this list of conditions and the following disclaimer in the |
| 13 * documentation and/or other materials provided with the distribution. |
| 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| 15 * its contributors may be used to endorse or promote products derived |
| 16 * from this software without specific prior written permission. |
| 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 */ |
| 29 |
| 30 WebInspector.ResourceView = function(resource) |
| 31 { |
| 32 WebInspector.View.call(this); |
| 33 |
| 34 this.element.addStyleClass("resource-view"); |
| 35 |
| 36 this.resource = resource; |
| 37 |
| 38 this.headersElement = document.createElement("div"); |
| 39 this.headersElement.className = "resource-view-headers"; |
| 40 this.element.appendChild(this.headersElement); |
| 41 |
| 42 this.contentElement = document.createElement("div"); |
| 43 this.contentElement.className = "resource-view-content"; |
| 44 this.element.appendChild(this.contentElement); |
| 45 |
| 46 this.headersListElement = document.createElement("ol"); |
| 47 this.headersListElement.className = "outline-disclosure"; |
| 48 this.headersElement.appendChild(this.headersListElement); |
| 49 |
| 50 this.headersTreeOutline = new TreeOutline(this.headersListElement); |
| 51 this.headersTreeOutline.expandTreeElementsWhenArrowing = true; |
| 52 |
| 53 this.urlTreeElement = new TreeElement("", null, false); |
| 54 this.urlTreeElement.selectable = false; |
| 55 this.headersTreeOutline.appendChild(this.urlTreeElement); |
| 56 |
| 57 this.httpInformationTreeElement = new TreeElement("", null, true); |
| 58 this.httpInformationTreeElement.expanded = false; |
| 59 this.httpInformationTreeElement.selectable = false; |
| 60 this.headersTreeOutline.appendChild(this.httpInformationTreeElement); |
| 61 |
| 62 this.requestHeadersTreeElement = new TreeElement("", null, true); |
| 63 this.requestHeadersTreeElement.expanded = false; |
| 64 this.requestHeadersTreeElement.selectable = false; |
| 65 this.headersTreeOutline.appendChild(this.requestHeadersTreeElement); |
| 66 |
| 67 this._decodeHover = WebInspector.UIString("Double-Click to toggle between UR
L encoded and decoded formats"); |
| 68 this._decodeRequestParameters = true; |
| 69 |
| 70 this.queryStringTreeElement = new TreeElement("", null, true); |
| 71 this.queryStringTreeElement.expanded = false; |
| 72 this.queryStringTreeElement.selectable = false; |
| 73 this.queryStringTreeElement.hidden = true; |
| 74 this.headersTreeOutline.appendChild(this.queryStringTreeElement); |
| 75 |
| 76 this.formDataTreeElement = new TreeElement("", null, true); |
| 77 this.formDataTreeElement.expanded = false; |
| 78 this.formDataTreeElement.selectable = false; |
| 79 this.formDataTreeElement.hidden = true; |
| 80 this.headersTreeOutline.appendChild(this.formDataTreeElement); |
| 81 |
| 82 this.requestPayloadTreeElement = new TreeElement(WebInspector.UIString("Requ
est Payload"), null, true); |
| 83 this.requestPayloadTreeElement.expanded = false; |
| 84 this.requestPayloadTreeElement.selectable = false; |
| 85 this.requestPayloadTreeElement.hidden = true; |
| 86 this.headersTreeOutline.appendChild(this.requestPayloadTreeElement); |
| 87 |
| 88 this.responseHeadersTreeElement = new TreeElement("", null, true); |
| 89 this.responseHeadersTreeElement.expanded = false; |
| 90 this.responseHeadersTreeElement.selectable = false; |
| 91 this.headersTreeOutline.appendChild(this.responseHeadersTreeElement); |
| 92 |
| 93 this.headersVisible = true; |
| 94 |
| 95 resource.addEventListener("url changed", this._refreshURL, this); |
| 96 resource.addEventListener("requestHeaders changed", this._refreshRequestHead
ers, this); |
| 97 resource.addEventListener("responseHeaders changed", this._refreshResponseHe
aders, this); |
| 98 resource.addEventListener("finished", this._refreshHTTPInformation, this); |
| 99 |
| 100 this._refreshURL(); |
| 101 this._refreshRequestHeaders(); |
| 102 this._refreshResponseHeaders(); |
| 103 this._refreshHTTPInformation(); |
| 104 } |
| 105 |
| 106 WebInspector.ResourceView.prototype = { |
| 107 get headersVisible() |
| 108 { |
| 109 return this._headersVisible; |
| 110 }, |
| 111 |
| 112 set headersVisible(x) |
| 113 { |
| 114 if (x === this._headersVisible) |
| 115 return; |
| 116 |
| 117 this._headersVisible = x; |
| 118 |
| 119 if (x) |
| 120 this.element.addStyleClass("headers-visible"); |
| 121 else |
| 122 this.element.removeStyleClass("headers-visible"); |
| 123 }, |
| 124 |
| 125 attach: function() |
| 126 { |
| 127 if (!this.element.parentNode) { |
| 128 var parentElement = (document.getElementById("resource-views") || do
cument.getElementById("script-resource-views")); |
| 129 if (parentElement) |
| 130 parentElement.appendChild(this.element); |
| 131 } |
| 132 }, |
| 133 |
| 134 _refreshURL: function() |
| 135 { |
| 136 var url = this.resource.url; |
| 137 var statusCodeImage = ""; |
| 138 if (this.resource.statusCode) { |
| 139 var statusImageSource = ""; |
| 140 |
| 141 if (this.resource.statusCode < 300) |
| 142 statusImageSource = "Images/successGreenDot.png"; |
| 143 else if (this.resource.statusCode < 400) |
| 144 statusImageSource = "Images/warningOrangeDot.png"; |
| 145 else |
| 146 statusImageSource = "Images/errorRedDot.png"; |
| 147 |
| 148 statusCodeImage = "<img class=\"resource-status-image\" src=\"" + st
atusImageSource + "\" title=\"" + WebInspector.Resource.StatusTextForCode(this.r
esource.statusCode) + "\">"; |
| 149 } |
| 150 |
| 151 this.urlTreeElement.title = statusCodeImage + "<span class=\"resource-ur
l\">" + url.escapeHTML() + "</span>"; |
| 152 this._refreshQueryString(); |
| 153 }, |
| 154 |
| 155 _refreshQueryString: function() |
| 156 { |
| 157 var url = this.resource.url; |
| 158 var hasQueryString = url.indexOf("?") >= 0; |
| 159 |
| 160 if (!hasQueryString) { |
| 161 this.queryStringTreeElement.hidden = true; |
| 162 return; |
| 163 } |
| 164 |
| 165 this.queryStringTreeElement.hidden = false; |
| 166 var parmString = url.split("?", 2)[1]; |
| 167 this._refreshParms(WebInspector.UIString("Query String Parameters"), par
mString, this.queryStringTreeElement); |
| 168 }, |
| 169 |
| 170 _refreshFormData: function() |
| 171 { |
| 172 this.formDataTreeElement.hidden = true; |
| 173 this.requestPayloadTreeElement.hidden = true; |
| 174 |
| 175 var isFormData = this.resource.requestFormData; |
| 176 if (!isFormData) |
| 177 return; |
| 178 |
| 179 var isFormEncoded = false; |
| 180 var requestContentType = this._getHeaderValue(this.resource.requestHeade
rs, "Content-Type"); |
| 181 if (requestContentType && requestContentType.match(/^application\/x-www-
form-urlencoded\s*(;.*)?$/i)) |
| 182 isFormEncoded = true; |
| 183 |
| 184 if (isFormEncoded) { |
| 185 this.formDataTreeElement.hidden = false; |
| 186 this._refreshParms(WebInspector.UIString("Form Data"), this.resource
.requestFormData, this.formDataTreeElement); |
| 187 } else { |
| 188 this.requestPayloadTreeElement.hidden = false; |
| 189 this._refreshRequestPayload(this.resource.requestFormData); |
| 190 } |
| 191 }, |
| 192 |
| 193 _refreshRequestPayload: function(formData) |
| 194 { |
| 195 this.requestPayloadTreeElement.removeChildren(); |
| 196 |
| 197 var title = "<div class=\"header-name\"> </div>"; |
| 198 title += "<div class=\"raw-form-data header-value\">" + formData.escapeH
TML() + "</div>"; |
| 199 var parmTreeElement = new TreeElement(title, null, false); |
| 200 parmTreeElement.selectable = false; |
| 201 this.requestPayloadTreeElement.appendChild(parmTreeElement); |
| 202 }, |
| 203 |
| 204 _refreshParms: function(title, parmString, parmsTreeElement) |
| 205 { |
| 206 var parms = parmString.split("&"); |
| 207 for (var i = 0; i < parms.length; ++i) { |
| 208 var parm = parms[i]; |
| 209 parm = parm.split("=", 2); |
| 210 if (parm.length == 1) |
| 211 parm.push(""); |
| 212 parms[i] = parm; |
| 213 } |
| 214 |
| 215 parmsTreeElement.removeChildren(); |
| 216 |
| 217 parmsTreeElement.title = title + "<span class=\"header-count\">" + WebIn
spector.UIString(" (%d)", parms.length) + "</span>"; |
| 218 |
| 219 for (var i = 0; i < parms.length; ++i) { |
| 220 var key = parms[i][0]; |
| 221 var value = parms[i][1]; |
| 222 |
| 223 var errorDecoding = false; |
| 224 if (this._decodeRequestParameters) { |
| 225 if (value.indexOf("%") >= 0) { |
| 226 try { |
| 227 value = decodeURIComponent(value); |
| 228 } catch(e) { |
| 229 errorDecoding = true; |
| 230 } |
| 231 } |
| 232 |
| 233 value = value.replace(/\+/g, " "); |
| 234 } |
| 235 |
| 236 valueEscaped = value.escapeHTML(); |
| 237 if (errorDecoding) |
| 238 valueEscaped += " <span class=\"error-message\">" + WebInspector
.UIString("(unable to decode value)").escapeHTML() + "</span>"; |
| 239 |
| 240 var title = "<div class=\"header-name\">" + key.escapeHTML() + ":</d
iv>"; |
| 241 title += "<div class=\"header-value\">" + valueEscaped + "</div>"; |
| 242 |
| 243 var parmTreeElement = new TreeElement(title, null, false); |
| 244 parmTreeElement.selectable = false; |
| 245 parmTreeElement.tooltip = this._decodeHover; |
| 246 parmTreeElement.ondblclick = this._toggleURLdecoding.bind(this); |
| 247 parmsTreeElement.appendChild(parmTreeElement); |
| 248 } |
| 249 }, |
| 250 |
| 251 _toggleURLdecoding: function(treeElement, event) |
| 252 { |
| 253 this._decodeRequestParameters = !this._decodeRequestParameters; |
| 254 this._refreshQueryString(); |
| 255 this._refreshFormData(); |
| 256 }, |
| 257 |
| 258 _getHeaderValue: function(headers, key) |
| 259 { |
| 260 var lowerKey = key.toLowerCase(); |
| 261 for (var testKey in headers) { |
| 262 if (testKey.toLowerCase() === lowerKey) |
| 263 return headers[testKey]; |
| 264 } |
| 265 }, |
| 266 |
| 267 _refreshRequestHeaders: function() |
| 268 { |
| 269 this._refreshHeaders(WebInspector.UIString("Request Headers"), this.reso
urce.sortedRequestHeaders, this.requestHeadersTreeElement); |
| 270 this._refreshFormData(); |
| 271 }, |
| 272 |
| 273 _refreshResponseHeaders: function() |
| 274 { |
| 275 this._refreshHeaders(WebInspector.UIString("Response Headers"), this.res
ource.sortedResponseHeaders, this.responseHeadersTreeElement); |
| 276 }, |
| 277 |
| 278 _refreshHTTPInformation: function() |
| 279 { |
| 280 const listElements = 2; |
| 281 |
| 282 var headerElement = this.httpInformationTreeElement; |
| 283 headerElement.removeChildren(); |
| 284 headerElement.hidden = !this.resource.statusCode; |
| 285 |
| 286 if (this.resource.statusCode) { |
| 287 headerElement.title = WebInspector.UIString("HTTP Information") + "
<span class=\"header-count\">" + WebInspector.UIString(" (%d)", listElements) +
"</span>"; |
| 288 |
| 289 var title = "<div class=\"header-name\">" + WebInspector.UIString("R
equest Method") + ":</div>"; |
| 290 title += "<div class=\"header-value\">" + this.resource.requestMetho
d + "</div>" |
| 291 |
| 292 var headerTreeElement = new TreeElement(title, null, false); |
| 293 headerTreeElement.selectable = false; |
| 294 headerElement.appendChild(headerTreeElement); |
| 295 |
| 296 title = "<div class=\"header-name\">" + WebInspector.UIString("Statu
s Code") + ":</div>"; |
| 297 title += "<div class=\"header-value\">" + WebInspector.Resource.Stat
usTextForCode(this.resource.statusCode) + "</div>" |
| 298 |
| 299 headerTreeElement = new TreeElement(title, null, false); |
| 300 headerTreeElement.selectable = false; |
| 301 headerElement.appendChild(headerTreeElement); |
| 302 } |
| 303 }, |
| 304 |
| 305 _refreshHeaders: function(title, headers, headersTreeElement) |
| 306 { |
| 307 headersTreeElement.removeChildren(); |
| 308 |
| 309 var length = headers.length; |
| 310 headersTreeElement.title = title.escapeHTML() + "<span class=\"header-co
unt\">" + WebInspector.UIString(" (%d)", length) + "</span>"; |
| 311 headersTreeElement.hidden = !length; |
| 312 |
| 313 var length = headers.length; |
| 314 for (var i = 0; i < length; ++i) { |
| 315 var title = "<div class=\"header-name\">" + headers[i].header.escape
HTML() + ":</div>"; |
| 316 title += "<div class=\"header-value\">" + headers[i].value.escapeHTM
L() + "</div>" |
| 317 |
| 318 var headerTreeElement = new TreeElement(title, null, false); |
| 319 headerTreeElement.selectable = false; |
| 320 headersTreeElement.appendChild(headerTreeElement); |
| 321 } |
| 322 } |
| 323 } |
| 324 |
| 325 WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype; |
OLD | NEW |