mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-10-31 16:28:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			237 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* eslint-disable mozilla/no-arbitrary-setTimeout */
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| // This test tends to trigger a race in the fullscreen time telemetry,
 | |
| // where the fullscreen enter and fullscreen exit events (which use the
 | |
| // same histogram ID) overlap. That causes TelemetryStopwatch to log an
 | |
| // error.
 | |
| SimpleTest.ignoreAllUncaughtExceptions(true);
 | |
| 
 | |
| function listenOneEvent(aEvent, aListener) {
 | |
|   function listener(evt) {
 | |
|     removeEventListener(aEvent, listener);
 | |
|     aListener(evt);
 | |
|   }
 | |
|   addEventListener(aEvent, listener);
 | |
| }
 | |
| 
 | |
| function queryFullscreenState(browser) {
 | |
|   return SpecialPowers.spawn(browser, [], () => {
 | |
|     return {
 | |
|       inDOMFullscreen: !!content.document.fullscreenElement,
 | |
|       inFullscreen: content.fullScreen,
 | |
|     };
 | |
|   });
 | |
| }
 | |
| 
 | |
| function captureUnexpectedFullscreenChange() {
 | |
|   ok(false, "catched an unexpected fullscreen change");
 | |
| }
 | |
| 
 | |
| const FS_CHANGE_DOM = 1 << 0;
 | |
| const FS_CHANGE_SIZE = 1 << 1;
 | |
| const FS_CHANGE_BOTH = FS_CHANGE_DOM | FS_CHANGE_SIZE;
 | |
| 
 | |
| function waitForDocActivated(aBrowser) {
 | |
|   return SpecialPowers.spawn(aBrowser, [], () => {
 | |
|     return ContentTaskUtils.waitForCondition(
 | |
|       () => content.browsingContext.isActive && content.document.hasFocus()
 | |
|     );
 | |
|   });
 | |
| }
 | |
| 
 | |
| function waitForFullscreenChanges(aBrowser, aFlags) {
 | |
|   return new Promise(resolve => {
 | |
|     let fullscreenData = null;
 | |
|     let sizemodeChanged = false;
 | |
|     function tryResolve() {
 | |
|       if (
 | |
|         (!(aFlags & FS_CHANGE_DOM) || fullscreenData) &&
 | |
|         (!(aFlags & FS_CHANGE_SIZE) || sizemodeChanged)
 | |
|       ) {
 | |
|         // In the platforms that support reporting occlusion state (e.g. Mac),
 | |
|         // enter/exit fullscreen mode will trigger docshell being set to
 | |
|         // non-activate and then set to activate back again.
 | |
|         // For those platform, we should wait until the docshell has been
 | |
|         // activated again, otherwise, the fullscreen request might be denied.
 | |
|         waitForDocActivated(aBrowser).then(() => {
 | |
|           if (!fullscreenData) {
 | |
|             queryFullscreenState(aBrowser).then(resolve);
 | |
|           } else {
 | |
|             resolve(fullscreenData);
 | |
|           }
 | |
|         });
 | |
|       }
 | |
|     }
 | |
|     if (aFlags & FS_CHANGE_SIZE) {
 | |
|       listenOneEvent("sizemodechange", () => {
 | |
|         sizemodeChanged = true;
 | |
|         tryResolve();
 | |
|       });
 | |
|     }
 | |
|     if (aFlags & FS_CHANGE_DOM) {
 | |
|       BrowserTestUtils.waitForContentEvent(aBrowser, "fullscreenchange").then(
 | |
|         async () => {
 | |
|           fullscreenData = await queryFullscreenState(aBrowser);
 | |
|           tryResolve();
 | |
|         }
 | |
|       );
 | |
|     }
 | |
|   });
 | |
| }
 | |
| 
 | |
| var gTests = [
 | |
|   {
 | |
|     desc: "document method",
 | |
|     affectsFullscreenMode: false,
 | |
|     exitFunc: browser => {
 | |
|       SpecialPowers.spawn(browser, [], () => {
 | |
|         content.document.exitFullscreen();
 | |
|       });
 | |
|     },
 | |
|   },
 | |
|   {
 | |
|     desc: "escape key",
 | |
|     affectsFullscreenMode: false,
 | |
|     exitFunc: () => {
 | |
|       executeSoon(() => EventUtils.synthesizeKey("KEY_Escape"));
 | |
|     },
 | |
|   },
 | |
|   {
 | |
|     desc: "F11 key",
 | |
|     affectsFullscreenMode: true,
 | |
|     exitFunc() {
 | |
|       executeSoon(() => EventUtils.synthesizeKey("KEY_F11"));
 | |
|     },
 | |
|   },
 | |
| ];
 | |
| 
 | |
| function checkState(expectedStates, contentStates) {
 | |
|   is(
 | |
|     contentStates.inDOMFullscreen,
 | |
|     expectedStates.inDOMFullscreen,
 | |
|     "The DOM fullscreen state of the content should match"
 | |
|   );
 | |
|   // TODO window.fullScreen is not updated as soon as the fullscreen
 | |
|   //      state flips in child process, hence checking it could cause
 | |
|   //      anonying intermittent failure. As we just want to confirm the
 | |
|   //      fullscreen state of the browser window, we can just check the
 | |
|   //      that on the chrome window below.
 | |
|   // is(contentStates.inFullscreen, expectedStates.inFullscreen,
 | |
|   //    "The fullscreen state of the content should match");
 | |
|   is(
 | |
|     !!document.fullscreenElement,
 | |
|     expectedStates.inDOMFullscreen,
 | |
|     "The DOM fullscreen state of the chrome should match"
 | |
|   );
 | |
|   is(
 | |
|     window.fullScreen,
 | |
|     expectedStates.inFullscreen,
 | |
|     "The fullscreen state of the chrome should match"
 | |
|   );
 | |
| }
 | |
| 
 | |
| const kPage =
 | |
|   // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | |
|   "http://example.org/browser/browser/" +
 | |
|   "base/content/test/general/dummy_page.html";
 | |
| 
 | |
| add_task(async function () {
 | |
|   await pushPrefs(
 | |
|     ["full-screen-api.transition-duration.enter", "0 0"],
 | |
|     ["full-screen-api.transition-duration.leave", "0 0"]
 | |
|   );
 | |
| 
 | |
|   registerCleanupFunction(async function () {
 | |
|     if (window.fullScreen) {
 | |
|       let fullscreenPromise = waitForFullscreenChanges(
 | |
|         gBrowser.selectedBrowser,
 | |
|         FS_CHANGE_SIZE
 | |
|       );
 | |
|       executeSoon(() => BrowserCommands.fullScreen());
 | |
|       await fullscreenPromise;
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   let tab = await BrowserTestUtils.openNewForegroundTab({
 | |
|     gBrowser,
 | |
|     url: kPage,
 | |
|   });
 | |
|   let browser = tab.linkedBrowser;
 | |
| 
 | |
|   // As requestFullscreen checks the active state of the docshell,
 | |
|   // wait for the document to be activated, just to be sure that
 | |
|   // the fullscreen request won't be denied.
 | |
|   await waitForDocActivated(browser);
 | |
| 
 | |
|   for (let test of gTests) {
 | |
|     let contentStates;
 | |
|     info("Testing exit DOM fullscreen via " + test.desc);
 | |
| 
 | |
|     contentStates = await queryFullscreenState(browser);
 | |
|     checkState({ inDOMFullscreen: false, inFullscreen: false }, contentStates);
 | |
| 
 | |
|     /* DOM fullscreen without fullscreen mode */
 | |
| 
 | |
|     info("> Enter DOM fullscreen");
 | |
|     let fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_BOTH);
 | |
|     await SpecialPowers.spawn(browser, [], () => {
 | |
|       content.document.body.requestFullscreen();
 | |
|     });
 | |
|     contentStates = await fullscreenPromise;
 | |
|     checkState({ inDOMFullscreen: true, inFullscreen: true }, contentStates);
 | |
| 
 | |
|     info("> Exit DOM fullscreen");
 | |
|     fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_BOTH);
 | |
|     test.exitFunc(browser);
 | |
|     contentStates = await fullscreenPromise;
 | |
|     checkState({ inDOMFullscreen: false, inFullscreen: false }, contentStates);
 | |
| 
 | |
|     /* DOM fullscreen with fullscreen mode */
 | |
| 
 | |
|     info("> Enter fullscreen mode");
 | |
|     // Need to be asynchronous because sizemodechange event could be
 | |
|     // dispatched synchronously, which would cause the event listener
 | |
|     // miss that event and wait infinitely.
 | |
|     fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_SIZE);
 | |
|     executeSoon(() => BrowserCommands.fullScreen());
 | |
|     contentStates = await fullscreenPromise;
 | |
|     checkState({ inDOMFullscreen: false, inFullscreen: true }, contentStates);
 | |
| 
 | |
|     info("> Enter DOM fullscreen in fullscreen mode");
 | |
|     fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_DOM);
 | |
|     await SpecialPowers.spawn(browser, [], () => {
 | |
|       content.document.body.requestFullscreen();
 | |
|     });
 | |
|     contentStates = await fullscreenPromise;
 | |
|     checkState({ inDOMFullscreen: true, inFullscreen: true }, contentStates);
 | |
| 
 | |
|     info("> Exit DOM fullscreen in fullscreen mode");
 | |
|     fullscreenPromise = waitForFullscreenChanges(
 | |
|       browser,
 | |
|       test.affectsFullscreenMode ? FS_CHANGE_BOTH : FS_CHANGE_DOM
 | |
|     );
 | |
|     test.exitFunc(browser);
 | |
|     contentStates = await fullscreenPromise;
 | |
|     checkState(
 | |
|       {
 | |
|         inDOMFullscreen: false,
 | |
|         inFullscreen: !test.affectsFullscreenMode,
 | |
|       },
 | |
|       contentStates
 | |
|     );
 | |
| 
 | |
|     /* Cleanup */
 | |
| 
 | |
|     // Exit fullscreen mode if we are still in
 | |
|     if (window.fullScreen) {
 | |
|       info("> Cleanup");
 | |
|       fullscreenPromise = waitForFullscreenChanges(browser, FS_CHANGE_SIZE);
 | |
|       executeSoon(() => BrowserCommands.fullScreen());
 | |
|       await fullscreenPromise;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   BrowserTestUtils.removeTab(tab);
 | |
| });
 | 
