Bug 1265785 - replace uses of inIDOMUtils.getCSSPseudoElementNames r=pbro
--- a/devtools/client/inspector/rules/models/element-style.js
+++ b/devtools/client/inspector/rules/models/element-style.js
@@ -1,30 +1,21 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set 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 {Cc, Ci} = require("chrome");
const promise = require("promise");
const {Rule} = require("devtools/client/inspector/rules/models/rule");
const {promiseWarn} = require("devtools/client/inspector/shared/utils");
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
-const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
-
-loader.lazyGetter(this, "PSEUDO_ELEMENTS", () => {
- return domUtils.getCSSPseudoElementNames();
-});
-
-XPCOMUtils.defineLazyGetter(this, "domUtils", function () {
- return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
-});
+const {getCssProperties} = require("devtools/shared/fronts/css-properties");
/**
* ElementStyle is responsible for the following:
* Keeps track of which properties are overridden.
* Maintains a list of Rule objects for a given element.
*
* @param {Element} element
* The element whose style we are viewing.
@@ -43,16 +34,17 @@ XPCOMUtils.defineLazyGetter(this, "domUt
function ElementStyle(element, ruleView, store, pageStyle,
showUserAgentStyles) {
this.element = element;
this.ruleView = ruleView;
this.store = store || {};
this.pageStyle = pageStyle;
this.showUserAgentStyles = showUserAgentStyles;
this.rules = [];
+ this.cssProperties = getCssProperties(this.ruleView.inspector.toolbox);
// We don't want to overwrite this.store.userProperties so we only create it
// if it doesn't already exist.
if (!("userProperties" in this.store)) {
this.store.userProperties = new UserProperties();
}
if (!("disabled" in this.store)) {
@@ -203,17 +195,17 @@ ElementStyle.prototype = {
return true;
},
/**
* Calls markOverridden with all supported pseudo elements
*/
markOverriddenAll: function () {
this.markOverridden();
- for (let pseudo of PSEUDO_ELEMENTS) {
+ for (let pseudo of this.cssProperties.pseudoElements) {
this.markOverridden(pseudo);
}
},
/**
* Mark the properties listed in this.rules for a given pseudo element
* with an overridden flag if an earlier property overrides it.
*
--- a/devtools/server/actors/css-properties.js
+++ b/devtools/server/actors/css-properties.js
@@ -23,44 +23,57 @@ exports.CssPropertiesActor = ActorClassW
this.parent = parent;
},
destroy() {
Actor.prototype.destroy.call(this);
},
getCSSDatabase() {
- const db = {};
- const properties = DOMUtils.getCSSPropertyNames(DOMUtils.INCLUDE_ALIASES);
-
- properties.forEach(name => {
- // Get the list of CSS types this property supports.
- let supports = [];
- for (let type in CSS_TYPES) {
- if (safeCssPropertySupportsType(name, DOMUtils["TYPE_" + type])) {
- supports.push(CSS_TYPES[type]);
- }
- }
+ const properties = generateCssProperties();
+ const pseudoElements = DOMUtils.getCSSPseudoElementNames();
- // In order to maintain any backwards compatible changes when debugging older
- // clients, take the definition from the static CSS properties database, and fill it
- // in with the most recent property definition from the server.
- const clientDefinition = CSS_PROPERTIES[name] || {};
- const serverDefinition = {
- isInherited: DOMUtils.isInheritedProperty(name),
- supports
- };
- db[name] = Object.assign(clientDefinition, serverDefinition);
- });
-
- return db;
+ return { properties, pseudoElements };
}
});
/**
+ * Generate the CSS properties object. Every key is the property name, while
+ * the values are objects that contain information about that property.
+ *
+ * @return {Object}
+ */
+function generateCssProperties() {
+ const properties = {};
+ const propertyNames = DOMUtils.getCSSPropertyNames(DOMUtils.INCLUDE_ALIASES);
+
+ propertyNames.forEach(name => {
+ // Get the list of CSS types this property supports.
+ let supports = [];
+ for (let type in CSS_TYPES) {
+ if (safeCssPropertySupportsType(name, DOMUtils["TYPE_" + type])) {
+ supports.push(CSS_TYPES[type]);
+ }
+ }
+
+ // In order to maintain any backwards compatible changes when debugging older
+ // clients, take the definition from the static CSS properties database, and fill it
+ // in with the most recent property definition from the server.
+ const clientDefinition = CSS_PROPERTIES[name] || {};
+ const serverDefinition = {
+ isInherited: DOMUtils.isInheritedProperty(name),
+ supports
+ };
+ properties[name] = Object.assign(clientDefinition, serverDefinition);
+ });
+
+ return properties;
+}
+
+/**
* Test if a CSS is property is known using server-code.
*
* @param {string} name
* @return {Boolean}
*/
function isCssPropertyKnown(name) {
try {
// If the property name is unknown, the cssPropertyIsShorthand
--- a/devtools/shared/css-properties-db.js
+++ b/devtools/shared/css-properties-db.js
@@ -40,16 +40,31 @@ exports.COLOR_TAKING_FUNCTIONS = ["linea
*/
exports.ANGLE_TAKING_FUNCTIONS = ["linear-gradient", "-moz-linear-gradient",
"repeating-linear-gradient",
"-moz-repeating-linear-gradient", "rotate", "rotateX",
"rotateY", "rotateZ", "rotate3d", "skew", "skewX",
"skewY", "hue-rotate"];
/**
+ * The list of all CSS Pseudo Elements. This list can be generated from:
+ *
+ * let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
+ * domUtils.getCSSPseudoElementNames();
+ */
+exports.PSEUDO_ELEMENTS = [":after", ":before", ":backdrop", ":first-letter",
+ ":first-line", ":-moz-selection", ":-moz-focus-inner",
+ ":-moz-focus-outer", ":-moz-list-bullet",
+ ":-moz-list-number", ":-moz-math-anonymous",
+ ":-moz-progress-bar", ":-moz-range-track",
+ ":-moz-range-progress", ":-moz-range-thumb",
+ ":-moz-meter-bar", ":-moz-placeholder",
+ ":-moz-color-swatch"];
+
+/**
* This list is generated from the output of the CssPropertiesActor. If a server
* does not support the actor, this is loaded as a backup. This list does not
* guarantee that the server actually supports these CSS properties.
*/
exports.CSS_PROPERTIES = {
"align-content": {
isInherited: false,
supports: []
@@ -1738,8 +1753,13 @@ exports.CSS_PROPERTIES = {
isInherited: false,
supports: []
},
"-webkit-user-select": {
isInherited: false,
supports: []
}
};
+
+exports.CSS_PROPERTIES_DB = {
+ properties: exports.CSS_PROPERTIES,
+ pseudoElements: exports.PSEUDO_ELEMENTS
+};
--- a/devtools/shared/fronts/css-properties.js
+++ b/devtools/shared/fronts/css-properties.js
@@ -1,17 +1,17 @@
/* 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 { FrontClassWithSpec, Front } = require("devtools/shared/protocol");
const { cssPropertiesSpec } = require("devtools/shared/specs/css-properties");
const { Task } = require("devtools/shared/task");
-const { CSS_PROPERTIES } = require("devtools/shared/css-properties-db");
+const { CSS_PROPERTIES_DB } = require("devtools/shared/css-properties-db");
/**
* Build up a regular expression that matches a CSS variable token. This is an
* ident token that starts with two dashes "--".
*
* https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
*/
var NON_ASCII = "[^\\x00-\\x7F]";
@@ -48,24 +48,25 @@ const CssPropertiesFront = FrontClassWit
exports.CssPropertiesFront = CssPropertiesFront;
/**
* Ask questions to a CSS database. This class does not care how the database
* gets loaded in, only the questions that you can ask to it.
* Prototype functions are bound to 'this' so they can be passed around as helper
* functions.
*
- * @param {Array} propertiesList
- * A list of known properties.
+ * @param {Object} db
+ * A database of CSS properties
* @param {Object} inheritedList
* The key is the property name, the value is whether or not
* that property is inherited.
*/
-function CssProperties(properties) {
- this.properties = properties;
+function CssProperties(db) {
+ this.properties = db.properties;
+ this.pseudoElements = db.pseudoElements;
this.isKnown = this.isKnown.bind(this);
this.isInherited = this.isInherited.bind(this);
this.supportsType = this.supportsType.bind(this);
}
CssProperties.prototype = {
/**
@@ -123,31 +124,41 @@ exports.initCssProperties = Task.async(f
let db, front;
// Get the list dynamically if the cssProperties actor exists.
if (toolbox.target.hasActor("cssProperties")) {
front = CssPropertiesFront(client, toolbox.target.form);
db = yield front.getCSSDatabase();
- // Even if the target has the cssProperties actor, it may not be the latest version.
- // So, the "supports" data may be missing.
- // Start with the server's list (because that's the correct one), and add the supports
- // information if required.
- if (!db.color.supports) {
- for (let name in db) {
- if (typeof CSS_PROPERTIES[name] === "object") {
- db[name].supports = CSS_PROPERTIES[name].supports;
+ // Even if the target has the cssProperties actor, the returned data may
+ // not be in the same shape or have all of the data we need. The following
+ // code normalizes this data.
+
+ // Firefox 49's getCSSDatabase() just returned the properties object, but
+ // now it returns an object with multiple types of CSS information.
+ if (!db.properties) {
+ db = { properties: db };
+ }
+
+ // Fill in any missing DB information from the static database.
+ db = Object.assign({}, CSS_PROPERTIES_DB, db);
+
+ // Add "supports" information to the css properties if it's missing.
+ if (!db.properties.color.supports) {
+ for (let name in db.properties) {
+ if (typeof CSS_PROPERTIES_DB.properties[name] === "object") {
+ db.properties[name].supports = CSS_PROPERTIES_DB.properties[name].supports;
}
}
}
} else {
// The target does not support this actor, so require a static list of supported
// properties.
- db = CSS_PROPERTIES;
+ db = CSS_PROPERTIES_DB;
}
const cssProperties = new CssProperties(db);
cachedCssProperties.set(client, {cssProperties, front});
return {cssProperties, front};
});
/**
new file mode 100644
--- /dev/null
+++ b/devtools/shared/tests/unit/test_css-properties-db.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that css-properties-db matches platform.
+
+"use strict";
+
+const DOMUtils = Components.classes["@mozilla.org/inspector/dom-utils;1"]
+ .getService(Components.interfaces.inIDOMUtils);
+
+const {PSEUDO_ELEMENTS} = require("devtools/shared/css-properties-db");
+
+function run_test() {
+ // Check that the platform and client match for pseudo elements.
+ let foundPseudoElements = 0;
+ const platformPseudoElements = DOMUtils.getCSSPseudoElementNames();
+ const instructions = "If this assertion fails then it means that pseudo elements " +
+ "have been added, removed, or changed on the platform and need " +
+ "to be updated on the static client-side list of pseudo " +
+ "elements within the devtools. " +
+ "See devtools/shared/css-properties-db.js and " +
+ "exports.PSEUDO_ELEMENTS for information on how to update the " +
+ "list of pseudo elements to fix this test.";
+
+ for (let element of PSEUDO_ELEMENTS) {
+ const hasElement = platformPseudoElements.includes(element);
+ ok(hasElement,
+ `"${element}" pseudo element from the client-side CSS properties database was ` +
+ `found on the platform. ${instructions}`);
+ foundPseudoElements += hasElement ? 1 : 0;
+ }
+
+ equal(foundPseudoElements, platformPseudoElements.length,
+ `The client side CSS properties database of psuedo element names should match ` +
+ `those found on the platform. ${instructions}`);
+}
--- a/devtools/shared/tests/unit/xpcshell.ini
+++ b/devtools/shared/tests/unit/xpcshell.ini
@@ -4,16 +4,17 @@ head = head_devtools.js
tail =
firefox-appdir = browser
skip-if = toolkit == 'android' || toolkit == 'gonk'
support-files =
exposeLoader.js
[test_assert.js]
[test_csslexer.js]
+[test_css-properties-db.js]
[test_fetch-chrome.js]
[test_fetch-file.js]
[test_fetch-http.js]
[test_fetch-resource.js]
[test_flatten.js]
[test_indentation.js]
[test_independent_loaders.js]
[test_invisible_loader.js]