/* * 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.ProfileManager = function() { WebInspector.Object.call(this); this._javaScriptProfileType = new WebInspector.JavaScriptProfileType; this._canvasProfileType = new WebInspector.CanvasProfileType; if (window.ProfilerAgent) { ProfilerAgent.enable(); ProfilerAgent.getProfileHeaders(); } WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this); this.initialize(); }; WebInspector.ProfileManager.Event = { ProfileWasAdded: "profile-manager-profile-was-added", ProfileWasUpdated: "profile-manager-profile-was-updated", ProfilingStarted: "profile-manager-profiling-started", ProfilingEnded: "profile-manager-profiling-ended", ProfilingInterrupted: "profile-manager-profiling-interrupted", Cleared: "profile-manager-cleared" }; WebInspector.ProfileManager.UserInitiatedProfileName = "org.webkit.profiles.user-initiated"; WebInspector.ProfileManager.prototype = { constructor: WebInspector.ProfileManager, // Public initialize: function() { this._checkForInterruptions(); this._recordingJavaScriptProfile = null; this._recordingCanvasProfile = null; this._isProfiling = false; this.dispatchEventToListeners(WebInspector.ProfileManager.Event.Cleared); }, isProfilingJavaScript: function() { return this._javaScriptProfileType.isRecordingProfile(); }, startProfilingJavaScript: function() { this._javaScriptProfileType.startRecordingProfile(); }, stopProfilingJavaScript: function() { this._javaScriptProfileType.stopRecordingProfile(); }, isProfilingCanvas: function() { return this._canvasProfileType.isRecordingProfile(); }, startProfilingCanvas: function() { this._canvasProfileType.startRecordingProfile(); var id = this._canvasProfileType.nextProfileId(); this._recordingCanvasProfile = new WebInspector.CanvasProfileObject(WebInspector.UIString("Canvas Profile %d").format(id), id, true); this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfileWasAdded, {profile: this._recordingCanvasProfile}); this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfilingStarted); }, stopProfilingCanvas: function() { function canvasProfilingStopped(error, profile) { if (error) return; console.assert(this._recordingCanvasProfile); this._recordingCanvasProfile.data = profile.data; this._recordingCanvasProfile.recording = false; this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfileWasUpdated, {profile: this._recordingCanvasProfile}); this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfilingEnded, {profile: this._recordingCanvasProfile}); this._recordingCanvasProfile = null; } this._canvasProfileType.stopRecordingProfile(canvasProfilingStopped.bind(this)); }, profileWasStartedFromConsole: function(title) { this.setRecordingJavaScriptProfile(true, true); if (title.indexOf(WebInspector.ProfileManager.UserInitiatedProfileName) === -1) { this._recordingJavaScriptProfile.title = title; this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfileWasUpdated, {profile: this._recordingJavaScriptProfile}); } }, profileWasEndedFromConsole: function() { this.setRecordingJavaScriptProfile(false, true); }, addJavaScriptProfile: function(profile) { console.assert(this._recordingJavaScriptProfile); if (!this._recordingJavaScriptProfile) return; this._recordingJavaScriptProfile.type = profile.typeId; this._recordingJavaScriptProfile.title = profile.title; this._recordingJavaScriptProfile.id = profile.uid; this._recordingJavaScriptProfile.recording = false; this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfileWasUpdated, {profile: this._recordingJavaScriptProfile}); // We want to reset _recordingJavaScriptProfile so that we can identify // interruptions, but we also want to keep track of the last profile // we've recorded so that we can provide it as data to the ProfilingEnded event // we'll dispatch in setRecordingJavaScriptProfile(). this._lastJavaScriptProfileAdded = this._recordingJavaScriptProfile; this._recordingJavaScriptProfile = null; }, setRecordingJavaScriptProfile: function(isProfiling, fromConsole) { if (this._isProfiling === isProfiling) return; this._isProfiling = isProfiling; // We've interrupted the current JS profile due to a page reload. Return // now and _attemptToResumeProfiling will pick things up after the reload. if (!isProfiling && !!this._recordingJavaScriptProfile) return; if (isProfiling && !this._recordingJavaScriptProfile) this._recordingJavaScriptProfile = new WebInspector.JavaScriptProfileObject(WebInspector.ProfileManager.UserInitiatedProfileName, -1, true); if (isProfiling) { this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfileWasAdded, {profile: this._recordingJavaScriptProfile}); if (!fromConsole) this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfilingStarted); } else { this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfilingEnded, { profile: this._lastJavaScriptProfileAdded, fromConsole: fromConsole }); this._lastJavaScriptProfileAdded = null; } }, // Private _mainResourceDidChange: function(event) { console.assert(event.target instanceof WebInspector.Frame); if (!event.target.isMainFrame()) return; var oldMainResource = event.data.oldMainResource; var newMainResource = event.target.mainResource; if (oldMainResource.url !== newMainResource.url) this.initialize(); else this._attemptToResumeProfiling(); }, _checkForInterruptions: function() { if (this._recordingJavaScriptProfile) { this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfilingInterrupted, {profile: this._recordingJavaScriptProfile}); this._javaScriptProfileType.setRecordingProfile(false); } else if (this._recordingCanvasProfile) { this.dispatchEventToListeners(WebInspector.ProfileManager.Event.ProfilingInterrupted, {profile: this._recordingCanvasProfile}); this._canvasProfileType.setRecordingProfile(false); } }, _attemptToResumeProfiling: function() { this._checkForInterruptions(); if (this._recordingJavaScriptProfile) this.startProfilingJavaScript(); else if (this._recordingCanvasProfile) this.startProfilingCanvas(); } }; WebInspector.ProfileManager.prototype.__proto__ = WebInspector.Object.prototype;