зеркало из https://github.com/mozilla/gecko-dev.git
Bug 779917 - Implement CSS.supports(). r=dbaron f=bz
This commit is contained in:
Родитель
eaa651ac88
Коммит
df75460fb8
|
@ -144,6 +144,10 @@ DOMInterfaces = {
|
|||
'resultNotAddRefed': [ 'item' ]
|
||||
},
|
||||
|
||||
'CSS': {
|
||||
'concrete': False,
|
||||
},
|
||||
|
||||
'CSS2Properties': {
|
||||
'nativeType': 'nsDOMCSSDeclaration'
|
||||
},
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* -*- 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dev.w3.org/csswg/css3-conditional/
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[PrefControlled]
|
||||
interface CSS {
|
||||
[Throws, Pref="layout.css.supports-rule.enabled"]
|
||||
static boolean supports(DOMString property, DOMString value);
|
||||
|
||||
[Throws, Pref="layout.css.supports-rule.enabled"]
|
||||
static boolean supports(DOMString conditionText);
|
||||
};
|
|
@ -21,6 +21,7 @@ webidl_files = \
|
|||
Blob.webidl \
|
||||
CanvasRenderingContext2D.webidl \
|
||||
ClientRectList.webidl \
|
||||
CSS.webidl \
|
||||
CSSPrimitiveValue.webidl \
|
||||
CSSStyleDeclaration.webidl \
|
||||
CSSValue.webidl \
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; 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/. */
|
||||
|
||||
/* DOM object holding utility CSS functions */
|
||||
|
||||
#include "CSS.h"
|
||||
|
||||
#include "nsCSSParser.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct SupportsParsingInfo
|
||||
{
|
||||
nsIURI* mDocURI;
|
||||
nsIURI* mBaseURI;
|
||||
nsIPrincipal* mPrincipal;
|
||||
};
|
||||
|
||||
static nsresult
|
||||
GetParsingInfo(nsISupports* aGlobal,
|
||||
SupportsParsingInfo& aInfo)
|
||||
{
|
||||
nsGlobalWindow* win = nsGlobalWindow::FromSupports(aGlobal);
|
||||
nsCOMPtr<nsIDocument> doc = win->GetDoc();
|
||||
if (!doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aInfo.mDocURI = nsCOMPtr<nsIURI>(doc->GetDocumentURI());
|
||||
aInfo.mBaseURI = nsCOMPtr<nsIURI>(doc->GetBaseURI());
|
||||
aInfo.mPrincipal = win->GetPrincipal();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
CSS::Supports(nsISupports* aGlobal,
|
||||
const nsAString& aProperty,
|
||||
const nsAString& aValue,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCSSParser parser;
|
||||
SupportsParsingInfo info;
|
||||
|
||||
nsresult rv = GetParsingInfo(aGlobal, info);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return false;
|
||||
}
|
||||
|
||||
return parser.EvaluateSupportsDeclaration(aProperty, aValue, info.mDocURI,
|
||||
info.mBaseURI, info.mPrincipal);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
CSS::Supports(nsISupports* aGlobal,
|
||||
const nsAString& aCondition,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCSSParser parser;
|
||||
SupportsParsingInfo info;
|
||||
|
||||
nsresult rv = GetParsingInfo(aGlobal, info);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return false;
|
||||
}
|
||||
|
||||
return parser.EvaluateSupportsCondition(aCondition, info.mDocURI,
|
||||
info.mBaseURI, info.mPrincipal);
|
||||
}
|
||||
|
||||
} // dom
|
||||
} // mozilla
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; 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/. */
|
||||
|
||||
/* DOM object holding utility CSS functions */
|
||||
|
||||
#ifndef mozilla_dom_CSS_h_
|
||||
#define mozilla_dom_CSS_h_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class CSS {
|
||||
private:
|
||||
CSS() MOZ_DELETE;
|
||||
|
||||
public:
|
||||
static bool Supports(nsISupports* aGlobal,
|
||||
const nsAString& aProperty,
|
||||
const nsAString& aValue,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static bool Supports(nsISupports* aGlobal,
|
||||
const nsAString& aDeclaration,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static bool PrefEnabled()
|
||||
{
|
||||
return Preferences::GetBool("layout.css.supports-rule.enabled");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_CSS_h_
|
|
@ -43,7 +43,7 @@ EXPORTS = \
|
|||
nsCSSValue.h \
|
||||
nsDOMCSSAttrDeclaration.h \
|
||||
nsDOMCSSDeclaration.h \
|
||||
nsDOMCSSRGBColor.h \
|
||||
nsDOMCSSRGBColor.h \
|
||||
nsDOMMediaQueryList.h \
|
||||
nsICSSDeclaration.h \
|
||||
nsICSSLoaderObserver.h \
|
||||
|
@ -83,11 +83,13 @@ EXPORTS_mozilla/css = \
|
|||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla/dom = \
|
||||
CSSValue.h \
|
||||
$(null)
|
||||
CSS.h \
|
||||
CSSValue.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
AnimationCommon.cpp \
|
||||
CSS.cpp \
|
||||
nsCSSAnonBoxes.cpp \
|
||||
nsCSSDataBlock.cpp \
|
||||
Declaration.cpp \
|
||||
|
@ -140,6 +142,7 @@ include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
|||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../base \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
-I$(srcdir)/../generic \
|
||||
-I$(srcdir)/../xul/base/src \
|
||||
-I$(srcdir)/../../content/base/src \
|
||||
|
|
|
@ -229,6 +229,17 @@ public:
|
|||
uint32_t aLineNumber, // for error reporting
|
||||
InfallibleTArray<float>& aSelectorList);
|
||||
|
||||
bool EvaluateSupportsDeclaration(const nsAString& aProperty,
|
||||
const nsAString& aValue,
|
||||
nsIURI* aDocURL,
|
||||
nsIURI* aBaseURL,
|
||||
nsIPrincipal* aDocPrincipal);
|
||||
|
||||
bool EvaluateSupportsCondition(const nsAString& aCondition,
|
||||
nsIURI* aDocURL,
|
||||
nsIURI* aBaseURL,
|
||||
nsIPrincipal* aDocPrincipal);
|
||||
|
||||
protected:
|
||||
class nsAutoParseCompoundProperty;
|
||||
friend class nsAutoParseCompoundProperty;
|
||||
|
@ -299,7 +310,7 @@ protected:
|
|||
class nsAutoSuppressErrors {
|
||||
public:
|
||||
nsAutoSuppressErrors(CSSParserImpl* aParser,
|
||||
bool aSuppressErrors)
|
||||
bool aSuppressErrors = true)
|
||||
: mParser(aParser),
|
||||
mOriginalValue(aParser->mSuppressErrors)
|
||||
{
|
||||
|
@ -1350,6 +1361,55 @@ CSSParserImpl::ParseKeyframeSelectorString(const nsSubstring& aSelectorString,
|
|||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::EvaluateSupportsDeclaration(const nsAString& aProperty,
|
||||
const nsAString& aValue,
|
||||
nsIURI* aDocURL,
|
||||
nsIURI* aBaseURL,
|
||||
nsIPrincipal* aDocPrincipal)
|
||||
{
|
||||
nsCSSProperty propID = nsCSSProps::LookupProperty(aProperty,
|
||||
nsCSSProps::eEnabled);
|
||||
if (propID == eCSSProperty_UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCSSScanner scanner(aValue, 0);
|
||||
css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aDocURL);
|
||||
InitScanner(scanner, reporter, aDocURL, aBaseURL, aDocPrincipal);
|
||||
nsAutoSuppressErrors suppressErrors(this);
|
||||
|
||||
bool parsedOK = ParseProperty(propID) && !GetToken(true);
|
||||
|
||||
CLEAR_ERROR();
|
||||
ReleaseScanner();
|
||||
|
||||
mTempData.ClearProperty(propID);
|
||||
mTempData.AssertInitialState();
|
||||
|
||||
return parsedOK;
|
||||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::EvaluateSupportsCondition(const nsAString& aDeclaration,
|
||||
nsIURI* aDocURL,
|
||||
nsIURI* aBaseURL,
|
||||
nsIPrincipal* aDocPrincipal)
|
||||
{
|
||||
nsCSSScanner scanner(aDeclaration, 0);
|
||||
css::ErrorReporter reporter(scanner, mSheet, mChildLoader, aDocURL);
|
||||
InitScanner(scanner, reporter, aDocURL, aBaseURL, aDocPrincipal);
|
||||
nsAutoSuppressErrors suppressErrors(this);
|
||||
|
||||
bool conditionMet;
|
||||
bool parsedOK = ParseSupportsCondition(conditionMet) && !GetToken(true);
|
||||
|
||||
CLEAR_ERROR();
|
||||
ReleaseScanner();
|
||||
|
||||
return parsedOK && conditionMet;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
|
@ -10214,3 +10274,25 @@ nsCSSParser::ParseKeyframeSelectorString(const nsSubstring& aSelectorString,
|
|||
ParseKeyframeSelectorString(aSelectorString, aURI, aLineNumber,
|
||||
aSelectorList);
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSSParser::EvaluateSupportsDeclaration(const nsAString& aProperty,
|
||||
const nsAString& aValue,
|
||||
nsIURI* aDocURL,
|
||||
nsIURI* aBaseURL,
|
||||
nsIPrincipal* aDocPrincipal)
|
||||
{
|
||||
return static_cast<CSSParserImpl*>(mImpl)->
|
||||
EvaluateSupportsDeclaration(aProperty, aValue, aDocURL, aBaseURL,
|
||||
aDocPrincipal);
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSSParser::EvaluateSupportsCondition(const nsAString& aCondition,
|
||||
nsIURI* aDocURL,
|
||||
nsIURI* aBaseURL,
|
||||
nsIPrincipal* aDocPrincipal)
|
||||
{
|
||||
return static_cast<CSSParserImpl*>(mImpl)->
|
||||
EvaluateSupportsCondition(aCondition, aDocURL, aBaseURL, aDocPrincipal);
|
||||
}
|
||||
|
|
|
@ -180,6 +180,25 @@ public:
|
|||
uint32_t aLineNumber,
|
||||
InfallibleTArray<float>& aSelectorList);
|
||||
|
||||
/**
|
||||
* Parse a property and value and return whether the property/value pair
|
||||
* is supported.
|
||||
*/
|
||||
bool EvaluateSupportsDeclaration(const nsAString& aProperty,
|
||||
const nsAString& aValue,
|
||||
nsIURI* aDocURL,
|
||||
nsIURI* aBaseURL,
|
||||
nsIPrincipal* aDocPrincipal);
|
||||
|
||||
/**
|
||||
* Parse an @supports condition and returns the result of evaluating the
|
||||
* condition.
|
||||
*/
|
||||
bool EvaluateSupportsCondition(const nsAString& aCondition,
|
||||
nsIURI* aDocURL,
|
||||
nsIURI* aBaseURL,
|
||||
nsIPrincipal* aDocPrincipal);
|
||||
|
||||
protected:
|
||||
// This is a CSSParserImpl*, but if we expose that type name in this
|
||||
// header, we can't put the type definition (in nsCSSParser.cpp) in
|
||||
|
|
|
@ -98,6 +98,7 @@ MOCHITEST_FILES = test_acid3_test46.html \
|
|||
test_default_computed_style.html \
|
||||
test_css_cross_domain.html \
|
||||
test_css_eof_handling.html \
|
||||
test_css_supports.html \
|
||||
test_default_bidi_css.html \
|
||||
test_descriptor_storage.html \
|
||||
test_descriptor_syntax_errors.html \
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=779917
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 779917</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.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=779917">Mozilla Bug 779917</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 779917 **/
|
||||
|
||||
function runTest()
|
||||
{
|
||||
var passingConditions = [
|
||||
"(color: green)",
|
||||
"((color: green))",
|
||||
"(color: green !important)",
|
||||
"(color: rainbow) or (color: green)",
|
||||
"(color: green) or (color: rainbow)",
|
||||
"(color: green) and (color: blue)",
|
||||
"(color: rainbow) or (color: iridescent) or (color: green)",
|
||||
"(color: red) and (color: green) and (color: blue)",
|
||||
"(color:green)",
|
||||
"not (color: rainbow)",
|
||||
"not (not (color: green))",
|
||||
"(unknown:) or (color: green)",
|
||||
"(unknown) or (color: green)",
|
||||
"(font: 16px serif)",
|
||||
"(color:) or (color: green)",
|
||||
"not (@page)",
|
||||
"not ({ something @with [ balanced ] brackets })",
|
||||
"an-extension(of some kind) or (color: green)",
|
||||
"not ()",
|
||||
"( Font: 20px serif ! Important) ",
|
||||
"(color: /* comment */ green)",
|
||||
"(/* comment */ color: green)",
|
||||
"(color: green /* comment */)",
|
||||
"(color: green) /* comment */",
|
||||
"/* comment */ (color: green)",
|
||||
"(color /* comment */: green)",
|
||||
"(color: green) /* unclosed comment",
|
||||
"(color: green",
|
||||
"(((((((color: green",
|
||||
"(font-family: 'Helvetica"
|
||||
];
|
||||
|
||||
var failingConditions = [
|
||||
"(color: rainbow)",
|
||||
"(color: rainbow) and (color: green)",
|
||||
"(color: blue) and (color: rainbow)",
|
||||
"(color: green) and (color: green) or (color: green)",
|
||||
"(color: green) or (color: green) and (color: green)",
|
||||
"not not (color: green)",
|
||||
"not (color: rainbow) and not (color: iridescent)",
|
||||
"not (color: rainbow) or (color: green)",
|
||||
"(not (color: rainbow) or (color: green))",
|
||||
"(unknown: green)",
|
||||
"not ({ something @with (unbalanced brackets })",
|
||||
"(color: green) or an-extension(that is [unbalanced)",
|
||||
"not(unknown: unknown)",
|
||||
"(color: green) or(color: blue)",
|
||||
"color: green",
|
||||
"(color: green;)",
|
||||
"(font-family: 'Helvetica\n",
|
||||
"(font-family: 'Helvetica\n')",
|
||||
"()",
|
||||
""
|
||||
];
|
||||
|
||||
var passingDeclarations = [
|
||||
["color", "green"],
|
||||
["color", " green "],
|
||||
["Color", "Green"],
|
||||
["color", "green /* comment */"],
|
||||
["color", "/* comment */ green"],
|
||||
["color", "green /* unclosed comment"],
|
||||
["font", "16px serif"],
|
||||
["font", "16px /* comment */ serif"],
|
||||
["font", "16px\nserif"],
|
||||
["color", "\\0067reen"]
|
||||
];
|
||||
|
||||
var failingDeclarations = [
|
||||
["color ", "green"],
|
||||
["color", "rainbow"],
|
||||
["color", "green green"],
|
||||
["color", "green !important"],
|
||||
["\\0063olor", "green"],
|
||||
["/* comment */color", "green"],
|
||||
["color/* comment */", "green"],
|
||||
["font-family", "'Helvetica\n"],
|
||||
["font-family", "'Helvetica\n'"],
|
||||
["color", "green;"],
|
||||
["color", ""],
|
||||
["unknown", "unknown"],
|
||||
["", "green"],
|
||||
["", ""]
|
||||
];
|
||||
|
||||
passingConditions.forEach(function(aCondition) {
|
||||
is(CSS.supports(aCondition), true, "CSS.supports returns true for passing condition \"" + aCondition + "\"");
|
||||
});
|
||||
|
||||
failingConditions.forEach(function(aCondition) {
|
||||
is(CSS.supports(aCondition), false, "CSS.supports returns false for failing condition \"" + aCondition + "\"");
|
||||
});
|
||||
|
||||
passingDeclarations.forEach(function(aDeclaration) {
|
||||
is(CSS.supports(aDeclaration[0], aDeclaration[1]), true, "CSS.supports returns true for supported declaration \"" + aDeclaration.join(":") + "\"");
|
||||
});
|
||||
|
||||
failingDeclarations.forEach(function(aDeclaration) {
|
||||
is(CSS.supports(aDeclaration[0], aDeclaration[1]), false, "CSS.supports returns false for unsupported declaration \"" + aDeclaration.join(":") + "\"");
|
||||
});
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({ "set": [["layout.css.supports-rule.enabled", true]] }, runTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче