tor-browser

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

file_fullscreen-api.html (12086B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <!--
      4 https://bugzilla.mozilla.org/show_bug.cgi?id=545812
      5 
      6 Test DOM full-screen API.
      7 
      8 -->
      9 <head>
     10  <title>Test for Bug 545812</title>
     11  <script src="/tests/SimpleTest/EventUtils.js"></script>
     12  <script src="/tests/SimpleTest/SimpleTest.js"></script>
     13  <script type="application/javascript" src="file_fullscreen-utils.js"></script>
     14  <style>
     15  body {
     16    background-color: black;
     17  }
     18  </style>
     19 </head>
     20 <body>
     21 <div id="fullscreen-element"></div>
     22 <script type="application/javascript">
     23 
     24 /** Test for Bug 545812 */
     25 
     26 function ok(condition, msg) {
     27  opener.ok(condition, "[fullscreen] " + msg);
     28 }
     29 
     30 function is(a, b, msg) {
     31  opener.is(a, b, "[fullscreen] " + msg);
     32 }
     33 
     34 /*
     35 <html>
     36  <body onload='document.body.requestFullscreen();'>
     37  <iframe id='inner-frame'></iframe>
     38  </body>
     39 </html>
     40 */
     41 var iframeContents = "<html><body onload='parent.SimpleTest.waitForFocus(function(){document.body.requestFullscreen();});'><iframe id='inner-frame'></iframe></body></html>";
     42 
     43 var iframe = null;
     44 var outOfDocElement = null;
     45 var inDocElement = null;
     46 var container = null;
     47 var button = null;
     48 
     49 
     50 function sendMouseClick(element) {
     51  synthesizeMouseAtCenter(element, {});
     52 }
     53 
     54 function assertPromiseResolved(promise, msg) {
     55  let { state, value } = SpecialPowers.PromiseDebugging.getState(promise);
     56  is(state, "fulfilled", "Promise should have been resolved " + msg);
     57  is(value, undefined, "Promise should be resolved with undefined " + msg);
     58 }
     59 
     60 function assertPromiseRejected(promise, msg) {
     61  let { state, reason } = SpecialPowers.PromiseDebugging.getState(promise);
     62  is(state, "rejected", "Promise should have been rejected " + msg);
     63  // XXX Actually we should be testing "instanceof TypeError", but it
     64  // doesn't work as expected currently. See bug 1412856.
     65  is(reason.name, "TypeError",
     66     "Promise should be rejected with TypeError " + msg);
     67 }
     68 
     69 const FULLSCREEN_ELEMENT = document.getElementById("fullscreen-element");
     70 let promise;
     71 
     72 function enter1(event) {
     73  is(event.target, FULLSCREEN_ELEMENT,
     74     "Event target should be the fullscreen element #1");
     75  ok(document.fullscreen, "Document should be in fullscreen");
     76  is(document.fullscreenElement, FULLSCREEN_ELEMENT,
     77     "Full-screen element should be div element.");
     78  ok(document.fullscreenElement.matches(":fullscreen"),
     79     "FSE should match :fullscreen");
     80  addFullscreenChangeContinuation("exit", exit1);
     81  FULLSCREEN_ELEMENT.remove();
     82  is(document.fullscreenElement, null,
     83     "Full-screen element should be null after removing.");
     84 }
     85 
     86 function exit1(event) {
     87  document.body.appendChild(FULLSCREEN_ELEMENT);
     88  is(document.fullscreenElement, null,
     89     "Full-screen element should still be null after re-adding former FSE.");
     90  is(event.target, document, "Event target should be the document #2");
     91  ok(!document.fullscreen, "Document should not be in fullscreen");
     92  is(document.fullscreenElement, null, "Full-screen element should be null.");
     93  iframe = document.createElement("iframe");
     94  iframe.allowFullscreen = true;
     95  addFullscreenChangeContinuation("enter", enter2);
     96  document.body.appendChild(iframe);
     97  iframe.srcdoc = iframeContents;
     98 }
     99 
    100 function enter2(event) {
    101  is(event.target, iframe,
    102     "Event target should be the fullscreen iframe #3");
    103  is(document.fullscreenElement, iframe,
    104     "Full-screen element should be iframe element.");
    105  is(iframe.contentDocument.fullscreenElement, iframe.contentDocument.body,
    106     "Full-screen element in subframe should be body");
    107  
    108  // The iframe's body is full-screen. Cancel full-screen in the subdocument to return
    109  // the full-screen element to the previous full-screen element. This causes
    110  // a fullscreenchange event.
    111  addFullscreenChangeContinuation("exit", exit2);
    112  promise = document.exitFullscreen();
    113 }
    114 
    115 function exit2() {
    116  is(document.fullscreenElement, null,
    117     "Full-screen element should have rolled back.");
    118  is(iframe.contentDocument.fullscreenElement, null,
    119     "Full-screen element in subframe should be null");
    120  assertPromiseResolved(promise, "in exit2");
    121  
    122  addFullscreenChangeContinuation("enter", enter3);
    123  promise = FULLSCREEN_ELEMENT.requestFullscreen();
    124 }
    125 
    126 function enter3(event) {
    127  is(event.target, FULLSCREEN_ELEMENT,
    128     "Event target should be the fullscreen element #3");
    129  is(document.fullscreenElement, FULLSCREEN_ELEMENT,
    130     "Full-screen element should be div.");
    131  assertPromiseResolved(promise, "in enter3");
    132  
    133  // Transplant the FSE into subdoc. Should exit full-screen.
    134  addFullscreenChangeContinuation("exit", exit3);
    135  var _innerFrame = iframe.contentDocument.getElementById("inner-frame");
    136  _innerFrame.contentDocument.body.appendChild(FULLSCREEN_ELEMENT);
    137  is(document.fullscreenElement, null,
    138     "Full-screen element transplanted, should be null.");
    139  is(iframe.contentDocument.fullscreenElement, null,
    140     "Full-screen element in outer frame should be null.");
    141  is(_innerFrame.contentDocument.fullscreenElement, null,
    142     "Full-screen element in inner frame should be null.");
    143 }
    144 
    145 function exit3(event) {
    146  document.body.appendChild(FULLSCREEN_ELEMENT);
    147  is(event.target, document, "Event target should be the document #3");
    148  is(document.fullscreenElement, null, "Full-screen element should be null.");
    149  document.body.removeChild(iframe);
    150  iframe = null;
    151 
    152  // Do a request out of document. It should be denied.
    153  // Continue test in the following fullscreenerror handler.
    154  outOfDocElement = document.createElement("div");
    155  addFullscreenErrorContinuation(error1);    
    156  promise = outOfDocElement.requestFullscreen();
    157 }
    158 
    159 function error1() {
    160  ok(!document.fullscreenElement,
    161     "Requests for full-screen from not-in-doc elements should fail.");
    162  assertPromiseRejected(promise, "in error1");
    163  container = document.createElement("div");
    164  inDocElement = document.createElement("div");
    165  container.appendChild(inDocElement);
    166  FULLSCREEN_ELEMENT.appendChild(container);
    167 
    168  addFullscreenChangeContinuation("enter", enter4);
    169  inDocElement.requestFullscreen();
    170 }
    171 
    172 function enter4(event) {
    173  is(event.target, inDocElement,
    174     "Event target should be the fullscreen element #4");
    175  is(document.fullscreenElement, inDocElement, "FSE should be inDocElement.");
    176 
    177  // Remove full-screen ancestor element from document, verify it stops being reported as current FSE.
    178  addFullscreenChangeContinuation("exit", exit_to_arg_test_1);
    179  container.remove();
    180  is(document.fullscreenElement, null,
    181     "Should not have a full-screen element again.");
    182 }
    183 
    184 async function exit_to_arg_test_1() {
    185  ok(!document.fullscreenElement,
    186     "Should have left full-screen mode (third time).");
    187  addFullscreenChangeContinuation("enter", enter_from_arg_test_1);
    188  var threw = false;
    189  try {
    190    await FULLSCREEN_ELEMENT.requestFullscreen(123);
    191  } catch (e) {
    192    threw = true;
    193    // trigger normal fullscreen so that we continue
    194    FULLSCREEN_ELEMENT.requestFullscreen();
    195  }
    196  ok(!threw, "requestFullscreen with bogus arg (123) shouldn't throw exception");
    197 }
    198 
    199 function enter_from_arg_test_1() {
    200  ok(document.fullscreenElement,
    201     "Should have entered full-screen after calling with bogus (ignored) argument (fourth time)");
    202  addFullscreenChangeContinuation("exit", exit_to_arg_test_2);
    203  document.exitFullscreen();
    204 }
    205 
    206 async function exit_to_arg_test_2() {
    207  ok(!document.fullscreenElement,
    208     "Should have left full-screen mode (fourth time).");
    209  addFullscreenChangeContinuation("enter", enter_from_arg_test_2);
    210  var threw = false;
    211  try {
    212    await FULLSCREEN_ELEMENT.requestFullscreen({ vrDisplay: null });
    213  } catch (e) {
    214    threw = true;
    215    // trigger normal fullscreen so that we continue
    216    FULLSCREEN_ELEMENT.requestFullscreen();
    217  }
    218  ok(!threw, "requestFullscreen with { vrDisplay: null } shouldn't throw exception");
    219 }
    220 
    221 function enter_from_arg_test_2() {
    222  ok(document.fullscreenElement,
    223     "Should have entered full-screen after calling with vrDisplay null argument (fifth time)");
    224  addFullscreenChangeContinuation("exit", exit4);
    225  document.exitFullscreen();
    226 }
    227 
    228 function exit4() {
    229  ok(!document.fullscreenElement,
    230     "Should be back in non-full-screen mode (fifth time)");
    231  SpecialPowers.pushPrefEnv({"set":[["full-screen-api.allow-trusted-requests-only", true]]}, function() {
    232    addFullscreenErrorContinuation(error2);
    233    FULLSCREEN_ELEMENT.requestFullscreen();
    234  });
    235 }
    236 
    237 function error2() {
    238  ok(!document.fullscreenElement,
    239     "Should still be in normal mode, because calling context isn't trusted.");
    240  button = document.createElement("button");
    241  button.onclick = function() {
    242    FULLSCREEN_ELEMENT.requestFullscreen();
    243  };
    244  FULLSCREEN_ELEMENT.appendChild(button);
    245  addFullscreenChangeContinuation("enter", enter5);
    246  sendMouseClick(button);
    247 }
    248 
    249 function enter5() {
    250  ok(document.fullscreenElement, "Moved to full-screen after mouse click");
    251  addFullscreenChangeContinuation("exit", exit5);
    252  document.exitFullscreen();
    253 }
    254 
    255 function exit5() {
    256  ok(!document.fullscreenElement,
    257     "Should have left full-screen mode (last time).");
    258  SpecialPowers.pushPrefEnv({
    259    "set":[["full-screen-api.allow-trusted-requests-only", false],
    260           ["full-screen-api.enabled", false]]}, function() {
    261              is(document.fullscreenEnabled, false, "document.fullscreenEnabled should be false if full-screen-api.enabled is false");
    262              addFullscreenErrorContinuation(error3);
    263              FULLSCREEN_ELEMENT.requestFullscreen();
    264  });
    265 }
    266 
    267 function error3() {
    268  ok(!document.fullscreenElement,
    269     "Should still be in normal mode, because pref is not enabled.");
    270 
    271  SpecialPowers.pushPrefEnv({"set":[["full-screen-api.enabled", true]]}, function() {
    272    is(document.fullscreenEnabled, true, "document.fullscreenEnabled should be true if full-screen-api.enabled is true");
    273    opener.nextTest();
    274  });
    275 }
    276 
    277 function begin() {
    278  testNamespaces(() => {
    279    addFullscreenChangeContinuation("enter", enter1);
    280    FULLSCREEN_ELEMENT.requestFullscreen();
    281  });
    282 }
    283 
    284 function testNamespaces(followupTestFn) {
    285  let tests = [
    286    {allowed: false, name: "element", ns: "http://www.w3.org/XML/1998/namespace"},
    287    {allowed: false, name: "element", ns: "http://www.w3.org/1999/xlink"},
    288    {allowed: false, name: "element", ns: "http://www.w3.org/2000/svg"},
    289    {allowed: false, name: "element", ns: "http://www.w3.org/1998/Math/MathML"},
    290    {allowed: false, name: "mathml",  ns: "unknown"},
    291    {allowed: false, name: "svg",     ns: "unknown"},
    292    {allowed: true,  name: "element", ns: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"},
    293    {allowed: true,  name: "element", ns: "http://www.w3.org/1999/xhtml"},
    294    {allowed: true,  name: "svg",     ns: "http://www.w3.org/1999/xhtml"},
    295    {allowed: true,  name: "math",    ns: "http://www.w3.org/1999/xhtml"},
    296    {allowed: true,  name: "svg",     ns: "http://www.w3.org/2000/svg"},
    297    {allowed: true,  name: "math",    ns: "http://www.w3.org/1998/Math/MathML"},
    298    {allowed: true,  name: "element"},
    299  ];
    300 
    301  function runNextNamespaceTest() {
    302    let test = tests.shift();
    303    if (!test) {
    304      followupTestFn();
    305      return;
    306    }
    307 
    308    let elem = test.ns ? document.createElementNS(test.ns, test.name) :
    309                         document.createElement(test.name);
    310    document.body.appendChild(elem);
    311 
    312    if (test.allowed) {
    313      addFullscreenChangeContinuation("enter", () => {
    314        ok(document.fullscreen, "Document should be in fullscreen");
    315        is(document.fullscreenElement, elem,
    316           `Element named '${test.name}' in this namespace should be allowed: ${test.ns}`);
    317        addFullscreenChangeContinuation("exit", () => {
    318          document.body.removeChild(elem);
    319          runNextNamespaceTest();
    320        });
    321        document.exitFullscreen();
    322      });
    323    } else {
    324      addFullscreenErrorContinuation(() => {
    325        ok(!document.fullscreenElement,
    326           `Element named '${test.name}' in this namespace should not be allowed: ${test.ns}`);
    327        document.body.removeChild(elem);
    328        runNextNamespaceTest();
    329      });
    330    }
    331 
    332    SimpleTest.waitForFocus(() => elem.requestFullscreen());
    333  }
    334 
    335  runNextNamespaceTest();
    336 }
    337 </script>
    338 </pre>
    339 </body>
    340 </html>