diff options
author | FranklinDM <mrmineshafter17@gmail.com> | 2023-01-06 21:07:37 +0800 |
---|---|---|
committer | FranklinDM <mrmineshafter17@gmail.com> | 2023-01-06 22:13:08 +0800 |
commit | b5f8fa64790d0ef75bfd79e72c9cd4a4098277f5 (patch) | |
tree | 9c92133410d592e3e953faa3d602c5263b62f2f2 /layout | |
parent | af3a27e8388fbb8cca9b30f2e8cbc0eb8ad9a336 (diff) | |
download | uxp-b5f8fa64790d0ef75bfd79e72c9cd4a4098277f5.tar.gz |
Issue #2084 - Part 1: Remove CSSUnprefixingService.js and associated code
It's effectively dead code since it's been supplanted by built-in webkit-prefixed-CSS support (landed before fork point in Firefox 49).
Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1259348
Diffstat (limited to 'layout')
-rw-r--r-- | layout/style/CSSUnprefixingService.js | 341 | ||||
-rw-r--r-- | layout/style/CSSUnprefixingService.manifest | 2 | ||||
-rw-r--r-- | layout/style/moz.build | 11 | ||||
-rw-r--r-- | layout/style/nsCSSParser.cpp | 215 | ||||
-rw-r--r-- | layout/style/nsICSSUnprefixingService.idl | 76 | ||||
-rw-r--r-- | layout/style/test/mochitest.ini | 4 | ||||
-rw-r--r-- | layout/style/test/test_unprefixing_service.html | 93 | ||||
-rw-r--r-- | layout/style/test/test_unprefixing_service_prefs.html | 132 | ||||
-rw-r--r-- | layout/style/test/unprefixing_service_iframe.html | 394 | ||||
-rw-r--r-- | layout/style/test/unprefixing_service_utils.js | 87 |
10 files changed, 11 insertions, 1344 deletions
diff --git a/layout/style/CSSUnprefixingService.js b/layout/style/CSSUnprefixingService.js deleted file mode 100644 index f6c63a0237..0000000000 --- a/layout/style/CSSUnprefixingService.js +++ /dev/null @@ -1,341 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- / -/* 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/. */ - -/* Implementation of a service that converts certain vendor-prefixed CSS - properties to their unprefixed equivalents, for sites on a whitelist. */ - -"use strict"; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cu = Components.utils; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -function CSSUnprefixingService() { -} - -CSSUnprefixingService.prototype = { - // Boilerplate: - classID: Components.ID("{f0729490-e15c-4a2f-a3fb-99e1cc946b42}"), - _xpcom_factory: XPCOMUtils.generateSingletonFactory(CSSUnprefixingService), - QueryInterface: XPCOMUtils.generateQI([Ci.nsICSSUnprefixingService]), - - // See documentation in nsICSSUnprefixingService.idl - generateUnprefixedDeclaration: function(aPropName, aRightHalfOfDecl, - aUnprefixedDecl /*out*/) { - - // Convert our input strings to lower-case, for easier string-matching. - // (NOTE: If we ever need to add support for unprefixing properties that - // have case-sensitive parts, then we should do these toLowerCase() - // conversions in a more targeted way, to avoid breaking those properties.) - aPropName = aPropName.toLowerCase(); - aRightHalfOfDecl = aRightHalfOfDecl.toLowerCase(); - - // We have several groups of supported properties: - // FIRST GROUP: Properties that can just be handled as aliases: - // ============================================================ - const propertiesThatAreJustAliases = { - "-webkit-background-size": "background-size", - "-webkit-box-flex": "flex-grow", - "-webkit-box-ordinal-group": "order", - "-webkit-box-sizing": "box-sizing", - "-webkit-transform": "transform", - "-webkit-transform-origin": "transform-origin", - }; - - let unprefixedPropName = propertiesThatAreJustAliases[aPropName]; - if (unprefixedPropName !== undefined) { - aUnprefixedDecl.value = unprefixedPropName + ":" + aRightHalfOfDecl; - return true; - } - - // SECOND GROUP: Properties that take a single keyword, where the - // unprefixed version takes a different (but analogous) set of keywords: - // ===================================================================== - const propertiesThatNeedKeywordMapping = { - "-webkit-box-align" : { - unprefixedPropName : "align-items", - valueMap : { - "start" : "flex-start", - "center" : "center", - "end" : "flex-end", - "baseline" : "baseline", - "stretch" : "stretch" - } - }, - "-webkit-box-orient" : { - unprefixedPropName : "flex-direction", - valueMap : { - "horizontal" : "row", - "inline-axis" : "row", - "vertical" : "column", - "block-axis" : "column" - } - }, - "-webkit-box-pack" : { - unprefixedPropName : "justify-content", - valueMap : { - "start" : "flex-start", - "center" : "center", - "end" : "flex-end", - "justify" : "space-between" - } - }, - }; - - let propInfo = propertiesThatNeedKeywordMapping[aPropName]; - if (typeof(propInfo) != "undefined") { - // Regexp for parsing the right half of a declaration, for keyword-valued - // properties. Divides the right half of the declaration into: - // 1) any leading whitespace - // 2) the property value (one or more alphabetical character or hyphen) - // 3) anything after that (e.g. "!important", ";") - // Then we can look up the appropriate unprefixed-property value for the - // value (part 2), and splice that together with the other parts and with - // the unprefixed property-name to make the final declaration. - const keywordValuedPropertyRegexp = /^(\s*)([a-z\-]+)(.*)/; - let parts = keywordValuedPropertyRegexp.exec(aRightHalfOfDecl); - if (!parts) { - // Failed to parse a keyword out of aRightHalfOfDecl. (It probably has - // no alphabetical characters.) - return false; - } - - let mappedKeyword = propInfo.valueMap[parts[2]]; - if (mappedKeyword === undefined) { - // We found a keyword in aRightHalfOfDecl, but we don't have a mapping - // to an equivalent keyword for the unprefixed version of the property. - return false; - } - - aUnprefixedDecl.value = propInfo.unprefixedPropName + ":" + - parts[1] + // any leading whitespace - mappedKeyword + - parts[3]; // any trailing text (e.g. !important, semicolon, etc) - - return true; - } - - // THIRD GROUP: Properties that may need arbitrary string-replacement: - // =================================================================== - const propertiesThatNeedStringReplacement = { - // "-webkit-transition" takes a multi-part value. If "-webkit-transform" - // appears as part of that value, replace it w/ "transform". - // And regardless, we unprefix the "-webkit-transition" property-name. - // (We could handle other prefixed properties in addition to 'transform' - // here, but in practice "-webkit-transform" is the main one that's - // likely to be transitioned & that we're concerned about supporting.) - "-webkit-transition": { - unprefixedPropName : "transition", - stringMap : { - "-webkit-transform" : "transform", - } - }, - }; - - propInfo = propertiesThatNeedStringReplacement[aPropName]; - if (typeof(propInfo) != "undefined") { - let newRightHalf = aRightHalfOfDecl; - for (let strToReplace in propInfo.stringMap) { - let replacement = propInfo.stringMap[strToReplace]; - newRightHalf = newRightHalf.split(strToReplace).join(replacement); - } - aUnprefixedDecl.value = propInfo.unprefixedPropName + ":" + newRightHalf; - - return true; - } - - // No known mapping for property aPropName. - return false; - }, - - // See documentation in nsICSSUnprefixingService.idl - generateUnprefixedGradientValue: function(aPrefixedFuncName, - aPrefixedFuncBody, - aUnprefixedFuncName, /*[out]*/ - aUnprefixedFuncBody /*[out]*/) { - var unprefixedFuncName, newValue; - if (aPrefixedFuncName == "-webkit-gradient") { - // Create expression for oldGradientParser: - var parts = this.oldGradientParser(aPrefixedFuncBody); - var type = parts[0].name; - newValue = this.standardizeOldGradientArgs(type, parts.slice(1)); - unprefixedFuncName = type + "-gradient"; - }else{ // we're dealing with more modern syntax - should be somewhat easier, at least for linear gradients. - // Fix three things: remove -webkit-, add 'to ' before reversed top/bottom keywords (linear) or 'at ' before position keywords (radial), recalculate deg-values - // -webkit-linear-gradient( [ [ <angle> | [top | bottom] || [left | right] ],]? <color-stop>[, <color-stop>]+); - if (aPrefixedFuncName != "-webkit-linear-gradient" && - aPrefixedFuncName != "-webkit-radial-gradient") { - // Unrecognized prefixed gradient type - return false; - } - unprefixedFuncName = aPrefixedFuncName.replace(/-webkit-/, ''); - - // Keywords top, bottom, left, right: can be stand-alone or combined pairwise but in any order ('top left' or 'left top') - // These give the starting edge or corner in the -webkit syntax. The standardised equivalent is 'to ' plus opposite values for linear gradients, 'at ' plus same values for radial gradients - if(unprefixedFuncName.indexOf('linear') > -1){ - newValue = aPrefixedFuncBody.replace(/(top|bottom|left|right)+\s*(top|bottom|left|right)*/, function(str){ - var words = str.split(/\s+/); - for(var i=0; i<words.length; i++){ - switch(words[i].toLowerCase()){ - case 'top': - words[i] = 'bottom'; - break; - case 'bottom': - words[i] = 'top'; - break; - case 'left': - words[i] = 'right'; - break; - case 'right': - words[i] = 'left'; - } - } - str = words.join(' '); - return ( 'to ' + str); - }); - }else{ - newValue = aPrefixedFuncBody.replace(/(top|bottom|left|right)+\s/, 'at $1 '); - } - - newValue = newValue.replace(/\d+deg/, function (val) { - return (360 - (parseInt(val)-90))+'deg'; - }); - - } - aUnprefixedFuncName.value = unprefixedFuncName; - aUnprefixedFuncBody.value = newValue; - return true; - }, - - // Helpers for generateUnprefixedGradientValue(): - // ---------------------------------------------- - oldGradientParser : function(str){ - /** This method takes a legacy -webkit-gradient() method call and parses it - to pull out the values, function names and their arguments. - It returns something like [{name:'-webkit-gradient',args:[{name:'linear'}, {name:'top left'} ... ]}] - */ - var objs = [{}], path=[], current, word='', separator_chars = [',', '(', ')']; - current = objs[0], path[0] = objs; - //str = str.replace(/\s*\(/g, '('); // sorry, ws in front of ( would make parsing a lot harder - for(var i = 0; i < str.length; i++){ - if(separator_chars.indexOf(str[i]) === -1){ - word += str[i]; - }else{ // now we have a "separator" - presumably we've also got a "word" or value - current.name = word.trim(); - //GM_log(word+' '+path.length+' '+str[i]) - word = ''; - if(str[i] === '('){ // we assume the 'word' is a function, for example -webkit-gradient() or rgb(), so we create a place to record the arguments - if(!('args' in current)){ - current.args = []; - } - current.args.push({}); - path.push(current.args); - current = current.args[current.args.length - 1]; - path.push(current); - }else if(str[i] === ')'){ // function is ended, no more arguments - go back to appending details to the previous branch of the tree - current = path.pop(); // drop 'current' - current = path.pop(); // drop 'args' reference - }else{ - path.pop(); // remove 'current' object from path, we have no arguments to add - var current_parent = path[path.length - 1] || objs; // last object on current path refers to array that contained the previous "current" - current_parent.push({}); // we need a new object to hold this "word" or value - current = current_parent[current_parent.length - 1]; // that object is now the 'current' - path.push(current); -//GM_log(path.length) - } - } - } - - return objs; - }, - - /* Given an array of args for "-webkit-gradient(...)" returned by - * oldGradientParser(), this function constructs a string representing the - * equivalent arguments for a standard "linear-gradient(...)" or - * "radial-gradient(...)" expression. - * - * @param type Either 'linear' or 'radial'. - * @param args An array of args for a "-webkit-gradient(...)" expression, - * provided by oldGradientParser() (not including gradient type). - */ - standardizeOldGradientArgs : function(type, args){ - var stdArgStr = ""; - var stops = []; - if(/^linear/.test(type)){ - // linear gradient, args 1 and 2 tend to be start/end keywords - var points = [].concat(args[0].name.split(/\s+/), args[1].name.split(/\s+/)); // example: [left, top, right, top] - // Old webkit syntax "uses a two-point syntax that lets you explicitly state where a linear gradient starts and ends" - // if start/end keywords are percentages, let's massage the values a little more.. - var rxPercTest = /\d+\%/; - if(rxPercTest.test(points[0]) || points[0] == 0){ - var startX = parseInt(points[0]), startY = parseInt(points[1]), endX = parseInt(points[2]), endY = parseInt(points[3]); - stdArgStr += ((Math.atan2(endY- startY, endX - startX)) * (180 / Math.PI)+90) + 'deg'; - }else{ - if(points[1] === points[3]){ // both 'top' or 'bottom, this linear gradient goes left-right - stdArgStr += 'to ' + points[2]; - }else if(points[0] === points[2]){ // both 'left' or 'right', this linear gradient goes top-bottom - stdArgStr += 'to ' + points[3]; - }else if(points[1] === 'top'){ // diagonal gradient - from top left to opposite corner is 135deg - stdArgStr += '135deg'; - }else{ - stdArgStr += '45deg'; - } - } - - }else if(/^radial/i.test(type)){ // oooh, radial gradients.. - stdArgStr += 'circle ' + args[3].name.replace(/(\d+)$/, '$1px') + ' at ' + args[0].name.replace(/(\d+) /, '$1px ').replace(/(\d+)$/, '$1px'); - } - - var toColor; - for(var j = type === 'linear' ? 2 : 4; j < args.length; j++){ - var position, color, colorIndex; - if(args[j].name === 'color-stop'){ - position = args[j].args[0].name; - colorIndex = 1; - }else if (args[j].name === 'to') { - position = '100%'; - colorIndex = 0; - }else if (args[j].name === 'from') { - position = '0%'; - colorIndex = 0; - }; - if (position.indexOf('%') === -1) { // original Safari syntax had 0.5 equivalent to 50% - position = (parseFloat(position) * 100) +'%'; - }; - color = args[j].args[colorIndex].name; - if (args[j].args[colorIndex].args) { // the color is itself a function call, like rgb() - color += '(' + this.colorValue(args[j].args[colorIndex].args) + ')'; - }; - if (args[j].name === 'from'){ - stops.unshift(color + ' ' + position); - }else if(args[j].name === 'to'){ - toColor = color; - }else{ - stops.push(color + ' ' + position); - } - } - - // translating values to right syntax - for(var j = 0; j < stops.length; j++){ - stdArgStr += ', ' + stops[j]; - } - if(toColor){ - stdArgStr += ', ' + toColor + ' 100%'; - } - return stdArgStr; - }, - - colorValue: function(obj){ - var ar = []; - for (var i = 0; i < obj.length; i++) { - ar.push(obj[i].name); - }; - return ar.join(', '); - }, -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([CSSUnprefixingService]); diff --git a/layout/style/CSSUnprefixingService.manifest b/layout/style/CSSUnprefixingService.manifest deleted file mode 100644 index 08143d4ab8..0000000000 --- a/layout/style/CSSUnprefixingService.manifest +++ /dev/null @@ -1,2 +0,0 @@ -component {f0729490-e15c-4a2f-a3fb-99e1cc946b42} CSSUnprefixingService.js -contract @mozilla.org/css-unprefixing-service;1 {f0729490-e15c-4a2f-a3fb-99e1cc946b42} diff --git a/layout/style/moz.build b/layout/style/moz.build index 066d8d3f80..48072b0cdc 100644 --- a/layout/style/moz.build +++ b/layout/style/moz.build @@ -20,12 +20,6 @@ with Files('nsDOM*'): TEST_DIRS += ['test'] -XPIDL_SOURCES += [ - 'nsICSSUnprefixingService.idl', -] - -XPIDL_MODULE = 'layout_base' - EXPORTS += [ '!nsStyleStructList.h', 'AnimationCommon.h', @@ -214,11 +208,6 @@ SOURCES += [ 'nsLayoutStylesheetCache.cpp', ] -EXTRA_COMPONENTS += [ - 'CSSUnprefixingService.js', - 'CSSUnprefixingService.manifest', -] - include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index b981a553f3..64ded6826e 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -43,7 +43,6 @@ #include "nsIMediaList.h" #include "nsStyleUtil.h" #include "nsIPrincipal.h" -#include "nsICSSUnprefixingService.h" #include "mozilla/Sprintf.h" #include "nsContentUtils.h" #include "nsAutoPtr.h" @@ -66,8 +65,6 @@ typedef nsCSSProps::KTableEntry KTableEntry; static bool sOpentypeSVGEnabled; static bool sWebkitPrefixedAliasesEnabled; static bool sWebkitDevicePixelRatioEnabled; -static bool sUnprefixingServiceEnabled; -static bool sUnprefixingServiceGloballyWhitelisted; static bool sMozGradientsEnabled; static bool sControlCharVisibility; @@ -798,9 +795,7 @@ protected: enum { eParseDeclaration_InBraces = 1 << 0, - eParseDeclaration_AllowImportant = 1 << 1, - // The declaration we're parsing was generated by the CSSUnprefixingService: - eParseDeclaration_FromUnprefixingSvc = 1 << 2 + eParseDeclaration_AllowImportant = 1 << 1 }; enum nsCSSContextType { eCSSContext_General, @@ -823,20 +818,6 @@ protected: nsCSSKeyword LookupKeywordPrefixAware(nsAString& aKeywordStr, const KTableEntry aKeywordTable[]); - bool ShouldUseUnprefixingService() const; - bool ParsePropertyWithUnprefixingService(const nsAString& aPropertyName, - css::Declaration* aDeclaration, - uint32_t aFlags, - bool aMustCallValueAppended, - bool* aChanged, - nsCSSContextType aContext); - // When we detect a webkit-prefixed gradient expression, this function can be - // used to parse its body into outparam |aValue|, with the help of the - // CSSUnprefixingService. - // Only call if ShouldUseUnprefixingService() returns true. - bool ParseWebkitPrefixedGradientWithService(nsAString& aPrefixedFuncName, - nsCSSValue& aValue); - bool ParseProperty(nsCSSPropertyID aPropID); bool ParsePropertyByFunction(nsCSSPropertyID aPropID); CSSParseResult ParseSingleValueProperty(nsCSSValue& aValue, @@ -1515,9 +1496,8 @@ protected: // This enum helps us track whether we've unprefixed "display: -webkit-box" // (treating it as "display: flex") in an earlier declaration within a series - // of declarations. (This only impacts behavior when the function - // "ShouldUseUnprefixingService()" returns true, and that should only happen - // for a short whitelist of origins.) + // of declarations. (This only impacts behavior if + // sWebkitPrefixedAliasesEnabled is true.) enum WebkitBoxUnprefixState : uint8_t { eNotParsingDecls, // We are *not* currently parsing a sequence of // CSS declarations. (default state) @@ -7142,7 +7122,9 @@ CSSParserImpl::LookupKeywordPrefixAware(nsAString& aKeywordStr, // explicitly defers to the former. if ((keyword == eCSSKeyword__webkit_box || keyword == eCSSKeyword__webkit_inline_box)) { - const bool usingUnprefixingService = ShouldUseUnprefixingService(); + const bool usingUnprefixingService = false; + // XXXdholbert This bool^ will be removed & this whole function will be + // simplified in the next patch in this series. if (sWebkitPrefixedAliasesEnabled || usingUnprefixingService) { // Make a note that we're accepting some "-webkit-{inline-}box" styling, // so we can give special treatment to subsequent "-moz-{inline}-box". @@ -7171,10 +7153,9 @@ CSSParserImpl::LookupKeywordPrefixAware(nsAString& aKeywordStr, if (mWebkitBoxUnprefixState == eHaveUnprefixed && (keyword == eCSSKeyword__moz_box || keyword == eCSSKeyword__moz_inline_box)) { - MOZ_ASSERT(sWebkitPrefixedAliasesEnabled || ShouldUseUnprefixingService(), - "mDidUnprefixWebkitBoxInEarlierDecl should only be set if " - "we're supporting webkit-prefixed aliases, or if we're using " - "the css unprefixing service on this site"); + MOZ_ASSERT(sWebkitPrefixedAliasesEnabled, + "The only way mWebkitBoxUnprefixState can be eHaveUnprefixed " + "is if we're supporting webkit-prefixed aliases"); if (sWebkitPrefixedAliasesEnabled) { return (keyword == eCSSKeyword__moz_box) ? eCSSKeyword__webkit_box : eCSSKeyword__webkit_inline_box; @@ -7189,152 +7170,6 @@ CSSParserImpl::LookupKeywordPrefixAware(nsAString& aKeywordStr, return keyword; } -bool -CSSParserImpl::ShouldUseUnprefixingService() const -{ - if (!sUnprefixingServiceEnabled) { - // Unprefixing is globally disabled. - return false; - } - if (sWebkitPrefixedAliasesEnabled) { - // Native webkit-prefix support is enabled, which trumps the unprefixing - // service for handling prefixed CSS. Don't try to use both at once. - return false; - } - - if (sUnprefixingServiceGloballyWhitelisted) { - // Unprefixing is globally whitelisted, - // so no need to check mSheetPrincipal. - return true; - } - - // Unprefixing enabled; see if our principal is whitelisted for unprefixing. - return mSheetPrincipal && mSheetPrincipal->IsOnCSSUnprefixingWhitelist(); -} - -bool -CSSParserImpl::ParsePropertyWithUnprefixingService( - const nsAString& aPropertyName, - css::Declaration* aDeclaration, - uint32_t aFlags, - bool aMustCallValueAppended, - bool* aChanged, - nsCSSContextType aContext) -{ - MOZ_ASSERT(ShouldUseUnprefixingService(), - "Caller should've checked ShouldUseUnprefixingService()"); - - nsCOMPtr<nsICSSUnprefixingService> unprefixingSvc = - do_GetService(NS_CSSUNPREFIXINGSERVICE_CONTRACTID); - NS_ENSURE_TRUE(unprefixingSvc, false); - - // Save the state so we can jump back to this spot if our unprefixing fails - // (so we can behave as if we didn't even try to unprefix). - nsAutoCSSParserInputStateRestorer parserStateBeforeTryingToUnprefix(this); - - // Caller has already parsed the first half of the declaration -- - // aPropertyName and the ":". Now, we record the rest of the CSS declaration - // (the part after ':') into rightHalfOfDecl. (This is the property value, - // plus anything else up to the end of the declaration -- maybe "!important", - // maybe trailing junk characters, maybe a semicolon, maybe a trailing "}".) - bool checkForBraces = (aFlags & eParseDeclaration_InBraces) != 0; - nsAutoString rightHalfOfDecl; - mScanner->StartRecording(); - SkipDeclaration(checkForBraces); - mScanner->StopRecording(rightHalfOfDecl); - - // Try to unprefix: - bool success; - nsAutoString unprefixedDecl; - nsresult rv = - unprefixingSvc->GenerateUnprefixedDeclaration(aPropertyName, - rightHalfOfDecl, - unprefixedDecl, &success); - if (NS_FAILED(rv) || !success) { - return false; - } - - // Attempt to parse the unprefixed declaration: - nsAutoScannerChanger scannerChanger(this, unprefixedDecl); - success = ParseDeclaration(aDeclaration, - aFlags | eParseDeclaration_FromUnprefixingSvc, - aMustCallValueAppended, aChanged, aContext); - if (success) { - // We succeeded, so we'll leave the parser pointing at the end of - // the declaration; don't restore it to the pre-recording position. - parserStateBeforeTryingToUnprefix.DoNotRestore(); - } - - return success; -} - -bool -CSSParserImpl::ParseWebkitPrefixedGradientWithService( - nsAString& aPrefixedFuncName, - nsCSSValue& aValue) -{ - MOZ_ASSERT(ShouldUseUnprefixingService(), - "Should only call if we're allowed to use unprefixing service"); - - // Record the body of the "-webkit-*gradient" function into a string. - // Note: we're already just after the opening "(". - nsAutoString prefixedFuncBody; - mScanner->StartRecording(); - bool gotCloseParen = SkipUntil(')'); - mScanner->StopRecording(prefixedFuncBody); - if (gotCloseParen) { - // Strip off trailing close-paren, so that the value we pass to the - // unprefixing service is *just* the function-body (no parens). - prefixedFuncBody.Truncate(prefixedFuncBody.Length() - 1); - } - - // NOTE: Even if we fail, we'll be leaving the parser's cursor just after - // the close of the "-webkit-*gradient(...)" expression. This is the same - // behavior that the other Parse*Gradient functions have in their failure - // cases -- they call "SkipUntil(')') before returning false. So this is - // probably what we want. - nsCOMPtr<nsICSSUnprefixingService> unprefixingSvc = - do_GetService(NS_CSSUNPREFIXINGSERVICE_CONTRACTID); - NS_ENSURE_TRUE(unprefixingSvc, false); - - bool success; - nsAutoString unprefixedFuncName; - nsAutoString unprefixedFuncBody; - nsresult rv = - unprefixingSvc->GenerateUnprefixedGradientValue(aPrefixedFuncName, - prefixedFuncBody, - unprefixedFuncName, - unprefixedFuncBody, - &success); - - if (NS_FAILED(rv) || !success) { - return false; - } - - // JS service thinks it successfully converted the gradient! Now let's try - // to parse the resulting string. - - // First, add a close-paren if we originally recorded one (so that what we're - // about to put into the CSS parser is a faithful representation of what it - // would've seen if it were just parsing the original input stream): - if (gotCloseParen) { - unprefixedFuncBody.Append(char16_t(')')); - } - - nsAutoScannerChanger scannerChanger(this, unprefixedFuncBody); - if (unprefixedFuncName.EqualsLiteral("linear-gradient")) { - return ParseLinearGradient(aValue, 0); - } - if (unprefixedFuncName.EqualsLiteral("radial-gradient")) { - return ParseRadialGradient(aValue, 0); - } - - NS_ERROR("CSSUnprefixingService returned an unrecognized type of " - "gradient function"); - - return false; -} - //---------------------------------------------------------------------- bool @@ -7424,19 +7259,7 @@ CSSParserImpl::ParseDeclaration(css::Declaration* aDeclaration, (aContext == eCSSContext_Page && !nsCSSProps::PropHasFlags(propID, CSS_PROPERTY_APPLIES_TO_PAGE_RULE))) { // unknown property - if (NonMozillaVendorIdentifier(propertyName)) { - if (!mInSupportsCondition && - aContext == eCSSContext_General && - !(aFlags & eParseDeclaration_FromUnprefixingSvc) && // no recursion - ShouldUseUnprefixingService()) { - if (ParsePropertyWithUnprefixingService(propertyName, - aDeclaration, aFlags, - aMustCallValueAppended, - aChanged, aContext)) { - return true; - } - } - } else { + if (!NonMozillaVendorIdentifier(propertyName)) { REPORT_UNEXPECTED_P(PEUnknownProperty, propertyName); REPORT_UNEXPECTED(PEDeclDropped); OUTPUT_ERROR(); @@ -8064,18 +7887,6 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue, } return CSSParseResult::Ok; } - - if (ShouldUseUnprefixingService() && - !gradientFlags && - StringBeginsWith(tmp, NS_LITERAL_STRING("-webkit-"))) { - // Copy 'tmp' into a string on the stack, since as soon as we - // start parsing, its backing store (in "tk") will be overwritten - nsAutoString prefixedFuncName(tmp); - if (!ParseWebkitPrefixedGradientWithService(prefixedFuncName, aValue)) { - return CSSParseResult::Error; - } - return CSSParseResult::Ok; - } } if ((aVariantMask & VARIANT_IMAGE_RECT) != 0 && eCSSToken_Function == tk->mType && @@ -12417,7 +12228,7 @@ CSSParserImpl::IsFunctionTokenValidForImageLayerImage( funcName.LowerCaseEqualsLiteral("-moz-repeating-radial-gradient") || funcName.LowerCaseEqualsLiteral("-moz-image-rect") || funcName.LowerCaseEqualsLiteral("-moz-element") || - ((sWebkitPrefixedAliasesEnabled || ShouldUseUnprefixingService()) && + (sWebkitPrefixedAliasesEnabled && (funcName.LowerCaseEqualsLiteral("-webkit-gradient") || funcName.LowerCaseEqualsLiteral("-webkit-linear-gradient") || funcName.LowerCaseEqualsLiteral("-webkit-radial-gradient") || @@ -17994,10 +17805,6 @@ nsCSSParser::Startup() "layout.css.prefixes.webkit"); Preferences::AddBoolVarCache(&sWebkitDevicePixelRatioEnabled, "layout.css.prefixes.device-pixel-ratio-webkit"); - Preferences::AddBoolVarCache(&sUnprefixingServiceEnabled, - "layout.css.unprefixing-service.enabled"); - Preferences::AddBoolVarCache(&sUnprefixingServiceGloballyWhitelisted, - "layout.css.unprefixing-service.globally-whitelisted"); Preferences::AddBoolVarCache(&sMozGradientsEnabled, "layout.css.prefixes.gradients"); Preferences::AddBoolVarCache(&sControlCharVisibility, diff --git a/layout/style/nsICSSUnprefixingService.idl b/layout/style/nsICSSUnprefixingService.idl deleted file mode 100644 index 11c3bf43f1..0000000000 --- a/layout/style/nsICSSUnprefixingService.idl +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -/* interface for a service that converts certain vendor-prefixed CSS properties - to their unprefixed equivalents */ - -#include "nsISupports.idl" - -[scriptable, uuid(a5d6e2f4-d3ec-11e4-b002-782bcbaebb28)] -interface nsICSSUnprefixingService : nsISupports -{ - /** - * This function helps to convert unsupported vendor-prefixed CSS into - * supported unprefixed CSS. Given a vendor-prefixed property name and a - * value (or e.g. value + trailing junk like " !important;}"), this function - * will attempt to produce an equivalent CSS declaration that uses a - * supported unprefixed CSS property. - * - * @param aPropName - * The vendor-prefixed property name. - * - * @param aRightHalfOfDecl - * Everything after the ":" in the CSS declaration. This includes - * the property's value, along with possibly some leading whitespace - * and trailing text like "!important", and possibly a ';' and/or - * '}' (along with any other bogus text the author happens to - * include before those, which will probably make the decl invalid). - * - * @param aUnprefixedDecl[out] - * The resulting unprefixed declaration, if we return true. - * - * @return true if we were able to unprefix -- i.e. if we were able to - * convert the property to a known unprefixed equivalent, and we also - * performed any known-to-be-necessary fixup on the value, and we put - * the result in aUnprefixedDecl. - * Otherwise, this function returns false. - */ - boolean generateUnprefixedDeclaration(in AString aPropName, - in AString aRightHalfOfDecl, - out AString aUnprefixedDecl); - - /** - * @param aPrefixedFuncName - * The webkit-prefixed gradient function: either - * "-webkit-gradient", "-webkit-linear-gradient", or - * "-webkit-radial-gradient". - * - * @param aPrefixedFuncBody - * The body of the gradient function, inside (& not including) the - * parenthesis. - * - * @param aUnprefixedFuncName[out] - * The resulting unprefixed gradient function name: - * either "linear-gradient" or "radial-gradient". - * - * @param aUnprefixedFuncBody[out] - * The resulting unprefixed gradient function body, suitable for - * including in a "linear-gradient(...)" or "radial-gradient(...)" - * expression. - * - * @returns true if we were able to successfully parse aWebkitGradientStr - * and populate the outparams accordingly; false otherwise. - * - */ - boolean generateUnprefixedGradientValue(in AString aPrefixedFuncName, - in AString aPrefixedFuncBody, - out AString aUnprefixedFuncName, - out AString aUnprefixedFuncBody); -}; - -%{C++ -#define NS_CSSUNPREFIXINGSERVICE_CONTRACTID \ - "@mozilla.org/css-unprefixing-service;1" -%} diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 8b36e3e1e8..2f0ab87a28 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -273,10 +273,6 @@ support-files = ../../reftests/fonts/markA.woff ../../reftests/fonts/markB.woff [test_units_frequency.html] [test_units_length.html] [test_units_time.html] -[test_unprefixing_service.html] -support-files = unprefixing_service_iframe.html unprefixing_service_utils.js -[test_unprefixing_service_prefs.html] -support-files = unprefixing_service_iframe.html unprefixing_service_utils.js [test_value_cloning.html] [test_value_computation.html] [test_value_storage.html] diff --git a/layout/style/test/test_unprefixing_service.html b/layout/style/test/test_unprefixing_service.html deleted file mode 100644 index c489e2ac01..0000000000 --- a/layout/style/test/test_unprefixing_service.html +++ /dev/null @@ -1,93 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=1107378 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 1107378</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <script type="application/javascript;version=1.7" src="unprefixing_service_utils.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1107378">Mozilla Bug 1107378</a> -<div id="display"> - <iframe id="testIframe"></iframe> -</div> -<pre id="test"> -<script type="application/javascript;version=1.7"> -"use strict"; -SimpleTest.waitForExplicitFinish(); - -/** - * This test checks that unprefixing is enabled for whitelisted domains, and - * that it's disabled for non-whitelisted domains. - * - * We do this using an iframe, in which we load a test file at a test domain, - * and we have the iframe report back to us (using postMessage) about - * whether unprefixing is working. - * - * High-level overview of the process here: - * - First, we tweak prefs to enable unprefixing & enable the test-only - * entries in our unprefixing whitelist. - * - The rest of this test is driven by the "startNextTest()" method. - * This method pops a hostname to test and loads a URL from that host - * in the iframe. - * - We then listen for test-results from the iframe, using the postMessage - * handler in unprefixing_service_utils.js. - * - When the iframe indicates that it's done, we call "startNextTest()" - * again to pop the next host & load *that* in the iframe. - * - When nothing remains to be popped, we're done. - */ - -const IFRAME_TESTFILE = "unprefixing_service_iframe.html"; - -// This function gets invoked when our iframe finishes a given round of testing. -function startNextTest() -{ - // Test the next whitelisted host, if any remain. - if (gWhitelistedHosts.length > 0) { - let host = gWhitelistedHosts.pop(); - info("Verifying that CSS Unprefixing Service is active, " + - "at whitelisted test-host '" + host + "'"); - testHost(host, true); - return; - } - - // Test the next not-whitelisted host, if any remain. - if (gNotWhitelistedHosts.length > 0) { - let host = gNotWhitelistedHosts.pop(); - info("Verifying that CSS Unprefixing Service is inactive, " + - "at non-whitelisted test-host '" + host + "'"); - testHost(host, false); - return; - } - - // Both arrays empty --> we're done. - SimpleTest.finish(); -} - -function begin() -{ - // Before we start loading things in iframes, set up postMessage handler. - registerPostMessageListener(startNextTest); - - // Turn on prefs & start the first test! - SpecialPowers.pushPrefEnv( - { set: [[PREF_UNPREFIXING_SERVICE, true], - [PREF_INCLUDE_TEST_DOMAINS, true], - // Make sure *native* -webkit prefix support is turned off. It's - // not whitelist-restricted, so if we left it enabled, it'd prevent - // us from being able to detect CSSUnprefixingService's domain - // whitelisting in this test. - ["layout.css.prefixes.webkit", false]]}, - startNextTest); -} - -begin(); - -</script> -</pre> -</body> -</html> diff --git a/layout/style/test/test_unprefixing_service_prefs.html b/layout/style/test/test_unprefixing_service_prefs.html deleted file mode 100644 index 329dce2a63..0000000000 --- a/layout/style/test/test_unprefixing_service_prefs.html +++ /dev/null @@ -1,132 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=1132743 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 1132743</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <script type="application/javascript;version=1.7" src="unprefixing_service_utils.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1132743">Mozilla Bug 1132743</a> -<div id="display"> - <iframe id="testIframe"></iframe> -</div> -<pre id="test"> -<script type="application/javascript;version=1.7"> -"use strict"; -SimpleTest.waitForExplicitFinish(); - -/** - * This test checks that our CSS unprefixing prefs are effective. - * - * We do this using an iframe, in which we load a test file at a test domain - * (whose whitelist-status depends on a pref), and we have the iframe report - * back to us (using postMessage) about whether unprefixing is working. - * - * High-level overview of the process here (starting with begin()): - * - First, we ensure that the pref... - * "layout.css.unprefixing-service.include-test-domains" - * ...is *unset* by default. (No point exposing it in about:config). - * - Then, we test that (as a result of this pref being unset) the - * unprefixing service is *inactive* at our test-domain, by default. - * - Then, via a series of calls to "startNextTest()"/"testHost()", we re-test - * the same test-domain with a variety of pref configurations, to ensure - * that unprefixing only happens there when we've preffed on the service - * *and* we've enabled the testing entries in the whiteslist. - */ - -const IFRAME_TESTFILE = "unprefixing_service_iframe.html"; - -// Just test the first host in our known-whitelisted-hosts list. -const WHITELISTED_TEST_HOST = gWhitelistedHosts[0]; - -// Configurations of our prefs to test. -// Each is a 3-entry array, whose entries mean: -// (1) should we enable the CSS Unprefixing Service pref? -// (2) should we enable the "include test domains in whitelist" pref? -// (3) in this pref-configuration, should we expect to see unprefixing active -// on our whitelisted test-domain? -// -// As you can see, the only configuration which should produce unprefixing -// activity is when *both* prefs are enabled. -let gTestConfigs = [ - [false, false, false], - [false, true, false], - [true, false, false], - [true, true, true], -]; - -// Test that a particular configuration of prefs will activate or inactivate -// the CSS unprefixing service, for styles loaded from WHITELISTED_TEST_HOST. -// aTestConfig is described above, in documentation for gTestConfigs. -function testConfig(aTestConfig) -{ - if (aTestConfig.length != 3) { - ok(false, "bug in test; need 3 entries. see gTestConfigs documentation"); - } - - info("Verifying that CSS Unprefixing Service is " + - (aTestConfig[2] ? "active" : "inactive") + - " at test host, with prefs: " + - PREF_UNPREFIXING_SERVICE + "=" + aTestConfig[0] + ", " + - PREF_INCLUDE_TEST_DOMAINS + "=" + aTestConfig[1]); - - SpecialPowers.pushPrefEnv( - { set: - [[PREF_UNPREFIXING_SERVICE, aTestConfig[0]], - [PREF_INCLUDE_TEST_DOMAINS, aTestConfig[1]]] - }, - function() { - testHost(WHITELISTED_TEST_HOST, aTestConfig[2]); - }); -} - -// This function gets invoked when our iframe finishes a given round of testing. -function startNextTest() -{ - if (gTestConfigs.length > 0) { - // Grab the next test-config, and kick off a test for it. - testConfig(gTestConfigs.pop()); - return; - } - - // Array empty --> we're done. - SimpleTest.finish(); -} - -function begin() -{ - // First, check that PREF_INCLUDE_TEST_DOMAINS is unset: - try { - let val = SpecialPowers.getBoolPref(PREF_INCLUDE_TEST_DOMAINS); - ok(false, "The test pref '" + PREF_INCLUDE_TEST_DOMAINS + - "' should be unspecified by default"); - } catch(e) { /* Good, we threw; pref is unset. */ } - - // Before we start loading things in iframes, set up postMessage handler. - registerPostMessageListener(startNextTest); - - // To kick things off, we don't set any prefs; we just test the default state - // (which should have the "include test domains" pref implicitly disabled, & - // hence unprefixing should end up being disabled in our iframe). Subsequent - // tests are kicked off via postMessage-triggered calls to startNextTest(), - // which will tweak prefs and re-test. - info("Verifying that CSS Unprefixing Service is inactive at test host, " + - "with default pref configuration"); - testHost(WHITELISTED_TEST_HOST, false); -} - -// Before we start, make sure *native* -webkit prefix support is turned off. -// It's not whitelist-restricted (and behaves slightly differently), so if we -// left it enabled, it'd prevent us from being able to detect -// CSSUnprefixingService's domain whitelisting in this test. -SpecialPowers.pushPrefEnv({ set: [["layout.css.prefixes.webkit", false]]}, - begin); -</script> -</pre> -</body> -</html> diff --git a/layout/style/test/unprefixing_service_iframe.html b/layout/style/test/unprefixing_service_iframe.html deleted file mode 100644 index 8edeb20dce..0000000000 --- a/layout/style/test/unprefixing_service_iframe.html +++ /dev/null @@ -1,394 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <meta charset="utf-8"> - <title>Helper file for testing CSS Unprefixing Service</title> - <script type="text/javascript" src="property_database.js"></script> - <style type="text/css"> - #wrapper { - width: 500px; - } - </style> -</head> -<body> -<div id="wrapper"> - <div id="content"></div> -</div> - -<script type="application/javascript;version=1.7"> -"use strict"; - -/** Helper file for testing the CSS Unprefixing Service **/ - -/* Testcases for CSS Unprefixing service. - * - * Each testcase MUST have the following fields: - * - decl: A CSS declaration with prefixed style, to be tested via elem.style. - * - targetPropName: The name of the property whose value should be - * affected by |decl|. - * - * And will have EITHER: - * - isInvalid: If set to something truthy, this implies that |decl| is - * invalid and should have no effect on |targetPropName|'s - * computed or specified style. - * - * ...OR: - * - expectedDOMStyleVal: The value that we expect to find in the specified - * style -- in elem.style.[targetPropName]. - * - expectedCompStyleVal: The value that we expect to find in the computed - * style -- in getComputedStyle(...)[targetPropName] - * If omitted, this is assumed to be the same as - * expectedDOMStyleVal. (Usually they'll be the same.) - */ -const gTestcases = [ - { decl: "-webkit-box-flex:5", - targetPropName: "flex-grow", - expectedDOMStyleVal: "5" }, - - /* If author happens to specify modern flexbox style after prefixed style, - make sure the modern stuff is preserved. */ - { decl: "-webkit-box-flex:4;flex-grow:6", - targetPropName: "flex-grow", - expectedDOMStyleVal: "6" }, - - /* Tests for handling !important: */ - { decl: "-webkit-box-flex:3!important;", - targetPropName: "flex-grow", - expectedDOMStyleVal: "3" }, - { decl: "-webkit-box-flex:2!important;flex-grow:1", - targetPropName: "flex-grow", - expectedDOMStyleVal: "2" }, - - { decl: "-webkit-box-flex:1!important bogusText;", - targetPropName: "flex-grow", - isInvalid: true }, - - // Make sure we handle weird capitalization in property & value, too: - { decl: "-WEBKIT-BoX-aLign: baSELine", - targetPropName: "align-items", - expectedDOMStyleVal: "baseline" }, - - { decl: "display:-webkit-box", - targetPropName: "display", - expectedDOMStyleVal: "flex" }, - - { decl: "display:-webkit-box; display:-moz-box;", - targetPropName: "display", - expectedDOMStyleVal: "flex" }, - - { decl: "display:-webkit-foobar; display:-moz-box;", - targetPropName: "display", - expectedDOMStyleVal: "-moz-box" }, - - // -webkit-box-align: baseline | center | end | start | stretch - // ...maps to: - // align-items: baseline | center | flex-end | flex-start | stretch - { decl: "-webkit-box-align: baseline", - targetPropName: "align-items", - expectedDOMStyleVal: "baseline" }, - { decl: "-webkit-box-align: center", - targetPropName: "align-items", - expectedDOMStyleVal: "center" }, - { decl: "-webkit-box-align: end", - targetPropName: "align-items", - expectedDOMStyleVal: "flex-end" }, - { decl: "-webkit-box-align: start", - targetPropName: "align-items", - expectedDOMStyleVal: "flex-start" }, - { decl: "-webkit-box-align: stretch", - targetPropName: "align-items", - expectedDOMStyleVal: "stretch" }, - - // -webkit-box-direction is not supported, because it's unused & would be - // complicated to support. See note in CSSUnprefixingService.js for more. - - // -webkit-box-ordinal-group: <number> maps directly to "order". - { decl: "-webkit-box-ordinal-group: 2", - targetPropName: "order", - expectedDOMStyleVal: "2" }, - { decl: "-webkit-box-ordinal-group: 6000", - targetPropName: "order", - expectedDOMStyleVal: "6000" }, - - // -webkit-box-orient: horizontal | inline-axis | vertical | block-axis - // ...maps to: - // flex-direction: row | row | column | column - { decl: "-webkit-box-orient: horizontal", - targetPropName: "flex-direction", - expectedDOMStyleVal: "row" }, - { decl: "-webkit-box-orient: inline-axis", - targetPropName: "flex-direction", - expectedDOMStyleVal: "row" }, - { decl: "-webkit-box-orient: vertical", - targetPropName: "flex-direction", - expectedDOMStyleVal: "column" }, - { decl: "-webkit-box-orient: block-axis", - targetPropName: "flex-direction", - expectedDOMStyleVal: "column" }, - - // -webkit-box-pack: start | center | end | justify - // ... maps to: - // justify-content: flex-start | center | flex-end | space-between - { decl: "-webkit-box-pack: start", - targetPropName: "justify-content", - expectedDOMStyleVal: "flex-start" }, - { decl: "-webkit-box-pack: center", - targetPropName: "justify-content", - expectedDOMStyleVal: "center" }, - { decl: "-webkit-box-pack: end", - targetPropName: "justify-content", - expectedDOMStyleVal: "flex-end" }, - { decl: "-webkit-box-pack: justify", - targetPropName: "justify-content", - expectedDOMStyleVal: "space-between" }, - - // -webkit-transform: <transform> maps directly to "transform" - { decl: "-webkit-transform: matrix(1, 2, 3, 4, 5, 6)", - targetPropName: "transform", - expectedDOMStyleVal: "matrix(1, 2, 3, 4, 5, 6)" }, - - // -webkit-transform-origin: <value> maps directly to "transform-origin" - { decl: "-webkit-transform-origin: 0 0", - targetPropName: "transform-origin", - expectedDOMStyleVal: "0px 0px 0px", - expectedCompStyleVal: "0px 0px" }, - - { decl: "-webkit-transform-origin: 100% 0", - targetPropName: "transform-origin", - expectedDOMStyleVal: "100% 0px 0px", - expectedCompStyleVal: "500px 0px" }, - - // -webkit-transition: <property> maps directly to "transition" - { decl: "-webkit-transition: width 1s linear 2s", - targetPropName: "transition", - expectedDOMStyleVal: "width 1s linear 2s" }, - - // -webkit-transition **with** -webkit-prefixed property in value. - { decl: "-webkit-transition: -webkit-transform 1s linear 2s", - targetPropName: "transition", - expectedDOMStyleVal: "transform 1s linear 2s" }, - // (Re-test to check that it sets the "transition-property" subproperty.) - { decl: "-webkit-transition: -webkit-transform 1s linear 2s", - targetPropName: "transition-property", - expectedDOMStyleVal: "transform" }, - - // Same as previous test, except with "-webkit-transform" in the - // middle of the value instead of at the beginning (still valid): - { decl: "-webkit-transition: 1s -webkit-transform linear 2s", - targetPropName: "transition", - expectedDOMStyleVal: "transform 1s linear 2s" }, - { decl: "-webkit-transition: 1s -webkit-transform linear 2s", - targetPropName: "transition-property", - expectedDOMStyleVal: "transform" }, - - // -webkit-gradient(linear, ...) expressions: - { decl: "background-image: -webkit-gradient(linear,0 0,0 100%,from(rgb(1, 2, 3)),to(rgb(104, 105, 106)))", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(180deg, rgb(1, 2, 3) 0%, rgb(104, 105, 106) 100%)"}, - { decl: "background-image: -webkit-gradient(linear, left top, right bottom, from(rgb(1, 2, 3)), to(rgb(201, 202, 203)))", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(135deg, rgb(1, 2, 3) 0%, rgb(201, 202, 203) 100%)"}, - - { decl: "background-image: -webkit-gradient(linear, left center, right center, from(rgb(1, 2, 3)), to(rgb(201, 202, 203)))", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(to right, rgb(1, 2, 3) 0%, rgb(201, 202, 203) 100%)"}, - - { decl: "background-image: -webkit-gradient(linear, left center, right center, from(rgb(0, 0, 0)), color-stop(30%, rgb(255, 0, 0)), color-stop(60%, rgb(0, 255, 0)), to(rgb(0, 0, 255)))", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(to right, rgb(0, 0, 0) 0%, rgb(255, 0, 0) 30%, rgb(0, 255, 0) 60%, rgb(0, 0, 255) 100%)"}, - - // -webkit-gradient(radial, ...) expressions: - { decl: "background-image: -webkit-gradient(radial, center center, 0, center center, 50, from(black), to(white)", - targetPropName: "background-image", - expectedDOMStyleVal: "radial-gradient(50px at center center , black 0%, white 100%)", - // XXXdholbert Note: unnecessary space, see bug 1160063----^ - expectedCompStyleVal: "radial-gradient(50px, rgb(0, 0, 0) 0%, rgb(255, 255, 255) 100%)", }, - - { decl: "background-image: -webkit-gradient(radial, left bottom, 0, center center, 50, from(yellow), color-stop(20%, orange), color-stop(40%, red), color-stop(60%, green), color-stop(80%, blue), to(purple))", - targetPropName: "background-image", - expectedDOMStyleVal: "radial-gradient(50px at left bottom , yellow 0%, orange 20%, red 40%, green 60%, blue 80%, purple 100%)", - // XXXdholbert Note: unnecessary space, see bug 1160063--^ - expectedCompStyleVal: "radial-gradient(50px at 0% 100%, rgb(255, 255, 0) 0%, rgb(255, 165, 0) 20%, rgb(255, 0, 0) 40%, rgb(0, 128, 0) 60%, rgb(0, 0, 255) 80%, rgb(128, 0, 128) 100%)" }, - - // -webkit-linear-gradient(...) expressions: - { decl: "background-image: -webkit-linear-gradient(top, blue, green)", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(to bottom, blue, green)", - expectedCompStyleVal: "linear-gradient(rgb(0, 0, 255), rgb(0, 128, 0))", }, - - { decl: "background-image: -webkit-linear-gradient(left, blue, green)", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(to right, blue, green)", - expectedCompStyleVal: "linear-gradient(to right, rgb(0, 0, 255), rgb(0, 128, 0))", }, - - { decl: "background-image: -webkit-linear-gradient(left bottom, blue, green)", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(to right top, blue, green)", - expectedCompStyleVal: "linear-gradient(to top right, rgb(0, 0, 255), rgb(0, 128, 0))", }, - - { decl: "background-image: -webkit-linear-gradient(130deg, blue, green)", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(320deg, blue, green)", - expectedCompStyleVal: "linear-gradient(320deg, rgb(0, 0, 255), rgb(0, 128, 0))", }, - - // -webkit-radial-gradient(...) expressions: - { decl: "background-image: -webkit-radial-gradient(#000, #fff)", - targetPropName: "background-image", - expectedDOMStyleVal: "radial-gradient(rgb(0, 0, 0), rgb(255, 255, 255))", }, - - { decl: "background-image: -webkit-radial-gradient(bottom right, white, black)", - targetPropName: "background-image", - expectedDOMStyleVal: "radial-gradient(at right bottom , white, black)", - // XXXdholbert Note: unnecessary space---------------^ see bug 1160063 - expectedCompStyleVal: "radial-gradient(at 100% 100%, rgb(255, 255, 255), rgb(0, 0, 0))", }, - - // Combination of unprefixed & prefixed gradient styles in a single 'background-image' expression - { decl: "background-image: -webkit-linear-gradient(black, white), radial-gradient(blue, purple), -webkit-gradient(linear,0 0,0 100%,from(red),to(orange))", - targetPropName: "background-image", - expectedDOMStyleVal: "linear-gradient(black, white), radial-gradient(blue, purple), linear-gradient(180deg, red 0%, orange 100%)", - expectedCompStyleVal: "linear-gradient(rgb(0, 0, 0), rgb(255, 255, 255)), radial-gradient(rgb(0, 0, 255), rgb(128, 0, 128)), linear-gradient(180deg, rgb(255, 0, 0) 0%, rgb(255, 165, 0) 100%)", }, - -]; - -function getComputedStyleWrapper(elem, prop) -{ - return window.getComputedStyle(elem, null).getPropertyValue(prop); -} - -// Shims for "is()" and "ok()", which defer to parent window using postMessage: -function is(aActual, aExpected, aDesc) -{ - // Add URL to description: - aDesc += " (iframe url: '" + window.location + "')"; - - window.parent.postMessage({type: "is", - actual: aActual, - expected: aExpected, - desc: aDesc}, "*"); -} - -function ok(aCondition, aDesc) -{ - // Add URL to description: - aDesc += " (iframe url: '" + window.location + "')"; - - window.parent.postMessage({type: "ok", - condition: aCondition, - desc: aDesc}, "*"); -} - -// Main test function to use, to test a given unprefixed CSS property. -// The argument aTestcase should be an entry from gTestcases above. -function runOneTest(aTestcase) -{ - let elem = document.getElementById("content"); - - // (self-test/sanity-check:) - if (!aTestcase.decl || !aTestcase.targetPropName) { - ok(false, "Bug in test; missing 'decl' or 'targetPropName' field"); - } - - // Populate testcase's implied fields: - if (aTestcase.isInvalid) { - // (self-test/sanity-check:) - if (aTestcase.expectedDOMStyleVal || aTestcase.expectedCompStyleVal) { - ok(false, "Bug in test; testcase w/ 'isInvalid' field also provided " + - "an expected*Val field, but should not have"); - } - aTestcase.expectedDOMStyleVal = ''; - aTestcase.expectedCompStyleVal = // initial computed style: - getComputedStyleWrapper(elem, aTestcase.targetPropName); - } else { - // (self-test/sanity-check:) - if (!aTestcase.expectedDOMStyleVal) { - ok(false, "Bug in test; testcase must provide expectedDOMStyleVal " + - "(or set isInvalid if it's testing an invalid decl)"); - } - // If expected computed style is unspecified, we assume it should match - // expected DOM style: - if (!aTestcase.expectedCompStyleVal) { - aTestcase.expectedCompStyleVal = aTestcase.expectedDOMStyleVal; - } - } - - elem.setAttribute("style", aTestcase.decl); - - // Check that DOM elem.style has the expected value: - is(elem.style[aTestcase.targetPropName], aTestcase.expectedDOMStyleVal, - "Checking if CSS Unprefixing Service produced expected result " + - "in elem.style['" + aTestcase.targetPropName + "'] " + - "when given decl '" + aTestcase.decl + "'"); - - // Check that computed style has the expected value: - // (only for longhand properties; shorthands aren't in computed style) - if (gCSSProperties[aTestcase.targetPropName].type == CSS_TYPE_LONGHAND) { - let computedValue = getComputedStyleWrapper(elem, aTestcase.targetPropName); - is(computedValue, aTestcase.expectedCompStyleVal, - "Checking if CSS Unprefixing Service produced expected result " + - "in computed value of property '" + aTestcase.targetPropName + "' " + - "when given decl '" + aTestcase.decl + "'"); - } - - elem.removeAttribute("style"); -} - -// Function used to quickly test that unprefixing is off: -function testUnprefixingDisabled() -{ - let elem = document.getElementById("content"); - - let initialFlexGrow = getComputedStyleWrapper(elem, "flex-grow"); - elem.setAttribute("style", "-webkit-box-flex:5"); - is(getComputedStyleWrapper(elem, "flex-grow"), initialFlexGrow, - "'-webkit-box-flex' shouldn't affect computed 'flex-grow' " + - "when CSS Unprefixing Service is inactive"); - - let initialDisplay = getComputedStyleWrapper(elem, "display"); - elem.setAttribute("style", "display:-webkit-box"); - is(getComputedStyleWrapper(elem, "display"), initialDisplay, - "'display:-webkit-box' shouldn't affect computed 'display' " + - "when CSS Unprefixing Service is inactive"); - - elem.style.display = "-webkit-box"; - is(getComputedStyleWrapper(elem, "display"), initialDisplay, - "Setting elem.style.display to '-webkit-box' shouldn't affect computed " + - "'display' when CSS Unprefixing Service is inactive"); -} - -// Focused test that CSS Unprefixing Service is functioning properly -// on direct tweaks to elem.style.display: -function testStyleDisplayDirectly() -{ - let elem = document.getElementById("content"); - elem.style.display = "-webkit-box"; - - is(elem.style.display, "flex", - "Setting elem.style.display to '-webkit-box' should produce 'flex' " + - "in elem.style.display, when CSS Unprefixing Service is active"); - is(getComputedStyleWrapper(elem, "display"), "flex", - "Setting elem.style.display to '-webkit-box' should produce 'flex' " + - "in computed style, when CSS Unprefixing Service is active"); - - // clean up: - elem.style.display = ""; -} - -function startTest() -{ - if (window.location.hash === "#expectEnabled") { - testStyleDisplayDirectly(); - gTestcases.forEach(runOneTest); - } else if (window.location.hash === "#expectDisabled") { - testUnprefixingDisabled(); - } else { - ok(false, - "Need a recognized 'window.location.hash' to indicate expectation. " + - "Got: '" + window.location.hash + "'"); - } - window.parent.postMessage({type: "testComplete"}, "*"); -} - -startTest(); -</script> -</body> -</html> diff --git a/layout/style/test/unprefixing_service_utils.js b/layout/style/test/unprefixing_service_utils.js deleted file mode 100644 index cd17d20d08..0000000000 --- a/layout/style/test/unprefixing_service_utils.js +++ /dev/null @@ -1,87 +0,0 @@ -/* 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/. */ - -// Shared data & functionality used in tests for CSS Unprefixing Service. - -// Whitelisted hosts: -// (per implementation of nsPrincipal::IsOnCSSUnprefixingWhitelist()) -var gWhitelistedHosts = [ - // test1.example.org is on the whitelist. - "test1.example.org", - // test2.example.org is on the "allow all subdomains" whitelist. - "test2.example.org", - "sub1.test2.example.org", - "sub2.test2.example.org" -]; - -// *NOT* whitelisted hosts: -var gNotWhitelistedHosts = [ - // Though test1.example.org is on the whitelist, its subdomains are not. - "sub1.test1.example.org", - // mochi.test is not on the whitelist. - "mochi.test:8888" -]; - -// Names of prefs: -const PREF_UNPREFIXING_SERVICE = - "layout.css.unprefixing-service.enabled"; -const PREF_INCLUDE_TEST_DOMAINS = - "layout.css.unprefixing-service.include-test-domains"; - -// Helper-function to make unique URLs in testHost(): -var gCounter = 0; -function getIncreasingCounter() { - return gCounter++; -} - -// This function tests a particular host in our iframe. -// @param aHost The host to be tested -// @param aExpectEnabled Should we expect unprefixing to be enabled for host? -function testHost(aHost, aExpectEnabled) { - // Build the URL: - let url = window.location.protocol; // "http:" or "https:" - url += "//"; - url += aHost; - - // Append the path-name, up to the actual filename (the final "/"): - const re = /(.*\/).*/; - url += window.location.pathname.replace(re, "$1"); - url += IFRAME_TESTFILE; - // In case this is the same URL as last time, we add "?N" for some unique N, - // to make each URL different, so that the iframe actually (re)loads: - url += "?" + getIncreasingCounter(); - // We give the URL a #suffix to indicate to the test whether it should expect - // that unprefixing is enabled or disabled: - url += (aExpectEnabled ? "#expectEnabled" : "#expectDisabled"); - - let iframe = document.getElementById("testIframe"); - iframe.contentWindow.location = url; - // The iframe will report its results back via postMessage. - // Our caller had better have set up a postMessage listener. -} - -// Register a postMessage() handler, to allow our cross-origin iframe to -// communicate back to the main page's mochitest functionality. -// The handler expects postMessage to be called with an object like: -// { type: ["is"|"ok"|"testComplete"], ... } -// The "is" and "ok" types will trigger the corresponding function to be -// called in the main page, with named arguments provided in the payload. -// The "testComplete" type will trigger the passed-in aTestCompleteCallback -// function to be invoked (e.g. to advance to the next testcase, or to finish -// the overall test, as-appropriate). -function registerPostMessageListener(aTestCompleteCallback) { - let receiveMessage = function(event) { - if (event.data.type === "is") { - is(event.data.actual, event.data.expected, event.data.desc); - } else if (event.data.type === "ok") { - ok(event.data.condition, event.data.desc); - } else if (event.data.type === "testComplete") { - aTestCompleteCallback(); - } else { - ok(false, "unrecognized data in postMessage call"); - } - }; - - window.addEventListener("message", receiveMessage, false); -} |