Bug 1172183 - Pull out the implementation of FramerateActor so that it can be consumed by other actors. r=vp

This commit is contained in:
Jordan Santell 2015-06-08 19:44:27 -07:00
Родитель 772f325a61
Коммит 6c318fe2b8
7 изменённых файлов: 154 добавлений и 110 удалений

Просмотреть файл

@ -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");

Просмотреть файл

@ -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);
}
}
});
/**

Просмотреть файл

@ -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") }
}),

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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',

Просмотреть файл

@ -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);
}
}
});

Просмотреть файл

@ -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'
]