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