Bug 1309065 - Be smarter about filling in the client-side css properties db; draft
authorgtatum@mozilla.com <gtatum@mozilla.com>
Tue, 11 Oct 2016 20:30:24 +0000
changeset 454310 d07dff385315591ea30dfa7439428fb3096c3510
parent 454222 a6d29e9432f5f88a941c0ea5284cb082f34bd097
child 540686 2fe028c44e27f831b1f9b93d122ef51f3ce6be17
push id39904
push userbmo:gtatum@mozilla.com
push dateThu, 29 Dec 2016 01:53:22 +0000
bugs1309065
milestone53.0a1
Bug 1309065 - Be smarter about filling in the client-side css properties db; MozReview-Commit-ID: BOYwveTH1Hy
devtools/server/actors/css-properties.js
devtools/server/tests/mochitest/chrome.ini
devtools/server/tests/mochitest/test_css-properties.html
devtools/server/tests/mochitest/test_css-properties_01.html
devtools/server/tests/mochitest/test_css-properties_02.html
devtools/shared/css/generated/mach_commands.py
devtools/shared/css/generated/properties-db.js
devtools/shared/css/generated/properties-db.js.in
devtools/shared/fronts/css-properties.js
devtools/shared/tests/unit/test_css-properties-db.js
--- a/devtools/server/actors/css-properties.js
+++ b/devtools/server/actors/css-properties.js
@@ -63,27 +63,22 @@ function generateCssProperties() {
     let values = DOMUtils.getCSSValuesForProperty(name);
     if (values.includes("aliceblue")) {
       values = values.filter(x => !colors.includes(x));
       values.unshift("COLOR");
     }
 
     let subproperties = DOMUtils.getSubpropertiesForCSSProperty(name);
 
-    // 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 = {
+    properties[name] = {
       isInherited: DOMUtils.isInheritedProperty(name),
       values,
       supports,
       subproperties,
     };
-    properties[name] = Object.assign(clientDefinition, serverDefinition);
   });
 
   return properties;
 }
 exports.generateCssProperties = generateCssProperties;
 
 /**
  * Test if a CSS is property is known using server-code.
--- a/devtools/server/tests/mochitest/chrome.ini
+++ b/devtools/server/tests/mochitest/chrome.ini
@@ -25,18 +25,17 @@ support-files =
   setup-in-parent.js
 
 [test_animation_actor-lifetime.html]
 [test_connection-manager.html]
 [test_connectToChild.html]
 [test_css-logic.html]
 [test_css-logic-media-queries.html]
 [test_css-logic-specificity.html]
-[test_css-properties_01.html]
-[test_css-properties_02.html]
+[test_css-properties.html]
 [test_Debugger.Source.prototype.introductionScript.html]
 [test_Debugger.Source.prototype.introductionType.html]
 [test_Debugger.Source.prototype.element.html]
 [test_Debugger.Script.prototype.global.html]
 [test_device.html]
 [test_director.html]
 [test_director_connectToChild.html]
 [test_executeInGlobal-outerized_this.html]
rename from devtools/server/tests/mochitest/test_css-properties_01.html
rename to devtools/server/tests/mochitest/test_css-properties.html
deleted file mode 100644
--- a/devtools/server/tests/mochitest/test_css-properties_02.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-Bug 1265798 - Replace inIDOMUtils.cssPropertyIsShorthand
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test CSS Properties Actor</title>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
-  <script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
-  <script type="application/javascript;version=1.8">
-window.onload = function() {
-  const { initCssProperties, getCssProperties } =
-    require("devtools/shared/fronts/css-properties");
-
-  const { CSS_PROPERTIES_DB } = require("devtools/shared/css/properties-db");
-
-  function promiseAttachUrl (url) {
-    return new Promise((resolve, reject) => {
-      attachURL(url, function(err, client, tab, doc) {
-        if (err) {
-          return reject(err);
-        }
-        resolve({client, tab, doc});
-      });
-    })
-  }
-
-  addAsyncTest(function* setup() {
-    let url = document.getElementById("cssProperties").href;
-
-    let attachmentA = yield promiseAttachUrl(url);
-    let attachmentB = yield promiseAttachUrl(url);
-    let attachmentC = yield promiseAttachUrl(url);
-
-    const toolboxMatchingVersions = {
-      target: {
-        hasActor: () => true,
-        client: attachmentA.client,
-        form: attachmentA.tab,
-      },
-      win: window
-    };
-    const toolboxDifferentVersions = {
-      target: {
-        hasActor: () => true,
-        client: attachmentB.client,
-        form: attachmentB.tab
-      },
-      win: { navigator: { userAgent:
-        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 " +
-        "Firefox/30.0" }}
-    };
-
-    // Modify a property on the static database, to differentiate between a generated
-    // and static CSS properties database.
-    CSS_PROPERTIES_DB.properties.color.isStatic = true;
-
-    yield initCssProperties(toolboxMatchingVersions);
-    yield initCssProperties(toolboxDifferentVersions);
-
-    const cssPropertiesMatching = getCssProperties(toolboxMatchingVersions);
-    const cssPropertiesDifferent = getCssProperties(toolboxDifferentVersions);
-
-    is(cssPropertiesMatching.properties.color.isStatic, true,
-       "The static CSS database is used when the client and platform versions match.");
-    isnot(cssPropertiesDifferent.properties.color.isStatic, undefined,
-       "The generated CSS database is used when the client and platform versions do " +
-       "not match, but the client is a Firefox.");
-
-    delete CSS_PROPERTIES_DB.properties.color.isStatic;
-
-    runNextTest();
-  });
-
-  SimpleTest.waitForExplicitFinish();
-  runNextTest();
-}
-  </script>
-</head>
-<body>
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265798">Mozilla Bug 1265798</a>
-  <a id="cssProperties" target="_blank" href="inspector_css-properties.html">Test Document</a>
-</body>
-</html>
--- a/devtools/shared/css/generated/mach_commands.py
+++ b/devtools/shared/css/generated/mach_commands.py
@@ -8,16 +8,17 @@ that uses inIDOMUtils to query the CSS p
 is used to generate the properties-db.js file.
 """
 
 import json
 import os
 import sys
 import string
 import subprocess
+from mozbuild import shellutil
 from mozbuild.base import (
     MozbuildObject,
     MachCommandBase,
 )
 from mach.decorators import (
     CommandProvider,
     Command,
 )
@@ -34,22 +35,56 @@ def stringify(obj):
 class MachCommands(MachCommandBase):
     @Command(
         'devtools-css-db', category='post-build',
         description='Rebuild the devtool\'s static css properties database.')
     def generate_css_db(self):
         """Generate the static css properties database for devtools and write it to file."""
 
         print("Re-generating the css properties database...")
+        preferences = self.get_preferences()
         db = self.get_properties_db_from_xpcshell()
 
         self.output_template({
+            'preferences': stringify(preferences),
             'cssProperties': stringify(db['cssProperties']),
             'pseudoElements': stringify(db['pseudoElements'])})
 
+    def get_preferences(self):
+        """Get all of the preferences associated with enabling and disabling a property."""
+        # Build the command to run the preprocessor on PythonCSSProps.h
+        headerPath = resolve_path(self.topsrcdir, 'layout/style/PythonCSSProps.h')
+
+        cpp = self.substs['CPP']
+
+        if not cpp:
+            print("Unable to find the cpp program. Please do a full, nonartifact")
+            print("build and try this again.")
+            sys.exit(1)
+
+        if type(cpp) is list:
+            cmd = cpp
+        else:
+            cmd = shellutil.split(cpp)
+        cmd += shellutil.split(self.substs['ACDEFINES'])
+        cmd.append(headerPath)
+
+        # The preprocessed list takes the following form:
+        # [ (name, prop, id, flags, pref, proptype), ... ]
+        preprocessed = eval(subprocess.check_output(cmd))
+
+        # Map this list
+        # (name, prop, id, flags, pref, proptype) => (name, pref)
+        preferences = [
+            (name, pref)
+            for name, prop, id, flags, pref, proptype in preprocessed
+            if 'CSS_PROPERTY_INTERNAL' not in flags and pref]
+
+        return preferences
+
     def get_properties_db_from_xpcshell(self):
         """Generate the static css properties db for devtools from an xpcshell script."""
         build = MozbuildObject.from_environment()
 
         # Get the paths
         script_path = resolve_path(self.topsrcdir,
             'devtools/shared/css/generated/generate-properties-db.js')
         gre_path = resolve_path(self.topobjdir, 'dist/bin')
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -2217,51 +2217,59 @@ exports.CSS_PROPERTIES = {
       "-moz-radial-gradient",
       "-moz-repeating-linear-gradient",
       "-moz-repeating-radial-gradient",
       "add",
       "alpha",
       "border-box",
       "content-box",
       "exclude",
+      "fill-box",
       "inherit",
       "initial",
       "intersect",
       "linear-gradient",
       "luminance",
       "match-source",
+      "no-clip",
       "no-repeat",
       "none",
       "padding-box",
       "radial-gradient",
       "repeat",
       "repeat-x",
       "repeat-y",
       "repeating-linear-gradient",
       "repeating-radial-gradient",
       "round",
       "space",
+      "stroke-box",
       "subtract",
       "unset",
-      "url"
+      "url",
+      "view-box"
     ]
   },
   "-webkit-mask-clip": {
     "isInherited": false,
     "subproperties": [
       "mask-clip"
     ],
     "supports": [],
     "values": [
       "border-box",
       "content-box",
-      "inherit",
-      "initial",
+      "fill-box",
+      "inherit",
+      "initial",
+      "no-clip",
       "padding-box",
-      "unset"
+      "stroke-box",
+      "unset",
+      "view-box"
     ]
   },
   "-webkit-mask-composite": {
     "isInherited": false,
     "subproperties": [
       "mask-composite"
     ],
     "supports": [],
@@ -2307,20 +2315,23 @@ exports.CSS_PROPERTIES = {
     "isInherited": false,
     "subproperties": [
       "mask-origin"
     ],
     "supports": [],
     "values": [
       "border-box",
       "content-box",
+      "fill-box",
       "inherit",
       "initial",
       "padding-box",
-      "unset"
+      "stroke-box",
+      "unset",
+      "view-box"
     ]
   },
   "-webkit-mask-position": {
     "isInherited": false,
     "subproperties": [
       "mask-position-x",
       "mask-position-y"
     ],
@@ -3252,16 +3263,17 @@ exports.CSS_PROPERTIES = {
       "extra-expanded",
       "fill",
       "fill-box",
       "fixed",
       "flat",
       "flex",
       "flex-end",
       "flex-start",
+      "flow-root",
       "forwards",
       "full-width",
       "geometricprecision",
       "grayscale",
       "grid",
       "groove",
       "groupbox",
       "hanging",
@@ -3333,16 +3345,17 @@ exports.CSS_PROPERTIES = {
       "menuseparator",
       "meterbar",
       "meterchunk",
       "middle",
       "miter",
       "mixed",
       "multiply",
       "no-change",
+      "no-clip",
       "no-drag",
       "no-repeat",
       "non-scaling-stroke",
       "none",
       "nonzero",
       "normal",
       "nowrap",
       "number-input",
@@ -3467,16 +3480,17 @@ exports.CSS_PROPERTIES = {
       "statusbarpanel",
       "step-end",
       "step-start",
       "steps",
       "sticky",
       "stretch",
       "stretch-to-fit",
       "stroke",
+      "stroke-box",
       "sub",
       "subtract",
       "super",
       "tab",
       "tab-scroll-arrow-back",
       "tab-scroll-arrow-forward",
       "table",
       "table-caption",
@@ -5676,16 +5690,17 @@ exports.CSS_PROPERTIES = {
       "-moz-stack",
       "-webkit-box",
       "-webkit-flex",
       "-webkit-inline-box",
       "-webkit-inline-flex",
       "block",
       "contents",
       "flex",
+      "flow-root",
       "grid",
       "inherit",
       "initial",
       "inline",
       "inline-block",
       "inline-flex",
       "inline-grid",
       "inline-table",
@@ -7184,51 +7199,59 @@ exports.CSS_PROPERTIES = {
       "-moz-radial-gradient",
       "-moz-repeating-linear-gradient",
       "-moz-repeating-radial-gradient",
       "add",
       "alpha",
       "border-box",
       "content-box",
       "exclude",
+      "fill-box",
       "inherit",
       "initial",
       "intersect",
       "linear-gradient",
       "luminance",
       "match-source",
+      "no-clip",
       "no-repeat",
       "none",
       "padding-box",
       "radial-gradient",
       "repeat",
       "repeat-x",
       "repeat-y",
       "repeating-linear-gradient",
       "repeating-radial-gradient",
       "round",
       "space",
+      "stroke-box",
       "subtract",
       "unset",
-      "url"
+      "url",
+      "view-box"
     ]
   },
   "mask-clip": {
     "isInherited": false,
     "subproperties": [
       "mask-clip"
     ],
     "supports": [],
     "values": [
       "border-box",
       "content-box",
-      "inherit",
-      "initial",
+      "fill-box",
+      "inherit",
+      "initial",
+      "no-clip",
       "padding-box",
-      "unset"
+      "stroke-box",
+      "unset",
+      "view-box"
     ]
   },
   "mask-composite": {
     "isInherited": false,
     "subproperties": [
       "mask-composite"
     ],
     "supports": [],
@@ -7289,20 +7312,23 @@ exports.CSS_PROPERTIES = {
     "isInherited": false,
     "subproperties": [
       "mask-origin"
     ],
     "supports": [],
     "values": [
       "border-box",
       "content-box",
+      "fill-box",
       "inherit",
       "initial",
       "padding-box",
-      "unset"
+      "stroke-box",
+      "unset",
+      "view-box"
     ]
   },
   "mask-position": {
     "isInherited": false,
     "subproperties": [
       "mask-position-x",
       "mask-position-y"
     ],
@@ -9372,8 +9398,555 @@ exports.PSEUDO_ELEMENTS = [
   ":-moz-range-track",
   ":-moz-range-progress",
   ":-moz-range-thumb",
   ":-moz-meter-bar",
   ":-moz-placeholder",
   ":placeholder",
   ":-moz-color-swatch"
 ];
+
+/**
+ * A list of the preferences keys for whether a CSS property is enabled or not. This is
+ * exposed for testing purposes.
+ */
+exports.PREFERENCES = [
+  [
+    "all",
+    "layout.css.all-shorthand.enabled"
+  ],
+  [
+    "background-blend-mode",
+    "layout.css.background-blend-mode.enabled"
+  ],
+  [
+    "box-decoration-break",
+    "layout.css.box-decoration-break.enabled"
+  ],
+  [
+    "color-adjust",
+    "layout.css.color-adjust.enabled"
+  ],
+  [
+    "contain",
+    "layout.css.contain.enabled"
+  ],
+  [
+    "font-variation-settings",
+    "layout.css.font-variations.enabled"
+  ],
+  [
+    "grid",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-area",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-auto-columns",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-auto-flow",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-auto-rows",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-column",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-column-end",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-column-gap",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-column-start",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-gap",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-row",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-row-end",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-row-gap",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-row-start",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-template",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-template-areas",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-template-columns",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "grid-template-rows",
+    "layout.css.grid.enabled"
+  ],
+  [
+    "initial-letter",
+    "layout.css.initial-letter.enabled"
+  ],
+  [
+    "image-orientation",
+    "layout.css.image-orientation.enabled"
+  ],
+  [
+    "isolation",
+    "layout.css.isolation.enabled"
+  ],
+  [
+    "mix-blend-mode",
+    "layout.css.mix-blend-mode.enabled"
+  ],
+  [
+    "object-fit",
+    "layout.css.object-fit-and-position.enabled"
+  ],
+  [
+    "object-position",
+    "layout.css.object-fit-and-position.enabled"
+  ],
+  [
+    "-moz-osx-font-smoothing",
+    "layout.css.osx-font-smoothing.enabled"
+  ],
+  [
+    "overflow-clip-box",
+    "layout.css.overflow-clip-box.enabled"
+  ],
+  [
+    "paint-order",
+    "svg.paint-order.enabled"
+  ],
+  [
+    "scroll-behavior",
+    "layout.css.scroll-behavior.property-enabled"
+  ],
+  [
+    "scroll-snap-coordinate",
+    "layout.css.scroll-snap.enabled"
+  ],
+  [
+    "scroll-snap-destination",
+    "layout.css.scroll-snap.enabled"
+  ],
+  [
+    "scroll-snap-points-x",
+    "layout.css.scroll-snap.enabled"
+  ],
+  [
+    "scroll-snap-points-y",
+    "layout.css.scroll-snap.enabled"
+  ],
+  [
+    "scroll-snap-type",
+    "layout.css.scroll-snap.enabled"
+  ],
+  [
+    "scroll-snap-type-x",
+    "layout.css.scroll-snap.enabled"
+  ],
+  [
+    "scroll-snap-type-y",
+    "layout.css.scroll-snap.enabled"
+  ],
+  [
+    "shape-outside",
+    "layout.css.shape-outside.enabled"
+  ],
+  [
+    "text-combine-upright",
+    "layout.css.text-combine-upright.enabled"
+  ],
+  [
+    "-webkit-text-fill-color",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-text-stroke",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-text-stroke-color",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-text-stroke-width",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "touch-action",
+    "layout.css.touch_action.enabled"
+  ],
+  [
+    "-moz-transform",
+    "layout.css.prefixes.transforms"
+  ],
+  [
+    "transform-box",
+    "svg.transform-box.enabled"
+  ],
+  [
+    "-moz-transform-origin",
+    "layout.css.prefixes.transforms"
+  ],
+  [
+    "-moz-perspective-origin",
+    "layout.css.prefixes.transforms"
+  ],
+  [
+    "-moz-perspective",
+    "layout.css.prefixes.transforms"
+  ],
+  [
+    "-moz-transform-style",
+    "layout.css.prefixes.transforms"
+  ],
+  [
+    "-moz-backface-visibility",
+    "layout.css.prefixes.transforms"
+  ],
+  [
+    "-moz-border-image",
+    "layout.css.prefixes.border-image"
+  ],
+  [
+    "-moz-transition",
+    "layout.css.prefixes.transitions"
+  ],
+  [
+    "-moz-transition-delay",
+    "layout.css.prefixes.transitions"
+  ],
+  [
+    "-moz-transition-duration",
+    "layout.css.prefixes.transitions"
+  ],
+  [
+    "-moz-transition-property",
+    "layout.css.prefixes.transitions"
+  ],
+  [
+    "-moz-transition-timing-function",
+    "layout.css.prefixes.transitions"
+  ],
+  [
+    "-moz-animation",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-animation-delay",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-animation-direction",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-animation-duration",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-animation-fill-mode",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-animation-iteration-count",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-animation-name",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-animation-play-state",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-animation-timing-function",
+    "layout.css.prefixes.animations"
+  ],
+  [
+    "-moz-box-sizing",
+    "layout.css.prefixes.box-sizing"
+  ],
+  [
+    "-moz-font-feature-settings",
+    "layout.css.prefixes.font-features"
+  ],
+  [
+    "-moz-font-language-override",
+    "layout.css.prefixes.font-features"
+  ],
+  [
+    "-webkit-animation",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-animation-delay",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-animation-direction",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-animation-duration",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-animation-fill-mode",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-animation-iteration-count",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-animation-name",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-animation-play-state",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-animation-timing-function",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-filter",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-text-size-adjust",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-transform",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-transform-origin",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-transform-style",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-backface-visibility",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-perspective",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-perspective-origin",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-transition",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-transition-delay",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-transition-duration",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-transition-property",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-transition-timing-function",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-border-radius",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-border-top-left-radius",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-border-top-right-radius",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-border-bottom-left-radius",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-border-bottom-right-radius",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-background-clip",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-background-origin",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-background-size",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-border-image",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-box-shadow",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-box-sizing",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-box-flex",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-box-ordinal-group",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-box-orient",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-box-direction",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-box-align",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-box-pack",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-flex-direction",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-flex-wrap",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-flex-flow",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-order",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-flex",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-flex-grow",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-flex-shrink",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-flex-basis",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-justify-content",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-align-items",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-align-self",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-align-content",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-user-select",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-clip",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-composite",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-image",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-origin",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-position",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-position-x",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-position-y",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-repeat",
+    "layout.css.prefixes.webkit"
+  ],
+  [
+    "-webkit-mask-size",
+    "layout.css.prefixes.webkit"
+  ]
+];
--- a/devtools/shared/css/generated/properties-db.js.in
+++ b/devtools/shared/css/generated/properties-db.js.in
@@ -13,8 +13,14 @@
  * A list of CSS Properties and their various characteristics.
  */
 exports.CSS_PROPERTIES = ${cssProperties};
 
 /**
  * A list of the pseudo elements.
  */
 exports.PSEUDO_ELEMENTS = ${pseudoElements};
+
+/**
+ * A list of the preferences keys for whether a CSS property is enabled or not. This is
+ * exposed for testing purposes.
+ */
+exports.PREFERENCES = ${preferences};
--- a/devtools/shared/fronts/css-properties.js
+++ b/devtools/shared/fronts/css-properties.js
@@ -229,25 +229,17 @@ const initCssProperties = Task.async(fun
     return cachedCssProperties.get(client);
   }
 
   let db, front;
 
   // Get the list dynamically if the cssProperties actor exists.
   if (toolbox.target.hasActor("cssProperties")) {
     front = CssPropertiesFront(client, toolbox.target.form);
-    const serverDB = yield front.getCSSDatabase();
-
-    // Ensure the database was returned in a format that is understood.
-    // Older versions of the protocol could return a blank database.
-    if (!serverDB.properties && !serverDB.margin) {
-      db = CSS_PROPERTIES_DB;
-    } else {
-      db = serverDB;
-    }
+    db = yield front.getCSSDatabase();
   } else {
     // The target does not support this actor, so require a static list of supported
     // properties.
     db = CSS_PROPERTIES_DB;
   }
 
   const cssProperties = new CssProperties(normalizeCssData(db));
   cachedCssProperties.set(client, {cssProperties, front});
@@ -289,19 +281,16 @@ function getClientCssProperties() {
 function normalizeCssData(db) {
   if (db !== CSS_PROPERTIES_DB) {
     // 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);
-
     let missingSupports = !db.properties.color.supports;
     let missingValues = !db.properties.color.values;
     let missingSubproperties = !db.properties.background.subproperties;
 
     for (let name in db.properties) {
       // Skip the current property if we can't find it in CSS_PROPERTIES_DB.
       if (typeof CSS_PROPERTIES_DB.properties[name] !== "object") {
         continue;
@@ -315,16 +304,20 @@ function normalizeCssData(db) {
       if (missingValues) {
         db.properties[name].values = CSS_PROPERTIES_DB.properties[name].values;
       }
       // Add "subproperties" information to the css properties if it's missing.
       if (missingSubproperties) {
         db.properties[name].subproperties =
           CSS_PROPERTIES_DB.properties[name].subproperties;
       }
+      // Add "isInherited" information to the css properties if it's missing.
+      if (db.properties.font.isInherited) {
+        db.properties[name].isInherited = CSS_PROPERTIES_DB.properties[name].isInherited;
+      }
     }
   }
 
   reattachCssColorValues(db);
 
   // If there is no supportedFeature in db, create an empty one.
   if (!db.supportedFeature) {
     db.supportedFeature = {};
--- a/devtools/shared/tests/unit/test_css-properties-db.js
+++ b/devtools/shared/tests/unit/test_css-properties-db.js
@@ -17,52 +17,56 @@
  * the inspected target in this particular case.
  */
 
 "use strict";
 
 const DOMUtils = Components.classes["@mozilla.org/inspector/dom-utils;1"]
                            .getService(Components.interfaces.inIDOMUtils);
 
-const {PSEUDO_ELEMENTS, CSS_PROPERTIES} = require("devtools/shared/css/generated/properties-db");
+const {PSEUDO_ELEMENTS, CSS_PROPERTIES, PREFERENCES} = require("devtools/shared/css/generated/properties-db");
 const {generateCssProperties} = require("devtools/server/actors/css-properties");
+const {Preferences} = require("resource://gre/modules/Preferences.jsm");
 
 function run_test() {
   const propertiesErrorMessage = "If this assertion fails, then the client side CSS " +
                                  "properties list in devtools is out of sync with the " +
                                  "CSS properties on the platform. To fix this " +
                                  "assertion run `mach devtools-css-db` to re-generate " +
                                  "the client side properties.";
 
   // Check that the platform and client match for pseudo elements.
   deepEqual(PSEUDO_ELEMENTS, DOMUtils.getCSSPseudoElementNames(), `The pseudo elements ` +
             `match on the client and platform. ${propertiesErrorMessage}`);
 
   /**
    * Check that the platform and client match for the details on their CSS properties.
-   * Enumerate each property to aid in debugging.
+   * Enumerate each property to aid in debugging. Sometimes these properties don't
+   * completely agree due to differences in preferences. Check the currently set
+   * preference for that property to see if it's enabled.
    */
   const platformProperties = generateCssProperties();
 
   for (let propertyName in CSS_PROPERTIES) {
     const platformProperty = platformProperties[propertyName];
     const clientProperty = CSS_PROPERTIES[propertyName];
     const deepEqual = isJsonDeepEqual(platformProperty, clientProperty);
 
+    // The "all" property can contain information that can be turned on and off by
+    // preferences. These values can be different between OSes, so ignore the equality
+    // check for this property, since this is likely to fail.
+    if (propertyName === "all") {
+      continue;
+    }
+
     if (deepEqual) {
       ok(true, `The static database and platform match for "${propertyName}".`);
     } else {
-      const prefMessage = `The static database and platform do not match ` +
-                          `for "${propertyName}".`;
-      if (getPreference(propertyName) === false) {
-        ok(true, `${prefMessage} However, there is a preference for disabling this ` +
-                 `property on the current build.`);
-      } else {
-        ok(false, `${prefMessage} ${propertiesErrorMessage}`);
-      }
+      ok(false, `The static database and platform do not match for ` + `
+        "${propertyName}". ${propertiesErrorMessage}`);
     }
   }
 
   /**
    * Check that the list of properties on the platform and client are the same. If
    * they are not, check that there may be preferences that are disabling them on the
    * target platform.
    */
@@ -70,18 +74,24 @@ function run_test() {
     // Filter out OS-specific properties.
     .filter(name => name && name.indexOf("-moz-osx-") === -1);
 
   if (mismatches.length === 0) {
     ok(true, "No client and platform CSS property database mismatches were found.");
   }
 
   mismatches.forEach(propertyName => {
-    ok(false, `The static database and platform do not agree on the property ` +
-              `"${propertyName}" ${propertiesErrorMessage}`);
+    if (getPreference(propertyName) === false) {
+      ok(true, `The static database and platform do not agree on the property ` +
+               `"${propertyName}" This is ok because it is currently disabled through ` +
+               `a preference.`);
+    } else {
+      ok(false, `The static database and platform do not agree on the property ` +
+                `"${propertyName}" ${propertiesErrorMessage}`);
+    }
   });
 }
 
 /**
  * Check JSON-serializable objects for deep equality.
  */
 function isJsonDeepEqual(a, b) {
   // Handle primitives.
@@ -129,8 +139,26 @@ function getKeyMismatches(a, b) {
   const bNames = Object.keys(b);
   const aMismatches = aNames.filter(key => !bNames.includes(key));
   const bMismatches = bNames.filter(key => {
     return !aNames.includes(key) && !aMismatches.includes(key);
   });
 
   return aMismatches.concat(bMismatches);
 }
+
+/**
+ * Get the preference value of whether this property is enabled. Returns an empty string
+ * if no preference exists.
+ *
+ * @param {String} propertyName
+ * @return {Boolean|undefined}
+ */
+function getPreference(propertyName) {
+  const preference = PREFERENCES.find(([prefPropertyName, preferenceKey]) => {
+    return prefPropertyName === propertyName && !!preferenceKey;
+  });
+
+  if (preference) {
+    return Preferences.get(preference[1]);
+  }
+  return undefined;
+}