tor-browser

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

test_fullscreen-api-race.html (5346B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4  <title>Test for race conditions of Fullscreen API</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <script src="/tests/SimpleTest/EventUtils.js"></script>
      7  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
      8 </head>
      9 <body>
     10 <script>
     11 
     12 function Deferred() {
     13  this.promise = new Promise(resolve => {
     14    this.resolve = resolve;
     15  });
     16 }
     17 
     18 function checkIsChromeFullscreen(win, inFullscreen) {
     19  return SimpleTest.promiseWaitForCondition(
     20    () => win.fullScreen == inFullscreen,
     21    "The window should exit fullscreen state");
     22 }
     23 
     24 SimpleTest.waitForExplicitFinish();
     25 // XXX This actually exposes a true race condition, but it could rarely
     26 // happen in real world, because it only happens when requestFullscreen
     27 // is called immediately after exiting fullscreen in certain condition,
     28 // and in real life, requestFullscreen can only be called inside a user
     29 // event handler. But we want to fix this race condition at some point,
     30 // via queuing all exiting request as well as entering request together
     31 // which we may eventually need to do for bug 1188256.
     32 SimpleTest.requestFlakyTimeout(
     33  "Need to wait for potential fullscreen transition");
     34 addLoadEvent(function () {
     35  SpecialPowers.pushPrefEnv({
     36    "set": [
     37      ["full-screen-api.allow-trusted-requests-only", false],
     38    ]
     39  }, next);
     40 });
     41 
     42 const OPEN_WINDOW_FUNCS = [
     43  function openNewTab() {
     44    return new Promise(resolve => {
     45      var win = window.open("about:blank");
     46      setTimeout(function() {
     47        resolve(win);
     48      }, 0);
     49    });
     50  },
     51  function openNewWindow() {
     52    return new Promise(resolve => {
     53      var win = window.open("about:blank", "", "width=300,height=200");
     54      setTimeout(function() {
     55        resolve(win);
     56      }, 0);
     57    });
     58  }
     59 ];
     60 
     61 const ACTION_FUNCS = [
     62  function navigate(win) {
     63    info("About to navigate to another page");
     64    var promise = new Promise(resolve => {
     65      window.addEventListener("message", () => {
     66        SimpleTest.waitForFocus(() => {
     67          checkIsChromeFullscreen(win, false).then(() => {
     68            win.close();
     69            resolve();
     70          });
     71        }, win);
     72      }, { once: true });
     73    });
     74    win.location = "file_fullscreen-api-race.html";
     75    return promise;
     76  },
     77  function closeWindow(win) {
     78    info("About to close the window");
     79    win.close();
     80    return Promise.resolve();
     81  },
     82  function exitFullscreen(win) {
     83    info("About to cancel fullscreen");
     84    var deferred = new Deferred();
     85    function listener() {
     86      win.removeEventListener("fullscreenchange", listener);
     87      ok(!win.document.fullscreenElement, "Should exit fullscreen");
     88      checkIsChromeFullscreen(win, false).then(() => {
     89        win.close();
     90        deferred.resolve();
     91      });
     92    }
     93    win.addEventListener("fullscreenchange", listener);
     94    win.document.exitFullscreen();
     95    return deferred.promise;
     96  },
     97  function exitAndClose(win) {
     98    info("About to cancel fullscreen and close the window");
     99    win.document.exitFullscreen();
    100    win.close();
    101    return Promise.resolve();
    102  }
    103 ];
    104 
    105 function* testGenerator() {
    106  for (var openWinFunc of OPEN_WINDOW_FUNCS) {
    107    for (var actionFunc of ACTION_FUNCS) {
    108      info(`Testing ${openWinFunc.name}, ${actionFunc.name}`);
    109      yield { openWinFunc, actionFunc };
    110    }
    111  }
    112 }
    113 
    114 function runTest(test) {
    115  var winPromise = test.openWinFunc();
    116  return winPromise.then((win) => {
    117    return new Promise(resolve => {
    118      SimpleTest.waitForFocus(() => resolve(win), win, true);
    119    });
    120  }).then((win) => {
    121    return new Promise((resolve, reject) => {
    122      var retried = false;
    123      function listener(evt) {
    124        if (!retried && evt.type == "fullscreenerror") {
    125          todo(false, "Failed to enter fullscreen, but try again");
    126          retried = true;
    127          SimpleTest.waitForFocus(() => {
    128            win.document.documentElement.requestFullscreen();
    129          }, win, true);
    130          return;
    131        }
    132        win.removeEventListener("fullscreenchange", listener);
    133        win.removeEventListener("fullscreenerror", listener);
    134        is(evt.type, "fullscreenchange", "Should get fullscreenchange");
    135        ok(win.document.fullscreenElement, "Should have entered fullscreen");
    136        ok(win.fullScreen, "The window should be in fullscreen");
    137        test.actionFunc(win).then(() => resolve(win));
    138      }
    139      if (win.fullScreen) {
    140        todo(false, "Should not open in fullscreen mode");
    141        win.close();
    142        reject();
    143        return;
    144      }
    145      info("About to enter fullscreen");
    146      win.addEventListener("fullscreenchange", listener);
    147      win.addEventListener("fullscreenerror", listener);
    148      win.document.documentElement.requestFullscreen();
    149    });
    150  }).then((win) => {
    151    ok(win.closed, "The window should have been closed");
    152  });
    153 }
    154 
    155 var tests = testGenerator();
    156 
    157 function next() {
    158  var test = tests.next().value;
    159  if (test) {
    160    runTest(test).catch(() => {
    161      return new Promise(resolve => {
    162        SimpleTest.waitForFocus(resolve);
    163      }).then(() => runTest(test));
    164    }).catch(() => {
    165      ok(false, "Fail to run test " +
    166         `${test.openWinFunc.name}, ${test.actionFunc.name}`);
    167    }).then(() => {
    168      setTimeout(() => SimpleTest.waitForFocus(next), 1000);
    169    });
    170  } else {
    171    SimpleTest.finish();
    172  }
    173 }
    174 
    175 </script>
    176 </body>
    177 </html>