6 <html xmlns:
foo=
"http://foo.com" xmlns=
"http://www.w3.org/1999/xhtml">
8 https://bugzilla.mozilla.org/show_bug.cgi?id=209275
11 <title>Test for Bug
209275</title>
12 <script src=
"/tests/SimpleTest/SimpleTest.js"></script>
13 <link rel=
"stylesheet" type=
"text/css" href=
"/tests/SimpleTest/test.css" />
16 @namespace svg url(
"http://www.w3.org/2000/svg");
18 svg|a:visited { fill:purple; }
22 base0 should be ignored because it's not in the XHTML namespace
24 <foo:base id=
"base0" href=
"http://www.foo.com" />
27 baseEmpty should be ignored because it has no href and never gets one.
29 <base id=
"baseEmpty" />
32 baseWrongAttrNS should be ignored because its href attribute isn't in the empty
35 <base id=
"baseWrongAttrNS" foo:
href=
"http://foo.com" />
41 <a target=
"_blank" href=
"https://bugzilla.mozilla.org/show_bug.cgi?id=209275">Mozilla Bug
209275</a>
45 <a href=
"/" id=
"link1">link1
</a>
46 <div style=
"display:none">
47 <a href=
"/" id=
"link2">link2
</a>
49 <a href=
"/" id=
"link3" style=
"display:none">link3
</a>
50 <a href=
"#" id=
"link4">link4
</a>
51 <a href=
"" id=
"colorlink">colorlink
</a>
52 <a href=
"#" id=
"link5">link5
</a>
53 <iframe id=
"iframe"></iframe>
55 <svg width=
"5cm" height=
"3cm" viewBox=
"0 0 5 3" version=
"1.1"
56 xmlns=
"http://www.w3.org/2000/svg"
57 xmlns:
xlink=
"http://www.w3.org/1999/xlink">
58 <a xlink:
href=
"" id=
"ellipselink">
59 <ellipse cx=
"2.5" cy=
"1.5" rx=
"2" ry=
"1" id=
"ellipse" />
65 <script type=
"text/javascript">
68 /** Test for Bug 209275 **/
69 SimpleTest
.waitForExplicitFinish();
71 function link123HrefIs(href
, testNum
) {
72 is($('link1').href
, href
, "link1 test " + testNum
);
73 is($('link2').href
, href
, "link2 test " + testNum
);
74 is($('link3').href
, href
, "link3 test " + testNum
);
79 function visitedDependentComputedStyle(win
, elem
, property
) {
80 var utils
= SpecialPowers
.getDOMWindowUtils(window
);
81 return utils
.getVisitedDependentComputedStyle(elem
, "", property
);
84 function getColor(elem
) {
85 return visitedDependentComputedStyle(document
.defaultView
, elem
, "color");
88 function getFill(elem
) {
89 return visitedDependentComputedStyle(document
.defaultView
, elem
, "fill");
92 function setXlinkHref(elem
, href
) {
93 elem
.setAttributeNS("http://www.w3.org/1999/xlink", "href", href
);
96 function continueTest() {
101 var iframe
= document
.getElementById("iframe");
102 var iframeCw
= iframe
.contentWindow
;
104 // First, set the visited/unvisited link/ellipse colors.
105 const unvisitedColor
= "rgb(0, 0, 238)";
106 const visitedColor
= "rgb(85, 26, 139)";
107 const unvisitedFill
= "rgb(0, 0, 255)";
108 const visitedFill
= "rgb(128, 0, 128)";
110 const rand
= Date
.now() + "-" + Math
.random();
112 // Now we can start the tests in earnest.
115 // everything from the location up to and including the final forward slash
116 var path
= /(.*\/)[^\/]*/.exec(location
)[1];
118 // Set colorlink's href so we can check that it changes colors after we
119 // change the base href.
120 $('colorlink').href
= "http://example.com/" + rand
;
121 setXlinkHref($("ellipselink"), "http://example.com/" + rand
);
123 // Load http://example.com/${rand} into a new window so we can test that
124 // changing the document's base changes the visitedness of our links.
126 // cross-origin window.open'd windows don't fire load / error events, so we
127 // wait to close it until we observed the visited color.
128 let win
= window
.open("http://example.com/" + rand
, "_blank");
130 // Make sure things are what as we expect them at the beginning.
131 link123HrefIs(`${location.origin}/`, 1);
132 is($('link4').href
, loc
+ "#", "link 4 test 1");
133 is($('link5').href
, loc
+ "#", "link 5 test 1");
135 // Remove link5 from the document. We're going to test that its href changes
136 // properly when we change our base.
137 var link5
= $('link5');
140 $('base1').href
= "http://example.com";
142 // Were the links' hrefs updated after the base change?
143 link123HrefIs("http://example.com/", 2);
144 is($('link4').href
, "http://example.com/#", "link 4 test 2");
145 is(link5
.href
, "http://example.com/#", "link 5 test 2");
147 // Were colorlink's color and ellipse's fill updated appropriately?
148 // Because link coloring is asynchronous, we wait until it is updated (or we
149 // timeout and fail anyway).
150 while (getColor($('colorlink')) != visitedColor
) {
151 requestIdleCallback(continueTest
);
154 is(getColor($('colorlink')), visitedColor
,
155 "Wrong link color after base change.");
156 while (getFill($('ellipselink')) != visitedFill
) {
157 requestIdleCallback(continueTest
);
160 is(getFill($('ellipselink')), visitedFill
,
161 "Wrong ellipse fill after base change.");
165 $('base1').href
= "foo/";
166 // Should be interpreted relative to current URI (not the current base), so
167 // base should now be http://mochi.test:8888/foo/
169 link123HrefIs(`${location.origin}/`, 3);
170 is($('link4').href
, path
+ "foo/#", "link 4 test 3");
172 // Changing base2 shouldn't affect anything, because it's not the first base
174 $('base2').href
= "http://example.org/bar/";
175 link123HrefIs(`${location.origin}/`, 4);
176 is($('link4').href
, path
+ "foo/#", "link 4 test 4");
178 // If we unset base1's href attribute, the document's base should come from
179 // base2, whose href is http://example.org/bar/.
180 $('base1').removeAttribute("href");
181 link123HrefIs("http://example.org/", 5);
182 is($('link4').href
, "http://example.org/bar/#", "link 4 test 5");
184 // If we remove base1, base2 should become the first base tag, and the hrefs
185 // of all the links should change accordingly.
187 link123HrefIs("http://example.org/", 6);
188 is($('link4').href
, "http://example.org/bar/#", "link 4 test 6");
190 // If we add a new base after base2, nothing should change.
191 var base3
= document
.createElement("base");
192 base3
.href
= "http://base3.example.org/";
193 $('base2').parentNode
.insertBefore(base3
, $('base2').nextSibling
);
194 link123HrefIs("http://example.org/", 7);
195 is($('link4').href
, "http://example.org/bar/#", "link 4 test 7");
197 // But now if we add a new base before base 2, it should become the primary
199 var base4
= document
.createElement("base");
200 base4
.href
= "http://base4.example.org/";
201 $('base2').parentNode
.insertBefore(base4
, $('base2'));
202 link123HrefIs("http://base4.example.org/", 8);
203 is($('link4').href
, "http://base4.example.org/#", "link 4 test 8");
205 // Now if we remove all the base tags, the base should become the page's URI
211 link123HrefIs(`${location.origin}/`, 9);
212 is($('link4').href
, loc
+ "#", "link 4 test 9");
214 // Setting the href of base0 shouldn't do anything because it's not in the
216 $('base0').href
= "http://bar.com";
217 link123HrefIs(`${location.origin}/`, 10);
218 is($('link4').href
, loc
+ "#", "link 4 test 10");
220 // We load into an iframe a document with a <base href="...">, then remove
221 // the document element. Then we add an <html>, <body>, and <a>, and make
222 // sure that the <a> is resolved relative to the page's location, not its
223 // original base. We do this twice, rebuilding the document in a different
226 iframeCw
.location
= "file_bug209275_1.html";
227 yield undefined; // wait for our child to call us back.
228 is(iframeCw
.document
.getElementById("link").href
,
229 path
+ "file_bug209275_1.html#",
230 "Wrong href after nuking document.");
232 iframeCw
.location
= "file_bug209275_2.html";
233 yield undefined; // wait for callback from child
234 is(iframeCw
.document
.getElementById("link").href
,
235 `${location.origin}/`,
236 "Wrong href after nuking document second time.");
238 // Make sure that document.open() makes the document forget about any <base>
240 iframeCw
.location
= "file_bug209275_3.html";
241 yield undefined; // wait for callback from child
242 is(iframeCw
.document
.getElementById("link").href
,
243 "http://mochi.test:8888/",
244 "Wrong href after document.open().");
249 window
.addEventListener("load", function() {