summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/TimelineOverview.js
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/WebInspectorUI/UserInterface/TimelineOverview.js
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-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.js251
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;