tor-browser

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

browser_domFullscreen_fullscreenMode.js (7202B)


      1 /* eslint-disable mozilla/no-arbitrary-setTimeout */
      2 
      3 "use strict";
      4 
      5 function listenOneEvent(aEvent, aListener) {
      6  function listener(evt) {
      7    removeEventListener(aEvent, listener);
      8    aListener(evt);
      9  }
     10  addEventListener(aEvent, listener);
     11 }
     12 
     13 function queryFullscreenState(browser) {
     14  return SpecialPowers.spawn(browser, [], () => {
     15    return {
     16      inDOMFullscreen: !!content.document.fullscreenElement,
     17      inFullscreen: content.fullScreen,
     18    };
     19  });
     20 }
     21 
     22 function captureUnexpectedFullscreenChange() {
     23  ok(false, "catched an unexpected fullscreen change");
     24 }
     25 
     26 const FS_CHANGE_DOM = 1 << 0;
     27 const FS_CHANGE_SIZE = 1 << 1;
     28 const FS_CHANGE_BOTH = FS_CHANGE_DOM | FS_CHANGE_SIZE;
     29 
     30 function waitForDocActivated(aBrowser) {
     31  return SpecialPowers.spawn(aBrowser, [], () => {
     32    return ContentTaskUtils.waitForCondition(
     33      () => content.browsingContext.isActive && content.document.hasFocus()
     34    );
     35  });
     36 }
     37 
     38 function waitForFullscreenChanges(aBrowser, aFlags) {
     39  return new Promise(resolve => {
     40    let fullscreenData = null;
     41    let sizemodeChanged = false;
     42    function tryResolve() {
     43      if (
     44        (!(aFlags & FS_CHANGE_DOM) || fullscreenData) &&
     45        (!(aFlags & FS_CHANGE_SIZE) || sizemodeChanged)
     46      ) {
     47        // In the platforms that support reporting occlusion state (e.g. Mac),
     48        // enter/exit fullscreen mode will trigger docshell being set to
     49        // non-activate and then set to activate back again.
     50        // For those platform, we should wait until the docshell has been
     51        // activated again, otherwise, the fullscreen request might be denied.
     52        waitForDocActivated(aBrowser).then(() => {
     53          if (!fullscreenData) {
     54            queryFullscreenState(aBrowser).then(resolve);
     55          } else {
     56            resolve(fullscreenData);
     57          }
     58        });
     59      }
     60    }
     61    if (aFlags & FS_CHANGE_SIZE) {
     62      listenOneEvent("sizemodechange", () => {
     63        sizemodeChanged = true;
     64        tryResolve();
     65      });
     66    }
     67    if (aFlags & FS_CHANGE_DOM) {
     68      BrowserTestUtils.waitForContentEvent(aBrowser, "fullscreenchange").then(
     69        async () => {
     70          fullscreenData = await queryFullscreenState(aBrowser);
     71          tryResolve();
     72        }
     73      );
     74    }
     75  });
     76 }
     77 
     78 var gTests = [
     79  {
     80    desc: "document method",
     81    affectsFullscreenMode: false,
     82    exitFunc: browser => {
     83      SpecialPowers.spawn(browser, [], () => {
     84        content.document.exitFullscreen();
     85      });
     86    },
     87  },
     88  {
     89    desc: "escape key",
     90    affectsFullscreenMode: false,
     91    exitFunc: () => {
     92      executeSoon(() => EventUtils.synthesizeKey("KEY_Escape"));
     93    },
     94  },
     95  {
     96    desc: "F11 key",
     97    affectsFullscreenMode: true,
     98    exitFunc() {
     99      executeSoon(() => EventUtils.synthesizeKey("KEY_F11"));
    100    },
    101  },
    102 ];
    103 
    104 function checkState(expectedStates, contentStates) {
    105  is(
    106    contentStates.inDOMFullscreen,
    107    expectedStates.inDOMFullscreen,
    108    "The DOM fullscreen state of the content should match"
    109  );
    110  // TODO window.fullScreen is not updated as soon as the fullscreen
    111  //      state flips in child process, hence checking it could cause
    112  //      anonying intermittent failure. As we just want to confirm the
    113  //      fullscreen state of the browser window, we can just check the
    114  //      that on the chrome window below.
    115  // is(contentStates.inFullscreen, expectedStates.inFullscreen,
    116  //    "The fullscreen state of the content should match");
    117  is(
    118    !!document.fullscreenElement,
    119    expectedStates.inDOMFullscreen,
    120    "The DOM fullscreen state of the chrome should match"
    121  );
    122  is(
    123    window.fullScreen,
    124    expectedStates.inFullscreen,
    125    "The fullscreen state of the chrome should match"
    126  );
    127 }
    128 
    129 const kPage =
    130  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    131  "http://example.org/browser/browser/" +
    132  "base/content/test/general/dummy_page.html";
    133 
    134 add_task(async function () {
    135  await pushPrefs(
    136    ["full-screen-api.transition-duration.enter", "0 0"],
    137    ["full-screen-api.transition-duration.leave", "0 0"]
    138  );
    139 
    140  registerCleanupFunction(async function () {
    141    if (window.fullScreen) {
    142      let fullscreenPromise = waitForFullscreenChanges(
    143        gBrowser.selectedBrowser,
    144        FS_CHANGE_SIZE
    145      );
    146      executeSoon(() => BrowserCommands.fullScreen());
    147      await fullscreenPromise;
    148    }
    149  });
    150 
    151  let tab = await BrowserTestUtils.openNewForegroundTab({
    152    gBrowser,
    153    url: kPage,
    154  });
    155  let browser = tab.linkedBrowser;
    156 
    157  // As requestFullscreen checks the active state of the docshell,
    158  // wait for the document to be activated, just to be sure that
    159  // the fullscreen request won't be denied.
    160  await waitForDocActivated(browser);
    161 
    162  for (let test of gTests) {
    163    let contentStates;
    164    info("Testing exit DOM fullscreen via " + test.desc);
    165 
    166    contentStates = await queryFullscreenState(browser);
    167    checkState({ inDOMFullscreen: false, inFullscreen: false }, contentStates);
    168 
    169    /* DOM fullscreen without fullscreen mode */
    170 
    171    info("> Enter DOM fullscreen");
    172    let fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_BOTH);
    173    await SpecialPowers.spawn(browser, [], () => {
    174      content.document.body.requestFullscreen();
    175    });
    176    contentStates = await fullscreenPromise;
    177    checkState({ inDOMFullscreen: true, inFullscreen: true }, contentStates);
    178 
    179    info("> Exit DOM fullscreen");
    180    fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_BOTH);
    181    test.exitFunc(browser);
    182    contentStates = await fullscreenPromise;
    183    checkState({ inDOMFullscreen: false, inFullscreen: false }, contentStates);
    184 
    185    /* DOM fullscreen with fullscreen mode */
    186 
    187    info("> Enter fullscreen mode");
    188    // Need to be asynchronous because sizemodechange event could be
    189    // dispatched synchronously, which would cause the event listener
    190    // miss that event and wait infinitely.
    191    fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_SIZE);
    192    executeSoon(() => BrowserCommands.fullScreen());
    193    contentStates = await fullscreenPromise;
    194    checkState({ inDOMFullscreen: false, inFullscreen: true }, contentStates);
    195 
    196    info("> Enter DOM fullscreen in fullscreen mode");
    197    fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_DOM);
    198    await SpecialPowers.spawn(browser, [], () => {
    199      content.document.body.requestFullscreen();
    200    });
    201    contentStates = await fullscreenPromise;
    202    checkState({ inDOMFullscreen: true, inFullscreen: true }, contentStates);
    203 
    204    info("> Exit DOM fullscreen in fullscreen mode");
    205    fullscreenPromise = waitForFullscreenChanges(
    206      browser,
    207      test.affectsFullscreenMode ? FS_CHANGE_BOTH : FS_CHANGE_DOM
    208    );
    209    test.exitFunc(browser);
    210    contentStates = await fullscreenPromise;
    211    checkState(
    212      {
    213        inDOMFullscreen: false,
    214        inFullscreen: !test.affectsFullscreenMode,
    215      },
    216      contentStates
    217    );
    218 
    219    /* Cleanup */
    220 
    221    // Exit fullscreen mode if we are still in
    222    if (window.fullScreen) {
    223      info("> Cleanup");
    224      fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_SIZE);
    225      executeSoon(() => BrowserCommands.fullScreen());
    226      await fullscreenPromise;
    227    }
    228  }
    229 
    230  BrowserTestUtils.removeTab(tab);
    231 });