<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[162402] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/162402">162402</a></dd>
<dt>Author</dt> <dd>timothy@apple.com</dd>
<dt>Date</dt> <dd>2014-01-20 18:54:04 -0800 (Mon, 20 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Correctly track time bounds of WebInspector.Timeline and WebInspector.TimelineRecording.

The startTime and endTime were not correct when Network timeline needed to be taken into
account (due to its dynamic loading nature.) This creates a network Timeline for the purposes
of tracking the ResourceTimelineRecords and getting accurate start and end times.

Also changes the way TimelineRecord tracks the inactive portion of time, needed for later
work on the timeline graphs.

https://bugs.webkit.org/show_bug.cgi?id=126676

Reviewed by Joseph Pecoraro.

* UserInterface/ResourceTimelineRecord.js:
(WebInspector.ResourceTimelineRecord.prototype.get updatesDynamically):
(WebInspector.ResourceTimelineRecord.prototype.get usesActiveStartTime):
(WebInspector.ResourceTimelineRecord.prototype.get startTime):
(WebInspector.ResourceTimelineRecord.prototype.get activeStartTime):
(WebInspector.ResourceTimelineRecord.prototype.get endTime):
* UserInterface/Timeline.js:
(WebInspector.Timeline):
(WebInspector.Timeline.prototype.get startTime):
(WebInspector.Timeline.prototype.get endTime):
(WebInspector.Timeline.prototype.addRecord):
(WebInspector.Timeline.prototype._updateTimesIfNeeded):
(WebInspector.Timeline.prototype._recordUpdated):
* UserInterface/TimelineRecord.js:
(WebInspector.TimelineRecord.prototype.get startTime):
(WebInspector.TimelineRecord.prototype.get activeStartTime):
(WebInspector.TimelineRecord.prototype.get endTime):
(WebInspector.TimelineRecord.prototype.get inactiveDuration):
(WebInspector.TimelineRecord.prototype.get activeDuration):
(WebInspector.TimelineRecord.prototype.get updatesDynamically):
(WebInspector.TimelineRecord.prototype.get usesActiveStartTime):
* UserInterface/TimelineRecording.js:
(WebInspector.TimelineRecording.prototype._timelineTimesUpdated):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceResourceTimelineRecordjs">trunk/Source/WebInspectorUI/UserInterface/ResourceTimelineRecord.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTimelinejs">trunk/Source/WebInspectorUI/UserInterface/Timeline.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTimelineRecordjs">trunk/Source/WebInspectorUI/UserInterface/TimelineRecord.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTimelineRecordingjs">trunk/Source/WebInspectorUI/UserInterface/TimelineRecording.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (162401 => 162402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2014-01-21 02:53:58 UTC (rev 162401)
+++ trunk/Source/WebInspectorUI/ChangeLog        2014-01-21 02:54:04 UTC (rev 162402)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2014-01-08  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
+        Correctly track time bounds of WebInspector.Timeline and WebInspector.TimelineRecording.
+
+        The startTime and endTime were not correct when Network timeline needed to be taken into
+        account (due to its dynamic loading nature.) This creates a network Timeline for the purposes
+        of tracking the ResourceTimelineRecords and getting accurate start and end times.
+
+        Also changes the way TimelineRecord tracks the inactive portion of time, needed for later
+        work on the timeline graphs.
+
+        https://bugs.webkit.org/show_bug.cgi?id=126676
+
+        Reviewed by Joseph Pecoraro.
+
+        * UserInterface/ResourceTimelineRecord.js:
+        (WebInspector.ResourceTimelineRecord.prototype.get updatesDynamically):
+        (WebInspector.ResourceTimelineRecord.prototype.get usesActiveStartTime):
+        (WebInspector.ResourceTimelineRecord.prototype.get startTime):
+        (WebInspector.ResourceTimelineRecord.prototype.get activeStartTime):
+        (WebInspector.ResourceTimelineRecord.prototype.get endTime):
+        * UserInterface/Timeline.js:
+        (WebInspector.Timeline):
+        (WebInspector.Timeline.prototype.get startTime):
+        (WebInspector.Timeline.prototype.get endTime):
+        (WebInspector.Timeline.prototype.addRecord):
+        (WebInspector.Timeline.prototype._updateTimesIfNeeded):
+        (WebInspector.Timeline.prototype._recordUpdated):
+        * UserInterface/TimelineRecord.js:
+        (WebInspector.TimelineRecord.prototype.get startTime):
+        (WebInspector.TimelineRecord.prototype.get activeStartTime):
+        (WebInspector.TimelineRecord.prototype.get endTime):
+        (WebInspector.TimelineRecord.prototype.get inactiveDuration):
+        (WebInspector.TimelineRecord.prototype.get activeDuration):
+        (WebInspector.TimelineRecord.prototype.get updatesDynamically):
+        (WebInspector.TimelineRecord.prototype.get usesActiveStartTime):
+        * UserInterface/TimelineRecording.js:
+        (WebInspector.TimelineRecording.prototype._timelineTimesUpdated):
+
</ins><span class="cx"> 2013-10-25  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement TimelineRecording and per-call-site timelines.
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceResourceTimelineRecordjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/ResourceTimelineRecord.js (162401 => 162402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/ResourceTimelineRecord.js        2014-01-21 02:53:58 UTC (rev 162401)
+++ trunk/Source/WebInspectorUI/UserInterface/ResourceTimelineRecord.js        2014-01-21 02:54:04 UTC (rev 162402)
</span><span class="lines">@@ -41,26 +41,31 @@
</span><span class="cx">         return this._resource;
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    get startTime()
</del><ins>+    get updatesDynamically()
</ins><span class="cx">     {
</span><del>-        return this._resource.firstTimestamp;
</del><ins>+        return true;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><del>-    get endTime()
</del><ins>+    get usesActiveStartTime()
</ins><span class="cx">     {
</span><del>-        return this._resource.lastTimestamp;
</del><ins>+        return true;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><del>-    get waitingDuration()
</del><ins>+    get startTime()
</ins><span class="cx">     {
</span><del>-        return this._resource.latency;
</del><ins>+        return this._resource.requestSentTimestamp;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><del>-    get activeDuration()
</del><ins>+    get activeStartTime()
</ins><span class="cx">     {
</span><del>-        return this._resource.receiveDuration;
</del><ins>+        return this._resource.responseReceivedTimestamp;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    get endTime()
+    {
+        return this._resource.finishedOrFailedTimestamp;
+    },
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _dispatchUpdatedEvent: function()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTimelinejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Timeline.js (162401 => 162402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Timeline.js        2014-01-21 02:53:58 UTC (rev 162401)
+++ trunk/Source/WebInspectorUI/UserInterface/Timeline.js        2014-01-21 02:54:04 UTC (rev 162402)
</span><span class="lines">@@ -28,14 +28,31 @@
</span><span class="cx">     WebInspector.Object.call(this);
</span><span class="cx"> 
</span><span class="cx">     this._records = [];
</span><ins>+    this._startTime = NaN;
+    this._endTime = NaN;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+WebInspector.Timeline.Event = {
+    RecordAdded: &quot;timeline-record-added&quot;,
+    TimesUpdated: &quot;timeline-times-updated&quot;
+};
+
</ins><span class="cx"> WebInspector.Timeline.prototype = {
</span><span class="cx">     constructor: WebInspector.Timeline,
</span><span class="cx">     __proto__: WebInspector.Object.prototype,
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><ins>+    get startTime()
+    {
+        return this._startTime;
+    },
+
+    get endTime()
+    {
+        return this._endTime;
+    },
+
</ins><span class="cx">     get records()
</span><span class="cx">     {
</span><span class="cx">         return this._records;
</span><span class="lines">@@ -43,6 +60,38 @@
</span><span class="cx"> 
</span><span class="cx">     addRecord: function(record)
</span><span class="cx">     {
</span><ins>+        if (record.updatesDynamically)
+            record.addEventListener(WebInspector.TimelineRecord.Event.Updated, this._recordUpdated, this);
+
</ins><span class="cx">         this._records.push(record);
</span><ins>+
+        this._updateTimesIfNeeded(record);
+
+        this.dispatchEventToListeners(WebInspector.Timeline.Event.RecordAdded, {record: record});
+    },
+
+    // Private
+
+    _updateTimesIfNeeded: function(record)
+    {
+        var changed = false;
+
+        if (isNaN(this._startTime) || record.startTime &lt; this._startTime) {
+            this._startTime = record.startTime;
+            changed = true;
+        }
+
+        if (isNaN(this._endTime) || this._endTime &lt; record.endTime) {
+            this._endTime = record.endTime;
+            changed = true;
+        }
+
+        if (changed)
+            this.dispatchEventToListeners(WebInspector.Timeline.Event.TimesUpdated);
+    },
+
+    _recordUpdated: function(event)
+    {
+        this._updateTimesIfNeeded(event.target);
</ins><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTimelineRecordjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/TimelineRecord.js (162401 => 162402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/TimelineRecord.js        2014-01-21 02:53:58 UTC (rev 162401)
+++ trunk/Source/WebInspectorUI/UserInterface/TimelineRecord.js        2014-01-21 02:54:04 UTC (rev 162402)
</span><span class="lines">@@ -61,11 +61,19 @@
</span><span class="cx"> 
</span><span class="cx">     get startTime()
</span><span class="cx">     {
</span><ins>+        // Implemented by subclasses if needed.
</ins><span class="cx">         return this._startTime;
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    get activeStartTime()
+    {
+        // Implemented by subclasses if needed.
+        return this._startTime;
+    },
+
</ins><span class="cx">     get endTime()
</span><span class="cx">     {
</span><ins>+        // Implemented by subclasses if needed.
</ins><span class="cx">         return this._endTime;
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="lines">@@ -75,18 +83,30 @@
</span><span class="cx">         return this.endTime - this.startTime;
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    get waitingDuration()
</del><ins>+    get inactiveDuration()
</ins><span class="cx">     {
</span><del>-        // Implemented by subclasses if needed.
-        return NaN;
</del><ins>+        // Use the getters instead of the properties so this works for subclasses that override the getters.
+        return this.activeStartTime - this.startTime;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     get activeDuration()
</span><span class="cx">     {
</span><ins>+        // Use the getters instead of the properties so this works for subclasses that override the getters.
+        return this.endTime - this.activeStartTime;
+    },
+
+    get updatesDynamically()
+    {
</ins><span class="cx">         // Implemented by subclasses if needed.
</span><del>-        return this.duration;
</del><ins>+        return false;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    get usesActiveStartTime()
+    {
+        // Implemented by subclasses if needed.
+        return false;
+    },
+
</ins><span class="cx">     get callFrames()
</span><span class="cx">     {
</span><span class="cx">         return this._callFrames;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTimelineRecordingjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/TimelineRecording.js (162401 => 162402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/TimelineRecording.js        2014-01-21 02:53:58 UTC (rev 162401)
+++ trunk/Source/WebInspectorUI/UserInterface/TimelineRecording.js        2014-01-21 02:54:04 UTC (rev 162402)
</span><span class="lines">@@ -32,7 +32,8 @@
</span><span class="cx"> 
</span><span class="cx"> WebInspector.TimelineRecording.Event = {
</span><span class="cx">     Reset: &quot;timeline-recording-reset&quot;,
</span><del>-    SourceCodeTimelineAdded: &quot;timeline-recording-source-code-timeline-added&quot;
</del><ins>+    SourceCodeTimelineAdded: &quot;timeline-recording-source-code-timeline-added&quot;,
+    TimesUpdated: &quot;timeline-recording-times-updated&quot;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.TimelineRecording.prototype = {
</span><span class="lines">@@ -48,11 +49,21 @@
</span><span class="cx"> 
</span><span class="cx">     reset: function(newObject)
</span><span class="cx">     {
</span><ins>+        if (this._timelines) {
+            this._timelines.forEach(function(timeline) {
+                timeline.removeEventListener(null, null, this);
+            }, this);
+        }
+
</ins><span class="cx">         this._timelines = new Map;
</span><span class="cx">         this._timelines.set(WebInspector.TimelineRecord.Type.Network, new WebInspector.Timeline);
</span><span class="cx">         this._timelines.set(WebInspector.TimelineRecord.Type.Script, new WebInspector.Timeline);
</span><span class="cx">         this._timelines.set(WebInspector.TimelineRecord.Type.Layout, new WebInspector.Timeline);
</span><span class="cx"> 
</span><ins>+        this._timelines.forEach(function(timeline) {
+            timeline.addEventListener(WebInspector.Timeline.Event.TimesUpdated, this._timelineTimesUpdated, this);
+        }, this);
+
</ins><span class="cx">         this._sourceCodeTimelinesMap = new Map;
</span><span class="cx">         this._eventMarkers = [];
</span><span class="cx"> 
</span><span class="lines">@@ -127,5 +138,24 @@
</span><span class="cx">         if (record.sourceCodeLocation)
</span><span class="cx">             key += &quot;:&quot; + record.sourceCodeLocation.lineNumber + &quot;:&quot; + record.sourceCodeLocation.columnNumber;
</span><span class="cx">         return key;
</span><ins>+    },
+
+    _timelineTimesUpdated: function(event)
+    {
+        var timeline = event.target;
+        var changed = false;
+
+        if (isNaN(this._startTime) || timeline.startTime &lt; this._startTime) {
+            this._startTime = timeline.startTime;
+            changed = true;
+        }
+
+        if (isNaN(this._endTime) || this._endTime &lt; timeline.endTime) {
+            this._endTime = timeline.endTime;
+            changed = true;
+        }
+
+        if (changed)
+            this.dispatchEventToListeners(WebInspector.TimelineRecording.Event.TimesUpdated);
</ins><span class="cx">     }
</span><span class="cx"> };
</span></span></pre>
</div>
</div>

</body>
</html>