blob: 617cdf8d851dde8d2589243a8346b0df84989651 [file] [log] [blame]
/*
* 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.TimelineRecording = function()
{
WebInspector.Object.call(this);
this.reset(true);
};
WebInspector.TimelineRecording.Event = {
Reset: "timeline-recording-reset",
SourceCodeTimelineAdded: "timeline-recording-source-code-timeline-added",
TimesUpdated: "timeline-recording-times-updated"
};
WebInspector.TimelineRecording.prototype = {
constructor: WebInspector.TimelineRecording,
__proto__: WebInspector.Object.prototype,
// Public
get timelines()
{
return this._timelines;
},
reset: function(newObject)
{
if (this._timelines) {
this._timelines.forEach(function(timeline) {
timeline.removeEventListener(null, null, this);
}, this);
}
this._timelines = new Map;
this._timelines.set(WebInspector.TimelineRecord.Type.Network, new WebInspector.NetworkTimeline);
this._timelines.set(WebInspector.TimelineRecord.Type.Script, new WebInspector.Timeline);
this._timelines.set(WebInspector.TimelineRecord.Type.Layout, new WebInspector.Timeline);
this._timelines.forEach(function(timeline) {
timeline.addEventListener(WebInspector.Timeline.Event.TimesUpdated, this._timelineTimesUpdated, this);
}, this);
this._sourceCodeTimelinesMap = new Map;
this._eventMarkers = [];
if (!newObject)
this.dispatchEventToListeners(WebInspector.TimelineRecording.Event.Reset);
},
sourceCodeTimelinesForSourceCode: function(sourceCode)
{
var timelines = this._sourceCodeTimelinesMap.get(sourceCode);
if (!timelines)
return [];
var result = [];
// FIXME: This could use a for..of loop once they are supported on Maps.
timelines.forEach(function(sourceCodeTimeline) {
result.push(sourceCodeTimeline);
});
return result;
},
addEventMarker: function(eventMarker)
{
this._eventMarkers.push(eventMarker);
},
addRecord: function(record)
{
// Add the record to the global timeline by type.
this._timelines.get(record.type).addRecord(record);
// Netowrk records don't have source code timelines.
if (record.type === WebInspector.TimelineRecord.Type.Network)
return;
// Add the record to the source code timelines.
var activeMainResource = WebInspector.frameResourceManager.mainFrame.provisionalMainResource || WebInspector.frameResourceManager.mainFrame.mainResource;
var sourceCode = record.sourceCodeLocation ? record.sourceCodeLocation.sourceCode : activeMainResource;
var sourceCodeTimelines = this._sourceCodeTimelinesMap.get(sourceCode);
if (!sourceCodeTimelines) {
sourceCodeTimelines = new Map;
this._sourceCodeTimelinesMap.set(sourceCode, sourceCodeTimelines);
}
var newTimeline = false;
var key = this._keyForRecord(record);
var sourceCodeTimeline = sourceCodeTimelines.get(key);
if (!sourceCodeTimeline) {
sourceCodeTimeline = new WebInspector.SourceCodeTimeline(sourceCode, record.sourceCodeLocation, record.type, record.eventType);
sourceCodeTimelines.set(key, sourceCodeTimeline);
newTimeline = true;
}
sourceCodeTimeline.addRecord(record);
if (newTimeline)
this.dispatchEventToListeners(WebInspector.TimelineRecording.Event.SourceCodeTimelineAdded, {sourceCodeTimeline: sourceCodeTimeline});
},
// Private
_keyForRecord: function(record)
{
var key = record.type;
if (record instanceof WebInspector.ScriptTimelineRecord || record instanceof WebInspector.LayoutTimelineRecord)
key += ":" + record.eventType;
if (record instanceof WebInspector.ScriptTimelineRecord && record.eventType === WebInspector.ScriptTimelineRecord.EventType.EventDispatched)
key += ":" + record.details;
if (record.sourceCodeLocation)
key += ":" + record.sourceCodeLocation.lineNumber + ":" + record.sourceCodeLocation.columnNumber;
return key;
},
_timelineTimesUpdated: function(event)
{
var timeline = event.target;
var changed = false;
if (isNaN(this._startTime) || timeline.startTime < this._startTime) {
this._startTime = timeline.startTime;
changed = true;
}
if (isNaN(this._endTime) || this._endTime < timeline.endTime) {
this._endTime = timeline.endTime;
changed = true;
}
if (changed)
this.dispatchEventToListeners(WebInspector.TimelineRecording.Event.TimesUpdated);
}
};