Bug 1339394 - Don't serialize transparent color to transparent keyword when not necessary. r=heycam,jaws draft
authorXidorn Quan <me@upsuper.org>
Thu, 16 Feb 2017 10:26:13 +1100
changeset 486854 3b927d3c056b66e98f457de1726cf9d459eb8708
parent 486853 acbd2222b9d3ec1d2fe06e3074aadeb75dcbf43f
child 546331 a0ca012a7e88daa5e064806511f705cfb4a3c0cf
push id46076
push userxquan@mozilla.com
push dateMon, 20 Feb 2017 03:59:33 +0000
reviewersheycam, jaws
bugs1339394
milestone54.0a1
Bug 1339394 - Don't serialize transparent color to transparent keyword when not necessary. r=heycam,jaws MozReview-Commit-ID: 59cmaCoFJMR
accessible/tests/mochitest/attributes.js
browser/base/content/test/general/browser_selectpopup.js
browser/base/content/test/general/browser_windowactivation.js
browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
browser/components/extensions/test/browser/browser_ext_tabs_insertCSS.js
browser/components/extensions/test/browser/browser_ext_tabs_removeCSS.js
devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
dom/browser-element/mochitest/browserElement_LoadEvents.js
dom/security/test/csp/test_docwrite_meta.html
dom/tests/mochitest/ajax/scriptaculous/test/unit/ajax_inplaceeditor_test.html
layout/style/nsCSSValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/test/chrome/hover_helper.html
layout/style/test/property_database.js
layout/style/test/stylo-failures.md
layout/style/test/test_additional_sheets.html
layout/style/test/test_bug229915.html
layout/style/test/test_bug372770.html
layout/style/test/test_bug635286.html
layout/style/test/test_computed_style.html
layout/style/test/test_default_computed_style.html
mobile/android/components/extensions/test/mochitest/test_ext_tabs_insertCSS.html
testing/marionette/harness/marionette_harness/tests/unit/test_chrome_element_css.py
testing/web-platform/meta/editing/run/forecolor.html.ini
testing/web-platform/meta/editing/run/hilitecolor.html.ini
toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html
toolkit/modules/SelectParentHelper.jsm
--- a/accessible/tests/mochitest/attributes.js
+++ b/accessible/tests/mochitest/attributes.js
@@ -264,17 +264,17 @@ function fontFamily(aComputedStyle)
  * @param aFontSize    [in] font size
  * @param aFontWeight  [in, optional] kBoldFontWeight or kNormalFontWeight,
  *                      default value is kNormalFontWeight
  */
 function buildDefaultTextAttrs(aID, aFontSize, aFontWeight, aFontFamily)
 {
   var elm = getNode(aID);
   var computedStyle = document.defaultView.getComputedStyle(elm);
-  var bgColor = computedStyle.backgroundColor == "transparent" ?
+  var bgColor = computedStyle.backgroundColor == "rgba(0, 0, 0, 0)" ?
     "rgb(255, 255, 255)" : computedStyle.backgroundColor;
 
   var defAttrs = {
     "font-style": computedStyle.fontStyle,
     "font-size": aFontSize,
     "background-color": bgColor,
     "font-weight": aFontWeight ? aFontWeight : kNormalFontWeight,
     "color": computedStyle.color,
--- a/browser/base/content/test/general/browser_selectpopup.js
+++ b/browser/base/content/test/general/browser_selectpopup.js
@@ -85,30 +85,30 @@ const PAGECONTENT_COLORS =
   "  .green { color: #800080; background-color: green; }" +
   "  .defaultColor { color: -moz-ComboboxText; }" +
   "  .defaultBackground { background-color: -moz-Combobox; }" +
   "</style>" +
   "<body><select id='one'>" +
   '  <option value="One" style="color: #fff; background-color: #f00;">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(255, 0, 0)"}</option>' +
   '  <option value="Two" class="blue">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(0, 0, 255)"}</option>' +
   '  <option value="Three" class="green">{"color": "rgb(128, 0, 128)", "backgroundColor": "rgb(0, 128, 0)"}</option>' +
-  '  <option value="Four" class="defaultColor defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "transparent", "unstyled": "true"}</option>' +
-  '  <option value="Five" class="defaultColor">{"color": "-moz-ComboboxText", "backgroundColor": "transparent", "unstyled": "true"}</option>' +
-  '  <option value="Six" class="defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "transparent", "unstyled": "true"}</option>' +
+  '  <option value="Four" class="defaultColor defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
+  '  <option value="Five" class="defaultColor">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
+  '  <option value="Six" class="defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
   '  <option value="Seven" selected="true">{"unstyled": "true"}</option>' +
   "</select></body></html>";
 
 const PAGECONTENT_COLORS_ON_SELECT =
   "<html><head><style>" +
   "  #one { background-color: #7E3A3A; color: #fff }" +
   "</style>" +
   "<body><select id='one'>" +
-  '  <option value="One">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
-  '  <option value="Two">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
-  '  <option value="Three">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
+  '  <option value="One">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+  '  <option value="Two">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+  '  <option value="Three">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
   '  <option value="Four" selected="true">{"end": "true"}</option>' +
   "</select></body></html>";
 
 const TRANSPARENT_SELECT =
   "<html><head><style>" +
   "  #one { background-color: transparent; }" +
   "</style>" +
   "<body><select id='one'>" +
--- a/browser/base/content/test/general/browser_windowactivation.js
+++ b/browser/base/content/test/general/browser_windowactivation.js
@@ -43,42 +43,42 @@ function reallyRunTests() {
   // while another window is focused. The third check is done after that window
   // is closed and the main window focused again. The fourth check is done after
   // switching to the second tab.
   window.messageManager.addMessageListener("Test:BackgroundColorChanged", function(message) {
     colorChangeNotifications++;
 
     switch (colorChangeNotifications) {
       case 1:
-        is(message.data.color, "transparent", "first window initial");
+        is(message.data.color, "rgba(0, 0, 0, 0)", "first window initial");
         break;
       case 2:
-        is(message.data.color, "transparent", "second window initial");
+        is(message.data.color, "rgba(0, 0, 0, 0)", "second window initial");
         runOtherWindowTests();
         break;
       case 3:
         is(message.data.color, "rgb(255, 0, 0)", "first window lowered");
         break;
       case 4:
         is(message.data.color, "rgb(255, 0, 0)", "second window lowered");
         sendGetBackgroundRequest(true);
         otherWindow.close();
         break;
       case 5:
-        is(message.data.color, "transparent", "first window raised");
+        is(message.data.color, "rgba(0, 0, 0, 0)", "first window raised");
         break;
       case 6:
-        is(message.data.color, "transparent", "second window raised");
+        is(message.data.color, "rgba(0, 0, 0, 0)", "second window raised");
         gBrowser.selectedTab = tab2;
         break;
       case 7:
-        is(message.data.color, "transparent", "first window after tab switch");
+        is(message.data.color, "rgba(0, 0, 0, 0)", "first window after tab switch");
         break;
       case 8:
-        is(message.data.color, "transparent", "second window after tab switch");
+        is(message.data.color, "rgba(0, 0, 0, 0)", "second window after tab switch");
         finishTest();
         break;
       case 9:
         ok(false, "too many color change notifications");
         break;
     }
   });
 
--- a/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
+++ b/browser/components/extensions/test/browser/browser_ext_pageAction_popup.js
@@ -17,17 +17,17 @@ add_task(function* testPageActionPopup()
       },
     },
 
     files: {
       "popup-a.html": scriptPage("popup-a.js"),
       "popup-a.js": function() {
         window.onload = () => {
           let background = window.getComputedStyle(document.body).backgroundColor;
-          browser.test.assertEq("transparent", background);
+          browser.test.assertEq("rgba(0, 0, 0, 0)", background);
           browser.runtime.sendMessage("from-popup-a");
         };
         browser.runtime.onMessage.addListener(msg => {
           if (msg == "close-popup") {
             window.close();
           }
         });
       },
--- a/browser/components/extensions/test/browser/browser_ext_tabs_insertCSS.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_insertCSS.js
@@ -8,17 +8,17 @@ add_task(function* testExecuteScript() {
   let messageManagersSize = MessageChannel.messageManagers.size;
   let responseManagersSize = MessageChannel.responseManagers.size;
 
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true);
 
   async function background() {
     let tasks = [
       {
-        background: "transparent",
+        background: "rgba(0, 0, 0, 0)",
         foreground: "rgb(0, 113, 4)",
         promise: () => {
           return browser.tabs.insertCSS({
             file: "file2.css",
           });
         },
       },
       {
--- a/browser/components/extensions/test/browser/browser_ext_tabs_removeCSS.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_removeCSS.js
@@ -4,17 +4,17 @@
 
 add_task(function* testExecuteScript() {
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true);
 
   async function background() {
     let tasks = [
       // Insert CSS file.
       {
-        background: "transparent",
+        background: "rgba(0, 0, 0, 0)",
         foreground: "rgb(0, 113, 4)",
         promise: () => {
           return browser.tabs.insertCSS({
             file: "file2.css",
           });
         },
       },
       // Insert CSS code.
@@ -24,27 +24,27 @@ add_task(function* testExecuteScript() {
         promise: () => {
           return browser.tabs.insertCSS({
             code: "* { background: rgb(42, 42, 42) }",
           });
         },
       },
       // Remove CSS code again.
       {
-        background: "transparent",
+        background: "rgba(0, 0, 0, 0)",
         foreground: "rgb(0, 113, 4)",
         promise: () => {
           return browser.tabs.removeCSS({
             code: "* { background: rgb(42, 42, 42) }",
           });
         },
       },
       // Remove CSS file again.
       {
-        background: "transparent",
+        background: "rgba(0, 0, 0, 0)",
         foreground: "rgb(0, 0, 0)",
         promise: () => {
           return browser.tabs.removeCSS({
             file: "file2.css",
           });
         },
       },
       // Insert CSS code.
@@ -55,17 +55,17 @@ add_task(function* testExecuteScript() {
           return browser.tabs.insertCSS({
             code: "* { background: rgb(42, 42, 42) }",
             cssOrigin: "user",
           });
         },
       },
       // Remove CSS code again.
       {
-        background: "transparent",
+        background: "rgba(0, 0, 0, 0)",
         foreground: "rgb(0, 0, 0)",
         promise: () => {
           return browser.tabs.removeCSS({
             code: "* { background: rgb(42, 42, 42) }",
             cssOrigin: "user",
           });
         },
       },
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
@@ -51,17 +51,17 @@ add_task(function* () {
   yield togglePropStatus(view, secondProp);
 
   is((yield getValue("#testid", "background-color")), "rgb(0, 128, 0)",
      "After disabling second property, first value should be used");
 
   info("Disabling the first property too and checking the applied style");
   yield togglePropStatus(view, firstProp);
 
-  is((yield getValue("#testid", "background-color")), "transparent",
+  is((yield getValue("#testid", "background-color")), "rgba(0, 0, 0, 0)",
      "After disabling both properties, value should be empty.");
 
   info("Re-enabling the second propertyt and checking the applied style");
   yield togglePropStatus(view, secondProp);
 
   is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
      "Value should be set correctly after re-enabling");
 
--- a/dom/browser-element/mochitest/browserElement_LoadEvents.js
+++ b/dom/browser-element/mochitest/browserElement_LoadEvents.js
@@ -95,17 +95,17 @@ function runTest2() {
   });
 
   iframe.addEventListener('mozbrowserloadend', function(e) {
     ok(e.isTrusted, 'Event should be trusted.');
     ok(!seenLoadEnd, 'Just one load end event.');
     seenLoadEnd = true;
     ok(seenLoadStart, 'Load end after load start.');
     ok(seenLocationChange, 'Load end after location change.');
-    is(e.detail.backgroundColor, 'transparent', 'Expected background color reported')
+    is(e.detail.backgroundColor, 'rgba(0, 0, 0, 0)', 'Expected background color reported')
   });
 
   iframe.src = browserElementTestHelpers.emptyPage2;
 
   function waitForAllCallbacks() {
     if (!seenLoadStart || !seenLoadEnd || !seenLocationChange) {
       SimpleTest.executeSoon(waitForAllCallbacks);
       return;
--- a/dom/security/test/csp/test_docwrite_meta.html
+++ b/dom/security/test/csp/test_docwrite_meta.html
@@ -36,17 +36,17 @@ function checkTestsDone() {
 
 // document.write(<meta csp ...>) should block resources from being included in the doc
 function checkResultsBlocked() {
   writemetacspframe.removeEventListener('load', checkResultsBlocked);
 
   // stylesheet: default background color within FF is transparent
   var bgcolor = window.getComputedStyle(writemetacspframe.contentDocument.body)
                       .getPropertyValue("background-color");
-  is(bgcolor, "transparent", "inital background value in FF should be 'transparent'");
+  is(bgcolor, "rgba(0, 0, 0, 0)", "inital background value in FF should be 'transparent'");
 
   // image: make sure image is blocked
   var img = writemetacspframe.contentDocument.getElementById("testimage");
   is(img.width, 0, "image widht should be 0");
   is(img.height, 0, "image widht should be 0");
 
   // script: make sure defined variable in external script is undefined
   is(writemetacspframe.contentDocument.myMetaCSPScript, undefined, "myMetaCSPScript should be 'undefined'");
--- a/dom/tests/mochitest/ajax/scriptaculous/test/unit/ajax_inplaceeditor_test.html
+++ b/dom/tests/mochitest/ajax/scriptaculous/test/unit/ajax_inplaceeditor_test.html
@@ -39,19 +39,19 @@
       });
     }},
 
     teardown: function() { with(this) {
       inPlaceEditor.dispose();
     }},
 
     testDisposesProperly: function() { with(this) {
-      assertEqual("transparent", Element.getStyle('tobeedited','background-color'));
+      assertEqual("rgba(0, 0, 0, 0)", Element.getStyle('tobeedited','background-color'));
       inPlaceEditor.dispose();
-      assertEqual("transparent", Element.getStyle('tobeedited','background-color'));
+      assertEqual("rgba(0, 0, 0, 0)", Element.getStyle('tobeedited','background-color'));
       assertVisible($('tobeedited'));
       Event.simulateMouse('tobeedited','click');
       assertVisible($('tobeedited'));
     }},
 
     testUsesTextAreaWhenMoreThanOneRows: function() { with(this) {
       inPlaceEditor.options.rows = 5;
       inPlaceEditor.enterEditMode();
@@ -79,17 +79,17 @@
       inPlaceEditor.options.formId = "myFormId";
       inPlaceEditor.enterEditMode();
       assertEqual("myFormId", document.forms[0].id);
     }},
 
     testCantEditWhileSaving: function() { with(this) {
       inPlaceEditor.onLoading();
       Event.simulateMouse('tobeedited','mouseover');
-      assertEqual("transparent", Element.getStyle('tobeedited','background-color'));
+      assertEqual("rgba(0, 0, 0, 0)", Element.getStyle('tobeedited','background-color'));
       Event.simulateMouse('tobeedited','click');
       assertVisible($('tobeedited'));
     }},
 
     testCallbackFunctionGetsCalled: function() { with(this) {
       called = false;
       inPlaceEditor.options.callback = function(form) {
         called = true;
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1655,48 +1655,41 @@ nsCSSValue::AppendToString(nsCSSProperty
       MOZ_ASSERT(false, "bad color value");
     }
   }
   else if (IsNumericColorUnit(unit)) {
     if (aSerialization == eNormalized ||
         unit == eCSSUnit_RGBColor ||
         unit == eCSSUnit_RGBAColor) {
       nscolor color = GetColorValue();
-      if (aSerialization == eNormalized &&
-          color == NS_RGBA(0, 0, 0, 0)) {
-        // Use the strictest match for 'transparent' so we do correct
-        // round-tripping of all other rgba() values.
-        aResult.AppendLiteral("transparent");
+      // For brevity, we omit the alpha component if it's equal to 255 (full
+      // opaque). Also, we try to preserve the author-specified function name,
+      // unless it's rgba() and we're omitting the alpha component - then we
+      // use rgb().
+      uint8_t a = NS_GET_A(color);
+      bool showAlpha = (a != 255);
+
+      if (unit == eCSSUnit_RGBAColor && showAlpha) {
+        aResult.AppendLiteral("rgba(");
       } else {
-        // For brevity, we omit the alpha component if it's equal to 255 (full
-        // opaque). Also, we try to preserve the author-specified function name,
-        // unless it's rgba() and we're omitting the alpha component - then we
-        // use rgb().
-        uint8_t a = NS_GET_A(color);
-        bool showAlpha = (a != 255);
-
-        if (unit == eCSSUnit_RGBAColor && showAlpha) {
-          aResult.AppendLiteral("rgba(");
-        } else {
-          aResult.AppendLiteral("rgb(");
-        }
-
-        NS_NAMED_LITERAL_STRING(comma, ", ");
-
-        aResult.AppendInt(NS_GET_R(color), 10);
+        aResult.AppendLiteral("rgb(");
+      }
+
+      NS_NAMED_LITERAL_STRING(comma, ", ");
+
+      aResult.AppendInt(NS_GET_R(color), 10);
+      aResult.Append(comma);
+      aResult.AppendInt(NS_GET_G(color), 10);
+      aResult.Append(comma);
+      aResult.AppendInt(NS_GET_B(color), 10);
+      if (showAlpha) {
         aResult.Append(comma);
-        aResult.AppendInt(NS_GET_G(color), 10);
-        aResult.Append(comma);
-        aResult.AppendInt(NS_GET_B(color), 10);
-        if (showAlpha) {
-          aResult.Append(comma);
-          aResult.AppendFloat(nsStyleUtil::ColorComponentToFloat(a));
-        }
-        aResult.Append(char16_t(')'));
+        aResult.AppendFloat(nsStyleUtil::ColorComponentToFloat(a));
       }
+      aResult.Append(char16_t(')'));
     } else if (eCSSUnit_HexColor == unit ||
                eCSSUnit_HexColorAlpha == unit) {
       nscolor color = GetColorValue();
       aResult.Append('#');
       aResult.AppendPrintf("%02x", NS_GET_R(color));
       aResult.AppendPrintf("%02x", NS_GET_G(color));
       aResult.AppendPrintf("%02x", NS_GET_B(color));
       if (eCSSUnit_HexColorAlpha == unit) {
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1111,21 +1111,16 @@ nsComputedDOMStyle::DoGetStackSizing()
                 eCSSKeyword_ignore);
   return val.forget();
 }
 
 void
 nsComputedDOMStyle::SetToRGBAColor(nsROCSSPrimitiveValue* aValue,
                                    nscolor aColor)
 {
-  if (NS_GET_A(aColor) == 0) {
-    aValue->SetIdent(eCSSKeyword_transparent);
-    return;
-  }
-
   nsROCSSPrimitiveValue *red   = new nsROCSSPrimitiveValue;
   nsROCSSPrimitiveValue *green = new nsROCSSPrimitiveValue;
   nsROCSSPrimitiveValue *blue  = new nsROCSSPrimitiveValue;
   nsROCSSPrimitiveValue *alpha  = new nsROCSSPrimitiveValue;
 
   uint8_t a = NS_GET_A(aColor);
   nsDOMCSSRGBColor *rgbColor =
     new nsDOMCSSRGBColor(red, green, blue, alpha, a < 255);
--- a/layout/style/test/chrome/hover_helper.html
+++ b/layout/style/test/chrome/hover_helper.html
@@ -60,27 +60,27 @@ function setResize(str) {
 }
 
 function step1() {
     /** test basic hover **/
     var divone = document.getElementById("one");
     synthesizeMouse(divone, 5, 7, moveEvent, window);
     is(getComputedStyle(divone, "").backgroundColor, "rgb(0, 0, 255)",
        ":hover applies");
-    is(getComputedStyle(divone.firstChild, "").backgroundColor, "transparent",
+    is(getComputedStyle(divone.firstChild, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
     synthesizeMouse(divone, 5, 2, moveEvent, window);
     is(getComputedStyle(divone, "").backgroundColor, "rgb(0, 0, 255)",
        ":hover applies hierarchically");
     is(getComputedStyle(divone.firstChild, "").backgroundColor, "rgb(255, 0, 0)",
        ":hover applies");
     synthesizeMouse(divone, 15, 7, moveEvent, window);
-    is(getComputedStyle(divone, "").backgroundColor, "transparent",
+    is(getComputedStyle(divone, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
-    is(getComputedStyle(divone.firstChild, "").backgroundColor, "transparent",
+    is(getComputedStyle(divone.firstChild, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
     synthesizeMouse(divone, 15, 2, moveEvent, window);
     is(getComputedStyle(divone, "").backgroundColor, "rgb(0, 0, 255)",
        ":hover applies hierarchically");
     is(getComputedStyle(divone.firstChild, "").backgroundColor, "rgb(255, 0, 0)",
        ":hover applies");
 
     /** Test for Bug 302561 **/
@@ -110,17 +110,17 @@ var step3called = false;
 function step3() {
     is(step3called, false, "step3 called only once");
     step3called = true;
     if (getComputedStyle(iframe, "").width == "100px") {
         // The two resize events may be coalesced into a single one.
         step4();
         return;
     }
-    is(getComputedStyle(divtwo, "").backgroundColor, "transparent",
+    is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
     setResize("step4()");
     /* expect to get a second resize from the oscillation */
 }
 
 var step4called = false;
 function step4() {
     is(step4called, false, "step4 called only once (more than two cycles of oscillation)");
@@ -139,29 +139,29 @@ function step5() {
     setResize("step6()");
     synthesizeMouse(divtwoparent, 25, 5, moveEvent, window);
 }
 
 var step6called = false;
 function step6() {
     is(step6called, false, "step6 called only once");
     step6called = true;
-    is(getComputedStyle(divtwo, "").backgroundColor, "transparent",
+    is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
     synthesizeMouse(divtwoparent, 2, 5, moveEvent, window);
     setTimeout(step7, 500); // time to detect oscillations if they exist
 }
 
 var step7called = false;
 function step7() {
     is(step7called, false, "step7 called only once (more than two cycles of oscillation)");
     if (step7called)
         return;
     step7called = true;
-    is(getComputedStyle(divtwo, "").backgroundColor, "transparent",
+    is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
     setTimeout(step8, 500); // time to detect oscillations if they exist
 }
 
 /* test the same case with scrolltop */
 
 var step8called = false;
 function step8() {
@@ -190,17 +190,17 @@ var step10called = false;
 function step10() {
     is(step10called, false, "step10 called only once");
     step10called = true;
     if (getComputedStyle(iframe, "").width == "100px") {
         // The two resize events may be coalesced into a single one.
         step11();
         return;
     }
-    is(getComputedStyle(divtwo, "").backgroundColor, "transparent",
+    is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
     setResize("step11()");
     /* expect to get a second resize from the oscillation */
 }
 
 var step11called = false;
 function step11() {
     is(step11called, false, "step11 called only once (more than two cycles of oscillation)");
@@ -219,17 +219,17 @@ function step12() {
     setResize("step13()");
     divtwoparent.scrollLeft = 25; /* mouse now over 27,5 */
 }
 
 var step13called = false;
 function step13() {
     is(step13called, false, "step13 called only once");
     step13called = true;
-    is(getComputedStyle(divtwo, "").backgroundColor, "transparent",
+    is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
     setResize("step14()");
     divtwoparent.scrollLeft = 0; /* mouse now over 2,5 */
 }
 
 var step14called = false;
 function step14() {
     is(step14called, false, "step14 called only once");
@@ -246,17 +246,17 @@ function step14() {
 }
 
 var step15called = false;
 function step15() {
     is(step15called, false, "step15 called only once (more than two cycles of oscillation)");
     if (step15called)
         return;
     step15called = true;
-    is(getComputedStyle(divtwo, "").backgroundColor, "transparent",
+    is(getComputedStyle(divtwo, "").backgroundColor, "rgba(0, 0, 0, 0)",
        ":hover does not apply");
     setTimeout(finish, 500); // time to detect oscillations if they exist
 }
 
 function finish() {
     document.getElementById("display").style.display = "none";
 
     var tester = window.SimpleTest;
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -2230,18 +2230,18 @@ var gCSSProperties = {
     initial_values: [ "border-box" ],
     other_values: [ "content-box", "padding-box", "border-box, padding-box", "padding-box, padding-box, padding-box", "border-box, border-box" ],
     invalid_values: [ "margin-box", "border-box border-box", "fill-box", "stroke-box", "view-box", "no-clip" ]
   },
   "background-color": {
     domProp: "backgroundColor",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
-    initial_values: [ "transparent", "rgba(255, 127, 15, 0)", "hsla(240, 97%, 50%, 0.0)", "rgba(0, 0, 0, 0)", "rgba(255,255,255,-3.7)" ],
-    other_values: [ "green", "rgb(255, 0, 128)", "#fc2", "#96ed2a", "black", "rgba(255,255,0,3)", "hsl(240, 50%, 50%)", "rgb(50%, 50%, 50%)", "-moz-default-background-color", "rgb(100, 100.0, 100)" ],
+    initial_values: [ "transparent", "rgba(0, 0, 0, 0)" ],
+    other_values: [ "green", "rgb(255, 0, 128)", "#fc2", "#96ed2a", "black", "rgba(255,255,0,3)", "hsl(240, 50%, 50%)", "rgb(50%, 50%, 50%)", "-moz-default-background-color", "rgb(100, 100.0, 100)", "rgba(255, 127, 15, 0)", "hsla(240, 97%, 50%, 0.0)", "rgba(255,255,255,-3.7)" ],
     invalid_values: [ "#0", "#00", "#00000", "#0000000", "#000000000", "rgb(100, 100%, 100)" ],
     quirks_values: { "000000": "#000000", "96ed2a": "#96ed2a" },
   },
   "background-image": {
     domProp: "backgroundImage",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "none" ],
--- a/layout/style/test/stylo-failures.md
+++ b/layout/style/test/stylo-failures.md
@@ -584,17 +584,16 @@ Any line which doesn't follow the format
 * test_value_cloning.html asserts: negative radius bug 1337618 [6]
 
 ## Need Gecko change
 
 * Servo is correct but Gecko is wrong
   * unitless zero as angle bug 1234357
     * test_property_syntax_errors.html `linear-gradient(0,` [10]
     * ... `hue-rotate(0)` [6]
-  * test_bug372770.html: rgba(0,0,0,0) and transparent bug 1328224 [4]
 * test_moz_device_pixel_ratio.html: probably unship -moz-device-pixel-ratio bug 1338425 [4]
 
 ## Spec Unclear
 
 * test_property_syntax_errors.html `'background'`: whether background shorthand should accept "text" [40]
 * test_inherit_computation.html `weight style`: whether font-synthesis should be reset by font w3c/csswg-drafts#1032 [8]
 
 ## Unknown / Unsure
--- a/layout/style/test/test_additional_sheets.html
+++ b/layout/style/test/test_additional_sheets.html
@@ -200,17 +200,17 @@ function loadAndCheck(win, firstType, se
     firstType.type + "(normal)" + " vs " + secondType.type + (swap ? "(important)" : "(normal)" ) + " 1");
   is(cs.getPropertyValue('background-color'), result2,
     firstType.type + "(important)" + " vs " + secondType.type + (swap ? "(normal)" : "(important)" ) + " 2");
 
   firstType.removeRules(win, firstStyle);
   secondType.removeRules(win, secondStyle);
 
   is(cs.getPropertyValue('color'), 'rgb(0, 0, 0)', firstType.type + " vs " + secondType.type + " 3");
-  is(cs.getPropertyValue('background-color'), 'transparent', firstType.type + " vs " + secondType.type + " 4");
+  is(cs.getPropertyValue('background-color'), 'rgba(0, 0, 0, 0)', firstType.type + " vs " + secondType.type + " 4");
 }
 
 // There are 8 cases. Regular against regular, regular against important, important
 // against regular, important against important. We can load style from typeA first
 // then typeB or the other way around so that's 4*2=8 cases.
 
 function testStyleVsStyle(win, typeA, typeB, results)
 {
--- a/layout/style/test/test_bug229915.html
+++ b/layout/style/test/test_bug229915.html
@@ -40,17 +40,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 229915 **/
 
 const GREEN = "rgb(0, 128, 0)";
 const BLACK = "rgb(0, 0, 0)";
-const TRANSPARENT = "transparent";
+const TRANSPARENT = "rgba(0, 0, 0, 0)";
 const WHITE = "rgb(255, 255, 255)";
 
 function make_prev() {
   var result = document.createElement("p");
   result.setAttribute("class", "prev");
   var t = document.createTextNode("Dynamically created previous paragraph.");
   result.appendChild(t);
   return result;
--- a/layout/style/test/test_bug372770.html
+++ b/layout/style/test/test_bug372770.html
@@ -30,28 +30,22 @@ var i;
 for (i = 0; i < colors.length; ++i) {
   var color = colors[i];
   style1.color = color;
   style2.color = color;
   is(style1.color, color, "Inline style color roundtripping failed at color " + i);
   is(style2.color, color, "Rule style color roundtripping failed at color " + i);
 }
 
-// This code is only here because of bug 372783.  Once that's fixed, this test
-// for "rgba(0, 0, 0, 0)" will fail.
 style1.color = "rgba(0, 0, 0, 0)";
 style2.color = "rgba(0, 0, 0, 0)";
-is(style1.color, "transparent",
-   "Inline style should give transparent for rgba(0,0,0,0)");
-is(style2.color, "transparent",
-   "Rule style should give transparent for rgba(0,0,0,0)");
-todo(style1.color == "rgba(0, 0, 0, 0)",
-     "Inline style should round-trip black transparent color correctly");
-todo(style2.color == "rgba(0, 0, 0, 0)",
-     "Rule style should round-trip black transparent color correctly");
+is(style1.color, "rgba(0, 0, 0, 0)",
+   "Inline style should round-trip black transparent color correctly");
+is(style2.color, "rgba(0, 0, 0, 0)",
+   "Rule style should round-trip black transparent color correctly");
 
 for (var i = 0; i <= 100; ++i) {
   if (i == 70 || i == 90) {
     // Tinderbox unhappy for some reason... just skip these for now?
     continue;
   }
   var color1 = "rgba(128, 128, 128, " + i/100 + ")";
   var color2 = "rgba(175, 63, 27, " + i/100 + ")";
--- a/layout/style/test/test_bug635286.html
+++ b/layout/style/test/test_bug635286.html
@@ -31,17 +31,17 @@ window.addEventListener("load", function
   var cases = Array.slice(document.getElementsByTagName("div"));
   cases.forEach(function(aCase, aIndex) {
     aCase.className = "after";
   });
   window.setTimeout(function() {
     cases.forEach(function(aCase, aIndex) {
       is(window.getComputedStyle(aCase)
            .getPropertyValue("background-color"),
-         "transparent",
+         "rgba(0, 0, 0, 0)",
          aCase.textContent);
     });
     SimpleTest.finish();
   }, 1);
 });
 
 SimpleTest.waitForExplicitFinish();
 SimpleTest.requestFlakyTimeout("untriaged");
--- a/layout/style/test/test_computed_style.html
+++ b/layout/style/test/test_computed_style.html
@@ -356,18 +356,18 @@ var noframe_container = document.getElem
 
   var testStyles = {
     "mask" : "",
     "markerStart" : "",
     "markerMid" : "",
     "markerEnd" : "",
     "clipPath" : "",
     "filter" : "",
-    "fill" : " transparent",
-    "stroke" : " transparent",
+    "fill" : " rgba(0, 0, 0, 0)",
+    "stroke" : " rgba(0, 0, 0, 0)",
   };
 
   for (var prop in testStyles) {
     p.style[prop] = localURL;
     is(cs[prop], localURL + testStyles[prop], "computed value of " + prop);
     p.style[prop] = nonLocalURL;
     is(cs[prop], resolvedNonLocalURL + testStyles[prop], "computed value of " + prop);
   }
--- a/layout/style/test/test_default_computed_style.html
+++ b/layout/style/test/test_default_computed_style.html
@@ -40,17 +40,17 @@ is(cs.marginTop, "0px", "We have 0 margi
 is(cs.backgroundColor, "rgb(255, 255, 0)", "We have yellow background");
 is(cs.color, "rgb(0, 0, 255)", "We have blue text");
 is(cs_pseudo.content, '"Visible"', "We have some content");
 is(cs_pseudo.display, "block", "Our ::before is block");
 
 // And now our actual tests
 is(cs_default.display, "block", "We have block display by default");
 is(cs_default.marginTop, "16px", "We have 16px margin by default");
-is(cs_default.backgroundColor, "transparent",
+is(cs_default.backgroundColor, "rgba(0, 0, 0, 0)",
    "We have transparent background by default");
 is(cs_default.color, "rgb(0, 0, 0)", "We have black text by default");
 is(cs_default_pseudo.content, "none", "We have no content by default");
 is(cs_default_pseudo.display, "inline", "Our ::before is inline by default");
 
 
 </script>
 </pre>
--- a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_insertCSS.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_insertCSS.html
@@ -14,17 +14,17 @@
 "use strict";
 
 add_task(function* testExecuteScript() {
   let win = window.open("http://mochi.test:8888/");
 
   async function background() {
     let tasks = [
       {
-        background: "transparent",
+        background: "rgba(0, 0, 0, 0)",
         foreground: "rgb(0, 113, 4)",
         promise: () => {
           return browser.tabs.insertCSS({
             file: "file2.css",
           });
         },
       },
       {
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_chrome_element_css.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_chrome_element_css.py
@@ -15,9 +15,9 @@ class TestChromeElementCSS(MarionetteTes
             element = self.marionette.find_element(By.ID, "identity-icon")
             favicon_image = element.value_of_css_property("list-style-image")
 
             self.assertIn("identity-icon.svg", favicon_image)
 
             element = self.marionette.find_element(By.ID, "identity-box")
             background_colour = element.value_of_css_property("background-color")
 
-            self.assertEqual("transparent", background_colour)
+            self.assertEqual("rgba(0, 0, 0, 0)", background_colour)
--- a/testing/web-platform/meta/editing/run/forecolor.html.ini
+++ b/testing/web-platform/meta/editing/run/forecolor.html.ini
@@ -97,19 +97,16 @@
     expected: FAIL
 
   [[["stylewithcss","false"\],["forecolor","rgb( 0 ,0 ,255)"\]\] "foo[bar\]baz" compare innerHTML]
     expected: FAIL
 
   [[["stylewithcss","false"\],["forecolor","rgb( 0 ,0 ,255)"\]\] "foo[bar\]baz" queryCommandValue("forecolor") after]
     expected: FAIL
 
-  [[["stylewithcss","true"\],["forecolor","rgba(0, 0, 255, 0.0)"\]\] "foo[bar\]baz" queryCommandValue("forecolor") after]
-    expected: FAIL
-
   [[["stylewithcss","false"\],["forecolor","rgba(0, 0, 255, 0.0)"\]\] "foo[bar\]baz" compare innerHTML]
     expected: FAIL
 
   [[["stylewithcss","false"\],["forecolor","rgba(0, 0, 255, 0.0)"\]\] "foo[bar\]baz" queryCommandValue("forecolor") after]
     expected: FAIL
 
   [[["stylewithcss","false"\],["forecolor","rgb(15, -10, 375)"\]\] "foo[bar\]baz" compare innerHTML]
     expected: FAIL
@@ -223,25 +220,19 @@
     expected: FAIL
 
   [[["stylewithcss","false"\],["forecolor","#0000FF"\]\] "<span style=\\"color: rgb(0%, 0%, 100%)\\">[foo\]</span>" compare innerHTML]
     expected: FAIL
 
   [[["stylewithcss","false"\],["forecolor","#0000FF"\]\] "<span style=\\"color: rgb( 0 ,0 ,255)\\">[foo\]</span>" compare innerHTML]
     expected: FAIL
 
-  [[["stylewithcss","true"\],["forecolor","#0000FF"\]\] "<span style=\\"color: rgba(0, 0, 255, 0.0)\\">[foo\]</span>" queryCommandValue("forecolor") before]
-    expected: FAIL
-
   [[["stylewithcss","false"\],["forecolor","#0000FF"\]\] "<span style=\\"color: rgba(0, 0, 255, 0.0)\\">[foo\]</span>" compare innerHTML]
     expected: FAIL
 
-  [[["stylewithcss","false"\],["forecolor","#0000FF"\]\] "<span style=\\"color: rgba(0, 0, 255, 0.0)\\">[foo\]</span>" queryCommandValue("forecolor") before]
-    expected: FAIL
-
   [[["stylewithcss","false"\],["forecolor","#0000FF"\]\] "<span style=\\"color: rgb(15, -10, 375)\\">[foo\]</span>" compare innerHTML]
     expected: FAIL
 
   [[["stylewithcss","false"\],["forecolor","#0000FF"\]\] "<span style=\\"color: rgba(0, 0, 0, 1)\\">[foo\]</span>" compare innerHTML]
     expected: FAIL
 
   [[["stylewithcss","false"\],["forecolor","#0000FF"\]\] "<span style=\\"color: rgba(255, 255, 255, 1)\\">[foo\]</span>" compare innerHTML]
     expected: FAIL
--- a/testing/web-platform/meta/editing/run/hilitecolor.html.ini
+++ b/testing/web-platform/meta/editing/run/hilitecolor.html.ini
@@ -304,19 +304,25 @@
     expected: FAIL
 
   [[["stylewithcss","true"\],["hilitecolor","#00FFFF"\]\] "<span style=background-color:tan>fo[o<span style=background-color:transparent>b\]ar</span></span>" queryCommandValue("hilitecolor") after]
     expected: FAIL
 
   [[["stylewithcss","false"\],["hilitecolor","#00FFFF"\]\] "<span style=background-color:tan>fo[o<span style=background-color:transparent>b\]ar</span></span>" queryCommandValue("hilitecolor") after]
     expected: FAIL
 
+  [[["stylewithcss","true"\],["hilitecolor","#00FFFF"\]\] "<font size=6>[foo\]</font>" queryCommandValue("hilitecolor") after]
+    expected: FAIL
+
   [[["stylewithcss","false"\],["hilitecolor","#00FFFF"\]\] "<font size=6>[foo\]</font>" queryCommandValue("hilitecolor") after]
     expected: FAIL
 
+  [[["stylewithcss","true"\],["hilitecolor","#00FFFF"\]\] "<span style=font-size:xx-large>[foo\]</span>" queryCommandValue("hilitecolor") after]
+    expected: FAIL
+
   [[["stylewithcss","false"\],["hilitecolor","#00FFFF"\]\] "<span style=font-size:xx-large>[foo\]</span>" queryCommandValue("hilitecolor") after]
     expected: FAIL
 
   [[["stylewithcss","true"\],["hilitecolor","#00FFFF"\]\] "<font size=6>foo[bar\]baz</font>" queryCommandValue("hilitecolor") after]
     expected: FAIL
 
   [[["stylewithcss","false"\],["hilitecolor","#00FFFF"\]\] "<font size=6>foo[bar\]baz</font>" queryCommandValue("hilitecolor") after]
     expected: FAIL
--- a/toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_contentscript_about_blank.html
@@ -98,17 +98,17 @@ add_task(function* test_contentscript_ab
   let style = win.getComputedStyle(win.document.body);
   is(style.color, "rgb(255, 0, 0)", "top window text color is red");
   is(style.backgroundColor, "rgb(255, 255, 0)", "top window background is yellow");
   is(style.textAlign, "right", "top window text is right-aligned");
 
   let a_b = win.document.getElementById("a_b");
   style = a_b.contentWindow.getComputedStyle(a_b.contentDocument.body);
   is(style.color, "rgb(255, 0, 0)", "about:blank iframe text color is red");
-  is(style.backgroundColor, "transparent", "about:blank iframe background is transparent");
+  is(style.backgroundColor, "rgba(0, 0, 0, 0)", "about:blank iframe background is transparent");
   is(style.textAlign, "right", "about:blank text is right-aligned");
 
   is(count, 10, "exactly 7 more scripts ran");
   win.close();
 
   yield extension.unload();
 });
 </script>
--- a/toolkit/modules/SelectParentHelper.jsm
+++ b/toolkit/modules/SelectParentHelper.jsm
@@ -47,25 +47,25 @@ this.SelectParentHelper = {
     }
 
     let ruleBody = "";
 
     // Some webpages set the <select> backgroundColor to transparent,
     // but they don't intend to change the popup to transparent.
     if (customStylingEnabled &&
         selectBackgroundColor != uaSelectBackgroundColor &&
-        selectBackgroundColor != "transparent" &&
+        selectBackgroundColor != "rgba(0, 0, 0, 0)" &&
         selectBackgroundColor != selectColor) {
       ruleBody = `background-color: ${selectBackgroundColor};`;
     }
 
     if (customStylingEnabled &&
         selectColor != uaSelectColor &&
         selectColor != selectBackgroundColor &&
-        (selectBackgroundColor != "transparent" ||
+        (selectBackgroundColor != "rgba(0, 0, 0, 0)" ||
          selectColor != uaSelectBackgroundColor)) {
       ruleBody += `color: ${selectColor};`;
     }
 
     if (ruleBody) {
       sheet.insertRule(`menupopup {
         ${ruleBody}
       }`, 0);
@@ -248,17 +248,17 @@ function populateChildren(menulist, opti
     // Keep track of which options are hidden by page content, so we can avoid showing
     // them on search input
     item.hiddenByContent = item.hidden;
     item.setAttribute("tooltiptext", option.tooltip);
 
     let ruleBody = "";
     if (customStylingEnabled &&
         option.backgroundColor &&
-        option.backgroundColor != "transparent" &&
+        option.backgroundColor != "rgba(0, 0, 0, 0)" &&
         option.backgroundColor != uaBackgroundColor) {
       ruleBody = `background-color: ${option.backgroundColor};`;
     }
 
     if (customStylingEnabled &&
         option.color &&
         option.color != uaColor) {
       ruleBody += `color: ${option.color};`;