diff options
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/TimelineManager.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/TimelineManager.js | 445 |
1 files changed, 0 insertions, 445 deletions
diff --git a/Source/WebInspectorUI/UserInterface/TimelineManager.js b/Source/WebInspectorUI/UserInterface/TimelineManager.js deleted file mode 100644 index 0bea0c7f8..000000000 --- a/Source/WebInspectorUI/UserInterface/TimelineManager.js +++ /dev/null @@ -1,445 +0,0 @@ -/* - * 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.TimelineManager = function() -{ - WebInspector.Object.call(this); - - WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ProvisionalLoadStarted, this._startAutoRecording, this); - WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this); - WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ResourceWasAdded, this._resourceWasAdded, this); - - this._recording = new WebInspector.TimelineRecording; - this._recordingEnabled = false; -}; - -WebInspector.TimelineManager.Event = { - RecordingStarted: "timeline-manager-recording-started", - RecordingStopped: "timeline-manager-recording-stopped" -}; - -WebInspector.TimelineManager.MaximumAutoRecordDuration = 90000; // 90 seconds -WebInspector.TimelineManager.MaximumAutoRecordDurationAfterLoadEvent = 10000; // 10 seconds -WebInspector.TimelineManager.DeadTimeRequiredToStopAutoRecordingEarly = 2000; // 2 seconds - -WebInspector.TimelineManager.prototype = { - constructor: WebInspector.TimelineManager, - - // Public - - get recording() - { - return this._recording; - }, - - get recordingEnabled() - { - return this._recordingEnabled; - }, - - startRecording: function() - { - if (this._recordingEnabled) - return; - - this._recordingEnabled = true; - - TimelineAgent.start(); - - this.dispatchEventToListeners(WebInspector.TimelineManager.Event.RecordingStarted); - }, - - stopRecording: function() - { - if (!this._recordingEnabled) - return; - - if (this._stopRecordingTimeout) { - clearTimeout(this._stopRecordingTimeout); - delete this._stopRecordingTimeout; - } - - if (this._deadTimeTimeout) { - clearTimeout(this._deadTimeTimeout); - delete this._deadTimeTimeout; - } - - TimelineAgent.stop(); - - this._recordingEnabled = false; - this._autoRecordingMainResource = null; - - this.dispatchEventToListeners(WebInspector.TimelineManager.Event.RecordingStopped); - }, - - eventRecorded: function(originalRecordPayload) - { - // Called from WebInspector.TimelineObserver. - - if (!this._recordingEnabled) - return; - - function processRecord(recordPayload, parentRecordPayload) - { - // Convert the timestamps to seconds to match the resource timestamps. - var startTime = recordPayload.startTime / 1000; - var endTime = recordPayload.endTime / 1000; - - var callFrames = this._callFramesFromPayload(recordPayload.stackTrace); - - var significantCallFrame = null; - if (callFrames) { - for (var i = 0; i < callFrames.length; ++i) { - if (callFrames[i].nativeCode) - continue; - significantCallFrame = callFrames[i]; - break; - } - } - - var sourceCodeLocation = significantCallFrame && significantCallFrame.sourceCodeLocation; - - switch (recordPayload.type) { - case TimelineAgent.EventType.MarkLoad: - console.assert(isNaN(endTime)); - - var frame = WebInspector.frameResourceManager.frameForIdentifier(recordPayload.frameId); - console.assert(frame); - if (!frame) - break; - - frame.markLoadEvent(startTime); - - if (!frame.isMainFrame()) - break; - - var eventMarker = new WebInspector.TimelineMarker(startTime, WebInspector.TimelineMarker.Type.LoadEvent); - this._recording.addEventMarker(eventMarker); - - this._stopAutoRecordingSoon(); - break; - - case TimelineAgent.EventType.MarkDOMContent: - console.assert(isNaN(endTime)); - - var frame = WebInspector.frameResourceManager.frameForIdentifier(recordPayload.frameId); - console.assert(frame); - if (!frame) - break; - - frame.markDOMContentReadyEvent(startTime); - - if (!frame.isMainFrame()) - break; - - var eventMarker = new WebInspector.TimelineMarker(startTime, WebInspector.TimelineMarker.Type.DOMContentEvent); - this._recording.addEventMarker(eventMarker); - break; - - case TimelineAgent.EventType.ScheduleStyleRecalculation: - console.assert(isNaN(endTime)); - - // Pass the startTime as the endTime since this record type has no duration. - this._addRecord(new WebInspector.LayoutTimelineRecord(WebInspector.LayoutTimelineRecord.EventType.InvalidateStyles, startTime, startTime, callFrames, sourceCodeLocation)); - break; - - case TimelineAgent.EventType.RecalculateStyles: - this._addRecord(new WebInspector.LayoutTimelineRecord(WebInspector.LayoutTimelineRecord.EventType.RecalculateStyles, startTime, endTime, callFrames, sourceCodeLocation)); - break; - - case TimelineAgent.EventType.InvalidateLayout: - console.assert(isNaN(endTime)); - - // Pass the startTime as the endTime since this record type has no duration. - this._addRecord(new WebInspector.LayoutTimelineRecord(WebInspector.LayoutTimelineRecord.EventType.InvalidateLayout, startTime, startTime, callFrames, sourceCodeLocation)); - break; - - case TimelineAgent.EventType.Layout: - // COMPATIBILITY (iOS 6): Layout records did not contain area properties. This is not exposed via a quad "root". - var quad = recordPayload.data.root ? new WebInspector.Quad(recordPayload.data.root) : null; - if (quad) - this._addRecord(new WebInspector.LayoutTimelineRecord(WebInspector.LayoutTimelineRecord.EventType.Layout, startTime, endTime, callFrames, sourceCodeLocation, quad.points[0].x, quad.points[0].y, quad.width, quad.height, quad)); - else - this._addRecord(new WebInspector.LayoutTimelineRecord(WebInspector.LayoutTimelineRecord.EventType.Layout, startTime, endTime, callFrames, sourceCodeLocation)); - break; - - case TimelineAgent.EventType.Paint: - // COMPATIBILITY (iOS 6): Paint records data contained x, y, width, height properties. This became a quad "clip". - var quad = recordPayload.data.clip ? new WebInspector.Quad(recordPayload.data.clip) : null; - if (quad) - this._addRecord(new WebInspector.LayoutTimelineRecord(WebInspector.LayoutTimelineRecord.EventType.Paint, startTime, endTime, callFrames, sourceCodeLocation, null, null, quad.width, quad.height, quad)); - else - this._addRecord(new WebInspector.LayoutTimelineRecord(WebInspector.LayoutTimelineRecord.EventType.Paint, startTime, endTime, callFrames, sourceCodeLocation, recordPayload.data.x, recordPayload.data.y, recordPayload.data.width, recordPayload.data.height)); - break; - - case TimelineAgent.EventType.EvaluateScript: - if (!sourceCodeLocation) { - var mainFrame = WebInspector.frameResourceManager.mainFrame; - var scriptResource = mainFrame.url === recordPayload.data.url ? mainFrame.mainResource : mainFrame.resourceForURL(recordPayload.data.url, true); - if (scriptResource) { - // The lineNumber is 1-based, but we expect 0-based. - var lineNumber = recordPayload.data.lineNumber - 1; - - // FIXME: No column number is provided. - sourceCodeLocation = scriptResource.createSourceCodeLocation(lineNumber, 0); - } - } - - switch (parentRecordPayload && parentRecordPayload.type) { - case TimelineAgent.EventType.TimerFire: - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.TimerFired, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.timerId)); - break; - default: - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.ScriptEvaluated, startTime, endTime, callFrames, sourceCodeLocation, null)); - break; - } - - break; - - case TimelineAgent.EventType.TimeStamp: - var eventMarker = new WebInspector.TimelineMarker(startTime, WebInspector.TimelineMarker.Type.TimeStamp); - this._recording.addEventMarker(eventMarker); - break; - - case TimelineAgent.EventType.FunctionCall: - // FunctionCall always happens as a child of another record, and since the FunctionCall record - // has useful info we just make the timeline record here (combining the data from both records). - if (!parentRecordPayload) - break; - - if (!sourceCodeLocation) { - var mainFrame = WebInspector.frameResourceManager.mainFrame; - var scriptResource = mainFrame.url === recordPayload.data.scriptName ? mainFrame.mainResource : mainFrame.resourceForURL(recordPayload.data.scriptName, true); - if (scriptResource) { - // The lineNumber is 1-based, but we expect 0-based. - var lineNumber = recordPayload.data.scriptLine - 1; - - // FIXME: No column number is provided. - sourceCodeLocation = scriptResource.createSourceCodeLocation(lineNumber, 0); - } - } - - switch (parentRecordPayload.type) { - case TimelineAgent.EventType.TimerFire: - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.TimerFired, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.timerId)); - break; - case TimelineAgent.EventType.EventDispatch: - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.EventDispatched, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.type)); - break; - case TimelineAgent.EventType.XHRLoad: - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.EventDispatched, startTime, endTime, callFrames, sourceCodeLocation, "load")); - break; - case TimelineAgent.EventType.XHRReadyStateChange: - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.EventDispatched, startTime, endTime, callFrames, sourceCodeLocation, "readystatechange")); - break; - case TimelineAgent.EventType.FireAnimationFrame: - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.AnimationFrameFired, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.id)); - break; - } - - break; - - case TimelineAgent.EventType.TimerInstall: - console.assert(isNaN(endTime)); - - // Pass the startTime as the endTime since this record type has no duration. - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.TimerInstalled, startTime, startTime, callFrames, sourceCodeLocation, recordPayload.data.timerId)); - break; - - case TimelineAgent.EventType.TimerRemove: - console.assert(isNaN(endTime)); - - // Pass the startTime as the endTime since this record type has no duration. - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.TimerRemoved, startTime, startTime, callFrames, sourceCodeLocation, recordPayload.data.timerId)); - break; - - case TimelineAgent.EventType.RequestAnimationFrame: - console.assert(isNaN(endTime)); - - // Pass the startTime as the endTime since this record type has no duration. - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.AnimationFrameRequested, startTime, startTime, callFrames, sourceCodeLocation, recordPayload.data.timerId)); - break; - - case TimelineAgent.EventType.CancelAnimationFrame: - console.assert(isNaN(endTime)); - - // Pass the startTime as the endTime since this record type has no duration. - this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.AnimationFrameCanceled, startTime, startTime, callFrames, sourceCodeLocation, recordPayload.data.timerId)); - break; - } - } - - // Iterate over the records tree using a stack. Doing this recursively has - // been known to cause a call stack overflow. https://webkit.org/b/79106 - var stack = [{array: [originalRecordPayload], parent: null, index: 0}]; - while (stack.length) { - var entry = stack.lastValue; - var recordPayloads = entry.array; - var parentRecordPayload = entry.parent; - - if (entry.index < recordPayloads.length) { - var recordPayload = recordPayloads[entry.index]; - - processRecord.call(this, recordPayload, parentRecordPayload); - - if (recordPayload.children) - stack.push({array: recordPayload.children, parent: recordPayload, index: 0}); - ++entry.index; - } else - stack.pop(); - } - }, - - pageDidLoad: function(timestamp) - { - if (isNaN(WebInspector.frameResourceManager.mainFrame.loadEventTimestamp)) - WebInspector.frameResourceManager.mainFrame.markLoadEvent(timestamp); - }, - - // Private - - _callFramesFromPayload: function(payload) - { - if (!payload) - return null; - - function createCallFrame(payload) - { - var url = payload.url; - var nativeCode = false; - - if (url === "[native code]") { - nativeCode = true; - url = null; - } - - var sourceCode = WebInspector.frameResourceManager.resourceForURL(url); - if (!sourceCode) - sourceCode = WebInspector.debuggerManager.scriptsForURL(url)[0]; - - // The lineNumber is 1-based, but we expect 0-based. - var lineNumber = payload.lineNumber - 1; - - var sourceCodeLocation = sourceCode ? sourceCode.createSourceCodeLocation(lineNumber, payload.columnNumber) : null; - var functionName = payload.functionName !== "global code" ? payload.functionName : null; - - return new WebInspector.CallFrame(null, sourceCodeLocation, functionName, null, null, nativeCode); - } - - return payload.map(createCallFrame); - }, - - _addRecord: function(record) - { - this._recording.addRecord(record); - - // Only worry about dead time after the load event. - if (!isNaN(WebInspector.frameResourceManager.mainFrame.loadEventTimestamp)) - this._resetAutoRecordingDeadTimeTimeout(); - }, - - _startAutoRecording: function(event) - { - if (!event.target.isMainFrame() || (this._recordingEnabled && !this._autoRecordingMainResource)) - return false; - - var mainResource = event.target.provisionalMainResource || event.target.mainResource; - if (mainResource === this._autoRecordingMainResource) - return false; - - this.stopRecording(); - - this._autoRecordingMainResource = mainResource; - - this._recording.reset(); - - this.startRecording(); - - this._addRecord(new WebInspector.ResourceTimelineRecord(mainResource)); - - if (this._stopRecordingTimeout) - clearTimeout(this._stopRecordingTimeout); - this._stopRecordingTimeout = setTimeout(this.stopRecording.bind(this), WebInspector.TimelineManager.MaximumAutoRecordDuration); - - return true; - }, - - _stopAutoRecordingSoon: function() - { - // Only auto stop when auto recording. - if (!this._recordingEnabled || !this._autoRecordingMainResource) - return; - - if (this._stopRecordingTimeout) - clearTimeout(this._stopRecordingTimeout); - this._stopRecordingTimeout = setTimeout(this.stopRecording.bind(this), WebInspector.TimelineManager.MaximumAutoRecordDurationAfterLoadEvent); - }, - - _resetAutoRecordingDeadTimeTimeout: function() - { - // Only monitor dead time when auto recording. - if (!this._recordingEnabled || !this._autoRecordingMainResource) - return; - - if (this._deadTimeTimeout) - clearTimeout(this._deadTimeTimeout); - this._deadTimeTimeout = setTimeout(this.stopRecording.bind(this), WebInspector.TimelineManager.DeadTimeRequiredToStopAutoRecordingEarly); - }, - - _mainResourceDidChange: function(event) - { - // Ignore resource events when there isn't a main frame yet. Those events are triggered by - // loading the cached resources when the inspector opens, and they do not have timing information. - if (!WebInspector.frameResourceManager.mainFrame) - return; - - if (this._startAutoRecording(event)) - return; - - if (!this._recordingEnabled) - return; - - var mainResource = event.target.mainResource; - if (mainResource === this._autoRecordingMainResource) - return; - - this._addRecord(new WebInspector.ResourceTimelineRecord(mainResource)); - }, - - _resourceWasAdded: function(event) - { - // Ignore resource events when there isn't a main frame yet. Those events are triggered by - // loading the cached resources when the inspector opens, and they do not have timing information. - if (!WebInspector.frameResourceManager.mainFrame) - return; - - if (!this._recordingEnabled) - return; - - this._addRecord(new WebInspector.ResourceTimelineRecord(event.data.resource)); - } -}; - -WebInspector.TimelineManager.prototype.__proto__ = WebInspector.Object.prototype; |