| 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 |