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 |