summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMoonchild <mcwerewolf@gmail.com>2018-09-05 03:20:16 +0200
committerGitHub <noreply@github.com>2018-09-05 03:20:16 +0200
commitae432c63672cd4c24204b9dd4a92470a710d2d98 (patch)
tree303622d3452ebd43e8926611e6d89bb2248b9145
parentb28ab55f9675f2e97dda9a4fcac0d4f5267a2bb9 (diff)
downloadUXP-ae432c63672cd4c24204b9dd4a92470a710d2d98.tar
UXP-ae432c63672cd4c24204b9dd4a92470a710d2d98.tar.gz
UXP-ae432c63672cd4c24204b9dd4a92470a710d2d98.tar.lz
UXP-ae432c63672cd4c24204b9dd4a92470a710d2d98.tar.xz
UXP-ae432c63672cd4c24204b9dd4a92470a710d2d98.zip
Bug 1357432 (#750)
* Part 1. Move IsLocalRefURL to nsContentUtils to reuse this function. (port-rewrite) `IsLocalRefURL` is originally designed to be used by URLValue only. Since we need this function in SVGUseElement::LookupHref too, move it to nsContentUtils as a util function. * Revert "Part 1. Move IsLocalRefURL to nsContentUtils to reuse this function. (port-rewrite)" This reverts commit 19f010c62022e269f99066a8d90e3522fe31adaf. * Part 1. Duplicate IsLocalRefURL to nsContentUtils to reuse this function. `IsLocalRefURL` is originally designed to be used by URLValue only. Since we need this function in SVGUseElement::LookupHref too, duplicate it to nsContentUtils as a util function. This is a duplication because CSSValue uses stringbuffers and not nsStrings. While Bug 1356060 - "Just use nsString in URLValueData" converts this use from stringbuffer to nsString, it builds on a bunch of vartype refactoring (nsString vs. nsAString, etc.) which is too much of a headache to deal with just to deduplicate this simple function. * Part 2. Implement nsSVGEffects::GetBaseURLForLocalRef to export local-ref-url-resolving logic. ResolveURLUsingLocalRef is designed to be internally used by nsSVGEffects::Get-{SVGEffect}-URI functions. Since we also need it in SVGUseElement::LookupHref, make it public in nsSVGEffects. * Part 3. Resolve local-ref in SVGUseElement::LookupHref by nsSVGEffects::GetBaseURLForLocalRef. * Part 4. Reftest for using local-ref as xlink:href value.
-rw-r--r--dom/base/nsContentUtils.cpp16
-rw-r--r--dom/base/nsContentUtils.h7
-rw-r--r--dom/svg/SVGUseElement.cpp9
-rw-r--r--layout/reftests/svg/reftest.list1
-rw-r--r--layout/reftests/svg/use-localRef-link.html16
-rw-r--r--layout/svg/nsSVGEffects.cpp46
-rw-r--r--layout/svg/nsSVGEffects.h14
7 files changed, 90 insertions, 19 deletions
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 34c7d23b8..8612e76df 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -9787,3 +9787,19 @@ nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
return reloadSucceeded;
}
+
+/* static */ bool
+nsContentUtils::IsLocalRefURL(const nsString& aString)
+{
+ // Find the first non-"C0 controls + space" character.
+ const char16_t* current = aString.get();
+ for (; *current != '\0'; current++) {
+ if (*current > 0x20) {
+ // if the first non-"C0 controls + space" character is '#', this is a
+ // local-ref URL.
+ return *current == '#';
+ }
+ }
+
+ return false;
+} \ No newline at end of file
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 9ae6d2155..c255f813a 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2730,6 +2730,13 @@ public:
static bool AttemptLargeAllocationLoad(nsIHttpChannel* aChannel);
+ /**
+ * Detect whether a string is a (CSS) local-url.
+ * https://drafts.csswg.org/css-values/#local-urls
+ */
+ static bool
+ IsLocalRefURL(const nsString& aString);
+
private:
static bool InitializeEventTable();
diff --git a/dom/svg/SVGUseElement.cpp b/dom/svg/SVGUseElement.cpp
index 4911e2cac..9212ab1aa 100644
--- a/dom/svg/SVGUseElement.cpp
+++ b/dom/svg/SVGUseElement.cpp
@@ -15,6 +15,7 @@
#include "mozilla/dom/Element.h"
#include "nsContentUtils.h"
#include "nsIURI.h"
+#include "nsSVGEffects.h"
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Use)
@@ -418,11 +419,15 @@ SVGUseElement::LookupHref()
return;
}
+ nsCOMPtr<nsIURI> originURI =
+ mOriginal ? mOriginal->GetBaseURI() : GetBaseURI();
+ nsCOMPtr<nsIURI> baseURI = nsContentUtils::IsLocalRefURL(href)
+ ? nsSVGEffects::GetBaseURLForLocalRef(this, originURI)
+ : originURI;
+
nsCOMPtr<nsIURI> targetURI;
- nsCOMPtr<nsIURI> baseURI = mOriginal ? mOriginal->GetBaseURI() : GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
GetComposedDoc(), baseURI);
-
mSource.Reset(this, targetURI);
}
diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list
index 520adc9e6..096628681 100644
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -396,6 +396,7 @@ fuzzy-if(skiaContent,1,300) == tspan-xy-05.svg tspan-xy-ref.svg # bug 773482
fuzzy-if(skiaContent,1,300) == tspan-xy-06.svg tspan-xy-ref.svg # bug 773482
fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-middle-01.svg tspan-xy-anchor-middle-ref.svg # bug 773482
fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-ref.svg # bug 773482
+== use-localRef-link.html pass.svg
== userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01-ref.svg
== viewBox-and-pattern-01.svg pass.svg
== viewBox-and-pattern-02.svg pass.svg
diff --git a/layout/reftests/svg/use-localRef-link.html b/layout/reftests/svg/use-localRef-link.html
new file mode 100644
index 000000000..672e9ffaa
--- /dev/null
+++ b/layout/reftests/svg/use-localRef-link.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<head>
+<base href="/test">
+</head>
+<body style="background-color: lime;">
+ <svg width="100" height="100">
+ <defs>
+ <rect id="a" x="0" y="0" width="50" height="50" fill="lime"/>
+ </defs>
+ <rect x="0" y="0" width="50" height="50" fill="red"/>
+ <use xlink:href="#a"/>
+ </svg>
+</body>
+</html>
+
+
diff --git a/layout/svg/nsSVGEffects.cpp b/layout/svg/nsSVGEffects.cpp
index eac094a91..e75c973c8 100644
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -888,24 +888,13 @@ nsSVGEffects::InvalidateDirectRenderingObservers(nsIFrame* aFrame, uint32_t aFla
}
}
-static already_AddRefed<nsIURI>
-ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL)
+already_AddRefed<nsIURI>
+nsSVGEffects::GetBaseURLForLocalRef(nsIContent* content, nsIURI* aDocURI)
{
- MOZ_ASSERT(aFrame);
-
- if (!aURL) {
- return nullptr;
- }
-
- // Non-local-reference URL.
- if (!aURL->IsLocalRef()) {
- nsCOMPtr<nsIURI> result = aURL->GetURI();
- return result.forget();
- }
+ MOZ_ASSERT(content);
// For a local-reference URL, resolve that fragment against the current
// document that relative URLs are resolved against.
- nsIContent* content = aFrame->GetContent();
nsCOMPtr<nsIURI> baseURI = content->OwnerDoc()->GetDocumentURI();
if (content->IsInAnonymousSubtree()) {
@@ -933,12 +922,37 @@ ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL)
}
}
- if (originalURI && aURL->EqualsExceptRef(originalURI)) {
- baseURI = originalURI;
+ if (originalURI) {
+ bool isEqualsExceptRef = false;
+ aDocURI->EqualsExceptRef(originalURI, &isEqualsExceptRef);
+ if (isEqualsExceptRef) {
+ baseURI = originalURI;
+ }
}
}
}
+ return baseURI.forget();
+}
+
+static already_AddRefed<nsIURI>
+ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL)
+{
+ MOZ_ASSERT(aFrame);
+
+ if (!aURL) {
+ return nullptr;
+ }
+
+ // Non-local-reference URL.
+ if (!aURL->IsLocalRef()) {
+ nsCOMPtr<nsIURI> result = aURL->GetURI();
+ return result.forget();
+ }
+
+ nsCOMPtr<nsIURI> baseURI =
+ nsSVGEffects::GetBaseURLForLocalRef(aFrame->GetContent(), aURL->GetURI());
+
return aURL->ResolveLocalRef(baseURI);
}
diff --git a/layout/svg/nsSVGEffects.h b/layout/svg/nsSVGEffects.h
index 9dd92fd31..0cf9b1500 100644
--- a/layout/svg/nsSVGEffects.h
+++ b/layout/svg/nsSVGEffects.h
@@ -626,11 +626,23 @@ public:
static already_AddRefed<nsIURI>
GetPaintURI(nsIFrame* aFrame, nsStyleSVGPaint nsStyleSVG::* aPaint);
- /**
+ /**
* A helper function to resolve SVG mask URL.
*/
static already_AddRefed<nsIURI>
GetMaskURI(nsIFrame* aFrame, uint32_t aIndex);
+
+ /**
+ * Return a baseURL for resolving a local-ref URL.
+ *
+ * @param aContent an element which uses a local-ref property. Here are some
+ * examples:
+ * <rect fill=url(#foo)>
+ * <circle clip-path=url(#foo)>
+ * <use xlink:href="#foo">
+ */
+ static already_AddRefed<nsIURI>
+ GetBaseURLForLocalRef(nsIContent* aContent, nsIURI* aDocURI);
};
#endif /*NSSVGEFFECTS_H_*/