Bug 1016330 - (Part 1) Make CSS Coverage work with B2G; r=paul

https://bugzilla.mozilla.org/show_bug.cgi?id=1016330#c3
> prettifyCSS needs to be used client side or moved at the toolkit level.
Done

https://bugzilla.mozilla.org/show_bug.cgi?id=1016330#c4
> Move the call to makeRemote to DeveloperToolbar.jsm
Not done. See https://bugzilla.mozilla.org/show_bug.cgi?id=1016330#c6

https://bugzilla.mozilla.org/show_bug.cgi?id=1016330#c5
> We need to test first there's a cssusage actor.
> A toolbox might be debugging gecko < 32.
Done

https://bugzilla.mozilla.org/show_bug.cgi?id=1016330#c2
> Kill reference to this._tabActor.browser. This might create issues
> with sub documents ("load" is sent to browser even for inner documents.
> It's not the case with tabActor.window).
Future work.
This commit is contained in:
Joe Walker 2014-06-08 22:33:36 +01:00
parent 35b319cccd
commit f9d16c16c0
7 changed files with 93 additions and 73 deletions

View File

@ -265,6 +265,9 @@ const NOTIFICATIONS = {
*/
DeveloperToolbar.prototype.NOTIFICATIONS = NOTIFICATIONS;
/**
* target is dynamic because the selectedTab changes
*/
Object.defineProperty(DeveloperToolbar.prototype, "target", {
get: function() {
return TargetFactory.forTab(this._chromeWindow.getBrowser().selectedTab);

View File

@ -490,6 +490,10 @@ StyleEditorUI.prototype = {
// Is there any CSS coverage markup to include?
csscoverage.getUsage(this._target).then(usage => {
if (usage == null) {
return;
}
let href = editor.styleSheet.href || editor.styleSheet.nodeHref;
usage.createEditorReport(href).then(data => {
editor.removeAllUnusedRegions();

View File

@ -226,7 +226,7 @@ StyleSheetEditor.prototype = {
fetchSource: function(callback) {
return this.styleSheet.getText().then((longStr) => {
longStr.string().then((source) => {
this._state.text = prettifyCSS(source);
this._state.text = CssLogic.prettifyCSS(source);
this.sourceLoaded = true;
if (callback) {
@ -640,73 +640,6 @@ StyleSheetEditor.prototype = {
}
}
const TAB_CHARS = "\t";
const CURRENT_OS = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
const LINE_SEPARATOR = CURRENT_OS === "WINNT" ? "\r\n" : "\n";
/**
* Prettify minified CSS text.
* This prettifies CSS code where there is no indentation in usual places while
* keeping original indentation as-is elsewhere.
*
* @param string text
* The CSS source to prettify.
* @return string
* Prettified CSS source
*/
function prettifyCSS(text)
{
// remove initial and terminating HTML comments and surrounding whitespace
text = text.replace(/(?:^\s*<!--[\r\n]*)|(?:\s*-->\s*$)/g, "");
let parts = []; // indented parts
let partStart = 0; // start offset of currently parsed part
let indent = "";
let indentLevel = 0;
for (let i = 0; i < text.length; i++) {
let c = text[i];
let shouldIndent = false;
switch (c) {
case "}":
if (i - partStart > 1) {
// there's more than just } on the line, add line
parts.push(indent + text.substring(partStart, i));
partStart = i;
}
indent = TAB_CHARS.repeat(--indentLevel);
/* fallthrough */
case ";":
case "{":
shouldIndent = true;
break;
}
if (shouldIndent) {
let la = text[i+1]; // one-character lookahead
if (!/\n/.test(la) || /^\s+$/.test(text.substring(i+1, text.length))) {
// following character should be a new line, but isn't,
// or it's whitespace at the end of the file
parts.push(indent + text.substring(partStart, i + 1));
if (c == "}") {
parts.push(""); // for extra line separator
}
partStart = i + 1;
} else {
return text; // assume it is not minified, early exit
}
}
if (c == "{") {
indent = TAB_CHARS.repeat(++indentLevel);
}
}
return parts.join(LINE_SEPARATOR);
}
/**
* Find a path on disk for a file given it's hosted uri, the uri of the
* original resource that generated it (e.g. Sass file), and the location of the

View File

@ -32,6 +32,9 @@ exports.items = [
description: l10n.lookup("csscoverageStartDesc"),
exec: function*(args, context) {
let usage = yield csscoverage.getUsage(context.environment.target);
if (usage == null) {
throw new Error(l10n.lookup("csscoverageNoRemoteError"));
}
yield usage.start(context.environment.chromeWindow,
context.environment.target);
}
@ -43,6 +46,9 @@ exports.items = [
exec: function*(args, context) {
let target = context.environment.target;
let usage = yield csscoverage.getUsage(target);
if (usage == null) {
throw new Error(l10n.lookup("csscoverageNoRemoteError"));
}
yield usage.stop();
yield gDevTools.showToolbox(target, "styleeditor");
}
@ -54,6 +60,9 @@ exports.items = [
exec: function*(args, context) {
let target = context.environment.target;
let usage = yield csscoverage.getUsage(target);
if (usage == null) {
throw new Error(l10n.lookup("csscoverageNoRemoteError"));
}
yield usage.oneshot();
yield gDevTools.showToolbox(target, "styleeditor");
}
@ -65,6 +74,9 @@ exports.items = [
exec: function*(args, context) {
let target = context.environment.target;
let usage = yield csscoverage.getUsage(target);
if (usage == null) {
throw new Error(l10n.lookup("csscoverageNoRemoteError"));
}
let running = yield usage.toggle();
if (running) {
@ -81,6 +93,10 @@ exports.items = [
description: l10n.lookup("csscoverageReportDesc"),
exec: function*(args, context) {
let usage = yield csscoverage.getUsage(context.environment.target);
if (usage == null) {
throw new Error(l10n.lookup("csscoverageNoRemoteError"));
}
return {
isTypedData: true,
type: "csscoveragePageReport",

View File

@ -21,9 +21,6 @@ loader.lazyGetter(this, "gDevTools", () => {
loader.lazyGetter(this, "DOMUtils", () => {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils)
});
loader.lazyGetter(this, "prettifyCSS", () => {
return require("resource:///modules/devtools/StyleSheetEditor.jsm").prettifyCSS;
});
const CSSRule = Ci.nsIDOMCSSRule;
@ -367,7 +364,7 @@ let UsageReportActor = protocol.ActorClass({
shortUrl: rule.url.split("/").slice(-1),
start: { line: rule.line, column: rule.column },
selectorText: ruleData.selectorText,
formattedCssText: prettifyCSS(ruleData.cssText)
formattedCssText: CssLogic.prettifyCSS(ruleData.cssText)
};
}
@ -757,11 +754,13 @@ const knownFronts = new WeakMap();
/**
* Create a UsageReportFront 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) {
if (front == null && target.form.usageReportActor != null) {
front = new UsageReportFront(target.client, target.form);
knownFronts.set(target.client, front);
}

View File

@ -928,6 +928,70 @@ CssLogic.findCssSelector = function CssLogic_findCssSelector(ele) {
return selector;
};
const TAB_CHARS = "\t";
/**
* Prettify minified CSS text.
* This prettifies CSS code where there is no indentation in usual places while
* keeping original indentation as-is elsewhere.
* @param string text The CSS source to prettify.
* @return string Prettified CSS source
*/
CssLogic.prettifyCSS = function(text) {
if (CssLogic.LINE_SEPARATOR == null) {
let os = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
CssLogic.LINE_SEPARATOR = (os === "WINNT" ? "\r\n" : "\n");
}
// remove initial and terminating HTML comments and surrounding whitespace
text = text.replace(/(?:^\s*<!--[\r\n]*)|(?:\s*-->\s*$)/g, "");
let parts = []; // indented parts
let partStart = 0; // start offset of currently parsed part
let indent = "";
let indentLevel = 0;
for (let i = 0; i < text.length; i++) {
let c = text[i];
let shouldIndent = false;
switch (c) {
case "}":
if (i - partStart > 1) {
// there's more than just } on the line, add line
parts.push(indent + text.substring(partStart, i));
partStart = i;
}
indent = TAB_CHARS.repeat(--indentLevel);
/* fallthrough */
case ";":
case "{":
shouldIndent = true;
break;
}
if (shouldIndent) {
let la = text[i+1]; // one-character lookahead
if (!/\n/.test(la) || /^\s+$/.test(text.substring(i+1, text.length))) {
// following character should be a new line, but isn't,
// or it's whitespace at the end of the file
parts.push(indent + text.substring(partStart, i + 1));
if (c == "}") {
parts.push(""); // for extra line separator
}
partStart = i + 1;
} else {
return text; // assume it is not minified, early exit
}
}
if (c == "{") {
indent = TAB_CHARS.repeat(++indentLevel);
}
}
return parts.join(CssLogic.LINE_SEPARATOR);
};
/**
* A safe way to access cached bits of information about a stylesheet.
*

View File

@ -26,3 +26,4 @@ csscoverageDoneReply=CSS Coverage analysis completed
csscoverageRunningError=CSS coverage analysis already running
csscoverageNotRunningError=CSS coverage analysis not running
csscoverageNotRunError=CSS coverage analysis has not been run
csscoverageNoRemoteError=Target does not support CSS Coverage