1
0
mirror of https://github.com/roytam1/UXP.git synced 2026-05-26 13:58:49 +00:00

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
This commit is contained in:
FranklinDM
2023-01-06 21:07:37 +08:00
committed by roytam1
parent 845411a7ad
commit db3ce13f28
15 changed files with 24 additions and 1590 deletions
-2
View File
@@ -287,8 +287,6 @@ public:
virtual bool AddonHasPermission(const nsAString& aPerm);
virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
virtual bool IsCodebasePrincipal() const { return false; };
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
+1 -10
View File
@@ -21,7 +21,7 @@ interface nsIDOMDocument;
[ptr] native JSPrincipals(JSPrincipals);
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
[scriptable, builtinclass, uuid(3da7b133-f1a0-4de9-a2bc-5c49014c1077)]
[scriptable, builtinclass, uuid(f75f502d-79fd-48be-a079-e5a7b8f80c8b)]
interface nsIPrincipal : nsISerializable
{
/**
@@ -333,15 +333,6 @@ interface nsIPrincipal : nsISerializable
* Returns true iff this is the system principal.
*/
[infallible] readonly attribute boolean isSystemPrincipal;
/**
* Returns true if this principal's origin is recognized as being on the
* whitelist of sites that can use the CSS Unprefixing Service.
*
* (This interface provides a trivial implementation, just returning false;
* subclasses can implement something more complex as-needed.)
*/
[noscript,notxpcom,nostdcall] bool IsOnCSSUnprefixingWhitelist();
};
/**
-204
View File
@@ -35,7 +35,6 @@
using namespace mozilla;
static bool gIsWhitelistingTestDomains = false;
static bool gCodeBasePrincipalSupport = false;
static bool URIIsImmutable(nsIURI* aURI)
@@ -61,10 +60,6 @@ NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal,
/* static */ void
nsPrincipal::InitializeStatics()
{
Preferences::AddBoolVarCache(
&gIsWhitelistingTestDomains,
"layout.css.unprefixing-service.include-test-domains");
Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
"signed.applets.codebase_principal_support",
false);
@@ -483,196 +478,6 @@ nsPrincipal::Write(nsIObjectOutputStream* aStream)
return NS_OK;
}
// Helper-function to indicate whether the CSS Unprefixing Service
// whitelist should include dummy domains that are only intended for
// use in testing. (Controlled by a pref.)
static inline bool
IsWhitelistingTestDomains()
{
return gIsWhitelistingTestDomains;
}
// Checks if the given URI's host is on our "full domain" whitelist
// (i.e. if it's an exact match against a domain that needs unprefixing)
static bool
IsOnFullDomainWhitelist(nsIURI* aURI)
{
nsAutoCString hostStr;
nsresult rv = aURI->GetHost(hostStr);
NS_ENSURE_SUCCESS(rv, false);
// NOTE: This static whitelist is expected to be short. If that changes,
// we should consider a different representation; e.g. hash-set, prefix tree.
static const nsLiteralCString sFullDomainsOnWhitelist[] = {
// 0th entry only active when testing:
NS_LITERAL_CSTRING("test1.example.org"),
NS_LITERAL_CSTRING("map.baidu.com"),
NS_LITERAL_CSTRING("3g.163.com"),
NS_LITERAL_CSTRING("3glogo.gtimg.com"), // for 3g.163.com
NS_LITERAL_CSTRING("info.3g.qq.com"), // for 3g.qq.com
NS_LITERAL_CSTRING("3gimg.qq.com"), // for 3g.qq.com
NS_LITERAL_CSTRING("img.m.baidu.com"), // for [shucheng|ks].baidu.com
NS_LITERAL_CSTRING("m.mogujie.com"),
NS_LITERAL_CSTRING("touch.qunar.com"),
NS_LITERAL_CSTRING("mjs.sinaimg.cn"), // for sina.cn
NS_LITERAL_CSTRING("static.qiyi.com"), // for m.iqiyi.com
NS_LITERAL_CSTRING("cdn.kuaidi100.com"), // for m.kuaidi100.com
NS_LITERAL_CSTRING("m.pc6.com"),
NS_LITERAL_CSTRING("m.haosou.com"),
NS_LITERAL_CSTRING("m.mi.com"),
NS_LITERAL_CSTRING("wappass.baidu.com"),
NS_LITERAL_CSTRING("m.video.baidu.com"),
NS_LITERAL_CSTRING("m.video.baidu.com"),
NS_LITERAL_CSTRING("imgcache.gtimg.cn"), // for m.v.qq.com
NS_LITERAL_CSTRING("s.tabelog.jp"),
NS_LITERAL_CSTRING("s.yimg.jp"), // for s.tabelog.jp
NS_LITERAL_CSTRING("i.yimg.jp"), // for *.yahoo.co.jp
NS_LITERAL_CSTRING("ai.yimg.jp"), // for *.yahoo.co.jp
NS_LITERAL_CSTRING("m.finance.yahoo.co.jp"),
NS_LITERAL_CSTRING("daily.c.yimg.jp"), // for sp.daily.co.jp
NS_LITERAL_CSTRING("stat100.ameba.jp"), // for ameblo.jp
NS_LITERAL_CSTRING("user.ameba.jp"), // for ameblo.jp
NS_LITERAL_CSTRING("www.goo.ne.jp"),
NS_LITERAL_CSTRING("x.gnst.jp"), // for mobile.gnavi.co.jp
NS_LITERAL_CSTRING("c.x.gnst.jp"), // for mobile.gnavi.co.jp
NS_LITERAL_CSTRING("www.smbc-card.com"),
NS_LITERAL_CSTRING("static.card.jp.rakuten-static.com"), // for rakuten-card.co.jp
NS_LITERAL_CSTRING("img.travel.rakuten.co.jp"), // for travel.rakuten.co.jp
NS_LITERAL_CSTRING("img.mixi.net"), // for mixi.jp
NS_LITERAL_CSTRING("girlschannel.net"),
NS_LITERAL_CSTRING("www.fancl.co.jp"),
NS_LITERAL_CSTRING("s.cosme.net"),
NS_LITERAL_CSTRING("www.sapporobeer.jp"),
NS_LITERAL_CSTRING("www.mapion.co.jp"),
NS_LITERAL_CSTRING("touch.navitime.co.jp"),
NS_LITERAL_CSTRING("sp.mbga.jp"),
NS_LITERAL_CSTRING("ava-a.sp.mbga.jp"), // for sp.mbga.jp
NS_LITERAL_CSTRING("www.ntv.co.jp"),
NS_LITERAL_CSTRING("mobile.suntory.co.jp"), // for suntory.jp
NS_LITERAL_CSTRING("www.aeonsquare.net"),
NS_LITERAL_CSTRING("mw.nikkei.com"),
NS_LITERAL_CSTRING("www.nhk.or.jp"),
NS_LITERAL_CSTRING("www.tokyo-sports.co.jp"),
NS_LITERAL_CSTRING("www.bellemaison.jp"),
NS_LITERAL_CSTRING("www.kuronekoyamato.co.jp"),
NS_LITERAL_CSTRING("formassist.jp"), // for orico.jp
NS_LITERAL_CSTRING("sp.m.reuters.co.jp"),
NS_LITERAL_CSTRING("www.atre.co.jp"),
NS_LITERAL_CSTRING("www.jtb.co.jp"),
NS_LITERAL_CSTRING("www.sharp.co.jp"),
NS_LITERAL_CSTRING("www.biccamera.com"),
NS_LITERAL_CSTRING("weathernews.jp"),
NS_LITERAL_CSTRING("cache.ymail.jp"), // for www.yamada-denkiweb.com
};
static const size_t sNumFullDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sFullDomainsOnWhitelist);
// Skip 0th (dummy) entry in whitelist, unless a pref is enabled.
const size_t firstWhitelistIdx = IsWhitelistingTestDomains() ? 0 : 1;
for (size_t i = firstWhitelistIdx; i < sNumFullDomainsOnWhitelist; ++i) {
if (hostStr == sFullDomainsOnWhitelist[i]) {
return true;
}
}
return false;
}
// Checks if the given URI's host is on our "base domain" whitelist
// (i.e. if it's a subdomain of some host that we've whitelisted as needing
// unprefixing for all its subdomains)
static bool
IsOnBaseDomainWhitelist(nsIURI* aURI)
{
static const nsLiteralCString sBaseDomainsOnWhitelist[] = {
// 0th entry only active when testing:
NS_LITERAL_CSTRING("test2.example.org"),
NS_LITERAL_CSTRING("tbcdn.cn"), // for m.taobao.com
NS_LITERAL_CSTRING("alicdn.com"), // for m.taobao.com
NS_LITERAL_CSTRING("dpfile.com"), // for m.dianping.com
NS_LITERAL_CSTRING("hao123img.com"), // for hao123.com
NS_LITERAL_CSTRING("tabelog.k-img.com"), // for s.tabelog.com
NS_LITERAL_CSTRING("tsite.jp"), // for *.tsite.jp
};
static const size_t sNumBaseDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sBaseDomainsOnWhitelist);
nsCOMPtr<nsIEffectiveTLDService> tldService =
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
if (tldService) {
// Skip 0th test-entry in whitelist, unless the testing pref is enabled.
const size_t firstWhitelistIdx = IsWhitelistingTestDomains() ? 0 : 1;
// Right now, the test base-domain "test2.example.org" is the only entry in
// its whitelist with a nonzero "depth". So we'll only bother going beyond
// 0 depth (to 1) if that entry is enabled. (No point in slowing down the
// normal codepath, for the benefit of a disabled test domain.) If we add a
// "real" base-domain with a depth of >= 1 to our whitelist, we can get rid
// of this conditional & just make this a static variable.
const uint32_t maxSubdomainDepth = IsWhitelistingTestDomains() ? 1 : 0;
for (uint32_t subdomainDepth = 0;
subdomainDepth <= maxSubdomainDepth; ++subdomainDepth) {
// Get the base domain (to depth |subdomainDepth|) from passed-in URI:
nsAutoCString baseDomainStr;
nsresult rv = tldService->GetBaseDomain(aURI, subdomainDepth,
baseDomainStr);
if (NS_FAILED(rv)) {
// aURI doesn't have |subdomainDepth| levels of subdomains. If we got
// here without a match yet, then aURI is not on our whitelist.
return false;
}
// Compare the base domain against each entry in our whitelist:
for (size_t i = firstWhitelistIdx; i < sNumBaseDomainsOnWhitelist; ++i) {
if (baseDomainStr == sBaseDomainsOnWhitelist[i]) {
return true;
}
}
}
}
return false;
}
// The actual (non-cached) implementation of IsOnCSSUnprefixingWhitelist():
static bool
IsOnCSSUnprefixingWhitelistImpl(nsIURI* aURI)
{
// Check scheme, so we can drop any non-HTTP/HTTPS URIs right away
nsAutoCString schemeStr;
nsresult rv = aURI->GetScheme(schemeStr);
NS_ENSURE_SUCCESS(rv, false);
// Only proceed if scheme is "http" or "https"
if (!(StringBeginsWith(schemeStr, NS_LITERAL_CSTRING("http")) &&
(schemeStr.Length() == 4 ||
(schemeStr.Length() == 5 && schemeStr[4] == 's')))) {
return false;
}
return (IsOnFullDomainWhitelist(aURI) ||
IsOnBaseDomainWhitelist(aURI));
}
bool
nsPrincipal::IsOnCSSUnprefixingWhitelist()
{
if (mIsOnCSSUnprefixingWhitelist.isNothing()) {
// Value not cached -- perform our lazy whitelist-check.
// (NOTE: If our URI is mutable, we just assume it's not on the whitelist,
// since our caching strategy won't work. This isn't expected to be common.)
mIsOnCSSUnprefixingWhitelist.emplace(
mCodebaseImmutable &&
IsOnCSSUnprefixingWhitelistImpl(mCodebase));
}
return *mIsOnCSSUnprefixingWhitelist;
}
/************************************************************************************************************************/
NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
@@ -837,15 +642,6 @@ nsExpandedPrincipal::AddonHasPermission(const nsAString& aPerm)
return false;
}
bool
nsExpandedPrincipal::IsOnCSSUnprefixingWhitelist()
{
// CSS Unprefixing Whitelist is a per-origin thing; doesn't really make sense
// for an expanded principal. (And probably shouldn't be needed.)
return false;
}
nsresult
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
{
-3
View File
@@ -25,7 +25,6 @@ public:
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
bool IsCodebasePrincipal() const override { return true; }
nsresult GetOriginInternal(nsACString& aOrigin) override;
@@ -55,7 +54,6 @@ public:
bool mCodebaseImmutable;
bool mDomainImmutable;
bool mInitialized;
mozilla::Maybe<bool> mIsOnCSSUnprefixingWhitelist; // Lazily-computed
protected:
virtual ~nsPrincipal();
@@ -81,7 +79,6 @@ public:
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool AddonHasPermission(const nsAString& aPerm) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
virtual nsresult GetScriptLocation(nsACString &aStr) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;
-341
View File
@@ -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]);
@@ -1,2 +0,0 @@
component {f0729490-e15c-4a2f-a3fb-99e1cc946b42} CSSUnprefixingService.js
contract @mozilla.org/css-unprefixing-service;1 {f0729490-e15c-4a2f-a3fb-99e1cc946b42}
-11
View File
@@ -21,12 +21,6 @@ with Files('nsDOM*'):
DIRS += ['xbl-marquee']
TEST_DIRS += ['test']
XPIDL_SOURCES += [
'nsICSSUnprefixingService.idl',
]
XPIDL_MODULE = 'layout_base'
EXPORTS += [
'!nsStyleStructList.h',
'AnimationCommon.h',
@@ -215,11 +209,6 @@ SOURCES += [
'nsLayoutStylesheetCache.cpp',
]
EXTRA_COMPONENTS += [
'CSSUnprefixingService.js',
'CSSUnprefixingService.manifest',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
+23 -221
View File
@@ -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,10 +65,6 @@ typedef nsCSSProps::KTableEntry KTableEntry;
static bool sOpentypeSVGEnabled;
static bool sWebkitPrefixedAliasesEnabled;
static bool sWebkitDevicePixelRatioEnabled;
static bool sUnprefixingServiceEnabled;
#ifdef NIGHTLY_BUILD
static bool sUnprefixingServiceGloballyWhitelisted;
#endif
static bool sMozGradientsEnabled;
static bool sControlCharVisibility;
@@ -799,9 +794,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,
@@ -824,20 +817,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,
@@ -1518,9 +1497,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)
@@ -7151,7 +7129,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".
@@ -7180,10 +7160,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;
@@ -7198,153 +7177,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;
}
#ifdef NIGHTLY_BUILD
if (sUnprefixingServiceGloballyWhitelisted) {
// Unprefixing is globally whitelisted,
// so no need to check mSheetPrincipal.
return true;
}
#endif
// 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
@@ -7434,19 +7266,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();
@@ -8074,18 +7894,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 &&
@@ -10866,7 +10674,7 @@ CSSParserImpl::ParseWebkitGradientRadius(float& aRadius)
// (either a percentage or a number between 0 and 1.0), and a color (any
// valid CSS color). In addition the shorthand functions from and to are
// supported. These functions only require a color argument and are
// equivalent to color-stop(0, ...) and color-stop(1.0, …) respectively.
// equivalent to color-stop(0, ...) and color-stop(1.0, ?? respectively.
bool
CSSParserImpl::ParseWebkitGradientColorStop(nsCSSValueGradient* aGradient)
{
@@ -12412,7 +12220,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") ||
@@ -15324,17 +15132,17 @@ CSSParserImpl::ParseFontFeatureSettings(nsCSSValue& aValue)
return true;
}
bool
CSSParserImpl::ParseFontVariationSettings(nsCSSValue& aValue)
{
// TODO: Actually implement this.
// This stub is here because websites insist on considering this
// very hardware-dependent and O.S.-variable low-level font-control
// as a "critical feature" which it isn't as there is 0 guarantee
// that font variation settings are supported or honored by any
// operating system used by the client.
return true;
bool
CSSParserImpl::ParseFontVariationSettings(nsCSSValue& aValue)
{
// TODO: Actually implement this.
// This stub is here because websites insist on considering this
// very hardware-dependent and O.S.-variable low-level font-control
// as a "critical feature" which it isn't as there is 0 guarantee
// that font variation settings are supported or honored by any
// operating system used by the client.
return true;
}
bool
@@ -17989,12 +17797,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");
#ifdef NIGHTLY_BUILD
Preferences::AddBoolVarCache(&sUnprefixingServiceGloballyWhitelisted,
"layout.css.unprefixing-service.globally-whitelisted");
#endif
Preferences::AddBoolVarCache(&sMozGradientsEnabled,
"layout.css.prefixes.gradients");
Preferences::AddBoolVarCache(&sControlCharVisibility,
-76
View File
@@ -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"
%}
-4
View File
@@ -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]
@@ -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>
@@ -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>
@@ -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>
@@ -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);
}
-10
View File
@@ -2551,16 +2551,6 @@ pref("layout.css.prefixes.webkit", true);
// pref is set to false.)
pref("layout.css.prefixes.device-pixel-ratio-webkit", false);
// Is the CSS Unprefixing Service enabled? (This service emulates support
// for certain vendor-prefixed properties & values, for sites on a "fixlist".)
pref("layout.css.unprefixing-service.enabled", true);
#ifdef NIGHTLY_BUILD
// Is the CSS Unprefixing Service whitelisted for all domains?
// (This pref is only honored in Nightly builds and can be removed when
// Bug 1177263 is fixed.)
pref("layout.css.unprefixing-service.globally-whitelisted", false);
#endif
// Is support for the :scope selector enabled?
pref("layout.css.scope-pseudo.enabled", true);