diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebInspectorUI/UserInterface/TimelineOverview.js | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/TimelineOverview.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/TimelineOverview.js | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/TimelineOverview.js b/Source/WebInspectorUI/UserInterface/TimelineOverview.js new file mode 100644 index 000000000..a17eb83e7 --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/TimelineOverview.js @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.TimelineOverview = function(dataSource, recordTypes) +{ + WebInspector.Object.call(this); + + console.assert(dataSource); + console.assert(recordTypes instanceof Array); + + this._element = document.createElement("div"); + this._element.className = WebInspector.TimelineOverview.StyleClassName; + + this._recordTypes = recordTypes; + + this._timelineDecorations = new WebInspector.TimelineDecorations; + + this._timelineElements = []; + for (var i = 0; i < this._recordTypes.length; ++i) { + var timelineElement = document.createElement("div"); + timelineElement.classList.add(WebInspector.TimelineOverview.TimelineElementStyleClassName); + timelineElement.classList.add(this._recordTypes[i]); + this._element.appendChild(timelineElement); + + var barContainerElement = document.createElement("div"); + barContainerElement.className = WebInspector.TimelineOverview.BarContainerElementStyleClassName; + timelineElement.appendChild(barContainerElement); + timelineElement._barContainerElement = barContainerElement; + + this._timelineElements.push(timelineElement); + } + + this._element.appendChild(this._timelineDecorations.element); + + this._dataSource = dataSource; +}; + +WebInspector.TimelineOverview.StyleClassName = "timeline-overview"; +WebInspector.TimelineOverview.TimelineElementStyleClassName = "timeline"; +WebInspector.TimelineOverview.BarContainerElementStyleClassName = "bar-container"; +WebInspector.TimelineOverview.BarElementStyleClassName = "bar"; +WebInspector.TimelineOverview.WaitingBarElementStyleClassName = "waiting"; + +WebInspector.TimelineOverview.prototype = { + constructor: WebInspector.TimelineOverview, + + // Public + + get element() + { + return this._element; + }, + + get recordTypes() + { + return this._recordTypes; + }, + + clear: function() + { + this._minimumBoundary = NaN; + this._maximumBoundary = NaN; + this._boundarySpan = NaN; + + this._timelineDecorations.clear(); + this._timelineDecorations.updateHeaderTimes(this._boundarySpan); + + for (var i = 0; i < this._timelineElements.length; ++i) + this._timelineElements[i]._barContainerElement.removeChildren(); + }, + + update: function() + { + var minimumBoundary = NaN; + var maximumBoundary = NaN; + + var records = []; + for (var i = 0; i < this._recordTypes.length; ++i) + records.push(this._dataSource.timelineOverviewRecordsWithType(this._recordTypes[i])); + + for (var i = 0; i < records.length; ++i) { + var currentRecords = records[i]; + if (!currentRecords.length) + continue; + + // The first record can be assumed to be the oldest start time. + var firstRecord = currentRecords[0]; + if (isNaN(minimumBoundary) || firstRecord.startTime < minimumBoundary) + minimumBoundary = firstRecord.startTime; + + if (this._recordTypes[i] === WebInspector.TimelineRecord.Type.Network) { + // For the Network timeline we need to look at all the records since + // long loading resources can be anywhere, not just at the end. The other + // timelines are static, so the last record is always the newest. + for (var j = currentRecords.length - 1; j >= 0; --j) { + var record = currentRecords[j]; + if (isNaN(maximumBoundary) || record.endTime > maximumBoundary) + maximumBoundary = record.endTime; + } + } else { + // The newest record will always be at the end. + var lastRecord = currentRecords.lastValue; + if (isNaN(maximumBoundary) || lastRecord.endTime > maximumBoundary) + maximumBoundary = lastRecord.endTime; + } + } + + this._minimumBoundary = minimumBoundary; + this._maximumBoundary = maximumBoundary; + this._boundarySpan = maximumBoundary - minimumBoundary; + + this._timelineDecorations.updateHeaderTimes(this._boundarySpan); + this._timelineDecorations.updateEventMarkers(this._minimumBoundary, this._maximumBoundary); + + for (var i = 0; i < records.length; ++i) + this._updateTimelineBars(this._timelineElements[i], this._recordTypes[i], records[i]); + }, + + updateLayout: function() + { + this._timelineDecorations.updateHeaderTimes(this._boundarySpan); + }, + + addTimelineEventMarker: function(eventMarker) + { + this._timelineDecorations.addTimelineEventMarker(eventMarker); + }, + + // Private + + _updateTimelineBars: function(timelineElement, type, records) + { + function computeActivePercentages(record) + { + // Compute percentages for endTime and the start of activeDuration. + + var activeStartTime = record.endTime - record.activeDuration; + if (isNaN(activeStartTime)) + activeStartTime = record.endTime; + + if (isNaN(activeStartTime)) + var start = 0; + else + var start = ((activeStartTime - this._minimumBoundary) / this._boundarySpan) * 100; + + if (isNaN(record.endTime)) + var end = 100; + else + var end = ((record.endTime - this._minimumBoundary) / this._boundarySpan) * 100; + + return {start: start, end: end}; + } + + function computePercentages(record) + { + // Compute percentages for startTime and endTime. + + if (isNaN(record.startTime)) + var start = 0; + else + var start = ((record.startTime - this._minimumBoundary) / this._boundarySpan) * 100; + + if (isNaN(record.endTime)) + var end = 100; + else + var end = ((record.endTime - this._minimumBoundary) / this._boundarySpan) * 100; + + return {start: start, end: end}; + } + + function addBar(startPercentage, endPercentage, extraBarStyleClass) + { + var barElement = document.createElement("div"); + barElement.className = WebInspector.TimelineOverview.BarElementStyleClassName; + if (extraBarStyleClass) + barElement.classList.add(extraBarStyleClass); + + if (startPercentage === 0 || startPercentage !== endPercentage) + barElement.style.left = startPercentage + "%"; + barElement.style.right = (100 - endPercentage) + "%"; + + timelineElement._barContainerElement.appendChild(barElement); + } + + function createBars(percentageCalculator, extraBarStyleClass) + { + // Iterate over the records and find the percentage distribution on the graph. + // The percentages are recorded in a sparse array from 0-100. + + var timelineSlots = new Array(101); + for (var i = 0; i < records.length; ++i) { + var percentages = percentageCalculator.call(this, records[i]); + var end = Math.round(percentages.end); + for (var j = Math.round(percentages.start); j <= end; ++j) + timelineSlots[j] = true; + } + + var barStart = NaN; + for (var i = 0; i < timelineSlots.length; ++i) { + if (timelineSlots[i]) { + if (isNaN(barStart)) + barStart = i; + } else { + if (!isNaN(barStart)) { + addBar.call(this, barStart, i, extraBarStyleClass); + barStart = NaN; + } + } + } + + if (!isNaN(barStart)) { + addBar.call(this, barStart, 100, extraBarStyleClass); + barStart = NaN; + } + } + + timelineElement._barContainerElement.removeChildren(); + + // The Network timeline shows two bars. The first is the total time (waiting for the resource until it finishes). + // The second bar is the active download time (first first response to finish.) + if (type === WebInspector.TimelineRecord.Type.Network) { + createBars.call(this, computePercentages, WebInspector.TimelineOverview.WaitingBarElementStyleClassName); + createBars.call(this, computeActivePercentages); + } else + createBars.call(this, computePercentages); + } +}; + +WebInspector.TimelineOverview.prototype.__proto__ = WebInspector.Object.prototype; |