OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. | |
3 * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org> | |
4 * Copyright (C) 2010, 2011, 2012, 2013, 2014 Google Inc. All rights reserved. | |
5 * | |
6 * Redistribution and use in source and binary forms, with or without | |
7 * modification, are permitted provided that the following conditions | |
8 * are met: | |
9 * | |
10 * 1. Redistributions of source code must retain the above copyright | |
11 * notice, this list of conditions and the following disclaimer. | |
12 * 2. Redistributions in binary form must reproduce the above copyright | |
13 * notice, this list of conditions and the following disclaimer in the | |
14 * documentation and/or other materials provided with the distribution. | |
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | |
16 * its contributors may be used to endorse or promote products derived | |
17 * from this software without specific prior written permission. | |
18 * | |
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 /** | |
32 * @constructor | |
33 * @implements {WebInspector.Searchable} | |
34 * @implements {WebInspector.TargetManager.Observer} | |
35 * @extends {WebInspector.VBox} | |
36 * @param {!WebInspector.FilterBar} filterBar | |
37 * @param {!WebInspector.Setting} coulmnsVisibilitySetting | |
38 */ | |
39 WebInspector.NetworkLogView = function(filterBar, coulmnsVisibilitySetting) | |
40 { | |
41 WebInspector.VBox.call(this); | |
42 this.registerRequiredCSS("network/networkLogView.css"); | |
43 this.registerRequiredCSS("ui/filter.css"); | |
44 | |
45 this._filterBar = filterBar; | |
46 this._coulmnsVisibilitySetting = coulmnsVisibilitySetting; | |
47 /** @type {!Map.<string, !WebInspector.NetworkDataGridNode>} */ | |
48 this._nodesByRequestId = new Map(); | |
49 /** @type {!Object.<string, boolean>} */ | |
50 this._staleRequestIds = {}; | |
51 /** @type {number} */ | |
52 this._mainRequestLoadTime = -1; | |
53 /** @type {number} */ | |
54 this._mainRequestDOMContentLoadedTime = -1; | |
55 this._matchedRequestCount = 0; | |
56 this._highlightedSubstringChanges = []; | |
57 | |
58 /** @type {!Array.<!WebInspector.NetworkLogView.Filter>} */ | |
59 this._filters = []; | |
60 | |
61 this._currentMatchedRequestNode = null; | |
62 this._currentMatchedRequestIndex = -1; | |
63 | |
64 this._createStatusbarButtons(); | |
65 this._createStatusBarItems(); | |
66 this._linkifier = new WebInspector.Linkifier(); | |
67 | |
68 this._allowPopover = true; | |
69 | |
70 /** @type {number} */ | |
71 this._rowHeight = 0; | |
72 | |
73 this._addFilters(); | |
74 this._resetSuggestionBuilder(); | |
75 this._initializeView(); | |
76 this._toggleRecordButton(true); | |
77 | |
78 WebInspector.targetManager.observeTargets(this); | |
79 WebInspector.targetManager.addModelListener(WebInspector.NetworkManager, Web
Inspector.NetworkManager.EventTypes.RequestStarted, this._onRequestStarted, this
); | |
80 WebInspector.targetManager.addModelListener(WebInspector.NetworkManager, Web
Inspector.NetworkManager.EventTypes.RequestUpdated, this._onRequestUpdated, this
); | |
81 WebInspector.targetManager.addModelListener(WebInspector.NetworkManager, Web
Inspector.NetworkManager.EventTypes.RequestFinished, this._onRequestUpdated, thi
s); | |
82 | |
83 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel,
WebInspector.ResourceTreeModel.EventTypes.WillReloadPage, this._willReloadPage,
this); | |
84 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel,
WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNav
igated, this); | |
85 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel,
WebInspector.ResourceTreeModel.EventTypes.Load, this._loadEventFired, this); | |
86 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel,
WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._domContentLoad
edEventFired, this); | |
87 } | |
88 | |
89 WebInspector.NetworkLogView._isFilteredOutSymbol = Symbol("isFilteredOut"); | |
90 WebInspector.NetworkLogView._isMatchingSearchQuerySymbol = Symbol("isMatchingSea
rchQuery"); | |
91 | |
92 WebInspector.NetworkLogView.HTTPSchemas = {"http": true, "https": true, "ws": tr
ue, "wss": true}; | |
93 WebInspector.NetworkLogView._responseHeaderColumns = ["Cache-Control", "Connecti
on", "Content-Encoding", "Content-Length", "ETag", "Keep-Alive", "Last-Modified"
, "Server", "Vary"]; | |
94 WebInspector.NetworkLogView.defaultColumnsVisibility = { | |
95 method: true, status: true, scheme: false, domain: false, remoteAddress: fal
se, type: true, initiator: true, cookies: false, setCookies: false, size: true,
time: true, connectionId: false, | |
96 "Cache-Control": false, "Connection": false, "Content-Encoding": false, "Con
tent-Length": false, "ETag": false, "Keep-Alive": false, "Last-Modified": false,
"Server": false, "Vary": false | |
97 }; | |
98 WebInspector.NetworkLogView._defaultRefreshDelay = 500; | |
99 | |
100 /** @enum {string} */ | |
101 WebInspector.NetworkLogView.FilterType = { | |
102 Domain: "Domain", | |
103 HasResponseHeader: "HasResponseHeader", | |
104 Is: "Is", | |
105 Method: "Method", | |
106 MimeType: "MimeType", | |
107 Scheme: "Scheme", | |
108 SetCookieDomain: "SetCookieDomain", | |
109 SetCookieName: "SetCookieName", | |
110 SetCookieValue: "SetCookieValue", | |
111 StatusCode: "StatusCode" | |
112 }; | |
113 | |
114 /** @enum {string} */ | |
115 WebInspector.NetworkLogView.IsFilterType = { | |
116 Running: "running" | |
117 }; | |
118 | |
119 /** @type {!Array.<string>} */ | |
120 WebInspector.NetworkLogView._searchKeys = Object.values(WebInspector.NetworkLogV
iew.FilterType); | |
121 | |
122 /** @type {!Object.<string, string>} */ | |
123 WebInspector.NetworkLogView._columnTitles = { | |
124 "name": WebInspector.UIString("Name"), | |
125 "method": WebInspector.UIString("Method"), | |
126 "status": WebInspector.UIString("Status"), | |
127 "scheme": WebInspector.UIString("Scheme"), | |
128 "domain": WebInspector.UIString("Domain"), | |
129 "remoteAddress": WebInspector.UIString("Remote Address"), | |
130 "type": WebInspector.UIString("Type"), | |
131 "initiator": WebInspector.UIString("Initiator"), | |
132 "cookies": WebInspector.UIString("Cookies"), | |
133 "setCookies": WebInspector.UIString("Set-Cookies"), | |
134 "size": WebInspector.UIString("Size"), | |
135 "time": WebInspector.UIString("Time"), | |
136 "connectionId": WebInspector.UIString("Connection Id"), | |
137 "timeline": WebInspector.UIString("Timeline"), | |
138 | |
139 // Response header columns | |
140 "Cache-Control": WebInspector.UIString("Cache-Control"), | |
141 "Connection": WebInspector.UIString("Connection"), | |
142 "Content-Encoding": WebInspector.UIString("Content-Encoding"), | |
143 "Content-Length": WebInspector.UIString("Content-Length"), | |
144 "ETag": WebInspector.UIString("ETag"), | |
145 "Keep-Alive": WebInspector.UIString("Keep-Alive"), | |
146 "Last-Modified": WebInspector.UIString("Last-Modified"), | |
147 "Server": WebInspector.UIString("Server"), | |
148 "Vary": WebInspector.UIString("Vary") | |
149 }; | |
150 | |
151 WebInspector.NetworkLogView.prototype = { | |
152 /** | |
153 * @param {!WebInspector.Target} target | |
154 */ | |
155 targetAdded: function(target) | |
156 { | |
157 target.networkLog.requests.forEach(this._appendRequest.bind(this)); | |
158 }, | |
159 | |
160 /** | |
161 * @param {!WebInspector.Target} target | |
162 */ | |
163 targetRemoved: function(target) | |
164 { | |
165 }, | |
166 | |
167 /** | |
168 * @return {boolean} | |
169 */ | |
170 allowRequestSelection: function() | |
171 { | |
172 return !this._allowPopover; | |
173 }, | |
174 | |
175 _addFilters: function() | |
176 { | |
177 this._textFilterUI = new WebInspector.TextFilterUI(); | |
178 this._textFilterUI.addEventListener(WebInspector.FilterUI.Events.FilterC
hanged, this._filterChanged, this); | |
179 this._filterBar.addFilter(this._textFilterUI); | |
180 | |
181 var types = []; | |
182 for (var typeId in WebInspector.resourceTypes) { | |
183 var resourceType = WebInspector.resourceTypes[typeId]; | |
184 if (resourceType === WebInspector.resourceTypes.TextTrack) | |
185 continue; | |
186 types.push({name: resourceType.name(), label: resourceType.categoryT
itle()}); | |
187 } | |
188 this._resourceTypeFilterUI = new WebInspector.NamedBitSetFilterUI(types,
WebInspector.settings.networkResourceTypeFilters); | |
189 this._resourceTypeFilterUI.addEventListener(WebInspector.FilterUI.Events
.FilterChanged, this._filterChanged.bind(this), this); | |
190 this._filterBar.addFilter(this._resourceTypeFilterUI); | |
191 | |
192 var dataURLSetting = WebInspector.settings.networkHideDataURL; | |
193 this._dataURLFilterUI = new WebInspector.CheckboxFilterUI("hide-data-url
", WebInspector.UIString("Hide data URLs"), true, dataURLSetting); | |
194 this._dataURLFilterUI.addEventListener(WebInspector.FilterUI.Events.Filt
erChanged, this._filterChanged.bind(this), this); | |
195 this._filterBar.addFilter(this._dataURLFilterUI); | |
196 }, | |
197 | |
198 _resetSuggestionBuilder: function() | |
199 { | |
200 this._suggestionBuilder = new WebInspector.FilterSuggestionBuilder(WebIn
spector.NetworkLogView._searchKeys); | |
201 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterType.I
s, WebInspector.NetworkLogView.IsFilterType.Running); | |
202 this._textFilterUI.setSuggestionBuilder(this._suggestionBuilder); | |
203 }, | |
204 | |
205 /** | |
206 * @param {!WebInspector.Event} event | |
207 */ | |
208 _filterChanged: function(event) | |
209 { | |
210 this._removeAllNodeHighlights(); | |
211 this._parseFilterQuery(this._textFilterUI.value()); | |
212 this._filterRequests(); | |
213 }, | |
214 | |
215 _initializeView: function() | |
216 { | |
217 this.element.id = "network-container"; | |
218 | |
219 this._createSortingFunctions(); | |
220 this._createCalculators(); | |
221 this._createTable(); | |
222 this._createTimelineGrid(); | |
223 this._summaryBarElement = this.element.createChild("div", "network-summa
ry-bar"); | |
224 | |
225 this._updateRowsSize(); | |
226 | |
227 this._popoverHelper = new WebInspector.PopoverHelper(this.element, this.
_getPopoverAnchor.bind(this), this._showPopover.bind(this), this._onHidePopover.
bind(this)); | |
228 // Enable faster hint. | |
229 this._popoverHelper.setTimeout(250, 250); | |
230 | |
231 this.switchViewMode(true); | |
232 }, | |
233 | |
234 /** | |
235 * @return {!Array.<!Element>} | |
236 */ | |
237 statusBarItems: function() | |
238 { | |
239 return [ | |
240 this._recordButton.element, | |
241 this._clearButton.element, | |
242 this._filterBar.filterButton().element, | |
243 this._largerRequestsButton.element, | |
244 this._preserveLogCheckbox.element, | |
245 this._disableCacheCheckbox.element, | |
246 this._progressBarContainer]; | |
247 }, | |
248 | |
249 /** | |
250 * @return {boolean} | |
251 */ | |
252 usesLargeRows: function() | |
253 { | |
254 return !!WebInspector.settings.resourcesLargeRows.get(); | |
255 }, | |
256 | |
257 /** | |
258 * @param {boolean} flag | |
259 */ | |
260 setAllowPopover: function(flag) | |
261 { | |
262 this._allowPopover = flag; | |
263 }, | |
264 | |
265 /** | |
266 * @return {!Array.<!Element>} | |
267 */ | |
268 elementsToRestoreScrollPositionsFor: function() | |
269 { | |
270 if (!this._dataGrid) // Not initialized yet. | |
271 return []; | |
272 return [this._dataGrid.scrollContainer]; | |
273 }, | |
274 | |
275 _createTimelineGrid: function() | |
276 { | |
277 this._timelineGrid = new WebInspector.TimelineGrid(); | |
278 this._timelineGrid.element.classList.add("network-timeline-grid"); | |
279 this._dataGrid.element.appendChild(this._timelineGrid.element); | |
280 }, | |
281 | |
282 _createTable: function() | |
283 { | |
284 var columns = []; | |
285 columns.push({ | |
286 id: "name", | |
287 titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Na
me"), WebInspector.UIString("Path")), | |
288 title: WebInspector.NetworkLogView._columnTitles["name"], | |
289 sortable: true, | |
290 weight: 20, | |
291 disclosure: true | |
292 }); | |
293 | |
294 columns.push({ | |
295 id: "method", | |
296 title: WebInspector.NetworkLogView._columnTitles["method"], | |
297 sortable: true, | |
298 weight: 6 | |
299 }); | |
300 | |
301 columns.push({ | |
302 id: "status", | |
303 titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("St
atus"), WebInspector.UIString("Text")), | |
304 title: WebInspector.NetworkLogView._columnTitles["status"], | |
305 sortable: true, | |
306 weight: 6 | |
307 }); | |
308 | |
309 columns.push({ | |
310 id: "scheme", | |
311 title: WebInspector.NetworkLogView._columnTitles["scheme"], | |
312 sortable: true, | |
313 weight: 6 | |
314 }); | |
315 | |
316 columns.push({ | |
317 id: "domain", | |
318 title: WebInspector.NetworkLogView._columnTitles["domain"], | |
319 sortable: true, | |
320 weight: 6 | |
321 }); | |
322 | |
323 columns.push({ | |
324 id: "remoteAddress", | |
325 title: WebInspector.NetworkLogView._columnTitles["remoteAddress"], | |
326 sortable: true, | |
327 weight: 10, | |
328 align: WebInspector.DataGrid.Align.Right | |
329 }); | |
330 | |
331 columns.push({ | |
332 id: "type", | |
333 title: WebInspector.NetworkLogView._columnTitles["type"], | |
334 sortable: true, | |
335 weight: 6 | |
336 }); | |
337 | |
338 columns.push({ | |
339 id: "initiator", | |
340 title: WebInspector.NetworkLogView._columnTitles["initiator"], | |
341 sortable: true, | |
342 weight: 10 | |
343 }); | |
344 | |
345 columns.push({ | |
346 id: "cookies", | |
347 title: WebInspector.NetworkLogView._columnTitles["cookies"], | |
348 sortable: true, | |
349 weight: 6, | |
350 align: WebInspector.DataGrid.Align.Right | |
351 }); | |
352 | |
353 columns.push({ | |
354 id: "setCookies", | |
355 title: WebInspector.NetworkLogView._columnTitles["setCookies"], | |
356 sortable: true, | |
357 weight: 6, | |
358 align: WebInspector.DataGrid.Align.Right | |
359 }); | |
360 | |
361 columns.push({ | |
362 id: "size", | |
363 titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Si
ze"), WebInspector.UIString("Content")), | |
364 title: WebInspector.NetworkLogView._columnTitles["size"], | |
365 sortable: true, | |
366 weight: 6, | |
367 align: WebInspector.DataGrid.Align.Right | |
368 }); | |
369 | |
370 columns.push({ | |
371 id: "time", | |
372 titleDOMFragment: this._makeHeaderFragment(WebInspector.UIString("Ti
me"), WebInspector.UIString("Latency")), | |
373 title: WebInspector.NetworkLogView._columnTitles["time"], | |
374 sortable: true, | |
375 weight: 6, | |
376 align: WebInspector.DataGrid.Align.Right | |
377 }); | |
378 | |
379 columns.push({ | |
380 id: "connectionId", | |
381 title: WebInspector.NetworkLogView._columnTitles["connectionId"], | |
382 sortable: true, | |
383 weight: 6 | |
384 }); | |
385 | |
386 var responseHeaderColumns = WebInspector.NetworkLogView._responseHeaderC
olumns; | |
387 for (var i = 0; i < responseHeaderColumns.length; ++i) { | |
388 var headerName = responseHeaderColumns[i]; | |
389 var descriptor = { | |
390 id: headerName, | |
391 title: WebInspector.NetworkLogView._columnTitles[headerName], | |
392 weight: 6 | |
393 } | |
394 if (headerName === "Content-Length") | |
395 descriptor.align = WebInspector.DataGrid.Align.Right; | |
396 columns.push(descriptor); | |
397 } | |
398 | |
399 columns.push({ | |
400 id: "timeline", | |
401 titleDOMFragment: createDocumentFragment(), | |
402 title: WebInspector.NetworkLogView._columnTitles["timeline"], | |
403 sortable: false, | |
404 weight: 40, | |
405 sort: WebInspector.DataGrid.Order.Ascending | |
406 }); | |
407 | |
408 this._dataGrid = new WebInspector.SortableDataGrid(columns); | |
409 this._dataGrid.setStickToBottom(true); | |
410 this._updateColumns(); | |
411 this._dataGrid.setName("networkLog"); | |
412 this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last); | |
413 this._dataGrid.element.classList.add("network-log-grid"); | |
414 this._dataGrid.element.addEventListener("contextmenu", this._contextMenu
.bind(this), true); | |
415 this._dataGrid.show(this.element); | |
416 | |
417 // Event listeners need to be added _after_ we attach to the document, s
o that owner document is properly update. | |
418 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChan
ged, this._sortItems, this); | |
419 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.ColumnsResi
zed, this._updateDividersIfNeeded, this); | |
420 | |
421 this._patchTimelineHeader(); | |
422 this._dataGrid.sortNodes(this._sortingFunctions.startTime, false); | |
423 }, | |
424 | |
425 /** | |
426 * @param {string} title | |
427 * @param {string} subtitle | |
428 * @return {!DocumentFragment} | |
429 */ | |
430 _makeHeaderFragment: function(title, subtitle) | |
431 { | |
432 var fragment = createDocumentFragment(); | |
433 fragment.createTextChild(title); | |
434 var subtitleDiv = fragment.createChild("div", "network-header-subtitle")
; | |
435 subtitleDiv.createTextChild(subtitle); | |
436 return fragment; | |
437 }, | |
438 | |
439 _patchTimelineHeader: function() | |
440 { | |
441 var timelineSorting = createElement("select"); | |
442 | |
443 var option = createElement("option"); | |
444 option.value = "startTime"; | |
445 option.label = WebInspector.UIString("Timeline"); | |
446 timelineSorting.appendChild(option); | |
447 | |
448 option = createElement("option"); | |
449 option.value = "startTime"; | |
450 option.label = WebInspector.UIString("Start Time"); | |
451 timelineSorting.appendChild(option); | |
452 | |
453 option = createElement("option"); | |
454 option.value = "responseTime"; | |
455 option.label = WebInspector.UIString("Response Time"); | |
456 timelineSorting.appendChild(option); | |
457 | |
458 option = createElement("option"); | |
459 option.value = "endTime"; | |
460 option.label = WebInspector.UIString("End Time"); | |
461 timelineSorting.appendChild(option); | |
462 | |
463 option = createElement("option"); | |
464 option.value = "duration"; | |
465 option.label = WebInspector.UIString("Duration"); | |
466 timelineSorting.appendChild(option); | |
467 | |
468 option = createElement("option"); | |
469 option.value = "latency"; | |
470 option.label = WebInspector.UIString("Latency"); | |
471 timelineSorting.appendChild(option); | |
472 | |
473 var header = this._dataGrid.headerTableHeader("timeline"); | |
474 header.replaceChild(timelineSorting, header.firstChild); | |
475 | |
476 timelineSorting.addEventListener("click", function(event) { event.consum
e() }, false); | |
477 timelineSorting.addEventListener("change", this._sortByTimeline.bind(thi
s), false); | |
478 this._timelineSortSelector = timelineSorting; | |
479 }, | |
480 | |
481 _createSortingFunctions: function() | |
482 { | |
483 this._sortingFunctions = {}; | |
484 this._sortingFunctions.name = WebInspector.NetworkDataGridNode.NameCompa
rator; | |
485 this._sortingFunctions.method = WebInspector.NetworkDataGridNode.Request
PropertyComparator.bind(null, "method", false); | |
486 this._sortingFunctions.status = WebInspector.NetworkDataGridNode.Request
PropertyComparator.bind(null, "statusCode", false); | |
487 this._sortingFunctions.scheme = WebInspector.NetworkDataGridNode.Request
PropertyComparator.bind(null, "scheme", false); | |
488 this._sortingFunctions.domain = WebInspector.NetworkDataGridNode.Request
PropertyComparator.bind(null, "domain", false); | |
489 this._sortingFunctions.remoteAddress = WebInspector.NetworkDataGridNode.
RemoteAddressComparator; | |
490 this._sortingFunctions.type = WebInspector.NetworkDataGridNode.RequestPr
opertyComparator.bind(null, "mimeType", false); | |
491 this._sortingFunctions.initiator = WebInspector.NetworkDataGridNode.Init
iatorComparator; | |
492 this._sortingFunctions.cookies = WebInspector.NetworkDataGridNode.Reques
tCookiesCountComparator; | |
493 this._sortingFunctions.setCookies = WebInspector.NetworkDataGridNode.Res
ponseCookiesCountComparator; | |
494 this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeCompa
rator; | |
495 this._sortingFunctions.time = WebInspector.NetworkDataGridNode.RequestPr
opertyComparator.bind(null, "duration", false); | |
496 this._sortingFunctions.connectionId = WebInspector.NetworkDataGridNode.R
equestPropertyComparator.bind(null, "connectionId", false); | |
497 this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.Reque
stPropertyComparator.bind(null, "startTime", false); | |
498 this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.Requ
estPropertyComparator.bind(null, "startTime", false); | |
499 this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.Reques
tPropertyComparator.bind(null, "endTime", false); | |
500 this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.R
equestPropertyComparator.bind(null, "responseReceivedTime", false); | |
501 this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.Reque
stPropertyComparator.bind(null, "duration", true); | |
502 this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.Reques
tPropertyComparator.bind(null, "latency", true); | |
503 }, | |
504 | |
505 _createCalculators: function() | |
506 { | |
507 /** @type {!WebInspector.NetworkTransferTimeCalculator} */ | |
508 this._timeCalculator = new WebInspector.NetworkTransferTimeCalculator(); | |
509 /** @type {!WebInspector.NetworkTransferDurationCalculator} */ | |
510 this._durationCalculator = new WebInspector.NetworkTransferDurationCalcu
lator(); | |
511 | |
512 /** @type {!Object.<string, !WebInspector.NetworkTimeCalculator>} */ | |
513 this._calculators = {}; | |
514 this._calculators.timeline = this._timeCalculator; | |
515 this._calculators.startTime = this._timeCalculator; | |
516 this._calculators.endTime = this._timeCalculator; | |
517 this._calculators.responseTime = this._timeCalculator; | |
518 this._calculators.duration = this._durationCalculator; | |
519 this._calculators.latency = this._durationCalculator; | |
520 | |
521 this._calculator = this._timeCalculator; | |
522 }, | |
523 | |
524 _sortItems: function() | |
525 { | |
526 this._removeAllNodeHighlights(); | |
527 var columnIdentifier = this._dataGrid.sortColumnIdentifier(); | |
528 if (columnIdentifier === "timeline") { | |
529 this._sortByTimeline(); | |
530 return; | |
531 } | |
532 var sortingFunction = this._sortingFunctions[columnIdentifier]; | |
533 if (!sortingFunction) | |
534 return; | |
535 | |
536 this._dataGrid.sortNodes(sortingFunction, !this._dataGrid.isSortOrderAsc
ending()); | |
537 this._highlightNthMatchedRequestForSearch(this._updateMatchCountAndFindM
atchIndex(this._currentMatchedRequestNode), false); | |
538 this._timelineSortSelector.selectedIndex = 0; | |
539 | |
540 WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMet
rics.UserAction, { | |
541 action: WebInspector.UserMetrics.UserActionNames.NetworkSort, | |
542 column: columnIdentifier, | |
543 sortOrder: this._dataGrid.sortOrder() | |
544 }); | |
545 }, | |
546 | |
547 _sortByTimeline: function() | |
548 { | |
549 this._removeAllNodeHighlights(); | |
550 var selectedIndex = this._timelineSortSelector.selectedIndex; | |
551 if (!selectedIndex) | |
552 selectedIndex = 1; // Sort by start time by default. | |
553 var selectedOption = this._timelineSortSelector[selectedIndex]; | |
554 var value = selectedOption.value; | |
555 | |
556 this._setCalculator(this._calculators[value]); | |
557 var sortingFunction = this._sortingFunctions[value]; | |
558 this._dataGrid.sortNodes(sortingFunction); | |
559 this._highlightNthMatchedRequestForSearch(this._updateMatchCountAndFindM
atchIndex(this._currentMatchedRequestNode), false); | |
560 this._dataGrid.markColumnAsSortedBy("timeline", WebInspector.DataGrid.Or
der.Ascending); | |
561 }, | |
562 | |
563 _createStatusBarItems: function() | |
564 { | |
565 this._progressBarContainer = createElement("div"); | |
566 this._progressBarContainer.className = "status-bar-item"; | |
567 }, | |
568 | |
569 _updateSummaryBar: function() | |
570 { | |
571 var requestsNumber = this._nodesByRequestId.size; | |
572 | |
573 if (!requestsNumber) { | |
574 if (this._summaryBarElement._isDisplayingWarning) | |
575 return; | |
576 this._summaryBarElement._isDisplayingWarning = true; | |
577 this._summaryBarElement.removeChildren(); | |
578 this._summaryBarElement.createChild("div", "warning-icon-small"); | |
579 var text = WebInspector.UIString("No requests captured. Reload the p
age to see detailed information on the network activity."); | |
580 this._summaryBarElement.createTextChild(text); | |
581 this._summaryBarElement.title = text; | |
582 return; | |
583 } | |
584 delete this._summaryBarElement._isDisplayingWarning; | |
585 | |
586 var transferSize = 0; | |
587 var selectedRequestsNumber = 0; | |
588 var selectedTransferSize = 0; | |
589 var baseTime = -1; | |
590 var maxTime = -1; | |
591 var nodes = this._nodesByRequestId.valuesArray(); | |
592 for (var i = 0; i < nodes.length; ++i) { | |
593 var request = nodes[i].request(); | |
594 var requestTransferSize = request.transferSize; | |
595 transferSize += requestTransferSize; | |
596 if (!nodes[i][WebInspector.NetworkLogView._isFilteredOutSymbol]) { | |
597 selectedRequestsNumber++; | |
598 selectedTransferSize += requestTransferSize; | |
599 } | |
600 if (request.url === request.target().resourceTreeModel.inspectedPage
URL()) | |
601 baseTime = request.startTime; | |
602 if (request.endTime > maxTime) | |
603 maxTime = request.endTime; | |
604 } | |
605 var text = ""; | |
606 if (selectedRequestsNumber !== requestsNumber) { | |
607 text += String.sprintf(WebInspector.UIString("%d / %d requests"), se
lectedRequestsNumber, requestsNumber); | |
608 text += " \u2758 " + String.sprintf(WebInspector.UIString("%s / %s
transferred"), Number.bytesToString(selectedTransferSize), Number.bytesToString
(transferSize)); | |
609 } else { | |
610 text += String.sprintf(WebInspector.UIString("%d requests"), request
sNumber); | |
611 text += " \u2758 " + String.sprintf(WebInspector.UIString("%s tran
sferred"), Number.bytesToString(transferSize)); | |
612 } | |
613 if (baseTime !== -1 && this._mainRequestLoadTime !== -1 && this._mainReq
uestDOMContentLoadedTime !== -1 && this._mainRequestDOMContentLoadedTime > baseT
ime) { | |
614 text += " \u2758 " + String.sprintf(WebInspector.UIString("%s (loa
d: %s, DOMContentLoaded: %s)"), | |
615 Number.secondsToString(maxTime - baseTime), | |
616 Number.secondsToString(this._mainRequestLoadTime - baseT
ime), | |
617 Number.secondsToString(this._mainRequestDOMContentLoaded
Time - baseTime)); | |
618 } | |
619 this._summaryBarElement.textContent = text; | |
620 this._summaryBarElement.title = text; | |
621 }, | |
622 | |
623 _scheduleRefresh: function() | |
624 { | |
625 if (this._needsRefresh) | |
626 return; | |
627 | |
628 this._needsRefresh = true; | |
629 | |
630 if (this.isShowing() && !this._refreshTimeout) | |
631 this._refreshTimeout = setTimeout(this.refresh.bind(this), WebInspec
tor.NetworkLogView._defaultRefreshDelay); | |
632 }, | |
633 | |
634 _updateDividersIfNeeded: function() | |
635 { | |
636 var timelineOffset = this._dataGrid.columnOffset("timeline"); | |
637 // Position timline grid location. | |
638 if (timelineOffset) | |
639 this._timelineGrid.element.style.left = timelineOffset + "px"; | |
640 | |
641 var calculator = this.calculator(); | |
642 var proceed = true; | |
643 if (!this.isShowing()) { | |
644 this._scheduleRefresh(); | |
645 proceed = false; | |
646 } else { | |
647 calculator.setDisplayWindow(this._timelineGrid.dividersElement.clien
tWidth); | |
648 proceed = this._timelineGrid.updateDividers(calculator); | |
649 } | |
650 if (!proceed) | |
651 return; | |
652 | |
653 if (calculator.startAtZero) { | |
654 // If our current sorting method starts at zero, that means it shows
all | |
655 // requests starting at the same point, and so onLoad event and DOMC
ontent | |
656 // event lines really wouldn't make much sense here, so don't render
them. | |
657 return; | |
658 } | |
659 | |
660 this._timelineGrid.removeEventDividers(); | |
661 var loadTimePercent = calculator.computePercentageFromEventTime(this._ma
inRequestLoadTime); | |
662 if (this._mainRequestLoadTime !== -1 && loadTimePercent >= 0) { | |
663 var loadDivider = createElementWithClass("div", "network-event-divid
er-padding"); | |
664 loadDivider.createChild("div", "network-event-divider network-red-di
vider"); | |
665 loadDivider.title = WebInspector.UIString("Load event"); | |
666 loadDivider.style.left = loadTimePercent + "%"; | |
667 this._timelineGrid.addEventDivider(loadDivider); | |
668 } | |
669 | |
670 var domLoadTimePrecent = calculator.computePercentageFromEventTime(this.
_mainRequestDOMContentLoadedTime); | |
671 if (this._mainRequestDOMContentLoadedTime !== -1 && domLoadTimePrecent >
= 0) { | |
672 var domContentLoadedDivider = createElementWithClass("div", "network
-event-divider-padding"); | |
673 domContentLoadedDivider.createChild("div", "network-event-divider ne
twork-blue-divider"); | |
674 domContentLoadedDivider.title = WebInspector.UIString("DOMContentLoa
ded event"); | |
675 domContentLoadedDivider.style.left = domLoadTimePrecent + "%"; | |
676 this._timelineGrid.addEventDivider(domContentLoadedDivider); | |
677 } | |
678 }, | |
679 | |
680 _refreshIfNeeded: function() | |
681 { | |
682 if (this._needsRefresh) | |
683 this.refresh(); | |
684 }, | |
685 | |
686 _invalidateAllItems: function() | |
687 { | |
688 var requestIds = this._nodesByRequestId.keysArray(); | |
689 for (var i = 0; i < requestIds.length; ++i) | |
690 this._staleRequestIds[requestIds[i]] = true; | |
691 }, | |
692 | |
693 /** | |
694 * @return {!WebInspector.NetworkTimeCalculator} | |
695 */ | |
696 calculator: function() | |
697 { | |
698 return this._calculator; | |
699 }, | |
700 | |
701 /** | |
702 * @param {!WebInspector.NetworkTimeCalculator} x | |
703 */ | |
704 _setCalculator: function(x) | |
705 { | |
706 if (!x || this._calculator === x) | |
707 return; | |
708 | |
709 this._calculator = x; | |
710 this._calculator.reset(); | |
711 | |
712 if (this._calculator.startAtZero) | |
713 this._timelineGrid.hideEventDividers(); | |
714 else | |
715 this._timelineGrid.showEventDividers(); | |
716 | |
717 this._invalidateAllItems(); | |
718 this.refresh(); | |
719 }, | |
720 | |
721 _createStatusbarButtons: function() | |
722 { | |
723 this._recordButton = new WebInspector.StatusBarButton("", "record-profil
e-status-bar-item"); | |
724 this._recordButton.addEventListener("click", this._onRecordButtonClicked
, this); | |
725 | |
726 this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIStri
ng("Clear"), "clear-status-bar-item"); | |
727 this._clearButton.addEventListener("click", this._reset, this); | |
728 | |
729 this._largerRequestsButton = new WebInspector.StatusBarButton(WebInspect
or.UIString("Use small resource rows."), "network-larger-resources-status-bar-it
em"); | |
730 this._largerRequestsButton.toggled = WebInspector.settings.resourcesLarg
eRows.get(); | |
731 this._largerRequestsButton.addEventListener("click", this._toggleLargerR
equests, this); | |
732 | |
733 this._preserveLogCheckbox = new WebInspector.StatusBarCheckbox(WebInspec
tor.UIString("Preserve log")); | |
734 this._preserveLogCheckbox.element.title = WebInspector.UIString("Do not
clear log on page reload / navigation."); | |
735 | |
736 this._disableCacheCheckbox = new WebInspector.StatusBarCheckbox(WebInspe
ctor.UIString("Disable cache")); | |
737 WebInspector.SettingsUI.bindCheckbox(this._disableCacheCheckbox.inputEle
ment, WebInspector.settings.cacheDisabled); | |
738 this._disableCacheCheckbox.element.title = WebInspector.UIString("Disabl
e cache (while DevTools is open)."); | |
739 }, | |
740 | |
741 /** | |
742 * @param {!WebInspector.Event} event | |
743 */ | |
744 _loadEventFired: function(event) | |
745 { | |
746 if (!this._recordButton.toggled) | |
747 return; | |
748 | |
749 var data = /** @type {number} */ (event.data); | |
750 this._mainRequestLoadTime = data || -1; | |
751 // Schedule refresh to update boundaries and draw the new line. | |
752 this._scheduleRefresh(); | |
753 }, | |
754 | |
755 /** | |
756 * @param {!WebInspector.Event} event | |
757 */ | |
758 _domContentLoadedEventFired: function(event) | |
759 { | |
760 if (!this._recordButton.toggled) | |
761 return; | |
762 var data = /** @type {number} */ (event.data); | |
763 this._mainRequestDOMContentLoadedTime = data || -1; | |
764 // Schedule refresh to update boundaries and draw the new line. | |
765 this._scheduleRefresh(); | |
766 }, | |
767 | |
768 wasShown: function() | |
769 { | |
770 this._refreshIfNeeded(); | |
771 }, | |
772 | |
773 willHide: function() | |
774 { | |
775 this._popoverHelper.hidePopover(); | |
776 }, | |
777 | |
778 refresh: function() | |
779 { | |
780 this._needsRefresh = false; | |
781 if (this._refreshTimeout) { | |
782 clearTimeout(this._refreshTimeout); | |
783 delete this._refreshTimeout; | |
784 } | |
785 | |
786 this._removeAllNodeHighlights(); | |
787 var boundariesChanged = false; | |
788 var calculator = this.calculator(); | |
789 if (calculator.updateBoundariesForEventTime) { | |
790 boundariesChanged = calculator.updateBoundariesForEventTime(this._ma
inRequestLoadTime) || boundariesChanged; | |
791 boundariesChanged = calculator.updateBoundariesForEventTime(this._ma
inRequestDOMContentLoadedTime) || boundariesChanged; | |
792 } | |
793 | |
794 var dataGrid = this._dataGrid; | |
795 var rootNode = dataGrid.rootNode(); | |
796 var nodesToInsert = []; | |
797 for (var requestId in this._staleRequestIds) { | |
798 var node = this._nodesByRequestId.get(requestId); | |
799 if (!node) | |
800 continue; | |
801 if (!node[WebInspector.NetworkLogView._isFilteredOutSymbol]) | |
802 rootNode.removeChild(node); | |
803 node[WebInspector.NetworkLogView._isFilteredOutSymbol] = !this._appl
yFilter(node); | |
804 if (!node[WebInspector.NetworkLogView._isFilteredOutSymbol]) | |
805 nodesToInsert.push(node); | |
806 } | |
807 | |
808 for (var i = 0; i < nodesToInsert.length; ++i) { | |
809 var node = nodesToInsert[i]; | |
810 var request = node.request(); | |
811 node.refresh(); | |
812 dataGrid.insertChild(node); | |
813 node[WebInspector.NetworkLogView._isMatchingSearchQuerySymbol] = thi
s._matchRequest(request); | |
814 if (calculator.updateBoundaries(request)) | |
815 boundariesChanged = true; | |
816 } | |
817 | |
818 this._highlightNthMatchedRequestForSearch(this._updateMatchCountAndFindM
atchIndex(this._currentMatchedRequestNode), false); | |
819 | |
820 if (boundariesChanged) { | |
821 // The boundaries changed, so all item graphs are stale. | |
822 this._updateDividersIfNeeded(); | |
823 var nodes = this._nodesByRequestId.valuesArray(); | |
824 for (var i = 0; i < nodes.length; ++i) | |
825 nodes[i].refreshGraph(); | |
826 } | |
827 | |
828 this._staleRequestIds = {}; | |
829 this._updateSummaryBar(); | |
830 }, | |
831 | |
832 _onRecordButtonClicked: function() | |
833 { | |
834 if (!this._recordButton.toggled) | |
835 this._reset(); | |
836 this._toggleRecordButton(!this._recordButton.toggled); | |
837 }, | |
838 | |
839 /** | |
840 * @param {boolean} toggled | |
841 */ | |
842 _toggleRecordButton: function(toggled) | |
843 { | |
844 this._recordButton.toggled = toggled; | |
845 this._recordButton.title = toggled ? WebInspector.UIString("Stop Recordi
ng Network Log") : WebInspector.UIString("Record Network Log"); | |
846 }, | |
847 | |
848 _reset: function() | |
849 { | |
850 this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.Vie
wCleared); | |
851 | |
852 this._clearSearchMatchedList(); | |
853 if (this._popoverHelper) | |
854 this._popoverHelper.hidePopover(); | |
855 | |
856 if (this._calculator) | |
857 this._calculator.reset(); | |
858 | |
859 var nodes = this._nodesByRequestId.valuesArray(); | |
860 for (var i = 0; i < nodes.length; ++i) | |
861 nodes[i].dispose(); | |
862 | |
863 this._nodesByRequestId.clear(); | |
864 this._staleRequestIds = {}; | |
865 this._resetSuggestionBuilder(); | |
866 | |
867 if (this._dataGrid) { | |
868 this._dataGrid.rootNode().removeChildren(); | |
869 this._updateDividersIfNeeded(); | |
870 this._updateSummaryBar(); | |
871 } | |
872 | |
873 this._mainRequestLoadTime = -1; | |
874 this._mainRequestDOMContentLoadedTime = -1; | |
875 }, | |
876 | |
877 /** | |
878 * @param {!WebInspector.Event} event | |
879 */ | |
880 _onRequestStarted: function(event) | |
881 { | |
882 if (this._recordButton.toggled) { | |
883 var request = /** @type {!WebInspector.NetworkRequest} */ (event.dat
a); | |
884 this._appendRequest(request); | |
885 } | |
886 }, | |
887 | |
888 /** | |
889 * @param {!WebInspector.NetworkRequest} request | |
890 */ | |
891 _appendRequest: function(request) | |
892 { | |
893 var node = new WebInspector.NetworkDataGridNode(this, request); | |
894 node[WebInspector.NetworkLogView._isFilteredOutSymbol] = true; | |
895 node[WebInspector.NetworkLogView._isMatchingSearchQuerySymbol] = false; | |
896 | |
897 // In case of redirect request id is reassigned to a redirected | |
898 // request and we need to update _nodesByRequestId and search results. | |
899 var originalRequestNode = this._nodesByRequestId.get(request.requestId); | |
900 if (originalRequestNode) | |
901 this._nodesByRequestId.set(originalRequestNode.request().requestId,
originalRequestNode); | |
902 this._nodesByRequestId.set(request.requestId, node); | |
903 | |
904 // Pull all the redirects of the main request upon commit load. | |
905 if (request.redirects) { | |
906 for (var i = 0; i < request.redirects.length; ++i) | |
907 this._refreshRequest(request.redirects[i]); | |
908 } | |
909 | |
910 this._refreshRequest(request); | |
911 }, | |
912 | |
913 /** | |
914 * @param {!WebInspector.Event} event | |
915 */ | |
916 _onRequestUpdated: function(event) | |
917 { | |
918 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data); | |
919 this._refreshRequest(request); | |
920 }, | |
921 | |
922 /** | |
923 * @param {!WebInspector.NetworkRequest} request | |
924 */ | |
925 _refreshRequest: function(request) | |
926 { | |
927 if (!this._nodesByRequestId.get(request.requestId)) | |
928 return; | |
929 | |
930 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterType.D
omain, request.domain); | |
931 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterType.M
ethod, request.requestMethod); | |
932 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterType.M
imeType, request.mimeType); | |
933 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterType.S
cheme, "" + request.scheme); | |
934 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterType.S
tatusCode, "" + request.statusCode); | |
935 | |
936 var responseHeaders = request.responseHeaders; | |
937 for (var i = 0, l = responseHeaders.length; i < l; ++i) | |
938 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterTy
pe.HasResponseHeader, responseHeaders[i].name); | |
939 var cookies = request.responseCookies; | |
940 for (var i = 0, l = cookies ? cookies.length : 0; i < l; ++i) { | |
941 var cookie = cookies[i]; | |
942 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterTy
pe.SetCookieDomain, cookie.domain()); | |
943 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterTy
pe.SetCookieName, cookie.name()); | |
944 this._suggestionBuilder.addItem(WebInspector.NetworkLogView.FilterTy
pe.SetCookieValue, cookie.value()); | |
945 } | |
946 | |
947 this._staleRequestIds[request.requestId] = true; | |
948 this._scheduleRefresh(); | |
949 }, | |
950 | |
951 /** | |
952 * @param {!WebInspector.Event} event | |
953 */ | |
954 _willReloadPage: function(event) | |
955 { | |
956 this._recordButton.toggled = true; | |
957 if (!this._preserveLogCheckbox.checked()) | |
958 this._reset(); | |
959 }, | |
960 | |
961 /** | |
962 * @param {!WebInspector.Event} event | |
963 */ | |
964 _mainFrameNavigated: function(event) | |
965 { | |
966 if (!this._recordButton.toggled || this._preserveLogCheckbox.checked()) | |
967 return; | |
968 | |
969 var frame = /** @type {!WebInspector.ResourceTreeFrame} */ (event.data); | |
970 var loaderId = frame.loaderId; | |
971 | |
972 // Pick provisional load requests. | |
973 var requestsToPick = []; | |
974 var requests = frame.target().networkLog.requests; | |
975 for (var i = 0; i < requests.length; ++i) { | |
976 var request = requests[i]; | |
977 if (request.loaderId === loaderId) | |
978 requestsToPick.push(request); | |
979 } | |
980 | |
981 this._reset(); | |
982 | |
983 for (var i = 0; i < requestsToPick.length; ++i) | |
984 this._appendRequest(requestsToPick[i]); | |
985 }, | |
986 | |
987 /** | |
988 * @param {boolean} detailed | |
989 */ | |
990 switchViewMode: function(detailed) | |
991 { | |
992 if (this._detailedMode === detailed) | |
993 return; | |
994 this._detailedMode = detailed; | |
995 | |
996 if (detailed) { | |
997 if (this._dataGrid.selectedNode) | |
998 this._dataGrid.selectedNode.selected = false; | |
999 } else { | |
1000 this._removeAllNodeHighlights(); | |
1001 this._popoverHelper.hidePopover(); | |
1002 } | |
1003 | |
1004 this.element.classList.toggle("brief-mode", !detailed); | |
1005 this._updateColumns(); | |
1006 }, | |
1007 | |
1008 _toggleLargerRequests: function() | |
1009 { | |
1010 WebInspector.settings.resourcesLargeRows.set(!WebInspector.settings.reso
urcesLargeRows.get()); | |
1011 this._updateRowsSize(); | |
1012 }, | |
1013 | |
1014 /** | |
1015 * @return {number} | |
1016 */ | |
1017 rowHeight: function() | |
1018 { | |
1019 return this._rowHeight; | |
1020 }, | |
1021 | |
1022 _updateRowsSize: function() | |
1023 { | |
1024 var largeRows = this.usesLargeRows(); | |
1025 this._largerRequestsButton.toggled = largeRows; | |
1026 this._rowHeight = largeRows ? 41 : 21; | |
1027 this._largerRequestsButton.title = WebInspector.UIString(largeRows ? "Us
e small resource rows." : "Use large resource rows."); | |
1028 this._dataGrid.element.classList.toggle("small", !largeRows); | |
1029 this._timelineGrid.element.classList.toggle("small", !largeRows); | |
1030 this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.Row
SizeChanged, { largeRows: largeRows }); | |
1031 }, | |
1032 | |
1033 /** | |
1034 * @param {!Element} element | |
1035 * @param {!Event} event | |
1036 * @return {!Element|!AnchorBox|undefined} | |
1037 */ | |
1038 _getPopoverAnchor: function(element, event) | |
1039 { | |
1040 if (!this._allowPopover) | |
1041 return; | |
1042 var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") |
| element.enclosingNodeOrSelfWithClass("network-graph-label"); | |
1043 if (anchor && anchor.parentElement.request && anchor.parentElement.reque
st.timing) | |
1044 return anchor; | |
1045 anchor = element.enclosingNodeOrSelfWithClass("network-script-initiated"
); | |
1046 if (anchor && anchor.request) { | |
1047 var request = /** @type {!WebInspector.NetworkRequest} */ (anchor.re
quest); | |
1048 var initiator = anchor.request.initiator(); | |
1049 if (initiator && (initiator.stackTrace || initiator.asyncStackTrace)
) | |
1050 return anchor; | |
1051 } | |
1052 }, | |
1053 | |
1054 /** | |
1055 * @param {!Element} anchor | |
1056 * @param {!WebInspector.Popover} popover | |
1057 */ | |
1058 _showPopover: function(anchor, popover) | |
1059 { | |
1060 var content; | |
1061 if (anchor.classList.contains("network-script-initiated")) { | |
1062 content = this._generateScriptInitiatedPopoverContent(anchor.request
); | |
1063 popover.setCanShrink(true); | |
1064 } else { | |
1065 content = WebInspector.RequestTimingView.createTimingTable(anchor.pa
rentElement.request); | |
1066 popover.setCanShrink(false); | |
1067 } | |
1068 popover.show(content, anchor); | |
1069 }, | |
1070 | |
1071 _onHidePopover: function() | |
1072 { | |
1073 this._linkifier.reset(); | |
1074 }, | |
1075 | |
1076 /** | |
1077 * @param {!WebInspector.NetworkRequest} request | |
1078 * @return {!Element} | |
1079 */ | |
1080 _generateScriptInitiatedPopoverContent: function(request) | |
1081 { | |
1082 var framesTable = createElementWithClass("table", "network-stack-trace")
; | |
1083 | |
1084 /** | |
1085 * @param {!Array.<!ConsoleAgent.CallFrame>} stackTrace | |
1086 * @this {WebInspector.NetworkLogView} | |
1087 */ | |
1088 function appendStackTrace(stackTrace) | |
1089 { | |
1090 for (var i = 0; i < stackTrace.length; ++i) { | |
1091 var stackFrame = stackTrace[i]; | |
1092 var row = createElement("tr"); | |
1093 row.createChild("td").textContent = stackFrame.functionName || W
ebInspector.UIString("(anonymous function)"); | |
1094 row.createChild("td").textContent = " @ "; | |
1095 row.createChild("td").appendChild(this._linkifier.linkifyConsole
CallFrame(request.target(), stackFrame)); | |
1096 framesTable.appendChild(row); | |
1097 } | |
1098 } | |
1099 | |
1100 // Initiator is not null, checked in _getPopoverAnchor. | |
1101 var initiator = /** @type {!NetworkAgent.Initiator} */ (request.initiato
r()); | |
1102 if (initiator.stackTrace) | |
1103 appendStackTrace.call(this, initiator.stackTrace); | |
1104 | |
1105 var asyncStackTrace = initiator.asyncStackTrace; | |
1106 while (asyncStackTrace) { | |
1107 var callFrames = asyncStackTrace.callFrames; | |
1108 if (!callFrames || !callFrames.length) | |
1109 break; | |
1110 var row = framesTable.createChild("tr"); | |
1111 row.createChild("td", "network-async-trace-description").textContent
= WebInspector.asyncStackTraceLabel(asyncStackTrace.description); | |
1112 row.createChild("td"); | |
1113 row.createChild("td"); | |
1114 appendStackTrace.call(this, callFrames); | |
1115 asyncStackTrace = asyncStackTrace.asyncStackTrace; | |
1116 } | |
1117 | |
1118 return framesTable; | |
1119 }, | |
1120 | |
1121 _updateColumns: function() | |
1122 { | |
1123 var detailedMode = !!this._detailedMode; | |
1124 var visibleColumns = {"name": true}; | |
1125 if (detailedMode) { | |
1126 visibleColumns["timeline"] = true; | |
1127 var columnsVisibility = this._coulmnsVisibilitySetting.get(); | |
1128 for (var columnIdentifier in columnsVisibility) | |
1129 visibleColumns[columnIdentifier] = columnsVisibility[columnIdent
ifier]; | |
1130 } | |
1131 | |
1132 this._dataGrid.setColumnsVisiblity(visibleColumns); | |
1133 }, | |
1134 | |
1135 /** | |
1136 * @param {string} columnIdentifier | |
1137 */ | |
1138 _toggleColumnVisibility: function(columnIdentifier) | |
1139 { | |
1140 var columnsVisibility = this._coulmnsVisibilitySetting.get(); | |
1141 columnsVisibility[columnIdentifier] = !columnsVisibility[columnIdentifie
r]; | |
1142 this._coulmnsVisibilitySetting.set(columnsVisibility); | |
1143 | |
1144 this._updateColumns(); | |
1145 }, | |
1146 | |
1147 /** | |
1148 * @return {!Array.<string>} | |
1149 */ | |
1150 _getConfigurableColumnIDs: function() | |
1151 { | |
1152 if (this._configurableColumnIDs) | |
1153 return this._configurableColumnIDs; | |
1154 | |
1155 var columnTitles = WebInspector.NetworkLogView._columnTitles; | |
1156 function compare(id1, id2) | |
1157 { | |
1158 return columnTitles[id1].compareTo(columnTitles[id2]); | |
1159 } | |
1160 | |
1161 var columnIDs = Object.keys(this._coulmnsVisibilitySetting.get()); | |
1162 this._configurableColumnIDs = columnIDs.sort(compare); | |
1163 return this._configurableColumnIDs; | |
1164 }, | |
1165 | |
1166 /** | |
1167 * @param {!Event} event | |
1168 */ | |
1169 _contextMenu: function(event) | |
1170 { | |
1171 var contextMenu = new WebInspector.ContextMenu(event); | |
1172 | |
1173 if (this._detailedMode && event.target.isSelfOrDescendant(this._dataGrid
.headerTableBody)) { | |
1174 var columnsVisibility = this._coulmnsVisibilitySetting.get(); | |
1175 var columnIDs = this._getConfigurableColumnIDs(); | |
1176 var columnTitles = WebInspector.NetworkLogView._columnTitles; | |
1177 for (var i = 0; i < columnIDs.length; ++i) { | |
1178 var columnIdentifier = columnIDs[i]; | |
1179 contextMenu.appendCheckboxItem(columnTitles[columnIdentifier], t
his._toggleColumnVisibility.bind(this, columnIdentifier), !!columnsVisibility[co
lumnIdentifier]); | |
1180 } | |
1181 contextMenu.show(); | |
1182 return; | |
1183 } | |
1184 | |
1185 var gridNode = this._dataGrid.dataGridNodeFromNode(event.target); | |
1186 var request = gridNode && gridNode.request(); | |
1187 | |
1188 /** | |
1189 * @param {string} url | |
1190 */ | |
1191 function openResourceInNewTab(url) | |
1192 { | |
1193 InspectorFrontendHost.openInNewTab(url); | |
1194 } | |
1195 | |
1196 if (request) { | |
1197 contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), openR
esourceInNewTab.bind(null, request.url)); | |
1198 contextMenu.appendSeparator(); | |
1199 contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), this._co
pyLocation.bind(this, request)); | |
1200 if (request.requestHeadersText()) | |
1201 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLow
erCaseMenuTitles() ? "Copy request headers" : "Copy Request Headers"), this._cop
yRequestHeaders.bind(this, request)); | |
1202 if (request.responseHeadersText) | |
1203 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLow
erCaseMenuTitles() ? "Copy response headers" : "Copy Response Headers"), this._c
opyResponseHeaders.bind(this, request)); | |
1204 if (request.finished) | |
1205 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLow
erCaseMenuTitles() ? "Copy response" : "Copy Response"), this._copyResponse.bind
(this, request)); | |
1206 contextMenu.appendItem(WebInspector.UIString("Copy as cURL"), this._
copyCurlCommand.bind(this, request)); | |
1207 } | |
1208 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMe
nuTitles() ? "Copy all as HAR" : "Copy All as HAR"), this._copyAll.bind(this)); | |
1209 | |
1210 contextMenu.appendSeparator(); | |
1211 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMe
nuTitles() ? "Save as HAR with content" : "Save as HAR with Content"), this._exp
ortAll.bind(this)); | |
1212 | |
1213 contextMenu.appendSeparator(); | |
1214 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMe
nuTitles() ? "Clear browser cache" : "Clear Browser Cache"), this._clearBrowserC
ache.bind(this)); | |
1215 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMe
nuTitles() ? "Clear browser cookies" : "Clear Browser Cookies"), this._clearBrow
serCookies.bind(this)); | |
1216 | |
1217 if (request && request.resourceType() === WebInspector.resourceTypes.XHR
) { | |
1218 contextMenu.appendSeparator(); | |
1219 contextMenu.appendItem(WebInspector.UIString("Replay XHR"), request.
replayXHR.bind(request)); | |
1220 contextMenu.appendSeparator(); | |
1221 } | |
1222 | |
1223 contextMenu.show(); | |
1224 }, | |
1225 | |
1226 _harRequests: function() | |
1227 { | |
1228 var requests = this._nodesByRequestId.valuesArray().map(function(node) {
return node.request(); }); | |
1229 var httpRequests = requests.filter(WebInspector.NetworkLogView.HTTPReque
stsFilter); | |
1230 httpRequests = httpRequests.filter(WebInspector.NetworkLogView.FinishedR
equestsFilter); | |
1231 return httpRequests.filter(WebInspector.NetworkLogView.NonDevToolsReques
tsFilter); | |
1232 }, | |
1233 | |
1234 _copyAll: function() | |
1235 { | |
1236 var harArchive = { | |
1237 log: (new WebInspector.HARLog(this._harRequests())).build() | |
1238 }; | |
1239 InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2)); | |
1240 }, | |
1241 | |
1242 /** | |
1243 * @param {!WebInspector.NetworkRequest} request | |
1244 */ | |
1245 _copyLocation: function(request) | |
1246 { | |
1247 InspectorFrontendHost.copyText(request.url); | |
1248 }, | |
1249 | |
1250 /** | |
1251 * @param {!WebInspector.NetworkRequest} request | |
1252 */ | |
1253 _copyRequestHeaders: function(request) | |
1254 { | |
1255 InspectorFrontendHost.copyText(request.requestHeadersText()); | |
1256 }, | |
1257 | |
1258 /** | |
1259 * @param {!WebInspector.NetworkRequest} request | |
1260 */ | |
1261 _copyResponse: function(request) | |
1262 { | |
1263 /** | |
1264 * @param {?string} content | |
1265 */ | |
1266 function callback(content) | |
1267 { | |
1268 if (request.contentEncoded) | |
1269 content = request.asDataURL(); | |
1270 InspectorFrontendHost.copyText(content || ""); | |
1271 } | |
1272 request.requestContent(callback); | |
1273 }, | |
1274 | |
1275 /** | |
1276 * @param {!WebInspector.NetworkRequest} request | |
1277 */ | |
1278 _copyResponseHeaders: function(request) | |
1279 { | |
1280 InspectorFrontendHost.copyText(request.responseHeadersText); | |
1281 }, | |
1282 | |
1283 /** | |
1284 * @param {!WebInspector.NetworkRequest} request | |
1285 */ | |
1286 _copyCurlCommand: function(request) | |
1287 { | |
1288 InspectorFrontendHost.copyText(this._generateCurlCommand(request)); | |
1289 }, | |
1290 | |
1291 _exportAll: function() | |
1292 { | |
1293 var filename = WebInspector.targetManager.inspectedPageDomain() + ".har"
; | |
1294 var stream = new WebInspector.FileOutputStream(); | |
1295 stream.open(filename, openCallback.bind(this)); | |
1296 | |
1297 /** | |
1298 * @param {boolean} accepted | |
1299 * @this {WebInspector.NetworkLogView} | |
1300 */ | |
1301 function openCallback(accepted) | |
1302 { | |
1303 if (!accepted) | |
1304 return; | |
1305 var progressIndicator = new WebInspector.ProgressIndicator(); | |
1306 this._progressBarContainer.appendChild(progressIndicator.element); | |
1307 var harWriter = new WebInspector.HARWriter(); | |
1308 harWriter.write(stream, this._harRequests(), progressIndicator); | |
1309 } | |
1310 }, | |
1311 | |
1312 _clearBrowserCache: function() | |
1313 { | |
1314 if (confirm(WebInspector.UIString("Are you sure you want to clear browse
r cache?"))) | |
1315 NetworkAgent.clearBrowserCache(); | |
1316 }, | |
1317 | |
1318 _clearBrowserCookies: function() | |
1319 { | |
1320 if (confirm(WebInspector.UIString("Are you sure you want to clear browse
r cookies?"))) | |
1321 NetworkAgent.clearBrowserCookies(); | |
1322 }, | |
1323 | |
1324 /** | |
1325 * @param {!WebInspector.NetworkRequest} request | |
1326 * @return {boolean} | |
1327 */ | |
1328 _matchRequest: function(request) | |
1329 { | |
1330 var re = this._searchRegExp; | |
1331 if (!re) | |
1332 return false; | |
1333 return re.test(request.name()) || re.test(request.path()); | |
1334 }, | |
1335 | |
1336 _clearSearchMatchedList: function() | |
1337 { | |
1338 this._matchedRequestCount = -1; | |
1339 this._currentMatchedRequestNode = null; | |
1340 this._removeAllHighlights(); | |
1341 }, | |
1342 | |
1343 _removeAllHighlights: function() | |
1344 { | |
1345 this._removeAllNodeHighlights(); | |
1346 for (var i = 0; i < this._highlightedSubstringChanges.length; ++i) | |
1347 WebInspector.revertDomChanges(this._highlightedSubstringChanges[i]); | |
1348 this._highlightedSubstringChanges = []; | |
1349 }, | |
1350 | |
1351 /** | |
1352 * @param {number} n | |
1353 * @param {boolean} reveal | |
1354 */ | |
1355 _highlightNthMatchedRequestForSearch: function(n, reveal) | |
1356 { | |
1357 this._removeAllHighlights(); | |
1358 | |
1359 /** @type {!Array.<!WebInspector.NetworkDataGridNode>} */ | |
1360 var nodes = this._dataGrid.rootNode().children; | |
1361 var matchCount = 0; | |
1362 var node = null; | |
1363 for (var i = 0; i < nodes.length; ++i) { | |
1364 if (nodes[i][WebInspector.NetworkLogView._isMatchingSearchQuerySymbo
l]) { | |
1365 if (matchCount === n) { | |
1366 node = nodes[i]; | |
1367 break; | |
1368 } | |
1369 matchCount++; | |
1370 } | |
1371 } | |
1372 if (!node) { | |
1373 this._currentMatchedRequestNode = null; | |
1374 return; | |
1375 } | |
1376 | |
1377 var request = node.request(); | |
1378 var regExp = this._searchRegExp; | |
1379 var nameMatched = request.name().match(regExp); | |
1380 var pathMatched = request.path().match(regExp); | |
1381 if (!nameMatched && pathMatched && !this._largerRequestsButton.toggled) | |
1382 this._toggleLargerRequests(); | |
1383 if (reveal) | |
1384 WebInspector.Revealer.reveal(request); | |
1385 var highlightedSubstringChanges = node.highlightMatchedSubstring(regExp)
; | |
1386 this._highlightedSubstringChanges.push(highlightedSubstringChanges); | |
1387 | |
1388 this._currentMatchedRequestNode = node; | |
1389 this._currentMatchedRequestIndex = n; | |
1390 this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.Sea
rchIndexUpdated, n); | |
1391 }, | |
1392 | |
1393 /** | |
1394 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig | |
1395 * @param {boolean} shouldJump | |
1396 * @param {boolean=} jumpBackwards | |
1397 */ | |
1398 performSearch: function(searchConfig, shouldJump, jumpBackwards) | |
1399 { | |
1400 var query = searchConfig.query; | |
1401 var currentMatchedRequestNode = this._currentMatchedRequestNode; | |
1402 this._clearSearchMatchedList(); | |
1403 this._searchRegExp = createPlainTextSearchRegex(query, "i"); | |
1404 | |
1405 /** @type {!Array.<!WebInspector.NetworkDataGridNode>} */ | |
1406 var nodes = this._dataGrid.rootNode().children; | |
1407 for (var i = 0; i < nodes.length; ++i) | |
1408 nodes[i][WebInspector.NetworkLogView._isMatchingSearchQuerySymbol] =
this._matchRequest(nodes[i].request()); | |
1409 var newMatchedRequestIndex = this._updateMatchCountAndFindMatchIndex(cur
rentMatchedRequestNode); | |
1410 if (!newMatchedRequestIndex && jumpBackwards) | |
1411 newMatchedRequestIndex = this._matchedRequestCount - 1; | |
1412 this._highlightNthMatchedRequestForSearch(newMatchedRequestIndex, should
Jump); | |
1413 }, | |
1414 | |
1415 /** | |
1416 * @return {boolean} | |
1417 */ | |
1418 supportsCaseSensitiveSearch: function() | |
1419 { | |
1420 return false; | |
1421 }, | |
1422 | |
1423 /** | |
1424 * @return {boolean} | |
1425 */ | |
1426 supportsRegexSearch: function() | |
1427 { | |
1428 return false; | |
1429 }, | |
1430 | |
1431 /** | |
1432 * @param {?WebInspector.NetworkDataGridNode} node | |
1433 * @return {number} | |
1434 */ | |
1435 _updateMatchCountAndFindMatchIndex: function(node) | |
1436 { | |
1437 /** @type {!Array.<!WebInspector.NetworkDataGridNode>} */ | |
1438 var nodes = this._dataGrid.rootNode().children; | |
1439 var matchCount = 0; | |
1440 var matchIndex = 0; | |
1441 for (var i = 0; i < nodes.length; ++i) { | |
1442 if (!nodes[i][WebInspector.NetworkLogView._isMatchingSearchQuerySymb
ol]) | |
1443 continue; | |
1444 if (node === nodes[i]) | |
1445 matchIndex = matchCount; | |
1446 matchCount++; | |
1447 } | |
1448 if (this._matchedRequestCount !== matchCount) { | |
1449 this._matchedRequestCount = matchCount; | |
1450 this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes
.SearchCountUpdated, matchCount); | |
1451 } | |
1452 return matchIndex; | |
1453 }, | |
1454 | |
1455 /** | |
1456 * @param {number} index | |
1457 * @return {number} | |
1458 */ | |
1459 _normalizeSearchResultIndex: function(index) | |
1460 { | |
1461 return (index + this._matchedRequestCount) % this._matchedRequestCount; | |
1462 }, | |
1463 | |
1464 /** | |
1465 * @param {!WebInspector.NetworkDataGridNode} node | |
1466 * @return {boolean} | |
1467 */ | |
1468 _applyFilter: function(node) | |
1469 { | |
1470 var request = node.request(); | |
1471 var resourceType = request.resourceType(); | |
1472 if (resourceType === WebInspector.resourceTypes.TextTrack) | |
1473 resourceType = WebInspector.resourceTypes.Other; | |
1474 if (!this._resourceTypeFilterUI.accept(resourceType.name())) | |
1475 return false; | |
1476 if (this._dataURLFilterUI.checked() && request.parsedURL.isDataURL()) | |
1477 return false; | |
1478 for (var i = 0; i < this._filters.length; ++i) { | |
1479 if (!this._filters[i](request)) | |
1480 return false; | |
1481 } | |
1482 return true; | |
1483 }, | |
1484 | |
1485 /** | |
1486 * @param {string} query | |
1487 */ | |
1488 _parseFilterQuery: function(query) | |
1489 { | |
1490 var parsedQuery = this._suggestionBuilder.parseQuery(query); | |
1491 this._filters = parsedQuery.text.map(this._createTextFilter); | |
1492 var filters = parsedQuery.filters; | |
1493 var n = parsedQuery.filters.length; | |
1494 for (var i = 0; i < n; ++i) { | |
1495 var filter = parsedQuery.filters[i]; | |
1496 var filterType = /** @type {!WebInspector.NetworkLogView.FilterType}
*/ (filter.type); | |
1497 this._filters.push(this._createFilter(filterType, filter.data, filte
r.negative)); | |
1498 } | |
1499 }, | |
1500 | |
1501 /** | |
1502 * @param {string} text | |
1503 * @return {!WebInspector.NetworkLogView.Filter} | |
1504 */ | |
1505 _createTextFilter: function(text) | |
1506 { | |
1507 var regexp = new RegExp(text.escapeForRegExp(), "i"); | |
1508 return WebInspector.NetworkLogView._requestNameOrPathFilter.bind(null, r
egexp); | |
1509 }, | |
1510 | |
1511 /** | |
1512 * @param {!WebInspector.NetworkLogView.FilterType} type | |
1513 * @param {string} value | |
1514 * @param {boolean} negative | |
1515 * @return {!WebInspector.NetworkLogView.Filter} | |
1516 */ | |
1517 _createFilter: function(type, value, negative) | |
1518 { | |
1519 var filter = this._createSpecialFilter(type, value); | |
1520 if (!filter) | |
1521 return this._createTextFilter((negative ? "-" : "") + type + ":" + v
alue); | |
1522 if (negative) | |
1523 return WebInspector.NetworkLogView._negativeFilter.bind(null, filter
); | |
1524 return filter; | |
1525 }, | |
1526 | |
1527 /** | |
1528 * @param {!WebInspector.NetworkLogView.FilterType} type | |
1529 * @param {string} value | |
1530 * @return {?WebInspector.NetworkLogView.Filter} | |
1531 */ | |
1532 _createSpecialFilter: function(type, value) | |
1533 { | |
1534 switch (type) { | |
1535 case WebInspector.NetworkLogView.FilterType.Domain: | |
1536 return WebInspector.NetworkLogView._requestDomainFilter.bind(null, v
alue); | |
1537 | |
1538 case WebInspector.NetworkLogView.FilterType.HasResponseHeader: | |
1539 return WebInspector.NetworkLogView._requestResponseHeaderFilter.bind
(null, value); | |
1540 | |
1541 case WebInspector.NetworkLogView.FilterType.Is: | |
1542 if (value.toLowerCase() === WebInspector.NetworkLogView.IsFilterType
.Running) | |
1543 return WebInspector.NetworkLogView._runningRequestFilter; | |
1544 break; | |
1545 | |
1546 case WebInspector.NetworkLogView.FilterType.Method: | |
1547 return WebInspector.NetworkLogView._requestMethodFilter.bind(null, v
alue); | |
1548 | |
1549 case WebInspector.NetworkLogView.FilterType.MimeType: | |
1550 return WebInspector.NetworkLogView._requestMimeTypeFilter.bind(null,
value); | |
1551 | |
1552 case WebInspector.NetworkLogView.FilterType.Scheme: | |
1553 return WebInspector.NetworkLogView._requestSchemeFilter.bind(null, v
alue); | |
1554 | |
1555 case WebInspector.NetworkLogView.FilterType.SetCookieDomain: | |
1556 return WebInspector.NetworkLogView._requestSetCookieDomainFilter.bin
d(null, value); | |
1557 | |
1558 case WebInspector.NetworkLogView.FilterType.SetCookieName: | |
1559 return WebInspector.NetworkLogView._requestSetCookieNameFilter.bind(
null, value); | |
1560 | |
1561 case WebInspector.NetworkLogView.FilterType.SetCookieValue: | |
1562 return WebInspector.NetworkLogView._requestSetCookieValueFilter.bind
(null, value); | |
1563 | |
1564 case WebInspector.NetworkLogView.FilterType.StatusCode: | |
1565 return WebInspector.NetworkLogView._statusCodeFilter.bind(null, valu
e); | |
1566 } | |
1567 return null; | |
1568 }, | |
1569 | |
1570 _filterRequests: function() | |
1571 { | |
1572 this._removeAllHighlights(); | |
1573 this._invalidateAllItems(); | |
1574 this.refresh(); | |
1575 }, | |
1576 | |
1577 jumpToPreviousSearchResult: function() | |
1578 { | |
1579 if (!this._matchedRequestCount) | |
1580 return; | |
1581 var index = this._normalizeSearchResultIndex(this._currentMatchedRequest
Index - 1); | |
1582 this._highlightNthMatchedRequestForSearch(index, true); | |
1583 }, | |
1584 | |
1585 jumpToNextSearchResult: function() | |
1586 { | |
1587 if (!this._matchedRequestCount) | |
1588 return; | |
1589 var index = this._normalizeSearchResultIndex(this._currentMatchedRequest
Index + 1); | |
1590 this._highlightNthMatchedRequestForSearch(index, true); | |
1591 }, | |
1592 | |
1593 searchCanceled: function() | |
1594 { | |
1595 delete this._searchRegExp; | |
1596 this._clearSearchMatchedList(); | |
1597 this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.Sea
rchCountUpdated, 0); | |
1598 }, | |
1599 | |
1600 /** | |
1601 * @param {!WebInspector.NetworkRequest} request | |
1602 */ | |
1603 revealAndHighlightRequest: function(request) | |
1604 { | |
1605 this._removeAllNodeHighlights(); | |
1606 | |
1607 var node = this._nodesByRequestId.get(request.requestId); | |
1608 if (node) { | |
1609 node.reveal(); | |
1610 this._highlightNode(node); | |
1611 } | |
1612 }, | |
1613 | |
1614 _removeAllNodeHighlights: function() | |
1615 { | |
1616 if (this._highlightedNode) { | |
1617 this._highlightedNode.element().classList.remove("highlighted-row"); | |
1618 delete this._highlightedNode; | |
1619 } | |
1620 }, | |
1621 | |
1622 /** | |
1623 * @param {!WebInspector.NetworkDataGridNode} node | |
1624 */ | |
1625 _highlightNode: function(node) | |
1626 { | |
1627 WebInspector.runCSSAnimationOnce(node.element(), "highlighted-row"); | |
1628 this._highlightedNode = node; | |
1629 }, | |
1630 | |
1631 /** | |
1632 * @param {!WebInspector.NetworkRequest} request | |
1633 * @return {string} | |
1634 */ | |
1635 _generateCurlCommand: function(request) | |
1636 { | |
1637 var command = ["curl"]; | |
1638 // These headers are derived from URL (except "version") and would be ad
ded by cURL anyway. | |
1639 var ignoredHeaders = {"host": 1, "method": 1, "path": 1, "scheme": 1, "v
ersion": 1}; | |
1640 | |
1641 function escapeStringWin(str) | |
1642 { | |
1643 /* Replace quote by double quote (but not by \") because it is | |
1644 recognized by both cmd.exe and MS Crt arguments parser. | |
1645 | |
1646 Replace % by "%" because it could be expanded to an environment | |
1647 variable value. So %% becomes "%""%". Even if an env variable "" | |
1648 (2 doublequotes) is declared, the cmd.exe will not | |
1649 substitute it with its value. | |
1650 | |
1651 Replace each backslash with double backslash to make sure | |
1652 MS Crt arguments parser won't collapse them. | |
1653 | |
1654 Replace new line outside of quotes since cmd.exe doesn't let | |
1655 to do it inside. | |
1656 */ | |
1657 return "\"" + str.replace(/"/g, "\"\"") | |
1658 .replace(/%/g, "\"%\"") | |
1659 .replace(/\\/g, "\\\\") | |
1660 .replace(/[\r\n]+/g, "\"^$&\"") + "\""; | |
1661 } | |
1662 | |
1663 function escapeStringPosix(str) | |
1664 { | |
1665 function escapeCharacter(x) | |
1666 { | |
1667 var code = x.charCodeAt(0); | |
1668 if (code < 256) { | |
1669 // Add leading zero when needed to not care about the next c
haracter. | |
1670 return code < 16 ? "\\x0" + code.toString(16) : "\\x" + code
.toString(16); | |
1671 } | |
1672 code = code.toString(16); | |
1673 return "\\u" + ("0000" + code).substr(code.length, 4); | |
1674 } | |
1675 | |
1676 if (/[^\x20-\x7E]|\'/.test(str)) { | |
1677 // Use ANSI-C quoting syntax. | |
1678 return "$\'" + str.replace(/\\/g, "\\\\") | |
1679 .replace(/\'/g, "\\\'") | |
1680 .replace(/\n/g, "\\n") | |
1681 .replace(/\r/g, "\\r") | |
1682 .replace(/[^\x20-\x7E]/g, escapeCharacter) + "
'"; | |
1683 } else { | |
1684 // Use single quote syntax. | |
1685 return "'" + str + "'"; | |
1686 } | |
1687 } | |
1688 | |
1689 // cURL command expected to run on the same platform that DevTools run | |
1690 // (it may be different from the inspected page platform). | |
1691 var escapeString = WebInspector.isWin() ? escapeStringWin : escapeString
Posix; | |
1692 | |
1693 command.push(escapeString(request.url).replace(/[[{}\]]/g, "\\$&")); | |
1694 | |
1695 var inferredMethod = "GET"; | |
1696 var data = []; | |
1697 var requestContentType = request.requestContentType(); | |
1698 if (requestContentType && requestContentType.startsWith("application/x-w
ww-form-urlencoded") && request.requestFormData) { | |
1699 data.push("--data"); | |
1700 data.push(escapeString(request.requestFormData)); | |
1701 ignoredHeaders["content-length"] = true; | |
1702 inferredMethod = "POST"; | |
1703 } else if (request.requestFormData) { | |
1704 data.push("--data-binary"); | |
1705 data.push(escapeString(request.requestFormData)); | |
1706 ignoredHeaders["content-length"] = true; | |
1707 inferredMethod = "POST"; | |
1708 } | |
1709 | |
1710 if (request.requestMethod !== inferredMethod) { | |
1711 command.push("-X"); | |
1712 command.push(request.requestMethod); | |
1713 } | |
1714 | |
1715 var requestHeaders = request.requestHeaders(); | |
1716 for (var i = 0; i < requestHeaders.length; i++) { | |
1717 var header = requestHeaders[i]; | |
1718 var name = header.name.replace(/^:/, ""); // Translate SPDY v3 heade
rs to HTTP headers. | |
1719 if (name.toLowerCase() in ignoredHeaders) | |
1720 continue; | |
1721 command.push("-H"); | |
1722 command.push(escapeString(name + ": " + header.value)); | |
1723 } | |
1724 command = command.concat(data); | |
1725 command.push("--compressed"); | |
1726 return command.join(" "); | |
1727 }, | |
1728 | |
1729 __proto__: WebInspector.VBox.prototype | |
1730 } | |
1731 | |
1732 /** @typedef {function(!WebInspector.NetworkRequest): boolean} */ | |
1733 WebInspector.NetworkLogView.Filter; | |
1734 | |
1735 /** | |
1736 * @param {!WebInspector.NetworkLogView.Filter} filter | |
1737 * @param {!WebInspector.NetworkRequest} request | |
1738 * @return {boolean} | |
1739 */ | |
1740 WebInspector.NetworkLogView._negativeFilter = function(filter, request) | |
1741 { | |
1742 return !filter(request); | |
1743 } | |
1744 | |
1745 /** | |
1746 * @param {!RegExp} regex | |
1747 * @param {!WebInspector.NetworkRequest} request | |
1748 * @return {boolean} | |
1749 */ | |
1750 WebInspector.NetworkLogView._requestNameOrPathFilter = function(regex, request) | |
1751 { | |
1752 return regex.test(request.name()) || regex.test(request.path()); | |
1753 } | |
1754 | |
1755 /** | |
1756 * @param {string} value | |
1757 * @param {!WebInspector.NetworkRequest} request | |
1758 * @return {boolean} | |
1759 */ | |
1760 WebInspector.NetworkLogView._requestDomainFilter = function(value, request) | |
1761 { | |
1762 return request.domain === value; | |
1763 } | |
1764 | |
1765 /** | |
1766 * @param {!WebInspector.NetworkRequest} request | |
1767 * @return {boolean} | |
1768 */ | |
1769 WebInspector.NetworkLogView._runningRequestFilter = function(request) | |
1770 { | |
1771 return !request.finished; | |
1772 } | |
1773 | |
1774 /** | |
1775 * @param {string} value | |
1776 * @param {!WebInspector.NetworkRequest} request | |
1777 * @return {boolean} | |
1778 */ | |
1779 WebInspector.NetworkLogView._requestResponseHeaderFilter = function(value, reque
st) | |
1780 { | |
1781 return request.responseHeaderValue(value) !== undefined; | |
1782 } | |
1783 | |
1784 /** | |
1785 * @param {string} value | |
1786 * @param {!WebInspector.NetworkRequest} request | |
1787 * @return {boolean} | |
1788 */ | |
1789 WebInspector.NetworkLogView._requestMethodFilter = function(value, request) | |
1790 { | |
1791 return request.requestMethod === value; | |
1792 } | |
1793 | |
1794 /** | |
1795 * @param {string} value | |
1796 * @param {!WebInspector.NetworkRequest} request | |
1797 * @return {boolean} | |
1798 */ | |
1799 WebInspector.NetworkLogView._requestMimeTypeFilter = function(value, request) | |
1800 { | |
1801 return request.mimeType === value; | |
1802 } | |
1803 | |
1804 /** | |
1805 * @param {string} value | |
1806 * @param {!WebInspector.NetworkRequest} request | |
1807 * @return {boolean} | |
1808 */ | |
1809 WebInspector.NetworkLogView._requestSchemeFilter = function(value, request) | |
1810 { | |
1811 return request.scheme === value; | |
1812 } | |
1813 | |
1814 /** | |
1815 * @param {string} value | |
1816 * @param {!WebInspector.NetworkRequest} request | |
1817 * @return {boolean} | |
1818 */ | |
1819 WebInspector.NetworkLogView._requestSetCookieDomainFilter = function(value, requ
est) | |
1820 { | |
1821 var cookies = request.responseCookies; | |
1822 for (var i = 0, l = cookies ? cookies.length : 0; i < l; ++i) { | |
1823 if (cookies[i].domain() === value) | |
1824 return false; | |
1825 } | |
1826 return false; | |
1827 } | |
1828 | |
1829 /** | |
1830 * @param {string} value | |
1831 * @param {!WebInspector.NetworkRequest} request | |
1832 * @return {boolean} | |
1833 */ | |
1834 WebInspector.NetworkLogView._requestSetCookieNameFilter = function(value, reques
t) | |
1835 { | |
1836 var cookies = request.responseCookies; | |
1837 for (var i = 0, l = cookies ? cookies.length : 0; i < l; ++i) { | |
1838 if (cookies[i].name() === value) | |
1839 return false; | |
1840 } | |
1841 return false; | |
1842 } | |
1843 | |
1844 /** | |
1845 * @param {string} value | |
1846 * @param {!WebInspector.NetworkRequest} request | |
1847 * @return {boolean} | |
1848 */ | |
1849 WebInspector.NetworkLogView._requestSetCookieValueFilter = function(value, reque
st) | |
1850 { | |
1851 var cookies = request.responseCookies; | |
1852 for (var i = 0, l = cookies ? cookies.length : 0; i < l; ++i) { | |
1853 if (cookies[i].value() === value) | |
1854 return false; | |
1855 } | |
1856 return false; | |
1857 } | |
1858 | |
1859 /** | |
1860 * @param {string} value | |
1861 * @param {!WebInspector.NetworkRequest} request | |
1862 * @return {boolean} | |
1863 */ | |
1864 WebInspector.NetworkLogView._statusCodeFilter = function(value, request) | |
1865 { | |
1866 return ("" + request.statusCode) === value; | |
1867 } | |
1868 | |
1869 /** | |
1870 * @param {!WebInspector.NetworkRequest} request | |
1871 * @return {boolean} | |
1872 */ | |
1873 WebInspector.NetworkLogView.HTTPRequestsFilter = function(request) | |
1874 { | |
1875 return request.parsedURL.isValid && (request.scheme in WebInspector.NetworkL
ogView.HTTPSchemas); | |
1876 } | |
1877 | |
1878 /** | |
1879 * @param {!WebInspector.NetworkRequest} request | |
1880 * @return {boolean} | |
1881 */ | |
1882 WebInspector.NetworkLogView.NonDevToolsRequestsFilter = function(request) | |
1883 { | |
1884 return !WebInspector.NetworkManager.hasDevToolsRequestHeader(request); | |
1885 } | |
1886 | |
1887 /** | |
1888 * @param {!WebInspector.NetworkRequest} request | |
1889 * @return {boolean} | |
1890 */ | |
1891 WebInspector.NetworkLogView.FinishedRequestsFilter = function(request) | |
1892 { | |
1893 return request.finished; | |
1894 } | |
1895 | |
1896 WebInspector.NetworkLogView.EventTypes = { | |
1897 ViewCleared: "ViewCleared", | |
1898 RowSizeChanged: "RowSizeChanged", | |
1899 RequestSelected: "RequestSelected", | |
1900 SearchCountUpdated: "SearchCountUpdated", | |
1901 SearchIndexUpdated: "SearchIndexUpdated" | |
1902 }; | |
OLD | NEW |