From 6c318fe2b89a03634fd1952f0ae6b6e0f6b8e8d1 Mon Sep 17 00:00:00 2001 From: Jordan Santell Date: Mon, 8 Jun 2015 19:44:27 -0700 Subject: [PATCH] Bug 1172183 - Pull out the implementation of FramerateActor so that it can be consumed by other actors. r=vp --- .../devtools/server/actors/actor-registry.js | 3 +- toolkit/devtools/server/actors/framerate.js | 101 +++--------------- toolkit/devtools/server/actors/memory.js | 36 +++---- .../server/actors/utils/actor-utils.js | 24 +++++ toolkit/devtools/server/moz.build | 1 + toolkit/devtools/shared/framerate.js | 98 +++++++++++++++++ toolkit/devtools/shared/moz.build | 1 + 7 files changed, 154 insertions(+), 110 deletions(-) create mode 100644 toolkit/devtools/server/actors/utils/actor-utils.js create mode 100644 toolkit/devtools/shared/framerate.js diff --git a/toolkit/devtools/server/actors/actor-registry.js b/toolkit/devtools/server/actors/actor-registry.js index 4af0c353310a..94b3ecf5278a 100644 --- a/toolkit/devtools/server/actors/actor-registry.js +++ b/toolkit/devtools/server/actors/actor-registry.js @@ -11,8 +11,7 @@ const { Cu, CC, components } = require("chrome"); const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {}); const Services = require("Services"); const { DebuggerServer } = require("devtools/server/main"); -const ActorRegistryUtils = require("devtools/server/actors/utils/actor-registry-utils"); -const { registerActor, unregisterActor } = ActorRegistryUtils; +const { registerActor, unregisterActor } = require("devtools/server/actors/utils/actor-registry-utils"); loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); diff --git a/toolkit/devtools/server/actors/framerate.js b/toolkit/devtools/server/actors/framerate.js index 6d5b08e033c9..e5c828b27b85 100644 --- a/toolkit/devtools/server/actors/framerate.js +++ b/toolkit/devtools/server/actors/framerate.js @@ -3,59 +3,32 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; -const {Cc, Ci, Cu, Cr} = require("chrome"); -const Services = require("Services"); -const events = require("sdk/event/core"); const protocol = require("devtools/server/protocol"); -const DevToolsUtils = require("devtools/toolkit/DevToolsUtils.js"); - -const {on, once, off, emit} = events; -const {method, custom, Arg, Option, RetVal} = protocol; +const { actorBridge } = require("devtools/server/actors/utils/actor-utils"); +const { method, custom, Arg, Option, RetVal } = protocol; +const { on, once, off, emit } = require("sdk/event/core"); +const { Framerate } = require("devtools/toolkit/shared/framerate"); /** - * A very simple utility for monitoring framerate. + * An actor wrapper around Framerate. Uses exposed + * methods via bridge and provides RDP definitions. + * + * @see toolkit/devtools/shared/framerate.js for documentation. */ let FramerateActor = exports.FramerateActor = protocol.ActorClass({ typeName: "framerate", - initialize: function(conn, tabActor) { + initialize: function (conn, tabActor) { protocol.Actor.prototype.initialize.call(this, conn); - this.tabActor = tabActor; - this._contentWin = tabActor.window; - this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this); - this._onGlobalCreated = this._onGlobalCreated.bind(this); - on(this.tabActor, "window-ready", this._onGlobalCreated); + this.bridge = new Framerate(tabActor); }, destroy: function(conn) { - off(this.tabActor, "window-ready", this._onGlobalCreated); protocol.Actor.prototype.destroy.call(this, conn); - this.stopRecording(); + this.bridge.destroy(); }, - /** - * Starts monitoring framerate, storing the frames per second. - */ - startRecording: method(function() { - if (this._recording) { - return; - } - this._recording = true; - this._ticks = []; - this._startTime = this.tabActor.docShell.now(); - this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); - }, { - }), + startRecording: actorBridge("startRecording", {}), - /** - * Stops monitoring framerate, returning the recorded values. - */ - stopRecording: method(function(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) { - if (!this._recording) { - return []; - } - let ticks = this.getPendingTicks(beginAt, endAt); - this.cancelRecording(); - return ticks; - }, { + stopRecording: actorBridge("stopRecording", { request: { beginAt: Arg(0, "nullable:number"), endAt: Arg(1, "nullable:number") @@ -63,61 +36,19 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({ response: { ticks: RetVal("array:number") } }), - /** - * Stops monitoring framerate, without returning the recorded values. - */ - cancelRecording: method(function() { - this._contentWin.cancelAnimationFrame(this._rafID); - this._recording = false; - this._ticks = null; - this._rafID = -1; - }, { - }), + cancelRecording: actorBridge("cancelRecording"), - /** - * Returns whether this actor is currently active. - */ - isRecording: method(function() { - return !!this._recording; - }, { + isRecording: actorBridge("isRecording", { response: { recording: RetVal("boolean") } }), - /** - * Gets the refresh driver ticks recorded so far. - */ - getPendingTicks: method(function(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) { - if (!this._ticks) { - return []; - } - return this._ticks.filter(e => e >= beginAt && e <= endAt); - }, { + getPendingTicks: actorBridge("getPendingTicks", { request: { beginAt: Arg(0, "nullable:number"), endAt: Arg(1, "nullable:number") }, response: { ticks: RetVal("array:number") } }), - - /** - * Function invoked along with the refresh driver. - */ - _onRefreshDriverTick: function() { - if (!this._recording) { - return; - } - this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); - this._ticks.push(this.tabActor.docShell.now() - this._startTime); - }, - - /** - * When the content window for the tab actor is created. - */ - _onGlobalCreated: function (win) { - if (this._recording) { - this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); - } - } }); /** diff --git a/toolkit/devtools/server/actors/memory.js b/toolkit/devtools/server/actors/memory.js index d60bf1747ddf..95a7b21623ee 100644 --- a/toolkit/devtools/server/actors/memory.js +++ b/toolkit/devtools/server/actors/memory.js @@ -7,21 +7,11 @@ const protocol = require("devtools/server/protocol"); const { method, RetVal, Arg, types } = protocol; const { MemoryBridge } = require("./utils/memory-bridge"); +const { actorBridge } = require("./utils/actor-utils"); loader.lazyRequireGetter(this, "events", "sdk/event/core"); loader.lazyRequireGetter(this, "StackFrameCache", "devtools/server/actors/utils/stack", true); -/** - * Proxies a call to the MemoryActor to the underlying MemoryBridge, - * allowing access to MemoryBridge features by defining the RDP - * request/response signature. - */ -function linkBridge (methodName, definition) { - return method(function () { - return this.bridge[methodName].apply(this.bridge, arguments); - }, definition); -} - types.addDictType("AllocationsRecordingOptions", { // The probability we sample any given allocation when recording // allocations. Must be between 0.0 and 1.0. Defaults to 1.0, or sampling @@ -79,7 +69,7 @@ let MemoryActor = protocol.ActorClass({ * recording allocations or take a census of the heap. In addition, the * MemoryActor will start emitting GC events. */ - attach: linkBridge("attach", { + attach: actorBridge("attach", { request: {}, response: { type: "attached" @@ -89,7 +79,7 @@ let MemoryActor = protocol.ActorClass({ /** * Detach from this MemoryActor. */ - detach: linkBridge("detach", { + detach: actorBridge("detach", { request: {}, response: { type: "detached" @@ -99,7 +89,7 @@ let MemoryActor = protocol.ActorClass({ /** * Gets the current MemoryActor attach/detach state. */ - getState: linkBridge("getState", { + getState: actorBridge("getState", { response: { state: RetVal(0, "string") } @@ -109,7 +99,7 @@ let MemoryActor = protocol.ActorClass({ * Take a census of the heap. See js/src/doc/Debugger/Debugger.Memory.md for * more information. */ - takeCensus: linkBridge("takeCensus", { + takeCensus: actorBridge("takeCensus", { request: {}, response: RetVal("json") }), @@ -120,7 +110,7 @@ let MemoryActor = protocol.ActorClass({ * @param AllocationsRecordingOptions options * See the protocol.js definition of AllocationsRecordingOptions above. */ - startRecordingAllocations: linkBridge("startRecordingAllocations", { + startRecordingAllocations: actorBridge("startRecordingAllocations", { request: { options: Arg(0, "nullable:AllocationsRecordingOptions") }, @@ -133,7 +123,7 @@ let MemoryActor = protocol.ActorClass({ /** * Stop recording allocation sites. */ - stopRecordingAllocations: linkBridge("stopRecordingAllocations", { + stopRecordingAllocations: actorBridge("stopRecordingAllocations", { request: {}, response: { // Accept `nullable` in the case of server Gecko <= 37, handled on the front @@ -145,14 +135,14 @@ let MemoryActor = protocol.ActorClass({ * Return settings used in `startRecordingAllocations` for `probability` * and `maxLogLength`. Currently only uses in tests. */ - getAllocationsSettings: linkBridge("getAllocationsSettings", { + getAllocationsSettings: actorBridge("getAllocationsSettings", { request: {}, response: { options: RetVal(0, "json") } }), - getAllocations: linkBridge("getAllocations", { + getAllocations: actorBridge("getAllocations", { request: {}, response: RetVal("json") }), @@ -160,7 +150,7 @@ let MemoryActor = protocol.ActorClass({ /* * Force a browser-wide GC. */ - forceGarbageCollection: linkBridge("forceGarbageCollection", { + forceGarbageCollection: actorBridge("forceGarbageCollection", { request: {}, response: {} }), @@ -170,7 +160,7 @@ let MemoryActor = protocol.ActorClass({ * collection, see * https://developer.mozilla.org/en-US/docs/Interfacing_with_the_XPCOM_cycle_collector#What_the_cycle_collector_does */ - forceCycleCollection: linkBridge("forceCycleCollection", { + forceCycleCollection: actorBridge("forceCycleCollection", { request: {}, response: {} }), @@ -181,12 +171,12 @@ let MemoryActor = protocol.ActorClass({ * * @returns object */ - measure: linkBridge("measure", { + measure: actorBridge("measure", { request: {}, response: RetVal("json"), }), - residentUnique: linkBridge("residentUnique", { + residentUnique: actorBridge("residentUnique", { request: {}, response: { value: RetVal("number") } }), diff --git a/toolkit/devtools/server/actors/utils/actor-utils.js b/toolkit/devtools/server/actors/utils/actor-utils.js new file mode 100644 index 000000000000..e231757b2f6d --- /dev/null +++ b/toolkit/devtools/server/actors/utils/actor-utils.js @@ -0,0 +1,24 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* 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 { method } = require("devtools/server/protocol"); + +/** + * Proxies a call from an actor to an underlying module, stored + * as `bridge` on the actor. This allows a module to be defined in one + * place, usable by other modules/actors on the server, but a separate + * module defining the actor/RDP definition. + * + * @see Framerate implementation: toolkit/devtools/shared/framerate.js + * @see Framerate actor definition: toolkit/devtools/server/actors/framerate.js + */ +exports.actorBridge = function actorBridge (methodName, definition={}) { + return method(function () { + return this.bridge[methodName].apply(this.bridge, arguments); + }, definition); +} diff --git a/toolkit/devtools/server/moz.build b/toolkit/devtools/server/moz.build index be7bb2f520eb..cbf3d4b2ed21 100644 --- a/toolkit/devtools/server/moz.build +++ b/toolkit/devtools/server/moz.build @@ -98,6 +98,7 @@ EXTRA_JS_MODULES.devtools.server.actors += [ EXTRA_JS_MODULES.devtools.server.actors.utils += [ 'actors/utils/actor-registry-utils.js', + 'actors/utils/actor-utils.js', 'actors/utils/audionodes.json', 'actors/utils/automation-timeline.js', 'actors/utils/make-debugger.js', diff --git a/toolkit/devtools/shared/framerate.js b/toolkit/devtools/shared/framerate.js new file mode 100644 index 000000000000..3d4fa1ecb7f4 --- /dev/null +++ b/toolkit/devtools/shared/framerate.js @@ -0,0 +1,98 @@ +/* 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 { on, once, off, emit } = require("sdk/event/core"); +const { Class } = require("sdk/core/heritage"); + +/** + * A very simple utility for monitoring framerate. Takes a `tabActor` + * and monitors framerate over time. The actor wrapper around this + * can be found at toolkit/devtools/server/actors/framerate.js + */ +let Framerate = exports.Framerate = Class({ + initialize: function (tabActor) { + this.tabActor = tabActor; + this._contentWin = tabActor.window; + this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this); + this._onGlobalCreated = this._onGlobalCreated.bind(this); + on(this.tabActor, "window-ready", this._onGlobalCreated); + }, + destroy: function(conn) { + off(this.tabActor, "window-ready", this._onGlobalCreated); + this.stopRecording(); + }, + + /** + * Starts monitoring framerate, storing the frames per second. + */ + startRecording: function () { + if (this._recording) { + return; + } + this._recording = true; + this._ticks = []; + this._startTime = this.tabActor.docShell.now(); + this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); + }, + + /** + * Stops monitoring framerate, returning the recorded values. + */ + stopRecording: function (beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) { + if (!this._recording) { + return []; + } + let ticks = this.getPendingTicks(beginAt, endAt); + this.cancelRecording(); + return ticks; + }, + + /** + * Stops monitoring framerate, without returning the recorded values. + */ + cancelRecording: function () { + this._contentWin.cancelAnimationFrame(this._rafID); + this._recording = false; + this._ticks = null; + this._rafID = -1; + }, + + /** + * Returns whether this instance is currently recording. + */ + isRecording: function () { + return !!this._recording; + }, + + /** + * Gets the refresh driver ticks recorded so far. + */ + getPendingTicks: function (beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) { + if (!this._ticks) { + return []; + } + return this._ticks.filter(e => e >= beginAt && e <= endAt); + }, + + /** + * Function invoked along with the refresh driver. + */ + _onRefreshDriverTick: function () { + if (!this._recording) { + return; + } + this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); + this._ticks.push(this.tabActor.docShell.now() - this._startTime); + }, + + /** + * When the content window for the tab actor is created. + */ + _onGlobalCreated: function (win) { + if (this._recording) { + this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick); + } + } +}); diff --git a/toolkit/devtools/shared/moz.build b/toolkit/devtools/shared/moz.build index 0a612d77b06f..6eb5aefdb8f1 100644 --- a/toolkit/devtools/shared/moz.build +++ b/toolkit/devtools/shared/moz.build @@ -8,6 +8,7 @@ BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini'] EXTRA_JS_MODULES.devtools.shared += [ 'async-storage.js', + 'framerate.js', 'worker-helper.js', 'worker.js' ]