mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 785017 - Make SVG Fragment identifier processing more robust. r=dholbert
This commit is contained in:
parent
74da64cc78
commit
d35423bd41
@ -201,7 +201,7 @@ ToPreserveAspectRatio(const nsAString &aString,
|
||||
|
||||
nsresult
|
||||
SVGAnimatedPreserveAspectRatio::SetBaseValueString(
|
||||
const nsAString &aValueAsString, nsSVGElement *aSVGElement)
|
||||
const nsAString &aValueAsString, nsSVGElement *aSVGElement, bool aDoSetAttr)
|
||||
{
|
||||
SVGPreserveAspectRatio val;
|
||||
nsresult res = ToPreserveAspectRatio(aValueAsString, &val);
|
||||
@ -209,18 +209,23 @@ SVGAnimatedPreserveAspectRatio::SetBaseValueString(
|
||||
return res;
|
||||
}
|
||||
|
||||
nsAttrValue emptyOrOldValue;
|
||||
if (aDoSetAttr) {
|
||||
emptyOrOldValue = aSVGElement->WillChangePreserveAspectRatio();
|
||||
}
|
||||
|
||||
mBaseVal = val;
|
||||
mIsBaseSet = true;
|
||||
|
||||
if (!mIsAnimated) {
|
||||
mAnimVal = mBaseVal;
|
||||
}
|
||||
else {
|
||||
if (aDoSetAttr) {
|
||||
aSVGElement->DidChangePreserveAspectRatio(emptyOrOldValue);
|
||||
}
|
||||
if (mIsAnimated) {
|
||||
aSVGElement->AnimationNeedsResample();
|
||||
}
|
||||
|
||||
// We don't need to call DidChange* here - we're only called by
|
||||
// nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
|
||||
// which takes care of notifying.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,8 @@ public:
|
||||
}
|
||||
|
||||
nsresult SetBaseValueString(const nsAString& aValue,
|
||||
nsSVGElement *aSVGElement);
|
||||
nsSVGElement *aSVGElement,
|
||||
bool aDoSetAttr);
|
||||
void GetBaseValueString(nsAString& aValue) const;
|
||||
|
||||
void SetBaseValue(const SVGPreserveAspectRatio &aValue,
|
||||
|
@ -4,7 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SVGFragmentIdentifier.h"
|
||||
#include "mozilla/CharTokenizer.h"
|
||||
#include "nsIDOMSVGDocument.h"
|
||||
#include "nsSVGSVGElement.h"
|
||||
#include "nsSVGViewElement.h"
|
||||
@ -21,6 +20,12 @@ IsMatchingParameter(const nsAString &aString, const nsAString &aParameterName)
|
||||
aString.CharAt(aParameterName.Length()) == '(';
|
||||
}
|
||||
|
||||
inline bool
|
||||
IgnoreWhitespace(PRUnichar aChar)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static nsSVGViewElement*
|
||||
GetViewElement(nsIDocument *aDocument, const nsAString &aId)
|
||||
{
|
||||
@ -94,19 +99,20 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
|
||||
return false;
|
||||
}
|
||||
|
||||
// SVGViewAttribute may occur in any order, but each type may only occur at most one time
|
||||
// in a correctly formed SVGViewSpec.
|
||||
// If we encounter any element more than once or get any syntax errors we're going to
|
||||
// return without updating the root element
|
||||
|
||||
const nsAString *viewBoxParams = nullptr;
|
||||
const nsAString *preserveAspectRatioParams = nullptr;
|
||||
const nsAString *zoomAndPanParams = nullptr;
|
||||
// SVGViewAttributes may occur in any order, but each type may only occur
|
||||
// at most one time in a correctly formed SVGViewSpec.
|
||||
// If we encounter any attribute more than once or get any syntax errors
|
||||
// we're going to return false and cancel any changes.
|
||||
|
||||
bool viewBoxFound = false;
|
||||
bool preserveAspectRatioFound = false;
|
||||
bool zoomAndPanFound = false;
|
||||
|
||||
// Each token is a SVGViewAttribute
|
||||
int32_t bracketPos = aViewSpec.FindChar('(');
|
||||
CharTokenizer<';'>tokenizer(
|
||||
Substring(aViewSpec, bracketPos + 1, aViewSpec.Length() - bracketPos - 2));
|
||||
uint32_t lengthOfViewSpec = aViewSpec.Length() - bracketPos - 2;
|
||||
nsCharSeparatedTokenizerTemplate<IgnoreWhitespace> tokenizer(
|
||||
Substring(aViewSpec, bracketPos + 1, lengthOfViewSpec), ';');
|
||||
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
return false;
|
||||
@ -125,50 +131,62 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
|
||||
Substring(token, bracketPos + 1, token.Length() - bracketPos - 2);
|
||||
|
||||
if (IsMatchingParameter(token, NS_LITERAL_STRING("viewBox"))) {
|
||||
if (viewBoxParams) {
|
||||
if (viewBoxFound ||
|
||||
NS_FAILED(root->mViewBox.SetBaseValueString(
|
||||
params, root, true))) {
|
||||
return false;
|
||||
}
|
||||
viewBoxParams = ¶ms;
|
||||
viewBoxFound = true;
|
||||
} else if (IsMatchingParameter(token, NS_LITERAL_STRING("preserveAspectRatio"))) {
|
||||
if (preserveAspectRatioParams) {
|
||||
if (preserveAspectRatioFound ||
|
||||
NS_FAILED(root->mPreserveAspectRatio.SetBaseValueString(
|
||||
params, root, true))) {
|
||||
return false;
|
||||
}
|
||||
preserveAspectRatioParams = ¶ms;
|
||||
preserveAspectRatioFound = true;
|
||||
} else if (IsMatchingParameter(token, NS_LITERAL_STRING("zoomAndPan"))) {
|
||||
if (zoomAndPanParams) {
|
||||
if (zoomAndPanFound) {
|
||||
return false;
|
||||
}
|
||||
zoomAndPanParams = ¶ms;
|
||||
nsIAtom *valAtom = NS_GetStaticAtom(params);
|
||||
if (!valAtom) {
|
||||
return false;
|
||||
}
|
||||
const nsSVGEnumMapping *mapping = nsSVGSVGElement::sZoomAndPanMap;
|
||||
while (mapping->mKey) {
|
||||
if (valAtom == *(mapping->mKey)) {
|
||||
// If we've got a valid zoomAndPan value, then set it on our root element.
|
||||
if (NS_FAILED(root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(
|
||||
mapping->mVal, root))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
mapping++;
|
||||
}
|
||||
if (!mapping->mKey) {
|
||||
// Unrecognised zoomAndPan value
|
||||
return false;
|
||||
}
|
||||
zoomAndPanFound = true;
|
||||
} else {
|
||||
// We don't support transform or viewTarget currently
|
||||
return false;
|
||||
}
|
||||
} while (tokenizer.hasMoreTokens());
|
||||
|
||||
if (viewBoxParams) {
|
||||
root->mViewBox.SetBaseValueString(*viewBoxParams, root);
|
||||
} else {
|
||||
RestoreOldViewBox(root);
|
||||
}
|
||||
|
||||
if (preserveAspectRatioParams) {
|
||||
root->mPreserveAspectRatio.SetBaseValueString(*preserveAspectRatioParams, root);
|
||||
} else {
|
||||
RestoreOldPreserveAspectRatio(root);
|
||||
}
|
||||
|
||||
if (zoomAndPanParams) {
|
||||
nsCOMPtr<nsIAtom> valAtom = do_GetAtom(*zoomAndPanParams);
|
||||
const nsSVGEnumMapping *mapping = root->sZoomAndPanMap;
|
||||
while (mapping->mKey) {
|
||||
if (valAtom == *(mapping->mKey)) {
|
||||
root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(mapping->mVal, root);
|
||||
break;
|
||||
}
|
||||
mapping++;
|
||||
if (root->mUseCurrentView) {
|
||||
// A previous SVGViewSpec may have overridden some attributes.
|
||||
// If they are no longer overridden we need to restore the old values.
|
||||
if (!viewBoxFound) {
|
||||
RestoreOldViewBox(root);
|
||||
}
|
||||
if (!preserveAspectRatioFound) {
|
||||
RestoreOldPreserveAspectRatio(root);
|
||||
}
|
||||
if (!zoomAndPanFound) {
|
||||
RestoreOldZoomAndPan(root);
|
||||
}
|
||||
} else {
|
||||
RestoreOldZoomAndPan(root);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -521,7 +521,7 @@ nsSVGElement::ParseAttribute(int32_t aNamespaceID,
|
||||
if (aAttribute == nsGkAtoms::viewBox) {
|
||||
nsSVGViewBox* viewBox = GetViewBox();
|
||||
if (viewBox) {
|
||||
rv = viewBox->SetBaseValueString(aValue, this);
|
||||
rv = viewBox->SetBaseValueString(aValue, this, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
viewBox->Init();
|
||||
} else {
|
||||
@ -535,7 +535,7 @@ nsSVGElement::ParseAttribute(int32_t aNamespaceID,
|
||||
SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
|
||||
GetPreserveAspectRatio();
|
||||
if (preserveAspectRatio) {
|
||||
rv = preserveAspectRatio->SetBaseValueString(aValue, this);
|
||||
rv = preserveAspectRatio->SetBaseValueString(aValue, this, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
preserveAspectRatio->Init();
|
||||
} else {
|
||||
|
@ -148,20 +148,25 @@ ToSVGViewBoxRect(const nsAString& aStr, nsSVGViewBoxRect *aViewBox)
|
||||
|
||||
nsresult
|
||||
nsSVGViewBox::SetBaseValueString(const nsAString& aValue,
|
||||
nsSVGElement *aSVGElement)
|
||||
nsSVGElement *aSVGElement,
|
||||
bool aDoSetAttr)
|
||||
{
|
||||
nsSVGViewBoxRect viewBox;
|
||||
nsresult res = ToSVGViewBoxRect(aValue, &viewBox);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
nsAttrValue emptyOrOldValue;
|
||||
if (aDoSetAttr) {
|
||||
emptyOrOldValue = aSVGElement->WillChangeViewBox();
|
||||
}
|
||||
mBaseVal = nsSVGViewBoxRect(viewBox.x, viewBox.y, viewBox.width, viewBox.height);
|
||||
mHasBaseVal = true;
|
||||
|
||||
if (aDoSetAttr) {
|
||||
aSVGElement->DidChangeViewBox(emptyOrOldValue);
|
||||
}
|
||||
if (mAnimVal) {
|
||||
aSVGElement->AnimationNeedsResample();
|
||||
}
|
||||
// We don't need to call Will/DidChange* here - we're only called by
|
||||
// nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
|
||||
// which takes care of notifying.
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ public:
|
||||
nsSVGElement *aSVGElement);
|
||||
|
||||
nsresult SetBaseValueString(const nsAString& aValue,
|
||||
nsSVGElement *aSVGElement);
|
||||
nsSVGElement *aSVGElement,
|
||||
bool aDoSetAttr);
|
||||
void GetBaseValueString(nsAString& aValue) const;
|
||||
|
||||
nsresult ToDOMAnimatedRect(nsIDOMSVGAnimatedRect **aResult,
|
||||
|
@ -19,9 +19,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=759124
|
||||
<script class="testbody" type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function Test(svgFragmentIdentifier, valid) {
|
||||
function Test(svgFragmentIdentifier, valid, viewBoxString,
|
||||
preserveAspectRatioString, zoomAndPanString)
|
||||
{
|
||||
this.svgFragmentIdentifier = svgFragmentIdentifier;
|
||||
this.valid = valid;
|
||||
this.viewBoxString = viewBoxString;
|
||||
this.preserveAspectRatioString = preserveAspectRatioString;
|
||||
this.zoomAndPanString = zoomAndPanString;
|
||||
}
|
||||
|
||||
function runTests()
|
||||
@ -30,25 +35,43 @@ function runTests()
|
||||
var doc = svg.contentWindow.document;
|
||||
|
||||
var tests = [
|
||||
new Test("view", true),
|
||||
new Test("unknown", false),
|
||||
new Test("svgView(viewBox(0,0,200,200)))", true),
|
||||
new Test("svgView(preserveAspectRatio(xMaxYMin slice))", true),
|
||||
new Test("svgView(viewBox(1,2,3,4);preserveAspectRatio(xMaxYMin))", true),
|
||||
new Test("svgView(zoomAndPan(disable))", true),
|
||||
new Test("svgView", false),
|
||||
new Test("svgView(", false),
|
||||
new Test("svgView()", false)
|
||||
new Test("view", true, "0 200 100 100", "none", null),
|
||||
new Test("unknown", false, null, null, null),
|
||||
new Test("svgView(viewBox(0,0,200,200))", true, "0 0 200 200", null, null),
|
||||
new Test("svgView(preserveAspectRatio(xMaxYMin slice))", true, null, "xMaxYMin slice", null),
|
||||
new Test("svgView(viewBox(1,2,3,4);preserveAspectRatio(xMinYMax))", true, "1 2 3 4", "xMinYMax meet", null),
|
||||
new Test("svgView(zoomAndPan(disable))", true, null, null, "disable"),
|
||||
new Test("svgView(viewBox(bad)", false, null, null, null),
|
||||
new Test("svgView(preserveAspectRatio(bad))", false, null, null, null),
|
||||
new Test("svgView(zoomAndPan(bad))", false, null, null, null),
|
||||
new Test("svgView", false, null, null, null),
|
||||
new Test("svgView(", false, null, null, null),
|
||||
new Test("svgView()", false, null, null, null),
|
||||
// Be sure we verify that there's a closing paren for svgView()
|
||||
// (and not too many closing parens)
|
||||
new Test("svgView(zoomAndPan(disable)", false, null, null, null),
|
||||
new Test("svgView(zoomAndPan(disable) ", false, null, null, null),
|
||||
new Test("svgView(zoomAndPan(disable)]", false, null, null, null),
|
||||
new Test("svgView(zoomAndPan(disable)))", false, null, null, null)
|
||||
];
|
||||
|
||||
var src = svg.getAttribute("src");
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var test = tests[i];
|
||||
svg.setAttribute("src", src + "#" + test.svgFragmentIdentifier);
|
||||
is(doc.rootElement.useCurrentView, test.valid,
|
||||
"Expected " + test.svgFragmentIdentifier + " to be " +
|
||||
(test.valid ? "valid" : "invalid"));
|
||||
}
|
||||
var src = svg.getAttribute("src");
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var test = tests[i];
|
||||
svg.setAttribute("src", src + "#" + test.svgFragmentIdentifier);
|
||||
is(doc.rootElement.useCurrentView, test.valid,
|
||||
"Expected " + test.svgFragmentIdentifier + " to be " +
|
||||
(test.valid ? "valid" : "invalid"));
|
||||
|
||||
is(doc.rootElement.getAttribute("viewBox"),
|
||||
test.viewBoxString, "unexpected viewBox");
|
||||
|
||||
is(doc.rootElement.getAttribute("preserveAspectRatio"),
|
||||
test.preserveAspectRatioString, "unexpected preserveAspectRatio");
|
||||
|
||||
is(doc.rootElement.getAttribute("zoomAndPan"),
|
||||
test.zoomAndPanString, "unexpected zoomAndPan");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user