Bug 1277985 - Decouple the CSSUsageFront from the CSSUsageActor; r=ejpbruel

This commit is contained in:
Nick Fitzgerald 2016-06-06 10:24:34 -07:00
Родитель 54b647837c
Коммит 5f718a1500
9 изменённых файлов: 192 добавлений и 147 удалений

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

@ -3,7 +3,7 @@
// Tests that the addon commands works as they should
const csscoverage = require("devtools/server/actors/csscoverage");
const csscoverage = require("devtools/shared/fronts/csscoverage");
const PAGE_1 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page1.html";
const PAGE_2 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page2.html";
@ -50,7 +50,7 @@ function* navigate(usage, options) {
*/
function* checkPages(usage) {
let expectedVisited = [ PAGE_3 ];
let actualVisited = yield usage._testOnly_visitedPages();
let actualVisited = yield usage._testOnlyVisitedPages();
isEqualJson(actualVisited, expectedVisited, "Visited");
}

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

@ -3,7 +3,7 @@
// Tests that the addon commands works as they should
const csscoverage = require("devtools/server/actors/csscoverage");
const csscoverage = require("devtools/shared/fronts/csscoverage");
const PAGE_1 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page1.html";
const PAGE_2 = TEST_BASE_HTTPS + "browser_cmd_csscoverage_page2.html";
@ -64,7 +64,7 @@ function* navigate(usage, options) {
function* checkPages(usage) {
// 'load' event order. '' is for the initial location
let expectedVisited = [ "", PAGE_2, PAGE_1, PAGE_3 ];
let actualVisited = yield usage._testOnly_visitedPages();
let actualVisited = yield usage._testOnlyVisitedPages();
isEqualJson(actualVisited, expectedVisited, "Visited");
}

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

@ -24,7 +24,7 @@ const {StyleSheetEditor} = Cu.import("resource://devtools/client/styleeditor/Sty
loader.lazyImporter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
const {PrefObserver, PREF_ORIG_SOURCES} =
require("devtools/client/styleeditor/utils");
const csscoverage = require("devtools/server/actors/csscoverage");
const csscoverage = require("devtools/shared/fronts/csscoverage");
const {console} = require("resource://gre/modules/Console.jsm");
const promise = require("promise");
const {ResponsiveUIManager} =

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

@ -11,14 +11,14 @@ const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
const events = require("sdk/event/core");
const protocol = require("devtools/shared/protocol");
const { method, custom, RetVal, Arg } = protocol;
const { custom } = protocol;
const { cssUsageSpec } = require("devtools/shared/specs/csscoverage");
loader.lazyGetter(this, "DOMUtils", () => {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
});
loader.lazyRequireGetter(this, "stylesheets", "devtools/server/actors/stylesheets");
loader.lazyRequireGetter(this, "CssLogic", "devtools/shared/inspector/css-logic", true);
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
const CSSRule = Ci.nsIDOMCSSRule;
@ -68,16 +68,7 @@ const l10n = exports.l10n = {
* }, ...
* });
*/
var CSSUsageActor = protocol.ActorClass({
typeName: "cssUsage",
events: {
"state-change" : {
type: "stateChange",
stateChange: Arg(0, "json")
}
},
var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
initialize: function (conn, tabActor) {
protocol.Actor.prototype.initialize.call(this, conn);
@ -107,7 +98,7 @@ var CSSUsageActor = protocol.ActorClass({
* why we don't want to do that (e.g. the page contains state that will be
* lost across a reload)
*/
start: method(function (noreload) {
start: function (noreload) {
if (this._running) {
throw new Error(l10n.lookup("csscoverageRunningError"));
}
@ -152,14 +143,12 @@ var CSSUsageActor = protocol.ActorClass({
}
events.emit(this, "state-change", { isRunning: true });
}, {
request: { url: Arg(0, "boolean") }
}),
},
/**
* Cease recording usage data
*/
stop: method(function () {
stop: function () {
if (!this._running) {
throw new Error(l10n.lookup("csscoverageNotRunningError"));
}
@ -169,20 +158,20 @@ var CSSUsageActor = protocol.ActorClass({
this._running = false;
events.emit(this, "state-change", { isRunning: false });
}),
},
/**
* Start/stop recording usage data depending on what we're currently doing.
*/
toggle: method(function () {
toggle: function () {
return this._running ? this.stop() : this.start();
}),
},
/**
* Running start() quickly followed by stop() does a bunch of unnecessary
* work, so this cuts all that out
*/
oneshot: method(function () {
oneshot: function () {
if (this._running) {
throw new Error(l10n.lookup("csscoverageRunningError"));
}
@ -193,7 +182,7 @@ var CSSUsageActor = protocol.ActorClass({
this._populateKnownRules(this._tabActor.window.document);
this._updateUsage(this._tabActor.window.document, false);
}),
},
/**
* Called by the ProgressListener to simulate a "load" event
@ -326,7 +315,7 @@ var CSSUsageActor = protocol.ActorClass({
* ...
* ]
*/
createEditorReport: method(function (url) {
createEditorReport: function (url) {
if (this._knownRules == null) {
return { reports: [] };
}
@ -351,10 +340,7 @@ var CSSUsageActor = protocol.ActorClass({
}
return { reports: reports };
}, {
request: { url: Arg(0, "string") },
response: { reports: RetVal("array:json") }
}),
},
/**
* Returns a JSONable structure designed for the page report which shows
@ -391,7 +377,7 @@ var CSSUsageActor = protocol.ActorClass({
* ]
* }
*/
createPageReport: method(function () {
createPageReport: function () {
if (this._running) {
throw new Error(l10n.lookup("csscoverageRunningError"));
}
@ -475,18 +461,14 @@ var CSSUsageActor = protocol.ActorClass({
preload: preload,
unused: unused
};
}, {
response: RetVal("json")
}),
},
/**
* For testing only. What pages did we visit.
*/
_testOnly_visitedPages: method(function () {
_testOnlyVisitedPages: function () {
return [...this._visitedPages];
}, {
response: { value: RetVal("array:string") }
}),
},
});
exports.CSSUsageActor = CSSUsageActor;
@ -732,109 +714,3 @@ const sheetToUrl = exports.sheetToUrl = function (stylesheet) {
throw new Error("Unknown sheet source");
};
/**
* Running more than one usage report at a time is probably bad for performance
* and it isn't particularly useful, and it's confusing from a notification POV
* so we only allow one.
*/
var isRunning = false;
var notification;
var target;
var chromeWindow;
/**
* Front for CSSUsageActor
*/
const CSSUsageFront = protocol.FrontClass(CSSUsageActor, {
initialize: function (client, form) {
protocol.Front.prototype.initialize.call(this, client, form);
this.actorID = form.cssUsageActor;
this.manage(this);
},
_onStateChange: protocol.preEvent("state-change", function (ev) {
isRunning = ev.isRunning;
ev.target = target;
if (isRunning) {
let gnb = chromeWindow.document.getElementById("global-notificationbox");
notification = gnb.getNotificationWithValue("csscoverage-running");
if (notification == null) {
let notifyStop = reason => {
if (reason == "removed") {
this.stop();
}
};
let msg = l10n.lookup("csscoverageRunningReply");
notification = gnb.appendNotification(msg, "csscoverage-running",
"", // i.e. no image
gnb.PRIORITY_INFO_HIGH,
null, // i.e. no buttons
notifyStop);
}
}
else {
if (notification) {
notification.remove();
notification = undefined;
}
gDevTools.showToolbox(target, "styleeditor");
target = undefined;
}
}),
/**
* Server-side start is above. Client-side start adds a notification box
*/
start: custom(function (newChromeWindow, newTarget, noreload = false) {
target = newTarget;
chromeWindow = newChromeWindow;
return this._start(noreload);
}, {
impl: "_start"
}),
/**
* Server-side start is above. Client-side start adds a notification box
*/
toggle: custom(function (newChromeWindow, newTarget) {
target = newTarget;
chromeWindow = newChromeWindow;
return this._toggle();
}, {
impl: "_toggle"
}),
/**
* We count STARTING and STOPPING as 'running'
*/
isRunning: function () {
return isRunning;
}
});
exports.CSSUsageFront = CSSUsageFront;
const knownFronts = new WeakMap();
/**
* Create a CSSUsageFront only when needed (returns a promise)
* For notes on target.makeRemote(), see
* https://bugzilla.mozilla.org/show_bug.cgi?id=1016330#c7
*/
const getUsage = exports.getUsage = function (target) {
return target.makeRemote().then(() => {
let front = knownFronts.get(target.client);
if (front == null && target.form.cssUsageActor != null) {
front = new CSSUsageFront(target.client, target.form);
knownFronts.set(target.client, front);
}
return front;
});
};

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

@ -0,0 +1,129 @@
/* 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 Services = require("Services");
const {cssUsageSpec} = require("devtools/shared/specs/csscoverage");
const protocol = require("devtools/shared/protocol");
const {custom} = protocol;
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
/**
* Allow: let foo = l10n.lookup("csscoverageFoo");
*/
const l10n = exports.l10n = {
_URI: "chrome://devtools-shared/locale/csscoverage.properties",
lookup: function (msg) {
if (this._stringBundle == null) {
this._stringBundle = Services.strings.createBundle(this._URI);
}
return this._stringBundle.GetStringFromName(msg);
}
};
/**
* Running more than one usage report at a time is probably bad for performance
* and it isn't particularly useful, and it's confusing from a notification POV
* so we only allow one.
*/
var isRunning = false;
var notification;
var target;
var chromeWindow;
/**
* Front for CSSUsageActor
*/
const CSSUsageFront = protocol.FrontClassWithSpec(cssUsageSpec, {
initialize: function (client, form) {
protocol.Front.prototype.initialize.call(this, client, form);
this.actorID = form.cssUsageActor;
this.manage(this);
},
_onStateChange: protocol.preEvent("state-change", function (ev) {
isRunning = ev.isRunning;
ev.target = target;
if (isRunning) {
let gnb = chromeWindow.document.getElementById("global-notificationbox");
notification = gnb.getNotificationWithValue("csscoverage-running");
if (notification == null) {
let notifyStop = reason => {
if (reason == "removed") {
this.stop();
}
};
let msg = l10n.lookup("csscoverageRunningReply");
notification = gnb.appendNotification(msg, "csscoverage-running",
"",
gnb.PRIORITY_INFO_HIGH,
null,
notifyStop);
}
} else {
if (notification) {
notification.remove();
notification = undefined;
}
gDevTools.showToolbox(target, "styleeditor");
target = undefined;
}
}),
/**
* Server-side start is above. Client-side start adds a notification box
*/
start: custom(function (newChromeWindow, newTarget, noreload = false) {
target = newTarget;
chromeWindow = newChromeWindow;
return this._start(noreload);
}, {
impl: "_start"
}),
/**
* Server-side start is above. Client-side start adds a notification box
*/
toggle: custom(function (newChromeWindow, newTarget) {
target = newTarget;
chromeWindow = newChromeWindow;
return this._toggle();
}, {
impl: "_toggle"
}),
/**
* We count STARTING and STOPPING as 'running'
*/
isRunning: function () {
return isRunning;
}
});
exports.CSSUsageFront = CSSUsageFront;
const knownFronts = new WeakMap();
/**
* Create a CSSUsageFront only when needed (returns a promise)
* For notes on target.makeRemote(), see
* https://bugzilla.mozilla.org/show_bug.cgi?id=1016330#c7
*/
exports.getUsage = function (trgt) {
return trgt.makeRemote().then(() => {
let front = knownFronts.get(trgt.client);
if (front == null && trgt.form.cssUsageActor != null) {
front = new CSSUsageFront(trgt.client, trgt.form);
knownFronts.set(trgt.client, front);
}
return front;
});
};

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

@ -11,6 +11,7 @@ DevToolsModules(
'call-watcher.js',
'canvas.js',
'css-properties.js',
'csscoverage.js',
'highlighters.js',
'inspector.js',
'preference.js',

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

@ -7,7 +7,7 @@
const { Cc, Ci } = require("chrome");
const domtemplate = require("gcli/util/domtemplate");
const csscoverage = require("devtools/server/actors/csscoverage");
const csscoverage = require("devtools/shared/fronts/csscoverage");
const l10n = csscoverage.l10n;
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);

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

@ -0,0 +1,38 @@
/* 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 {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol");
const cssUsageSpec = generateActorSpec({
typeName: "cssUsage",
events: {
"state-change": {
type: "stateChange",
stateChange: Arg(0, "json")
}
},
methods: {
start: {
request: { url: Arg(0, "boolean") }
},
stop: {},
toggle: {},
oneshot: {},
createEditorReport: {
request: { url: Arg(0, "string") },
response: { reports: RetVal("array:json") }
},
createPageReport: {
response: RetVal("json")
},
_testOnlyVisitedPages: {
response: { value: RetVal("array:string") }
},
},
});
exports.cssUsageSpec = cssUsageSpec;

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

@ -12,6 +12,7 @@ DevToolsModules(
'call-watcher.js',
'canvas.js',
'css-properties.js',
'csscoverage.js',
'environment.js',
'frame.js',
'heap-snapshot-file.js',