tor-browser

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

dom-tree-accessors-001.html (8354B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <title>Shadow DOM Test: Upper-boundary encapsulation: document's DOM tree accessors</title>
      5 <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
      6 <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
      7 <link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
      8 <link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
      9 <link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
     10 <meta name="assert" content="Upper-boundary encapsulation: The shadow nodes and named shadow elements are not accessible using shadow host's document DOM tree accessors.">
     11 <script src="/resources/testharness.js"></script>
     12 <script src="/resources/testharnessreport.js"></script>
     13 <script src="../../../../html/resources/common.js"></script>
     14 </head>
     15 <body>
     16 <div id="log"></div>
     17 <script>
     18 // A document's "DOM tree accessors" include:
     19 //   (document.)head, title, body, images, embeds, plugins, links, forms,
     20 //   scripts, getElementsByName(), cssElementMap, and currentScript
     21 //
     22 // Of these, it is unclear how document.cssElementMap can be tested.
     23 // Except for it, there is a test corresponding to each accessor.
     24 //
     25 // Additionally, there are obsolete accessors
     26 // <http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#other-elements,-attributes-and-apis>:
     27 //   (document.)anchors, applets, and all.
     28 //
     29 // and some accessors defined in the DOM specification (formerly known as
     30 // "DOM Core") <http://dom.spec.whatwg.org/#interface-document>:
     31 //   (document.)documentElement, getElementsByTagName(),
     32 //   getElementsByTagNameNS(), getElementsByClassName(), and getElementById().
     33 //
     34 // As it seems reasonable to have tests for these accessors, this file also
     35 // includes tests for them, except for document.documentElement which is
     36 // unclear whether we can test; the distribution process of Shadow DOM does not
     37 // alter the host element, so the document element (e.g. <html>) cannot be
     38 // replaced with an element in a shadow tree.
     39 
     40 // ----------------------------------------------------------------------------
     41 // Constants and utility functions
     42 
     43 // Place the same HTML content into both the host document and the shadow root.
     44 // To differentiate these two, a class name is assigned to every element by
     45 // populateTestContentToHostDocument() and populateTestContentToShadowRoot().
     46 var HTML_CONTENT = [
     47    '<head>',
     48    '<title></title>',
     49    '<link rel="help" href="#">',
     50    '</head>',
     51    '<body>',
     52    '<p></p>',
     53    '<a name="test-name"></a>',
     54    '<a href="#"></a>',
     55    '<area href="#">',
     56    '<img src="#" alt="">',
     57    '<embed></embed>',
     58    '<form></form>',
     59    '<script><' + '/script>',
     60    '</body>'
     61 ].join('\n');
     62 
     63 function addClassNameToAllElements(document, root, className) {
     64    var nodeIterator = document.createNodeIterator(
     65        root, NodeFilter.SHOW_ELEMENT, null);
     66    var node;
     67    while (node = nodeIterator.nextNode())
     68        node.className = className;
     69 }
     70 
     71 function populateTestContentToHostDocument(document) {
     72    document.documentElement.innerHTML = HTML_CONTENT;
     73    addClassNameToAllElements(document, document.documentElement, 'host');
     74 }
     75 
     76 function populateTestContentToShadowRoot(shadowRoot) {
     77    shadowRoot.innerHTML = HTML_CONTENT;
     78    addClassNameToAllElements(shadowRoot.ownerDocument, shadowRoot, 'shadow');
     79 }
     80 
     81 function createDocumentForTesting() {
     82    var doc = document.implementation.createHTMLDocument('');
     83    populateTestContentToHostDocument(doc);
     84    var shadowRoot = doc.body.attachShadow({mode: 'open'});
     85    populateTestContentToShadowRoot(shadowRoot);
     86    return doc;
     87 }
     88 
     89 // Make sure the given HTMLCollection contains at least one elements and
     90 // all elements have the class named "host". This function works well with
     91 // HTMLCollection, HTMLAllCollection, and NodeList consisting of elements.
     92 function assert_collection(collection) {
     93    assert_true(collection.length > 0);
     94    Array.prototype.forEach.call(collection, function (element) {
     95        assert_equals(element.className, 'host');
     96    });
     97 }
     98 
     99 // ----------------------------------------------------------------------------
    100 // Tests for DOM tree accessors defined in HTML specification
    101 
    102 test(function () {
    103    var doc = createDocumentForTesting();
    104    assert_equals(doc.head.className, 'host');
    105    assert_equals(doc.body.className, 'host');
    106 },
    107    '<head> and <body> in a shadow tree should not be accessible from ' +
    108    'owner document\'s "head" and "body" properties, respectively.'
    109 );
    110 
    111 test(function () {
    112    var doc = document.implementation.createHTMLDocument('');
    113    populateTestContentToHostDocument(doc);
    114 
    115    // Note: this test is originally written to replace document.documentElement
    116    // with shadow contents, but among Shadow DOM V1 allowed elements body is the
    117    // most approximate to it, though some test may make lesser sense.
    118    var shadowRoot = doc.body.attachShadow({mode: 'open'});
    119    populateTestContentToShadowRoot(shadowRoot);
    120 
    121    // Replace the content of <title> to distinguish elements in a host
    122    // document and a shadow tree.
    123    doc.getElementsByTagName('title')[0].textContent = 'Title of host document';
    124    shadowRoot.querySelector('title').textContent =
    125        'Title of shadow tree';
    126 
    127    assert_equals(doc.title, 'Title of host document');
    128 },
    129    'The content of title element in a shadow tree should not be accessible ' +
    130    'from owner document\'s "title" attribute.'
    131 );
    132 
    133 function testHTMLCollection(accessor) {
    134    var doc = createDocumentForTesting();
    135    assert_collection(doc[accessor]);
    136 }
    137 
    138 generate_tests(
    139    testHTMLCollection,
    140    ['images', 'embeds', 'plugins', 'links', 'forms', 'scripts'].map(
    141        function (accessor) {
    142            return [
    143                'Elements in a shadow tree should not be accessible from ' +
    144                'owner document\'s "' + accessor + '" attribute.',
    145                accessor
    146            ];
    147        }));
    148 
    149 test(function () {
    150    var doc = createDocumentForTesting();
    151    assert_collection(doc.getElementsByName('test-name'));
    152 },
    153    'Elements in a shadow tree should not be accessible from owner ' +
    154    'document\'s getElementsByName() method.'
    155 );
    156 
    157 // ----------------------------------------------------------------------------
    158 // Tests for obsolete accessors
    159 
    160 generate_tests(
    161    testHTMLCollection,
    162    ['anchors', 'all'].map(
    163        function (accessor) {
    164            return [
    165                'Elements in a shadow tree should not be accessible from ' +
    166                'owner document\'s "' + accessor + '" attribute.',
    167                accessor
    168            ];
    169        }));
    170 
    171 // ----------------------------------------------------------------------------
    172 // Tests for accessors defined in DOM specification
    173 
    174 test(function () {
    175    var doc = createDocumentForTesting();
    176    assert_collection(doc.getElementsByTagName('p'));
    177 },
    178    'Elements in a shadow tree should not be accessible from owner ' +
    179    'document\'s getElementsByTagName() method.'
    180 );
    181 
    182 test(function () {
    183    // Create a XML document.
    184    var namespace = 'http://www.w3.org/1999/xhtml';
    185    var doc = document.implementation.createDocument(namespace, 'html');
    186    doc.documentElement.appendChild(doc.createElementNS(namespace, 'head'));
    187    var body = doc.createElementNS(namespace, 'body');
    188    var pHost = doc.createElementNS(namespace, 'p');
    189    pHost.className = "host";
    190    body.appendChild(pHost);
    191    doc.documentElement.appendChild(body);
    192 
    193    var shadowRoot = body.attachShadow({mode: 'open'});
    194    var pShadow = doc.createElementNS(namespace, 'p');
    195    pShadow.className = "shadow";
    196    shadowRoot.appendChild(pShadow);
    197 
    198    assert_collection(doc.getElementsByTagNameNS(namespace, 'p'));
    199 },
    200    'Elements in a shadow tree should not be accessible from owner ' +
    201    'document\'s getElementsByTagNameNS() method.'
    202 );
    203 
    204 test(function () {
    205    var doc = document.implementation.createHTMLDocument('');
    206    populateTestContentToHostDocument(doc);
    207    var shadowRoot = doc.body.attachShadow({mode: 'open'});
    208    populateTestContentToShadowRoot(shadowRoot);
    209 
    210    shadowRoot.querySelectorAll('p')[0].id = 'test-id';
    211    assert_equals(doc.getElementById('test-id'), null);
    212 },
    213    'Elements in a shadow tree should not be accessible from owner ' +
    214    'document\'s getElementById() method.'
    215 );
    216 </script>
    217 </body>
    218 </html>