tor-browser

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

cross-origin-subframe.html (4950B)


      1 <!DOCTYPE html>
      2 <div style="height: 200px; width: 100px;"></div>
      3 <div id="target" style="background-color: green; width:100px; height:100px"></div>
      4 <div id="empty-target" style="width: 100px"></div>
      5 <div style="height: 200px; width: 100px;"></div>
      6 
      7 <script>
      8 var port;
      9 var entries = [];
     10 var target = document.getElementById("target");
     11 var emptyTarget = document.getElementById("empty-target");
     12 var scroller = document.scrollingElement;
     13 var nextStep;
     14 
     15 function clientRectToJson(rect) {
     16  if (!rect)
     17    return "null";
     18  return {
     19    top: rect.top,
     20    right: rect.right,
     21    bottom: rect.bottom,
     22    left: rect.left
     23  };
     24 }
     25 
     26 function entryToJson(entry) {
     27  return {
     28    boundingClientRect: clientRectToJson(entry.boundingClientRect),
     29    intersectionRect: clientRectToJson(entry.intersectionRect),
     30    rootBounds: clientRectToJson(entry.rootBounds),
     31    isIntersecting: entry.isIntersecting,
     32    target: entry.target === document.documentElement ? "html" : entry.target.id
     33  };
     34 }
     35 
     36 function boundingClientRectToJson(element) {
     37  let r = element.getBoundingClientRect();
     38  return [r.left, r.right, r.top, r.bottom];
     39 }
     40 
     41 // Note that we never use RAF in this code, because this frame might get render-throttled.
     42 // Instead of RAF-ing, we just post an empty message to the parent window, which will
     43 // RAF when it is received, and then send us a message to cause the next step to run.
     44 
     45 // Use a rootMargin here, and verify it does NOT get applied for the cross-origin case.
     46 var observer = new IntersectionObserver(function(changes) {
     47    entries = entries.concat(changes)
     48 }, { rootMargin: "7px" });
     49 observer.observe(target);
     50 observer.observe(emptyTarget);
     51 observer.observe(document.documentElement);
     52 
     53 function step0() {
     54  entries = entries.concat(observer.takeRecords());
     55  nextStep = step1;
     56  var expected = [{
     57    boundingClientRect: [8, 108, 208, 308],
     58    intersectionRect: [0, 0, 0, 0],
     59    rootBounds: "null",
     60    isIntersecting: false,
     61    target: target.id
     62  }, {
     63    boundingClientRect: [8, 108, 308, 308],
     64    intersectionRect: [0, 0, 0, 0],
     65    rootBounds: "null",
     66    isIntersecting: false,
     67    target: emptyTarget.id
     68  }, {
     69    boundingClientRect: boundingClientRectToJson(document.documentElement),
     70    intersectionRect: [0, 0, 0, 0],
     71    rootBounds: "null",
     72    isIntersecting: false,
     73    target: "html"
     74  }];
     75  port.postMessage({
     76    actual: entries.map(entryToJson),
     77    expected: expected,
     78    description: "First rAF"
     79  }, "*");
     80  entries = [];
     81  port.postMessage({scrollTo: 200}, "*");
     82 }
     83 
     84 function step1() {
     85  entries = entries.concat(observer.takeRecords());
     86  var client_rect = boundingClientRectToJson(document.documentElement);
     87  // When the top document is scrolled all the way up, the iframe element is
     88  // 108px below the scrolling viewport, and the iframe has a 2px border. When
     89  // the top document is scrolled to y=200, the top 90px of the iframe's content
     90  // is visible.
     91  var expected = [{
     92    boundingClientRect: client_rect,
     93    intersectionRect: client_rect.slice(0, 3).concat(90),
     94    rootBounds: "null",
     95    isIntersecting: true,
     96    target: "html"
     97  }];
     98  port.postMessage({
     99    actual: entries.map(entryToJson),
    100    expected: expected,
    101    description: "topDocument.scrollingElement.scrollTop = 200"
    102  }, "*");
    103  entries = [];
    104  scroller.scrollTop = 250;
    105  nextStep = step2;
    106  port.postMessage({}, "*");
    107 }
    108 
    109 function step2() {
    110  entries = entries.concat(observer.takeRecords());
    111  var expected = [{
    112    boundingClientRect: [8, 108, -42, 58],
    113    intersectionRect: [8, 108, 0, 58],
    114    rootBounds: "null",
    115    isIntersecting: true,
    116    target: target.id
    117  }, {
    118    boundingClientRect: [8, 108, 58, 58],
    119    intersectionRect: [8, 108, 58, 58],
    120    rootBounds: "null",
    121    isIntersecting: true,
    122    target: emptyTarget.id
    123  }];
    124  port.postMessage({
    125    actual: entries.map(entryToJson),
    126    expected: expected,
    127    description: "iframeDocument.scrollingElement.scrollTop = 250"
    128  }, "*");
    129  entries = [];
    130  nextStep = step3;
    131  port.postMessage({scrollTo: 100}, "*");
    132 }
    133 
    134 function step3() {
    135  entries = entries.concat(observer.takeRecords());
    136  var expected = [{
    137    boundingClientRect: [8, 108, -42, 58],
    138    intersectionRect: [0, 0, 0, 0],
    139    rootBounds: "null",
    140    isIntersecting: false,
    141    target: target.id
    142  }, {
    143    boundingClientRect: [8, 108, 58, 58],
    144    intersectionRect: [0, 0, 0, 0],
    145    rootBounds: "null",
    146    isIntersecting: false,
    147    target: emptyTarget.id
    148  }, {
    149    boundingClientRect: boundingClientRectToJson(document.documentElement),
    150    intersectionRect: [0, 0, 0, 0],
    151    rootBounds: "null",
    152    isIntersecting: false,
    153    target: "html"
    154  }];
    155  port.postMessage({
    156    actual: entries.map(entryToJson),
    157    expected: expected,
    158    description: "topDocument.scrollingElement.scrollTop = 100"
    159  }, "*");
    160  port.postMessage({DONE: 1}, "*");
    161 }
    162 
    163 function handleMessage(event)
    164 {
    165  port = event.source;
    166  nextStep();
    167 }
    168 
    169 nextStep = step0;
    170 window.addEventListener("message", handleMessage);
    171 </script>