forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			165 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| 
 | |
| const TEST_PAGE =
 | |
|   "http://mochi.test:8888/browser/docshell/test/browser/file_bug1046022.html";
 | |
| const TARGETED_PAGE =
 | |
|   "data:text/html," +
 | |
|   encodeURIComponent("<body>Shouldn't be seeing this</body>");
 | |
| 
 | |
| const { PromptTestUtils } = ChromeUtils.import(
 | |
|   "resource://testing-common/PromptTestUtils.jsm"
 | |
| );
 | |
| 
 | |
| var loadStarted = false;
 | |
| var tabStateListener = {
 | |
|   resolveLoad: null,
 | |
|   expectLoad: null,
 | |
| 
 | |
|   onStateChange(webprogress, request, flags, status) {
 | |
|     const WPL = Ci.nsIWebProgressListener;
 | |
|     if (flags & WPL.STATE_IS_WINDOW) {
 | |
|       if (flags & WPL.STATE_START) {
 | |
|         loadStarted = true;
 | |
|       } else if (flags & WPL.STATE_STOP) {
 | |
|         let url = request.QueryInterface(Ci.nsIChannel).URI.spec;
 | |
|         is(url, this.expectLoad, "Should only see expected document loads");
 | |
|         if (url == this.expectLoad) {
 | |
|           this.resolveLoad();
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   QueryInterface: ChromeUtils.generateQI([
 | |
|     "nsIWebProgressListener",
 | |
|     "nsISupportsWeakReference",
 | |
|   ]),
 | |
| };
 | |
| 
 | |
| function promiseLoaded(url, callback) {
 | |
|   if (tabStateListener.expectLoad) {
 | |
|     throw new Error("Can't wait for multiple loads at once");
 | |
|   }
 | |
|   tabStateListener.expectLoad = url;
 | |
|   return new Promise(resolve => {
 | |
|     tabStateListener.resolveLoad = resolve;
 | |
|     if (callback) {
 | |
|       callback();
 | |
|     }
 | |
|   }).then(() => {
 | |
|     tabStateListener.expectLoad = null;
 | |
|     tabStateListener.resolveLoad = null;
 | |
|   });
 | |
| }
 | |
| 
 | |
| function promiseStayOnPagePrompt(browser, acceptNavigation) {
 | |
|   return PromptTestUtils.handleNextPrompt(
 | |
|     browser,
 | |
|     { modalType: Services.prompt.MODAL_TYPE_CONTENT, promptType: "confirmEx" },
 | |
|     { buttonNumClick: acceptNavigation ? 0 : 1 }
 | |
|   );
 | |
| }
 | |
| 
 | |
| add_task(async function test() {
 | |
|   await SpecialPowers.pushPrefEnv({
 | |
|     set: [["dom.require_user_interaction_for_beforeunload", false]],
 | |
|   });
 | |
| 
 | |
|   let testTab = await BrowserTestUtils.openNewForegroundTab(
 | |
|     gBrowser,
 | |
|     TEST_PAGE,
 | |
|     false,
 | |
|     true
 | |
|   );
 | |
|   let browser = testTab.linkedBrowser;
 | |
|   browser.addProgressListener(
 | |
|     tabStateListener,
 | |
|     Ci.nsIWebProgress.NOTIFY_STATE_WINDOW
 | |
|   );
 | |
| 
 | |
|   const NUM_TESTS = 7;
 | |
|   await SpecialPowers.spawn(browser, [NUM_TESTS], testCount => {
 | |
|     let { testFns } = this.content.wrappedJSObject;
 | |
|     Assert.equal(
 | |
|       testFns.length,
 | |
|       testCount,
 | |
|       "Should have the correct number of test functions"
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   for (let allowNavigation of [false, true]) {
 | |
|     for (let i = 0; i < NUM_TESTS; i++) {
 | |
|       info(
 | |
|         `Running test ${i} with navigation ${
 | |
|           allowNavigation ? "allowed" : "forbidden"
 | |
|         }`
 | |
|       );
 | |
| 
 | |
|       if (allowNavigation) {
 | |
|         // If we're allowing navigations, we need to re-load the test
 | |
|         // page after each test, since the tests will each navigate away
 | |
|         // from it.
 | |
|         await promiseLoaded(TEST_PAGE, () => {
 | |
|           browser.loadURI(TEST_PAGE, {
 | |
|             triggeringPrincipal: document.nodePrincipal,
 | |
|           });
 | |
|         });
 | |
|       }
 | |
| 
 | |
|       let promptPromise = promiseStayOnPagePrompt(browser, allowNavigation);
 | |
|       let loadPromise;
 | |
|       if (allowNavigation) {
 | |
|         loadPromise = promiseLoaded(TARGETED_PAGE);
 | |
|       }
 | |
| 
 | |
|       let winID = await SpecialPowers.spawn(
 | |
|         browser,
 | |
|         [i, TARGETED_PAGE],
 | |
|         (testIdx, url) => {
 | |
|           let { testFns } = this.content.wrappedJSObject;
 | |
|           this.content.onbeforeunload = testFns[testIdx];
 | |
|           this.content.location = url;
 | |
|           return this.content.windowGlobalChild.innerWindowId;
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       await promptPromise;
 | |
|       await loadPromise;
 | |
| 
 | |
|       if (allowNavigation) {
 | |
|         await SpecialPowers.spawn(
 | |
|           browser,
 | |
|           [TARGETED_PAGE, winID],
 | |
|           (url, winID) => {
 | |
|             this.content.onbeforeunload = null;
 | |
|             Assert.equal(
 | |
|               this.content.location.href,
 | |
|               url,
 | |
|               "Page should have navigated to the correct URL"
 | |
|             );
 | |
|             Assert.notEqual(
 | |
|               this.content.windowGlobalChild.innerWindowId,
 | |
|               winID,
 | |
|               "Page should have a new inner window"
 | |
|             );
 | |
|           }
 | |
|         );
 | |
|       } else {
 | |
|         await SpecialPowers.spawn(browser, [TEST_PAGE, winID], (url, winID) => {
 | |
|           this.content.onbeforeunload = null;
 | |
|           Assert.equal(
 | |
|             this.content.location.href,
 | |
|             url,
 | |
|             "Page should have the same URL"
 | |
|           );
 | |
|           Assert.equal(
 | |
|             this.content.windowGlobalChild.innerWindowId,
 | |
|             winID,
 | |
|             "Page should have the same inner window"
 | |
|           );
 | |
|         });
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   gBrowser.removeTab(testTab);
 | |
| });
 | 
