Make fragment-only URLs always be document-local references
This implements the 'local url' handling per:
https://drafts.csswg.org/css-values/#local-urls
which is also referenced from:
https://svgwg.org/svg2-draft/linking.html#linkRefAttrs
Most of the logic is handled by a new helper class named
SVGURLReferenceResolver, which keeps state, resolves the URL
and extracts the fragment identifier as needed.
BUG=470608
Review-Url: https://codereview.chromium.org/2174833002
Cr-Commit-Position: refs/heads/master@{#407299}
diff --git a/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base-expected.html b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base.html b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base.html
new file mode 100644
index 0000000..c928cbe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-local-url-with-base.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ filter: url(#filter);
+}
+</style>
+<div id="target"></div>
+<svg>
+ <filter id="filter" x="0" y="0" width="1" height="1" color-interpolation-filters="sRGB">
+ <feFlood flood-color="green"/>
+ </filter>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base-expected.html b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base.html b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base.html
new file mode 100644
index 0000000..3403359a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/masking/clip-path-reference-local-url-with-base.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ border-right: 100px solid red;
+ background-color: green;
+ -webkit-clip-path: url(#clip);
+ clip-path: url(#clip);
+}
+</style>
+<div id="target"></div>
+<svg>
+ <clipPath id="clip">
+ <rect width="100" height="100"/>
+ </filter>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource-expected.html b/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource-expected.html
new file mode 100644
index 0000000..5fc78bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 200px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource.html b/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource.html
new file mode 100644
index 0000000..14cbba5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/svg/local-url-with-valid-base-and-resource.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<base href="http://127.0.0.1:8000/svg/resources/red100x100.svg">
+<svg>
+ <rect id="rect" width="100" height="100" fill="green"/>
+ <use xlink:href="#rect" x="100"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/http/tests/svg/resources/red100x100.svg b/third_party/WebKit/LayoutTests/http/tests/svg/resources/red100x100.svg
new file mode 100644
index 0000000..263b3af
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/svg/resources/red100x100.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <rect id="rect" width="100" height="100" fill="red"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/platform/android/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/android/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index 5f49f784..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index 29a87826..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.txt
deleted file mode 100644
index 229e5d25..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/linking-base-external-reference-expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 604
- LayoutView at (0,0) size 800x600
-layer at (0,0) size 785x600
- LayoutBlockFlow {html} at (0,0) size 785x600
- LayoutInline {base} at (0,0) size 0x0
- LayoutText {#text} at (0,0) size 0x0
- LayoutText {#text} at (0,0) size 0x0
- LayoutSVGRoot {svg} at (0,0) size 100x100
- LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
- LayoutSVGResourceLinearGradient {linearGradient} [id="orange_red"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)]
- LayoutSVGGradientStop {stop} [offset=0.00] [color=#FF0000]
- LayoutSVGGradientStop {stop} [offset=1.00] [color=#FF0000]
- LayoutSVGRect {rect} at (0,0) size 100x100 [x=0.00] [y=0.00] [width=100.00] [height=100.00]
- LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index 8cc3425a..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index b76d497..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.txt
deleted file mode 100644
index 229e5d25..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/linking-base-external-reference-expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 604
- LayoutView at (0,0) size 800x600
-layer at (0,0) size 785x600
- LayoutBlockFlow {html} at (0,0) size 785x600
- LayoutInline {base} at (0,0) size 0x0
- LayoutText {#text} at (0,0) size 0x0
- LayoutText {#text} at (0,0) size 0x0
- LayoutSVGRoot {svg} at (0,0) size 100x100
- LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
- LayoutSVGResourceLinearGradient {linearGradient} [id="orange_red"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)]
- LayoutSVGGradientStop {stop} [offset=0.00] [color=#FF0000]
- LayoutSVGGradientStop {stop} [offset=1.00] [color=#FF0000]
- LayoutSVGRect {rect} at (0,0) size 100x100 [x=0.00] [y=0.00] [width=100.00] [height=100.00]
- LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.png
deleted file mode 100644
index b4e81fd..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.txt
deleted file mode 100644
index 3629126..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/linking-base-external-reference-expected.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 603
- LayoutView at (0,0) size 800x600
-layer at (0,0) size 785x600
- LayoutBlockFlow {html} at (0,0) size 785x600
- LayoutInline {base} at (0,0) size 0x0
- LayoutText {#text} at (0,0) size 0x0
- LayoutText {#text} at (0,0) size 0x0
- LayoutSVGRoot {svg} at (0,0) size 100x100
- LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
- LayoutSVGResourceLinearGradient {linearGradient} [id="orange_red"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)]
- LayoutSVGGradientStop {stop} [offset=0.00] [color=#FF0000]
- LayoutSVGGradientStop {stop} [offset=1.00] [color=#FF0000]
- LayoutSVGRect {rect} at (0,0) size 100x100 [x=0.00] [y=0.00] [width=100.00] [height=100.00]
- LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference-expected.html b/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference-expected.html
new file mode 100644
index 0000000..5fc78bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 200px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference.html b/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference.html
new file mode 100644
index 0000000..48985759
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/animations/local-url-target-reference.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<svg>
+ <script>
+ var svgRoot = document.querySelector('svg');
+ svgRoot.pauseAnimations();
+ svgRoot.setCurrentTime(1);
+ </script>
+ <defs>
+ <path id="path" d="M100,0z"/>
+ </defs>
+ <rect width="100" height="100" fill="green">
+ <animateMotion dur="0.01" fill="freeze">
+ <mpath xlink:href="#path"/>
+ </animateMotion>
+ </rect>
+ <rect id="rect" width="100" height="100" fill="red"/>
+ <set attributeName="fill" xlink:href="#rect" to="green" dur="indefinite"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/baseuri-href-expected.html b/third_party/WebKit/LayoutTests/svg/custom/baseuri-href-expected.html
index 75768a0..bc3a3d93 100644
--- a/third_party/WebKit/LayoutTests/svg/custom/baseuri-href-expected.html
+++ b/third_party/WebKit/LayoutTests/svg/custom/baseuri-href-expected.html
@@ -1,5 +1,6 @@
<!DOCTYPE html>
<svg>
- <rect id="rect" width="100" height="100" fill="green"/>
+ <rect width="100" height="100" fill="green"/>
+ <rect x="150" width="100" height="100" fill="green"/>
</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/linking-base-external-reference.xhtml b/third_party/WebKit/LayoutTests/svg/custom/linking-base-external-reference.xhtml
deleted file mode 100644
index 16cf05cc..0000000
--- a/third_party/WebKit/LayoutTests/svg/custom/linking-base-external-reference.xhtml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%">
- <base href="http://www.example.com"/>
- <!-- There should be no red -->
- <svg width="100%" height="100%" version="1.1"
- xmlns="http://www.w3.org/2000/svg">
-
- <defs>
- <linearGradient id="orange_red" x1="0%" y1="0%" x2="100%" y2="0%">
- <stop offset="0%" style="stop-color:red;"/>
- <stop offset="100%" style="stop-color:red;"/>
- </linearGradient>
-
- </defs>
-
- <rect x="0" y="0" width="100" height="100" style="fill: url(#orange_red)"/>
- </svg>
-</html>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc-expected.html b/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc.html b/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc.html
new file mode 100644
index 0000000..201ba10
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/local-url-reference-srcdoc.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<iframe srcdoc="
+ <!DOCTYPE html>
+ <style>body { margin: 0; }</style>
+ <svg xmlns='http://www.w3.org/2000/svg'>
+ <linearGradient id='gradient'>
+ <stop stop-color='green'/>
+ </linearGradient>
+ <rect width='100' height='100' fill='url(#gradient) red'/>
+ </svg>"
+ style="margin: 0; border: none" scrolling="no">
+</iframe>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/local-url-references-expected.html b/third_party/WebKit/LayoutTests/svg/custom/local-url-references-expected.html
new file mode 100644
index 0000000..2a4e1f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/local-url-references-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 400px; height: 300px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/svg/custom/local-url-references.html b/third_party/WebKit/LayoutTests/svg/custom/local-url-references.html
new file mode 100644
index 0000000..b8049870
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/custom/local-url-references.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<svg width="400" height="300">
+ <linearGradient id="paint">
+ <stop stop-color="green"/>
+ </linearGradient>
+ <linearGradient id="inheritedPaint" xlink:href="#paint"/>
+ <rect id="rect" width="100" height="100" fill="url(#paint) red"/>
+ <rect x="125" y="25" width="50" height="50" stroke="url(#paint) red" stroke-width="50"/>
+ <use x="200" xlink:href="#rect"/>
+ <rect x="300" width="100" height="100" fill="url(#inheritedPaint) red"/>
+
+ <filter id="filter" x="0" y="0" width="1" height="1" color-interpolation-filters="sRGB">
+ <feImage xlink:href="#rect"/>
+ </filter>
+ <rect y="100" width="100" height="100" fill="red" filter="url(#filter)"/>
+
+ <clipPath id="clip">
+ <rect y="50" width="100" height="50"/>
+ </clipPath>
+ <rect x="100" y="100" width="100" height="50" fill="green"/>
+ <g clip-path="url(#clip)" transform="translate(100, 100)">
+ <rect width="100" height="50" fill="red"/>
+ <rect y="50" width="100" height="50" fill="green"/>
+ </g>
+
+ <mask id="mask">
+ <rect y="50" width="100" height="50" fill="white"/>
+ </mask>
+ <rect y="100" x="200" width="100" height="50" fill="green"/>
+ <g mask="url(#mask)" transform="translate(200, 100)">
+ <rect width="100" height="50" fill="red"/>
+ <rect y="50" width="100" height="50" fill="green"/>
+ </g>
+
+ <pattern id="pattern" width="100" height="100" patternUnits="userSpaceOnUse">
+ <rect width="100" height="100" fill="green"/>
+ </pattern>
+ <pattern id="inheritedPattern" xlink:href="#pattern"/>
+ <rect x="300" y="100" width="100" height="100" fill="url(#inheritedPattern) red"/>
+
+ <marker id="marker" refY="0.5">
+ <rect width="1" height="1" fill="green"/>
+ </marker>
+ <polyline points="0,250 100,250 200,250" stroke="red" stroke-width="100"
+ marker-start="url(#marker)" marker-mid="url(#marker)" marker-end="url(#marker)"/>
+
+ <radialGradient id="radial">
+ <stop stop-color="green"/>
+ </radialGradient>
+ <radialGradient id="inheritedRadial" xlink:href="#radial"/>
+ <rect x="300" y="200" width="100" height="100" fill="url(#inheritedRadial) red"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference-expected.html b/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference.html b/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference.html
new file mode 100644
index 0000000..0051ba87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/text/textpath-local-url-reference.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<base href="http://www.example.com/">
+<script src="../../resources/ahem.js"></script>
+<svg>
+ <path id="path" d="M0,80h100"/>
+ <text font-size="100" font-family="Ahem" fill="green"><textPath xlink:href="#path">X</textPath></textPath>
+</svg>
diff --git a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
index 5f1a777..ade3260 100644
--- a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
@@ -35,6 +35,7 @@
#include "core/css/resolver/StyleResolverState.h"
#include "core/frame/UseCounter.h"
#include "core/layout/svg/ReferenceFilterBuilder.h"
+#include "core/svg/SVGURIReference.h"
namespace blink {
@@ -130,10 +131,9 @@
countFilterUse(FilterOperation::REFERENCE, state.document());
const CSSURIValue& urlValue = toCSSURIValue(*currValue);
- KURL url = state.document().completeURL(urlValue.url());
-
- ReferenceFilterOperation* operation = ReferenceFilterOperation::create(urlValue.url(), AtomicString(url.fragmentIdentifier()));
- if (!equalIgnoringFragmentIdentifier(url, state.document().url())) {
+ SVGURLReferenceResolver resolver(urlValue.value(), state.document());
+ ReferenceFilterOperation* operation = ReferenceFilterOperation::create(urlValue.value(), resolver.fragmentIdentifier());
+ if (!resolver.isLocal()) {
if (!urlValue.loadRequested())
state.elementStyleResources().addPendingSVGDocument(operation, &urlValue);
else if (urlValue.cachedDocument())
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
index bd5c532c..c1c4a2e 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -123,10 +123,9 @@
if (value.isBasicShapeValue())
return ShapeClipPathOperation::create(basicShapeForValue(state, value));
if (value.isURIValue()) {
- String cssURLValue = toCSSURIValue(value).value();
- KURL url = state.document().completeURL(cssURLValue);
+ SVGURLReferenceResolver resolver(toCSSURIValue(value).value(), state.document());
// TODO(fs): Doesn't work with forward or external SVG references (crbug.com/391604, crbug.com/109212, ...)
- return ReferenceClipPathOperation::create(cssURLValue, AtomicString(url.fragmentIdentifier()));
+ return ReferenceClipPathOperation::create(toCSSURIValue(value).value(), resolver.fragmentIdentifier());
}
DCHECK(value.isPrimitiveValue() && toCSSPrimitiveValue(value).getValueID() == CSSValueNone);
return nullptr;
diff --git a/third_party/WebKit/Source/core/svg/SVGURIReference.cpp b/third_party/WebKit/Source/core/svg/SVGURIReference.cpp
index 64fd240..8ed6a84 100644
--- a/third_party/WebKit/Source/core/svg/SVGURIReference.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGURIReference.cpp
@@ -56,24 +56,47 @@
return document.completeURL(stripLeadingAndTrailingHTMLSpaces(hrefString()));
}
+SVGURLReferenceResolver::SVGURLReferenceResolver(const String& urlString, const Document& document)
+ : m_relativeUrl(urlString)
+ , m_document(&document)
+ , m_isLocal(urlString.startsWith('#'))
+{
+}
+
+KURL SVGURLReferenceResolver::absoluteUrl() const
+{
+ if (m_absoluteUrl.isNull())
+ m_absoluteUrl = m_document->completeURL(m_relativeUrl);
+ return m_absoluteUrl;
+}
+
+bool SVGURLReferenceResolver::isLocal() const
+{
+ return m_isLocal || equalIgnoringFragmentIdentifier(absoluteUrl(), m_document->url());
+}
+
+AtomicString SVGURLReferenceResolver::fragmentIdentifier() const
+{
+ // If this is a "fragment-only" URL, then the reference is always local, so
+ // just return what's after the '#' as the fragment.
+ if (m_isLocal)
+ return AtomicString(m_relativeUrl.substring(1));
+ return AtomicString(absoluteUrl().fragmentIdentifier());
+}
+
AtomicString SVGURIReference::fragmentIdentifierFromIRIString(const String& urlString, const TreeScope& treeScope)
{
- const Document& document = treeScope.document();
-
- KURL url = document.completeURL(urlString);
- if (!url.hasFragmentIdentifier() || !equalIgnoringFragmentIdentifier(url, document.url()))
+ SVGURLReferenceResolver resolver(urlString, treeScope.document());
+ if (!resolver.isLocal())
return emptyAtom;
- return AtomicString(url.fragmentIdentifier());
+ return resolver.fragmentIdentifier();
}
Element* SVGURIReference::targetElementFromIRIString(const String& urlString, const TreeScope& treeScope, AtomicString* fragmentIdentifier)
{
- const Document& document = treeScope.document();
-
- KURL url = document.completeURL(urlString);
- if (!url.hasFragmentIdentifier() || !equalIgnoringFragmentIdentifier(url, document.url()))
+ AtomicString id = fragmentIdentifierFromIRIString(urlString, treeScope);
+ if (id.isEmpty())
return nullptr;
- AtomicString id(url.fragmentIdentifier());
if (fragmentIdentifier)
*fragmentIdentifier = id;
return treeScope.getElementById(id);
diff --git a/third_party/WebKit/Source/core/svg/SVGURIReference.h b/third_party/WebKit/Source/core/svg/SVGURIReference.h
index 97248ec..0bf7ddcc 100644
--- a/third_party/WebKit/Source/core/svg/SVGURIReference.h
+++ b/third_party/WebKit/Source/core/svg/SVGURIReference.h
@@ -48,18 +48,6 @@
static AtomicString fragmentIdentifierFromIRIString(const String&, const TreeScope&);
static Element* targetElementFromIRIString(const String&, const TreeScope&, AtomicString* = nullptr);
- static inline bool isExternalURIReference(const String& uri, const Document& document)
- {
- // Fragment-only URIs are always internal if the baseURL is same as the document URL.
- // This is common case, so check that first to avoid resolving URL (which is relatively expensive). See crbug.com/557979
- if (document.baseURL() == document.url() && uri.startsWith('#'))
- return false;
-
- // If the URI matches our documents URL, we're dealing with a local reference.
- KURL url = document.completeURL(uri);
- return !equalIgnoringFragmentIdentifier(url, document.url());
- }
-
const String& hrefString() const { return m_href->currentValue()->value(); }
// JS API
@@ -74,6 +62,24 @@
Member<SVGAnimatedHref> m_href;
};
+// Helper class used to resolve fragment references. Handles the 'local url
+// flag' per https://drafts.csswg.org/css-values/#local-urls .
+class SVGURLReferenceResolver {
+ STACK_ALLOCATED();
+public:
+ SVGURLReferenceResolver(const String& urlString, const Document&);
+
+ bool isLocal() const;
+ KURL absoluteUrl() const;
+ AtomicString fragmentIdentifier() const;
+
+private:
+ const String& m_relativeUrl;
+ Member<const Document> m_document;
+ mutable KURL m_absoluteUrl;
+ bool m_isLocal;
+};
+
} // namespace blink
#endif // SVGURIReference_h
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
index ca7d957..fe8395d 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
@@ -184,16 +184,21 @@
SVGGraphicsElement::collectStyleForPresentationAttribute(name, value, style);
}
+bool SVGUseElement::isStructurallyExternal() const
+{
+ return !m_elementIdentifierIsLocal;
+}
+
void SVGUseElement::updateTargetReference()
{
- KURL resolvedUrl = document().completeURL(hrefString());
- m_elementIdentifier = AtomicString(resolvedUrl.fragmentIdentifier());
- m_elementIdentifierIsLocal = resolvedUrl.isNull()
- || equalIgnoringFragmentIdentifier(resolvedUrl, document().url());
+ SVGURLReferenceResolver resolver(hrefString(), document());
+ m_elementIdentifier = resolver.fragmentIdentifier();
+ m_elementIdentifierIsLocal = resolver.isLocal();
if (m_elementIdentifierIsLocal) {
setDocumentResource(nullptr);
return;
}
+ KURL resolvedUrl = resolver.absoluteUrl();
if (m_elementIdentifier.isEmpty()
|| (m_resource && equalIgnoringFragmentIdentifier(resolvedUrl, m_resource->url())))
return;
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.h b/third_party/WebKit/Source/core/svg/SVGUseElement.h
index 26fe4b62..cd8332a 100644
--- a/third_party/WebKit/Source/core/svg/SVGUseElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGUseElement.h
@@ -73,7 +73,7 @@
void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) override;
bool isPresentationAttributeWithSVGDOM(const QualifiedName&) const override;
- bool isStructurallyExternal() const override { return !hrefString().isNull() && isExternalURIReference(hrefString(), document()); }
+ bool isStructurallyExternal() const override;
InsertionNotificationRequest insertedInto(ContainerNode*) override;
void removedFrom(ContainerNode*) override;