tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_doc.html (12742B)


      1 <!DOCTYPE html>
      2 <html>
      3 
      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" />
      8 
      9  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
     10 
     11  <script type="application/javascript"
     12          src="../common.js"></script>
     13  <script type="application/javascript"
     14          src="../role.js"></script>
     15  <script type="application/javascript"
     16          src="../states.js"></script>
     17  <script type="application/javascript"
     18          src="../events.js"></script>
     19 
     20  <script type="application/javascript">
     21 
     22    // //////////////////////////////////////////////////////////////////////////
     23    // Helpers
     24 
     25    function getDocNode(aID) {
     26      return getNode(aID).contentDocument;
     27    }
     28    function getDocChildNode(aID) {
     29      return getDocNode(aID).body.firstChild;
     30    }
     31 
     32    function rootContentReplaced(aID, aTextName, aRootContentRole) {
     33      this.eventSeq = [
     34        new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
     35        new invokerChecker(EVENT_REORDER, getDocNode, aID),
     36      ];
     37 
     38      this.finalCheck = function rootContentReplaced_finalCheck() {
     39        var tree = {
     40          role: aRootContentRole || ROLE_DOCUMENT,
     41          children: [
     42            {
     43              role: ROLE_TEXT_LEAF,
     44              name: aTextName,
     45            },
     46          ],
     47        };
     48        testAccessibleTree(getDocNode(aID), tree);
     49      };
     50    }
     51 
     52    function rootContentRemoved(aID) {
     53      this.eventSeq = [
     54        new invokerChecker(EVENT_HIDE, null),
     55        new invokerChecker(EVENT_REORDER, getDocNode, aID),
     56      ];
     57 
     58      this.preinvoke = function rootContentRemoved_preinvoke() {
     59        // Set up target for hide event before we invoke.
     60        var text = getAccessible(getAccessible(getDocNode(aID)).firstChild);
     61        this.eventSeq[0].target = text;
     62      };
     63 
     64      this.finalCheck = function rootContentRemoved_finalCheck() {
     65        var tree = {
     66          role: ROLE_DOCUMENT,
     67          children: [ ],
     68        };
     69        testAccessibleTree(getDocNode(aID), tree);
     70      };
     71    }
     72 
     73    function rootContentInserted(aID, aTextName) {
     74      this.eventSeq = [
     75        new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
     76        new invokerChecker(EVENT_REORDER, getDocNode, aID),
     77      ];
     78 
     79      this.finalCheck = function rootContentInserted_finalCheck() {
     80        var tree = {
     81          role: ROLE_DOCUMENT,
     82          children: [
     83            {
     84              role: ROLE_TEXT_LEAF,
     85              name: aTextName,
     86            },
     87          ],
     88        };
     89        testAccessibleTree(getDocNode(aID), tree);
     90      };
     91    }
     92 
     93    // //////////////////////////////////////////////////////////////////////////
     94    // Invokers
     95 
     96    function writeIFrameDoc(aID) {
     97      this.__proto__ = new rootContentReplaced(aID, "hello");
     98 
     99      this.invoke = function writeIFrameDoc_invoke() {
    100        var docNode = getDocNode(aID);
    101 
    102        // We can't use open/write/close outside of iframe document because of
    103        // security error.
    104        var script = docNode.createElement("script");
    105        script.textContent = "document.open(); document.write('hello'); document.close();";
    106        docNode.body.appendChild(script);
    107      };
    108 
    109      this.getID = function writeIFrameDoc_getID() {
    110        return "write document";
    111      };
    112    }
    113 
    114    /**
    115     * Replace HTML element.
    116     */
    117    function replaceIFrameHTMLElm(aID) {
    118      this.eventSeq = [
    119        new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
    120        new invokerChecker(EVENT_REORDER, getDocNode, aID),
    121      ];
    122 
    123      this.invoke = function replaceIFrameHTMLElm_invoke() {
    124        var docNode = getDocNode(aID);
    125        var newHTMLNode = docNode.createElement("html");
    126        newHTMLNode.innerHTML = `<body><p>New Wave</p></body`;
    127        docNode.replaceChild(newHTMLNode, docNode.documentElement);
    128      };
    129 
    130      this.finalCheck = function replaceIFrameHTMLElm_finalCheck() {
    131        var tree = {
    132          role: ROLE_DOCUMENT,
    133          children: [
    134            {
    135              role: ROLE_PARAGRAPH,
    136              children: [
    137                {
    138                  role: ROLE_TEXT_LEAF,
    139                  name: "New Wave",
    140                },
    141              ],
    142            },
    143          ],
    144        };
    145        testAccessibleTree(getDocNode(aID), tree);
    146      };
    147 
    148      this.getID = function replaceIFrameHTMLElm_getID() {
    149        return "replace HTML element";
    150      };
    151    }
    152 
    153    /**
    154     * Replace HTML body on new body having ARIA role.
    155     */
    156    function replaceIFrameBody(aID) {
    157      this.__proto__ = new rootContentReplaced(aID, "New Hello");
    158 
    159      this.invoke = function replaceIFrameBody_invoke() {
    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      };
    166 
    167      this.getID = function replaceIFrameBody_getID() {
    168        return "replace body";
    169      };
    170    }
    171 
    172    /**
    173     * Replace HTML body on new body having ARIA role.
    174     */
    175    function replaceIFrameBodyOnARIARoleBody(aID) {
    176      this.__proto__ = new rootContentReplaced(aID, "New Hello",
    177                                               ROLE_APPLICATION);
    178 
    179      this.invoke = function replaceIFrameBodyOnARIARoleBody_invoke() {
    180        var docNode = getDocNode(aID);
    181        var newBodyNode = docNode.createElement("body");
    182        var newTextNode = docNode.createTextNode("New Hello");
    183        newBodyNode.appendChild(newTextNode);
    184        newBodyNode.setAttribute("role", "application");
    185        docNode.documentElement.replaceChild(newBodyNode, docNode.body);
    186      };
    187 
    188      this.getID = function replaceIFrameBodyOnARIARoleBody_getID() {
    189        return "replace body on body having ARIA role";
    190      };
    191    }
    192 
    193    /**
    194     * Open/close document pair.
    195     */
    196    function openIFrameDoc(aID) {
    197      this.__proto__ = new rootContentRemoved(aID);
    198 
    199      this.invoke = function openIFrameDoc_invoke() {
    200        this.preinvoke();
    201 
    202        // Open document.
    203        var docNode = getDocNode(aID);
    204        var script = docNode.createElement("script");
    205        script.textContent = "function closeMe() { document.write('Works?'); document.close(); } window.closeMe = closeMe; document.open();";
    206        docNode.body.appendChild(script);
    207      };
    208 
    209      this.getID = function openIFrameDoc_getID() {
    210        return "open document";
    211      };
    212    }
    213 
    214    function closeIFrameDoc(aID) {
    215      this.__proto__ = new rootContentInserted(aID, "Works?");
    216 
    217      this.invoke = function closeIFrameDoc_invoke() {
    218        // Write and close document.
    219        getDocNode(aID).write("Works?"); getDocNode(aID).close();
    220      };
    221 
    222      this.getID = function closeIFrameDoc_getID() {
    223        return "close document";
    224      };
    225    }
    226 
    227    /**
    228     * Remove/insert HTML element pair.
    229     */
    230    function removeHTMLFromIFrameDoc(aID) {
    231      this.__proto__ = new rootContentRemoved(aID);
    232 
    233      this.invoke = function removeHTMLFromIFrameDoc_invoke() {
    234        this.preinvoke();
    235 
    236        // Remove HTML element.
    237        var docNode = getDocNode(aID);
    238        docNode.firstChild.remove();
    239      };
    240 
    241      this.getID = function removeHTMLFromIFrameDoc_getID() {
    242        return "remove HTML element";
    243      };
    244    }
    245 
    246    function insertHTMLToIFrameDoc(aID) {
    247      this.__proto__ = new rootContentInserted(aID, "Haha");
    248 
    249      this.invoke = function insertHTMLToIFrameDoc_invoke() {
    250        // Insert HTML element.
    251        var docNode = getDocNode(aID);
    252        var html = docNode.createElement("html");
    253        var body = docNode.createElement("body");
    254        var text = docNode.createTextNode("Haha");
    255        body.appendChild(text);
    256        html.appendChild(body);
    257        docNode.appendChild(html);
    258      };
    259 
    260      this.getID = function insertHTMLToIFrameDoc_getID() {
    261        return "insert HTML element document";
    262      };
    263    }
    264 
    265    /**
    266     * Remove/insert HTML body pair.
    267     */
    268    function removeBodyFromIFrameDoc(aID) {
    269      this.__proto__ = new rootContentRemoved(aID);
    270 
    271      this.invoke = function removeBodyFromIFrameDoc_invoke() {
    272        this.preinvoke();
    273 
    274        // Remove body element.
    275        var docNode = getDocNode(aID);
    276        docNode.documentElement.removeChild(docNode.body);
    277      };
    278 
    279      this.getID = function removeBodyFromIFrameDoc_getID() {
    280        return "remove body element";
    281      };
    282    }
    283 
    284    function insertElmUnderDocElmWhileBodyMissed(aID) {
    285      this.docNode = null;
    286      this.inputNode = null;
    287 
    288      function getInputNode() { return this.inputNode; }
    289 
    290      this.eventSeq = [
    291        new invokerChecker(EVENT_SHOW, getInputNode.bind(this)),
    292        new invokerChecker(EVENT_REORDER, getDocNode, aID),
    293      ];
    294 
    295      this.invoke = function invoke() {
    296        this.docNode = getDocNode(aID);
    297        this.inputNode = this.docNode.createElement("input");
    298        this.docNode.documentElement.appendChild(this.inputNode);
    299      };
    300 
    301      this.finalCheck = function finalCheck() {
    302        var tree =
    303          { DOCUMENT: [
    304            { ENTRY: [ ] },
    305          ] };
    306        testAccessibleTree(this.docNode, tree);
    307 
    308        // Remove aftermath of this test before next test starts.
    309        this.docNode.documentElement.removeChild(this.inputNode);
    310      };
    311 
    312      this.getID = function getID() {
    313        return "Insert element under document element while body is missed.";
    314      };
    315    }
    316 
    317    function insertBodyToIFrameDoc(aID) {
    318      this.__proto__ = new rootContentInserted(aID, "Yo ho ho i butylka roma!");
    319 
    320      this.invoke = function insertBodyToIFrameDoc_invoke() {
    321        // Insert body element.
    322        var docNode = getDocNode(aID);
    323        var body = docNode.createElement("body");
    324        var text = docNode.createTextNode("Yo ho ho i butylka roma!");
    325        body.appendChild(text);
    326        docNode.documentElement.appendChild(body);
    327      };
    328 
    329      this.getID = function insertBodyToIFrameDoc_getID() {
    330        return "insert body element";
    331      };
    332    }
    333 
    334    function changeSrc(aID) {
    335      this.containerNode = getNode(aID);
    336 
    337      this.eventSeq = [
    338        new invokerChecker(EVENT_REORDER, this.containerNode),
    339      ];
    340 
    341      this.invoke = function changeSrc_invoke() {
    342        this.containerNode.src = "data:text/html,<html><input></html>";
    343      };
    344 
    345      this.finalCheck = function changeSrc_finalCheck() {
    346        var tree =
    347          { INTERNAL_FRAME: [
    348            { DOCUMENT: [
    349              { ENTRY: [ ] },
    350            ] },
    351          ] };
    352        testAccessibleTree(this.containerNode, tree);
    353      };
    354 
    355      this.getID = function changeSrc_getID() {
    356        return "change src on iframe";
    357      };
    358    }
    359 
    360    // //////////////////////////////////////////////////////////////////////////
    361    // Test
    362 
    363    // gA11yEventDumpToConsole = true;
    364    // enableLogging('tree,verbose');
    365 
    366    var gQueue = null;
    367 
    368    function doTest() {
    369      gQueue = new eventQueue();
    370 
    371      gQueue.push(new writeIFrameDoc("iframe"));
    372      gQueue.push(new replaceIFrameHTMLElm("iframe"));
    373      gQueue.push(new replaceIFrameBody("iframe"));
    374      gQueue.push(new openIFrameDoc("iframe"));
    375      gQueue.push(new closeIFrameDoc("iframe"));
    376      gQueue.push(new removeHTMLFromIFrameDoc("iframe"));
    377      gQueue.push(new insertHTMLToIFrameDoc("iframe"));
    378      gQueue.push(new removeBodyFromIFrameDoc("iframe"));
    379      gQueue.push(new insertElmUnderDocElmWhileBodyMissed("iframe"));
    380      gQueue.push(new insertBodyToIFrameDoc("iframe"));
    381      gQueue.push(new changeSrc("iframe"));
    382      gQueue.push(new replaceIFrameBodyOnARIARoleBody("iframe"));
    383 
    384      gQueue.invoke(); // SimpleTest.finish() will be called in the end
    385    }
    386 
    387    SimpleTest.waitForExplicitFinish();
    388    addA11yLoadEvent(doTest);
    389  </script>
    390 </head>
    391 <body>
    392 
    393  <a target="_blank"
    394     title="Update accessible tree when root element is changed"
    395     href="https://bugzilla.mozilla.org/show_bug.cgi?id=606082">Mozilla Bug 606082</a>
    396  <a target="_blank"
    397     title="Elements inserted outside the body aren't accessible"
    398     href="https://bugzilla.mozilla.org/show_bug.cgi?id=608887">Mozilla Bug 608887</a>
    399  <a target="_blank"
    400     title="Reorder event for document must be fired after document initial tree creation"
    401     href="https://bugzilla.mozilla.org/show_bug.cgi?id=669263">Mozilla Bug 669263</a>
    402  <a target="_blank"
    403     title="Changing the HTML body doesn't pick up ARIA role"
    404     href="https://bugzilla.mozilla.org/show_bug.cgi?id=818407">Mozilla Bug 818407</a>
    405 
    406  <p id="display"></p>
    407  <div id="content" style="display: none"></div>
    408  <pre id="test">
    409  </pre>
    410 
    411  <iframe id="iframe"></iframe>
    412 
    413  <div id="eventdump"></div>
    414 </body>
    415 </html>