diff options
Diffstat (limited to 'devtools/server/actors/performance.js')
-rw-r--r-- | devtools/server/actors/performance.js | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/devtools/server/actors/performance.js b/devtools/server/actors/performance.js new file mode 100644 index 000000000..8b294a4de --- /dev/null +++ b/devtools/server/actors/performance.js @@ -0,0 +1,116 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { Cu } = require("chrome"); +const { Task } = require("devtools/shared/task"); +const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol"); +const { actorBridgeWithSpec } = require("devtools/server/actors/common"); +const { performanceSpec } = require("devtools/shared/specs/performance"); + +loader.lazyRequireGetter(this, "events", "sdk/event/core"); +loader.lazyRequireGetter(this, "extend", "sdk/util/object", true); + +loader.lazyRequireGetter(this, "PerformanceRecorder", + "devtools/server/performance/recorder", true); +loader.lazyRequireGetter(this, "normalizePerformanceFeatures", + "devtools/shared/performance/recording-utils", true); + +const PIPE_TO_FRONT_EVENTS = new Set([ + "recording-started", "recording-stopping", "recording-stopped", + "profiler-status", "timeline-data", "console-profile-start" +]); + +const RECORDING_STATE_CHANGE_EVENTS = new Set([ + "recording-started", "recording-stopping", "recording-stopped" +]); + +/** + * This actor wraps the Performance module at devtools/shared/shared/performance.js + * and provides RDP definitions. + * + * @see devtools/shared/shared/performance.js for documentation. + */ +var PerformanceActor = ActorClassWithSpec(performanceSpec, { + traits: { + features: { + withMarkers: true, + withTicks: true, + withMemory: true, + withFrames: true, + withGCEvents: true, + withDocLoadingEvents: true, + withAllocations: true, + }, + }, + + initialize: function (conn, tabActor) { + Actor.prototype.initialize.call(this, conn); + this._onRecorderEvent = this._onRecorderEvent.bind(this); + this.bridge = new PerformanceRecorder(conn, tabActor); + events.on(this.bridge, "*", this._onRecorderEvent); + }, + + /** + * `disconnect` method required to call destroy, since this + * actor is not managed by a parent actor. + */ + disconnect: function () { + this.destroy(); + }, + + destroy: function () { + events.off(this.bridge, "*", this._onRecorderEvent); + this.bridge.destroy(); + Actor.prototype.destroy.call(this); + }, + + connect: function (config) { + this.bridge.connect({ systemClient: config.systemClient }); + return { traits: this.traits }; + }, + + canCurrentlyRecord: function () { + return this.bridge.canCurrentlyRecord(); + }, + + startRecording: Task.async(function* (options = {}) { + if (!this.bridge.canCurrentlyRecord().success) { + return null; + } + + let normalizedOptions = normalizePerformanceFeatures(options, this.traits.features); + let recording = yield this.bridge.startRecording(normalizedOptions); + this.manage(recording); + + return recording; + }), + + stopRecording: actorBridgeWithSpec("stopRecording"), + isRecording: actorBridgeWithSpec("isRecording"), + getRecordings: actorBridgeWithSpec("getRecordings"), + getConfiguration: actorBridgeWithSpec("getConfiguration"), + setProfilerStatusInterval: actorBridgeWithSpec("setProfilerStatusInterval"), + + /** + * Filter which events get piped to the front. + */ + _onRecorderEvent: function (eventName, ...data) { + // If this is a recording state change, call + // a method on the related PerformanceRecordingActor so it can + // update its internal state. + if (RECORDING_STATE_CHANGE_EVENTS.has(eventName)) { + let recording = data[0]; + let extraData = data[1]; + recording._setState(eventName, extraData); + } + + if (PIPE_TO_FRONT_EVENTS.has(eventName)) { + events.emit(this, eventName, ...data); + } + }, +}); + +exports.PerformanceActor = PerformanceActor; |