Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 <!DOCTYPE html>
2 <html>
4 <head>
5 <title>Test document root content mutations</title>
6 <link rel="stylesheet" type="text/css"
7 href="chrome://mochikit/content/tests/SimpleTest/test.css" />
9 <script type="application/javascript"
10 src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
12 <script type="application/javascript"
13 src="../common.js"></script>
14 <script type="application/javascript"
15 src="../role.js"></script>
16 <script type="application/javascript"
17 src="../states.js"></script>
18 <script type="application/javascript"
19 src="../events.js"></script>
21 <script type="application/javascript">
23 ////////////////////////////////////////////////////////////////////////////
24 // Helpers
26 function getDocNode(aID)
27 {
28 return getNode(aID).contentDocument;
29 }
30 function getDocChildNode(aID)
31 {
32 return getDocNode(aID).body.firstChild;
33 }
35 function rootContentReplaced(aID, aTextName, aRootContentRole)
36 {
37 this.eventSeq = [
38 new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
39 new invokerChecker(EVENT_REORDER, getDocNode, aID)
40 ];
42 this.finalCheck = function rootContentReplaced_finalCheck()
43 {
44 var tree = {
45 role: aRootContentRole || ROLE_DOCUMENT,
46 children: [
47 {
48 role: ROLE_TEXT_LEAF,
49 name: aTextName
50 }
51 ]
52 };
53 testAccessibleTree(getDocNode(aID), tree);
54 }
55 }
57 function rootContentRemoved(aID)
58 {
59 this.eventSeq = [
60 new invokerChecker(EVENT_HIDE, null),
61 new invokerChecker(EVENT_REORDER, getDocNode, aID)
62 ];
64 this.preinvoke = function rootContentRemoved_preinvoke()
65 {
66 // Set up target for hide event before we invoke.
67 var text = getAccessible(getAccessible(getDocNode(aID)).firstChild);
68 this.eventSeq[0].target = text;
69 }
71 this.finalCheck = function rootContentRemoved_finalCheck()
72 {
73 var tree = {
74 role: ROLE_DOCUMENT,
75 children: [ ]
76 };
77 testAccessibleTree(getDocNode(aID), tree);
78 }
79 }
81 function rootContentInserted(aID, aTextName)
82 {
83 this.eventSeq = [
84 new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
85 new invokerChecker(EVENT_REORDER, getDocNode, aID)
86 ];
88 this.finalCheck = function rootContentInserted_finalCheck()
89 {
90 var tree = {
91 role: ROLE_DOCUMENT,
92 children: [
93 {
94 role: ROLE_TEXT_LEAF,
95 name: aTextName
96 }
97 ]
98 };
99 testAccessibleTree(getDocNode(aID), tree);
100 }
101 }
103 ////////////////////////////////////////////////////////////////////////////
104 // Invokers
106 function writeIFrameDoc(aID)
107 {
108 this.__proto__ = new rootContentReplaced(aID, "hello");
110 this.invoke = function writeIFrameDoc_invoke()
111 {
112 var docNode = getDocNode(aID);
114 // We can't use open/write/close outside of iframe document because of
115 // security error.
116 var script = docNode.createElement("script");
117 script.textContent = "document.open(); document.write('hello'); document.close();";
118 docNode.body.appendChild(script);
119 }
121 this.getID = function writeIFrameDoc_getID()
122 {
123 return "write document";
124 }
125 }
127 /**
128 * Replace HTML element.
129 */
130 function replaceIFrameHTMLElm(aID)
131 {
132 this.__proto__ = new rootContentReplaced(aID, "New Wave");
134 this.invoke = function replaceIFrameHTMLElm_invoke()
135 {
136 var docNode = getDocNode(aID);
137 var newHTMLNode = docNode.createElement("html");
138 var newBodyNode = docNode.createElement("body");
139 var newTextNode = docNode.createTextNode("New Wave");
140 newBodyNode.appendChild(newTextNode);
141 newHTMLNode.appendChild(newBodyNode);
142 docNode.replaceChild(newHTMLNode, docNode.documentElement);
143 }
145 this.getID = function replaceIFrameHTMLElm_getID()
146 {
147 return "replace HTML element";
148 }
149 }
151 /**
152 * Replace HTML body on new body having ARIA role.
153 */
154 function replaceIFrameBody(aID)
155 {
156 this.__proto__ = new rootContentReplaced(aID, "New Hello");
158 this.invoke = function replaceIFrameBody_invoke()
159 {
160 var docNode = getDocNode(aID);
161 var newBodyNode = docNode.createElement("body");
162 var newTextNode = docNode.createTextNode("New Hello");
163 newBodyNode.appendChild(newTextNode);
164 docNode.documentElement.replaceChild(newBodyNode, docNode.body);
165 }
167 this.getID = function replaceIFrameBody_getID()
168 {
169 return "replace body";
170 }
171 }
173 /**
174 * Replace HTML body on new body having ARIA role.
175 */
176 function replaceIFrameBodyOnARIARoleBody(aID)
177 {
178 this.__proto__ = new rootContentReplaced(aID, "New Hello",
179 ROLE_PUSHBUTTON);
181 this.invoke = function replaceIFrameBodyOnARIARoleBody_invoke()
182 {
183 var docNode = getDocNode(aID);
184 var newBodyNode = docNode.createElement("body");
185 var newTextNode = docNode.createTextNode("New Hello");
186 newBodyNode.appendChild(newTextNode);
187 newBodyNode.setAttribute("role", "button");
188 docNode.documentElement.replaceChild(newBodyNode, docNode.body);
189 }
191 this.getID = function replaceIFrameBodyOnARIARoleBody_getID()
192 {
193 return "replace body on body having ARIA role";
194 }
195 }
197 /**
198 * Open/close document pair.
199 */
200 function openIFrameDoc(aID)
201 {
202 this.__proto__ = new rootContentRemoved(aID);
204 this.invoke = function openIFrameDoc_invoke()
205 {
206 this.preinvoke();
208 // Open document.
209 var docNode = getDocNode(aID);
210 var script = docNode.createElement("script");
211 script.textContent = "function closeMe() { document.write('Works?'); document.close(); } window.closeMe = closeMe; document.open();";
212 docNode.body.appendChild(script);
213 }
215 this.getID = function openIFrameDoc_getID()
216 {
217 return "open document";
218 }
219 }
221 function closeIFrameDoc(aID)
222 {
223 this.__proto__ = new rootContentInserted(aID, "Works?");
225 this.invoke = function closeIFrameDoc_invoke()
226 {
227 // Write and close document.
228 getDocNode(aID).write('Works?'); getDocNode(aID).close();
229 }
231 this.getID = function closeIFrameDoc_getID()
232 {
233 return "close document";
234 }
235 }
237 /**
238 * Remove/insert HTML element pair.
239 */
240 function removeHTMLFromIFrameDoc(aID)
241 {
242 this.__proto__ = new rootContentRemoved(aID);
244 this.invoke = function removeHTMLFromIFrameDoc_invoke()
245 {
246 this.preinvoke();
248 // Remove HTML element.
249 var docNode = getDocNode(aID);
250 docNode.removeChild(docNode.firstChild);
251 }
253 this.getID = function removeHTMLFromIFrameDoc_getID()
254 {
255 return "remove HTML element";
256 }
257 }
259 function insertHTMLToIFrameDoc(aID)
260 {
261 this.__proto__ = new rootContentInserted(aID, "Haha");
263 this.invoke = function insertHTMLToIFrameDoc_invoke()
264 {
265 // Insert HTML element.
266 var docNode = getDocNode(aID);
267 var html = docNode.createElement("html");
268 var body = docNode.createElement("body");
269 var text = docNode.createTextNode("Haha");
270 body.appendChild(text);
271 html.appendChild(body);
272 docNode.appendChild(html);
273 }
275 this.getID = function insertHTMLToIFrameDoc_getID()
276 {
277 return "insert HTML element document";
278 }
279 }
281 /**
282 * Remove/insert HTML body pair.
283 */
284 function removeBodyFromIFrameDoc(aID)
285 {
286 this.__proto__ = new rootContentRemoved(aID);
288 this.invoke = function removeBodyFromIFrameDoc_invoke()
289 {
290 this.preinvoke();
292 // Remove body element.
293 var docNode = getDocNode(aID);
294 docNode.documentElement.removeChild(docNode.body);
295 }
297 this.getID = function removeBodyFromIFrameDoc_getID()
298 {
299 return "remove body element";
300 }
301 }
303 function insertElmUnderDocElmWhileBodyMissed(aID)
304 {
305 this.docNode = null;
306 this.inputNode = null;
308 function getInputNode()
309 { return this.inputNode; }
311 this.eventSeq = [
312 new invokerChecker(EVENT_SHOW, getInputNode.bind(this)),
313 new invokerChecker(EVENT_REORDER, getDocNode, aID)
314 ];
316 this.invoke = function invoke()
317 {
318 this.docNode = getDocNode(aID);
319 this.inputNode = this.docNode.createElement("input");
320 this.docNode.documentElement.appendChild(this.inputNode);
321 }
323 this.finalCheck = function finalCheck()
324 {
325 var tree =
326 { DOCUMENT: [
327 { ENTRY: [ ] }
328 ] };
329 testAccessibleTree(this.docNode, tree);
331 // Remove aftermath of this test before next test starts.
332 this.docNode.documentElement.removeChild(this.inputNode);
333 }
335 this.getID = function getID()
336 {
337 return "Insert element under document element while body is missed.";
338 }
339 }
341 function insertBodyToIFrameDoc(aID)
342 {
343 this.__proto__ = new rootContentInserted(aID, "Yo ho ho i butylka roma!");
345 this.invoke = function insertBodyToIFrameDoc_invoke()
346 {
347 // Insert body element.
348 var docNode = getDocNode(aID);
349 var body = docNode.createElement("body");
350 var text = docNode.createTextNode("Yo ho ho i butylka roma!");
351 body.appendChild(text);
352 docNode.documentElement.appendChild(body);
353 }
355 this.getID = function insertBodyToIFrameDoc_getID()
356 {
357 return "insert body element";
358 }
359 }
361 function changeSrc(aID)
362 {
363 this.containerNode = getNode(aID);
365 this.eventSeq = [
366 new invokerChecker(EVENT_REORDER, this.containerNode)
367 ];
369 this.invoke = function changeSrc_invoke()
370 {
371 this.containerNode.src = "data:text/html,<html><input></html>";
372 }
374 this.finalCheck = function changeSrc_finalCheck()
375 {
376 var tree =
377 { INTERNAL_FRAME: [
378 { DOCUMENT: [
379 { ENTRY: [ ] }
380 ] }
381 ] };
382 testAccessibleTree(this.containerNode, tree);
383 }
385 this.getID = function changeSrc_getID()
386 {
387 return "change src on iframe";
388 }
389 }
391 ////////////////////////////////////////////////////////////////////////////
392 // Test
394 //gA11yEventDumpID = "eventdump"; // debug stuff
395 //gA11yEventDumpToConsole = true;
397 var gQueue = null;
399 function doTest()
400 {
401 gQueue = new eventQueue();
403 gQueue.push(new writeIFrameDoc("iframe"));
404 gQueue.push(new replaceIFrameHTMLElm("iframe"));
405 gQueue.push(new replaceIFrameBody("iframe"));
406 gQueue.push(new openIFrameDoc("iframe"));
407 gQueue.push(new closeIFrameDoc("iframe"));
408 gQueue.push(new removeHTMLFromIFrameDoc("iframe"));
409 gQueue.push(new insertHTMLToIFrameDoc("iframe"));
410 gQueue.push(new removeBodyFromIFrameDoc("iframe"));
411 gQueue.push(new insertElmUnderDocElmWhileBodyMissed("iframe"));
412 gQueue.push(new insertBodyToIFrameDoc("iframe"));
413 gQueue.push(new changeSrc("iframe"));
414 gQueue.push(new replaceIFrameBodyOnARIARoleBody("iframe"));
416 gQueue.invoke(); // SimpleTest.finish() will be called in the end
417 }
419 SimpleTest.waitForExplicitFinish();
420 addA11yLoadEvent(doTest);
421 </script>
422 </head>
423 <body>
425 <a target="_blank"
426 title="Update accessible tree when root element is changed"
427 href="https://bugzilla.mozilla.org/show_bug.cgi?id=606082">Mozilla Bug 606082</a>
428 <a target="_blank"
429 title="Elements inserted outside the body aren't accessible"
430 href="https://bugzilla.mozilla.org/show_bug.cgi?id=608887">Mozilla Bug 608887</a>
431 <a target="_blank"
432 title="Reorder event for document must be fired after document initial tree creation"
433 href="https://bugzilla.mozilla.org/show_bug.cgi?id=669263">Mozilla Bug 669263</a>
434 <a target="_blank"
435 title="Changing the HTML body doesn't pick up ARIA role"
436 href="https://bugzilla.mozilla.org/show_bug.cgi?id=818407">Mozilla Bug 818407</a>
438 <p id="display"></p>
439 <div id="content" style="display: none"></div>
440 <pre id="test">
441 </pre>
443 <iframe id="iframe"></iframe>
445 <div id="eventdump"></div>
446 </body>
447 </html>