зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1132743: Only allow CSS Unprefixing Service to be activated for hosts on a small, hardcoded whitelist. r=dbaron f=bz
--HG-- rename : layout/style/test/test_unprefixing_service.html => layout/style/test/unprefixing_service_iframe.html
This commit is contained in:
Родитель
d38aa64d52
Коммит
908a699328
|
@ -20,7 +20,7 @@ interface nsIContentSecurityPolicy;
|
||||||
[ptr] native JSPrincipals(JSPrincipals);
|
[ptr] native JSPrincipals(JSPrincipals);
|
||||||
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(204555e7-04ad-4cc8-9f0e-840615cc43e8)]
|
[scriptable, builtinclass, uuid(264fe8ca-c382-11e4-95a6-782bcbaebb28)]
|
||||||
interface nsIPrincipal : nsISerializable
|
interface nsIPrincipal : nsISerializable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -230,6 +230,15 @@ interface nsIPrincipal : nsISerializable
|
||||||
* unknown, hence assumed minimally privileged, security context).
|
* unknown, hence assumed minimally privileged, security context).
|
||||||
*/
|
*/
|
||||||
[infallible] readonly attribute boolean isNullPrincipal;
|
[infallible] readonly attribute boolean isNullPrincipal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -318,6 +318,12 @@ nsNullPrincipal::GetBaseDomain(nsACString& aBaseDomain)
|
||||||
return mURI->GetPath(aBaseDomain);
|
return mURI->GetPath(aBaseDomain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsNullPrincipal::IsOnCSSUnprefixingWhitelist()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nsISerializable implementation
|
* nsISerializable implementation
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,12 +14,14 @@
|
||||||
#include "pratom.h"
|
#include "pratom.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
#include "nsJSPrincipals.h"
|
#include "nsJSPrincipals.h"
|
||||||
|
#include "nsIEffectiveTLDService.h"
|
||||||
#include "nsIObjectInputStream.h"
|
#include "nsIObjectInputStream.h"
|
||||||
#include "nsIObjectOutputStream.h"
|
#include "nsIObjectOutputStream.h"
|
||||||
#include "nsIClassInfoImpl.h"
|
#include "nsIClassInfoImpl.h"
|
||||||
#include "nsIProtocolHandler.h"
|
#include "nsIProtocolHandler.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
#include "nsIContentSecurityPolicy.h"
|
#include "nsIContentSecurityPolicy.h"
|
||||||
|
#include "nsNetCID.h"
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
|
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
|
@ -31,6 +33,8 @@
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
static bool gIsWhitelistingTestDomains = false;
|
||||||
|
// XXXdholbert Add to InitializeStatics():
|
||||||
static bool gCodeBasePrincipalSupport = false;
|
static bool gCodeBasePrincipalSupport = false;
|
||||||
static bool gIsObservingCodeBasePrincipalSupport = false;
|
static bool gIsObservingCodeBasePrincipalSupport = false;
|
||||||
|
|
||||||
|
@ -126,6 +130,15 @@ NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal,
|
||||||
NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal)
|
NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal)
|
||||||
NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal)
|
NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal)
|
||||||
|
|
||||||
|
// Called at startup:
|
||||||
|
/* static */ void
|
||||||
|
nsPrincipal::InitializeStatics()
|
||||||
|
{
|
||||||
|
Preferences::AddBoolVarCache(
|
||||||
|
&gIsWhitelistingTestDomains,
|
||||||
|
"layout.css.unprefixing-service.include-test-domains");
|
||||||
|
}
|
||||||
|
|
||||||
nsPrincipal::nsPrincipal()
|
nsPrincipal::nsPrincipal()
|
||||||
: mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
|
: mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
|
||||||
, mInMozBrowser(false)
|
, mInMozBrowser(false)
|
||||||
|
@ -608,6 +621,145 @@ nsPrincipal::GetAppStatus()
|
||||||
return nsScriptSecurityManager::AppStatusForPrincipal(this);
|
return nsScriptSecurityManager::AppStatusForPrincipal(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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("music.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"),
|
||||||
|
};
|
||||||
|
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("dpfile.com"), // for m.dianping.com
|
||||||
|
NS_LITERAL_CSTRING("hao123img.com"), // for hao123.com
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************/
|
/************************************************************************************************************************/
|
||||||
|
|
||||||
static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]";
|
static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]";
|
||||||
|
@ -823,6 +975,15 @@ nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
|
nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) MOZ_OVERRIDE;
|
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) MOZ_OVERRIDE;
|
||||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) MOZ_OVERRIDE;
|
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) MOZ_OVERRIDE;
|
||||||
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) MOZ_OVERRIDE;
|
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) MOZ_OVERRIDE;
|
||||||
|
virtual bool IsOnCSSUnprefixingWhitelist() MOZ_OVERRIDE;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
virtual void dumpImpl() MOZ_OVERRIDE;
|
virtual void dumpImpl() MOZ_OVERRIDE;
|
||||||
#endif
|
#endif
|
||||||
|
@ -102,6 +103,11 @@ public:
|
||||||
*/
|
*/
|
||||||
static nsresult GetOriginForURI(nsIURI* aURI, char **aOrigin);
|
static nsresult GetOriginForURI(nsIURI* aURI, char **aOrigin);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called at startup to setup static data, e.g. about:config pref-observers.
|
||||||
|
*/
|
||||||
|
static void InitializeStatics();
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> mDomain;
|
nsCOMPtr<nsIURI> mDomain;
|
||||||
nsCOMPtr<nsIURI> mCodebase;
|
nsCOMPtr<nsIURI> mCodebase;
|
||||||
uint32_t mAppId;
|
uint32_t mAppId;
|
||||||
|
@ -110,6 +116,7 @@ public:
|
||||||
bool mCodebaseImmutable;
|
bool mCodebaseImmutable;
|
||||||
bool mDomainImmutable;
|
bool mDomainImmutable;
|
||||||
bool mInitialized;
|
bool mInitialized;
|
||||||
|
mozilla::Maybe<bool> mIsOnCSSUnprefixingWhitelist; // Lazily-computed
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~nsPrincipal();
|
virtual ~nsPrincipal();
|
||||||
|
@ -149,6 +156,7 @@ public:
|
||||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) MOZ_OVERRIDE;
|
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) MOZ_OVERRIDE;
|
||||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) MOZ_OVERRIDE;
|
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) MOZ_OVERRIDE;
|
||||||
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) MOZ_OVERRIDE;
|
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) MOZ_OVERRIDE;
|
||||||
|
virtual bool IsOnCSSUnprefixingWhitelist() MOZ_OVERRIDE;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
virtual void dumpImpl() MOZ_OVERRIDE;
|
virtual void dumpImpl() MOZ_OVERRIDE;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -201,6 +201,13 @@ nsSystemPrincipal::GetBaseDomain(nsACString& aBaseDomain)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsSystemPrincipal::IsOnCSSUnprefixingWhitelist()
|
||||||
|
{
|
||||||
|
// chrome stylesheets should not be fed to the CSS Unprefixing Service.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
// Methods implementing nsISerializable //
|
// Methods implementing nsISerializable //
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
#include "nsImageFrame.h"
|
#include "nsImageFrame.h"
|
||||||
#include "nsLayoutStylesheetCache.h"
|
#include "nsLayoutStylesheetCache.h"
|
||||||
|
#include "nsPrincipal.h"
|
||||||
#include "nsRange.h"
|
#include "nsRange.h"
|
||||||
#include "nsRegion.h"
|
#include "nsRegion.h"
|
||||||
#include "nsRepeatService.h"
|
#include "nsRepeatService.h"
|
||||||
|
@ -270,6 +271,7 @@ nsLayoutStatics::Initialize()
|
||||||
nsIPresShell::InitializeStatics();
|
nsIPresShell::InitializeStatics();
|
||||||
TouchManager::InitializeStatics();
|
TouchManager::InitializeStatics();
|
||||||
nsRefreshDriver::InitializeStatics();
|
nsRefreshDriver::InitializeStatics();
|
||||||
|
nsPrincipal::InitializeStatics();
|
||||||
|
|
||||||
nsCORSListenerProxy::Startup();
|
nsCORSListenerProxy::Startup();
|
||||||
|
|
||||||
|
|
|
@ -6639,11 +6639,12 @@ bool
|
||||||
CSSParserImpl::ShouldUseUnprefixingService()
|
CSSParserImpl::ShouldUseUnprefixingService()
|
||||||
{
|
{
|
||||||
if (!sUnprefixingServiceEnabled) {
|
if (!sUnprefixingServiceEnabled) {
|
||||||
|
// Unprefixing is globally disabled.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXXdholbert Bug 1132743: Check if stylesheet URI is on fixlist here.
|
// Unprefixing enabled; see if our principal is whitelisted for unprefixing.
|
||||||
return true;
|
return mSheetPrincipal && mSheetPrincipal->IsOnCSSUnprefixingWhitelist();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -224,6 +224,9 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 775227 # b2g(times out,
|
||||||
[test_units_length.html]
|
[test_units_length.html]
|
||||||
[test_units_time.html]
|
[test_units_time.html]
|
||||||
[test_unprefixing_service.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_cloning.html]
|
||||||
skip-if = (toolkit == 'gonk' && debug) || toolkit == 'android' #bug 775227 #debug-only failure; timed out
|
skip-if = (toolkit == 'gonk' && debug) || toolkit == 'android' #bug 775227 #debug-only failure; timed out
|
||||||
[test_value_computation.html]
|
[test_value_computation.html]
|
||||||
|
|
|
@ -7,232 +7,80 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107378
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Test for Bug 1107378</title>
|
<title>Test for Bug 1107378</title>
|
||||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
<script type="text/javascript" src="property_database.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"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1107378">Mozilla Bug 1107378</a>
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1107378">Mozilla Bug 1107378</a>
|
||||||
<div id="display">
|
<div id="display">
|
||||||
<div id="content">
|
<iframe id="testIframe"></iframe>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<pre id="test">
|
<pre id="test">
|
||||||
<script type="application/javascript;version=1.7">
|
<script type="application/javascript;version=1.7">
|
||||||
"use strict";
|
"use strict";
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
/** Test for the CSS Unprefixing Service (Bug 1107378) **/
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
function getComputedStyleWrapper(elem, prop)
|
const IFRAME_TESTFILE = "unprefixing_service_iframe.html";
|
||||||
|
|
||||||
|
// This function gets invoked when our iframe finishes a given round of testing.
|
||||||
|
function startNextTest()
|
||||||
{
|
{
|
||||||
return window.getComputedStyle(elem, null).getPropertyValue(prop);
|
// Test the next whitelisted host, if any remain.
|
||||||
}
|
if (gWhitelistedHosts.length > 0) {
|
||||||
|
let host = gWhitelistedHosts.pop();
|
||||||
const gTestcases = [
|
info("Verifying that CSS Unprefixing Service is active, " +
|
||||||
{ decl: "-webkit-box-flex:5",
|
"at whitelisted test-host '" + host + "'");
|
||||||
targetPropName: "flex-grow",
|
testHost(host, true);
|
||||||
targetPropVal: "5" },
|
return;
|
||||||
|
|
||||||
/* 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",
|
|
||||||
targetPropVal: "6" },
|
|
||||||
|
|
||||||
/* Tests for handling !important: */
|
|
||||||
{ decl: "-webkit-box-flex:3!important;",
|
|
||||||
targetPropName: "flex-grow",
|
|
||||||
targetPropVal: "3" },
|
|
||||||
{ decl: "-webkit-box-flex:2!important;flex-grow:1",
|
|
||||||
targetPropName: "flex-grow",
|
|
||||||
targetPropVal: "2" },
|
|
||||||
|
|
||||||
{ decl: "-webkit-box-flex:1!important bogusText;",
|
|
||||||
targetPropName: "flex-grow"
|
|
||||||
/* invalid syntax --> no target prop-val. */
|
|
||||||
},
|
|
||||||
|
|
||||||
// Make sure we handle weird capitalization in property & value, too:
|
|
||||||
{ decl: "-WEBKIT-BoX-aLign: baSELine",
|
|
||||||
targetPropName: "align-items",
|
|
||||||
targetPropVal: "baseline" },
|
|
||||||
|
|
||||||
{ decl: "display:-webkit-box",
|
|
||||||
targetPropName: "display",
|
|
||||||
targetPropVal: "flex" },
|
|
||||||
|
|
||||||
{ decl: "display:-webkit-box; display:-moz-box;",
|
|
||||||
targetPropName: "display",
|
|
||||||
targetPropVal: "flex" },
|
|
||||||
|
|
||||||
{ decl: "display:-webkit-foobar; display:-moz-box;",
|
|
||||||
targetPropName: "display",
|
|
||||||
targetPropVal: "-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",
|
|
||||||
targetPropVal: "baseline" },
|
|
||||||
{ decl: "-webkit-box-align: center",
|
|
||||||
targetPropName: "align-items",
|
|
||||||
targetPropVal: "center" },
|
|
||||||
{ decl: "-webkit-box-align: end",
|
|
||||||
targetPropName: "align-items",
|
|
||||||
targetPropVal: "flex-end" },
|
|
||||||
{ decl: "-webkit-box-align: start",
|
|
||||||
targetPropName: "align-items",
|
|
||||||
targetPropVal: "flex-start" },
|
|
||||||
{ decl: "-webkit-box-align: stretch",
|
|
||||||
targetPropName: "align-items",
|
|
||||||
targetPropVal: "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",
|
|
||||||
targetPropVal: "2" },
|
|
||||||
{ decl: "-webkit-box-ordinal-group: 6000",
|
|
||||||
targetPropName: "order",
|
|
||||||
targetPropVal: "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",
|
|
||||||
targetPropVal: "row" },
|
|
||||||
{ decl: "-webkit-box-orient: inline-axis",
|
|
||||||
targetPropName: "flex-direction",
|
|
||||||
targetPropVal: "row" },
|
|
||||||
{ decl: "-webkit-box-orient: vertical",
|
|
||||||
targetPropName: "flex-direction",
|
|
||||||
targetPropVal: "column" },
|
|
||||||
{ decl: "-webkit-box-orient: block-axis",
|
|
||||||
targetPropName: "flex-direction",
|
|
||||||
targetPropVal: "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",
|
|
||||||
targetPropVal: "flex-start" },
|
|
||||||
{ decl: "-webkit-box-pack: center",
|
|
||||||
targetPropName: "justify-content",
|
|
||||||
targetPropVal: "center" },
|
|
||||||
{ decl: "-webkit-box-pack: end",
|
|
||||||
targetPropName: "justify-content",
|
|
||||||
targetPropVal: "flex-end" },
|
|
||||||
{ decl: "-webkit-box-pack: justify",
|
|
||||||
targetPropName: "justify-content",
|
|
||||||
targetPropVal: "space-between" },
|
|
||||||
|
|
||||||
// -webkit-transform: <transform> maps directly to "transform"
|
|
||||||
{ decl: "-webkit-transform: matrix(1, 2, 3, 4, 5, 6)",
|
|
||||||
targetPropName: "transform",
|
|
||||||
targetPropVal: "matrix(1, 2, 3, 4, 5, 6)" },
|
|
||||||
|
|
||||||
// -webkit-transition: <property> maps directly to "transition"
|
|
||||||
{ decl: "-webkit-transition: width 1s linear 2s",
|
|
||||||
targetPropName: "transition",
|
|
||||||
targetPropVal: "width 1s linear 2s" },
|
|
||||||
|
|
||||||
// -webkit-transition **with** -webkit-prefixed property in value.
|
|
||||||
{ decl: "-webkit-transition: -webkit-transform 1s linear 2s",
|
|
||||||
targetPropName: "transition",
|
|
||||||
targetPropVal: "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",
|
|
||||||
targetPropVal: "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",
|
|
||||||
targetPropVal: "transform 1s linear 2s" },
|
|
||||||
{ decl: "-webkit-transition: 1s -webkit-transform linear 2s",
|
|
||||||
targetPropName: "transition-property",
|
|
||||||
targetPropVal: "transform" },
|
|
||||||
];
|
|
||||||
|
|
||||||
// The main test function.
|
|
||||||
// aFlexboxTestcase is an entry from the list in flexbox_layout_testcases.js
|
|
||||||
function runOneTest(aTestcase)
|
|
||||||
{
|
|
||||||
let elem = document.getElementById("content");
|
|
||||||
|
|
||||||
let expectedValueInDOMStyle;
|
|
||||||
let expectedValueInComputedStyle;
|
|
||||||
if (typeof(aTestcase.targetPropVal) == 'undefined') {
|
|
||||||
expectedValueInDOMStyle = '';
|
|
||||||
expectedValueInComputedStyle = // initial computed style:
|
|
||||||
getComputedStyleWrapper(elem, aTestcase.targetPropName);
|
|
||||||
} else {
|
|
||||||
expectedValueInDOMStyle = aTestcase.targetPropVal;
|
|
||||||
expectedValueInComputedStyle = aTestcase.targetPropVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.setAttribute("style", aTestcase.decl);
|
// Test the next not-whitelisted host, if any remain.
|
||||||
|
if (gNotWhitelistedHosts.length > 0) {
|
||||||
// Check specified style for fixup:
|
let host = gNotWhitelistedHosts.pop();
|
||||||
is(elem.style[aTestcase.targetPropName], expectedValueInDOMStyle,
|
info("Verifying that CSS Unprefixing Service is inactive, " +
|
||||||
"Checking if unprefixing service produced expected result " +
|
"at non-whitelisted test-host '" + host + "'");
|
||||||
"in elem.style['" + aTestcase.targetPropName + "'] " +
|
testHost(host, false);
|
||||||
"when given decl '" + aTestcase.decl + "'");
|
return;
|
||||||
|
|
||||||
// Check computed style for fixup:
|
|
||||||
// (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, expectedValueInComputedStyle,
|
|
||||||
"Checking if unprefixing service produced expected result " +
|
|
||||||
"in computed value of property '" + aTestcase.targetPropName + "' " +
|
|
||||||
"when given decl '" + aTestcase.decl + "'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.setAttribute("style", "");
|
// Both arrays empty --> we're done.
|
||||||
}
|
|
||||||
|
|
||||||
function testWithUnprefixingDisabled()
|
|
||||||
{
|
|
||||||
// Sanity-check that -webkit-prefixed properties are rejected, when
|
|
||||||
// pref is disabled:
|
|
||||||
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 'flex-grow' " +
|
|
||||||
"when unprefixing pref is disabled");
|
|
||||||
|
|
||||||
let initialDisplay = getComputedStyleWrapper(elem, "display");
|
|
||||||
elem.setAttribute("style", "display:-webkit-box");
|
|
||||||
is(getComputedStyleWrapper(elem, "display"), initialDisplay,
|
|
||||||
"-webkit-box-flex shouldn't affect 'display' " +
|
|
||||||
"when unprefixing pref is disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
function testWithUnprefixingEnabled()
|
|
||||||
{
|
|
||||||
gTestcases.forEach(runOneTest);
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
function begin()
|
||||||
|
{
|
||||||
|
// Before we start loading things in iframes, set up postMessage handler.
|
||||||
|
registerPostMessageListener(startNextTest);
|
||||||
|
|
||||||
// First, test with unprefixing disabled (by default for now):
|
// Turn on prefs & start the first test!
|
||||||
testWithUnprefixingDisabled();
|
SpecialPowers.pushPrefEnv(
|
||||||
|
{ set: [[PREF_UNPREFIXING_SERVICE, true],
|
||||||
|
[PREF_INCLUDE_TEST_DOMAINS, true]]},
|
||||||
|
startNextTest);
|
||||||
|
}
|
||||||
|
|
||||||
// ...and then test with it enabled.
|
begin();
|
||||||
// XXXdholbert in bug 1132743, we'll be restricting unprefixing to only happen
|
|
||||||
// on a "fixlist" of domains. We'll need to run this test from a predetermined
|
|
||||||
// fake mochitest-domain, and include that domain in the "fixlist".
|
|
||||||
SpecialPowers.pushPrefEnv(
|
|
||||||
{ set: [["layout.css.unprefixing-service.enabled", true]] },
|
|
||||||
testWithUnprefixingEnabled);
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
<!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);
|
||||||
|
}
|
||||||
|
|
||||||
|
begin();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,250 @@
|
||||||
|
<!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>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="content"></div>
|
||||||
|
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** Helper file for testing the CSS Unprefixing Service **/
|
||||||
|
|
||||||
|
// Testcases for CSS Unprefixing service, with the (string) declaration that
|
||||||
|
// should be unprefixed, and the expected resulting property name & value:
|
||||||
|
const gTestcases = [
|
||||||
|
{ decl: "-webkit-box-flex:5",
|
||||||
|
targetPropName: "flex-grow",
|
||||||
|
targetPropVal: "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",
|
||||||
|
targetPropVal: "6" },
|
||||||
|
|
||||||
|
/* Tests for handling !important: */
|
||||||
|
{ decl: "-webkit-box-flex:3!important;",
|
||||||
|
targetPropName: "flex-grow",
|
||||||
|
targetPropVal: "3" },
|
||||||
|
{ decl: "-webkit-box-flex:2!important;flex-grow:1",
|
||||||
|
targetPropName: "flex-grow",
|
||||||
|
targetPropVal: "2" },
|
||||||
|
|
||||||
|
{ decl: "-webkit-box-flex:1!important bogusText;",
|
||||||
|
targetPropName: "flex-grow"
|
||||||
|
/* invalid syntax --> no target prop-val. */
|
||||||
|
},
|
||||||
|
|
||||||
|
// Make sure we handle weird capitalization in property & value, too:
|
||||||
|
{ decl: "-WEBKIT-BoX-aLign: baSELine",
|
||||||
|
targetPropName: "align-items",
|
||||||
|
targetPropVal: "baseline" },
|
||||||
|
|
||||||
|
{ decl: "display:-webkit-box",
|
||||||
|
targetPropName: "display",
|
||||||
|
targetPropVal: "flex" },
|
||||||
|
|
||||||
|
{ decl: "display:-webkit-box; display:-moz-box;",
|
||||||
|
targetPropName: "display",
|
||||||
|
targetPropVal: "flex" },
|
||||||
|
|
||||||
|
{ decl: "display:-webkit-foobar; display:-moz-box;",
|
||||||
|
targetPropName: "display",
|
||||||
|
targetPropVal: "-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",
|
||||||
|
targetPropVal: "baseline" },
|
||||||
|
{ decl: "-webkit-box-align: center",
|
||||||
|
targetPropName: "align-items",
|
||||||
|
targetPropVal: "center" },
|
||||||
|
{ decl: "-webkit-box-align: end",
|
||||||
|
targetPropName: "align-items",
|
||||||
|
targetPropVal: "flex-end" },
|
||||||
|
{ decl: "-webkit-box-align: start",
|
||||||
|
targetPropName: "align-items",
|
||||||
|
targetPropVal: "flex-start" },
|
||||||
|
{ decl: "-webkit-box-align: stretch",
|
||||||
|
targetPropName: "align-items",
|
||||||
|
targetPropVal: "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",
|
||||||
|
targetPropVal: "2" },
|
||||||
|
{ decl: "-webkit-box-ordinal-group: 6000",
|
||||||
|
targetPropName: "order",
|
||||||
|
targetPropVal: "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",
|
||||||
|
targetPropVal: "row" },
|
||||||
|
{ decl: "-webkit-box-orient: inline-axis",
|
||||||
|
targetPropName: "flex-direction",
|
||||||
|
targetPropVal: "row" },
|
||||||
|
{ decl: "-webkit-box-orient: vertical",
|
||||||
|
targetPropName: "flex-direction",
|
||||||
|
targetPropVal: "column" },
|
||||||
|
{ decl: "-webkit-box-orient: block-axis",
|
||||||
|
targetPropName: "flex-direction",
|
||||||
|
targetPropVal: "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",
|
||||||
|
targetPropVal: "flex-start" },
|
||||||
|
{ decl: "-webkit-box-pack: center",
|
||||||
|
targetPropName: "justify-content",
|
||||||
|
targetPropVal: "center" },
|
||||||
|
{ decl: "-webkit-box-pack: end",
|
||||||
|
targetPropName: "justify-content",
|
||||||
|
targetPropVal: "flex-end" },
|
||||||
|
{ decl: "-webkit-box-pack: justify",
|
||||||
|
targetPropName: "justify-content",
|
||||||
|
targetPropVal: "space-between" },
|
||||||
|
|
||||||
|
// -webkit-transform: <transform> maps directly to "transform"
|
||||||
|
{ decl: "-webkit-transform: matrix(1, 2, 3, 4, 5, 6)",
|
||||||
|
targetPropName: "transform",
|
||||||
|
targetPropVal: "matrix(1, 2, 3, 4, 5, 6)" },
|
||||||
|
|
||||||
|
// -webkit-transition: <property> maps directly to "transition"
|
||||||
|
{ decl: "-webkit-transition: width 1s linear 2s",
|
||||||
|
targetPropName: "transition",
|
||||||
|
targetPropVal: "width 1s linear 2s" },
|
||||||
|
|
||||||
|
// -webkit-transition **with** -webkit-prefixed property in value.
|
||||||
|
{ decl: "-webkit-transition: -webkit-transform 1s linear 2s",
|
||||||
|
targetPropName: "transition",
|
||||||
|
targetPropVal: "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",
|
||||||
|
targetPropVal: "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",
|
||||||
|
targetPropVal: "transform 1s linear 2s" },
|
||||||
|
{ decl: "-webkit-transition: 1s -webkit-transform linear 2s",
|
||||||
|
targetPropName: "transition-property",
|
||||||
|
targetPropVal: "transform" },
|
||||||
|
];
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
let expectedValueInDOMStyle;
|
||||||
|
let expectedValueInComputedStyle;
|
||||||
|
if (typeof(aTestcase.targetPropVal) == 'undefined') {
|
||||||
|
expectedValueInDOMStyle = '';
|
||||||
|
expectedValueInComputedStyle = // initial computed style:
|
||||||
|
getComputedStyleWrapper(elem, aTestcase.targetPropName);
|
||||||
|
} else {
|
||||||
|
expectedValueInDOMStyle = aTestcase.targetPropVal;
|
||||||
|
expectedValueInComputedStyle = aTestcase.targetPropVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
elem.setAttribute("style", aTestcase.decl);
|
||||||
|
|
||||||
|
// Check specified style for fixup:
|
||||||
|
is(elem.style[aTestcase.targetPropName], expectedValueInDOMStyle,
|
||||||
|
"Checking if CSS Unprefixing Service produced expected result " +
|
||||||
|
"in elem.style['" + aTestcase.targetPropName + "'] " +
|
||||||
|
"when given decl '" + aTestcase.decl + "'");
|
||||||
|
|
||||||
|
// Check computed style for fixup:
|
||||||
|
// (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, expectedValueInComputedStyle,
|
||||||
|
"Checking if CSS Unprefixing Service produced expected result " +
|
||||||
|
"in computed value of property '" + aTestcase.targetPropName + "' " +
|
||||||
|
"when given decl '" + aTestcase.decl + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
elem.setAttribute("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");
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTest()
|
||||||
|
{
|
||||||
|
if (window.location.hash === "#expectEnabled") {
|
||||||
|
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>
|
|
@ -0,0 +1,87 @@
|
||||||
|
/* 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())
|
||||||
|
let 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:
|
||||||
|
let 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():
|
||||||
|
let 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);
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче