forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			180 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
	
		
			5.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* Any copyright is dedicated to the Public Domain.
 | |
|    http://creativecommons.org/publicdomain/zero/1.0/ */
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| const URL = "about:blank";
 | |
| 
 | |
| async function getBrowsingContextId(browser, id) {
 | |
|   return SpecialPowers.spawn(browser, [id], async function (id) {
 | |
|     let contextId = content.window.docShell.browsingContext.id;
 | |
| 
 | |
|     let frames = [content.window];
 | |
|     while (frames.length) {
 | |
|       let frame = frames.pop();
 | |
|       let target = frame.document.getElementById(id);
 | |
|       if (target) {
 | |
|         contextId = target.docShell.browsingContext.id;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       frames = frames.concat(Array.from(frame.frames));
 | |
|     }
 | |
| 
 | |
|     return contextId;
 | |
|   });
 | |
| }
 | |
| 
 | |
| async function addFrame(browser, id, parentId) {
 | |
|   return SpecialPowers.spawn(
 | |
|     browser,
 | |
|     [{ parentId, id }],
 | |
|     async function ({ parentId, id }) {
 | |
|       let parent = null;
 | |
|       if (parentId) {
 | |
|         let frames = [content.window];
 | |
|         while (frames.length) {
 | |
|           let frame = frames.pop();
 | |
|           let target = frame.document.getElementById(parentId);
 | |
|           if (target) {
 | |
|             parent = target.contentWindow.document.body;
 | |
|             break;
 | |
|           }
 | |
|           frames = frames.concat(Array.from(frame.frames));
 | |
|         }
 | |
|       } else {
 | |
|         parent = content.document.body;
 | |
|       }
 | |
| 
 | |
|       let frame = await new Promise(resolve => {
 | |
|         let frame = content.document.createElement("iframe");
 | |
|         frame.id = id || "";
 | |
|         frame.url = "about:blank";
 | |
|         frame.onload = () => resolve(frame);
 | |
|         parent.appendChild(frame);
 | |
|       });
 | |
| 
 | |
|       return frame.contentWindow.docShell.browsingContext.id;
 | |
|     }
 | |
|   );
 | |
| }
 | |
| 
 | |
| async function removeFrame(browser, id) {
 | |
|   return SpecialPowers.spawn(browser, [id], async function (id) {
 | |
|     let frames = [content.window];
 | |
|     while (frames.length) {
 | |
|       let frame = frames.pop();
 | |
|       let target = frame.document.getElementById(id);
 | |
|       if (target) {
 | |
|         target.remove();
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       frames = frames.concat(Array.from(frame.frames));
 | |
|     }
 | |
|   });
 | |
| }
 | |
| 
 | |
| function getBrowsingContextById(id) {
 | |
|   return BrowsingContext.get(id);
 | |
| }
 | |
| 
 | |
| add_task(async function () {
 | |
|   await BrowserTestUtils.withNewTab(
 | |
|     { gBrowser, url: URL },
 | |
|     async function (browser) {
 | |
|       let topId = await getBrowsingContextId(browser, "");
 | |
|       let topContext = getBrowsingContextById(topId);
 | |
|       isnot(topContext, null);
 | |
|       is(topContext.parent, null);
 | |
|       is(
 | |
|         topId,
 | |
|         browser.browsingContext.id,
 | |
|         "<browser> has the correct browsingContext"
 | |
|       );
 | |
|       is(
 | |
|         browser.browserId,
 | |
|         topContext.browserId,
 | |
|         "browsing context should have a correct <browser> id"
 | |
|       );
 | |
| 
 | |
|       let id0 = await addFrame(browser, "frame0");
 | |
|       let browsingContext0 = getBrowsingContextById(id0);
 | |
|       isnot(browsingContext0, null);
 | |
|       is(browsingContext0.parent, topContext);
 | |
| 
 | |
|       await removeFrame(browser, "frame0");
 | |
| 
 | |
|       is(topContext.children.indexOf(browsingContext0), -1);
 | |
| 
 | |
|       // TODO(farre): Handle browsingContext removal [see Bug 1486719].
 | |
|       todo_isnot(browsingContext0.parent, topContext);
 | |
|     }
 | |
|   );
 | |
| });
 | |
| 
 | |
| add_task(async function () {
 | |
|   // If Fission is disabled, the pref is no-op.
 | |
|   await SpecialPowers.pushPrefEnv({ set: [["fission.bfcacheInParent", true]] });
 | |
| 
 | |
|   await BrowserTestUtils.withNewTab(
 | |
|     {
 | |
|       gBrowser,
 | |
|       url:
 | |
|         getRootDirectory(gTestPath).replace(
 | |
|           "chrome://mochitests/content",
 | |
|           // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | |
|           "http://example.com"
 | |
|         ) + "dummy_page.html",
 | |
|     },
 | |
|     async function (browser) {
 | |
|       let path = getRootDirectory(gTestPath).replace(
 | |
|         "chrome://mochitests/content",
 | |
|         // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | |
|         "http://example.com"
 | |
|       );
 | |
|       await SpecialPowers.spawn(browser, [path], async function (path) {
 | |
|         var bc = new content.BroadcastChannel("browser_browsingContext");
 | |
|         function waitForMessage(command) {
 | |
|           let p = new Promise(resolve => {
 | |
|             bc.addEventListener("message", e => resolve(e), { once: true });
 | |
|           });
 | |
|           command();
 | |
|           return p;
 | |
|         }
 | |
| 
 | |
|         // Open a new window and wait for the message.
 | |
|         let e1 = await waitForMessage(_ =>
 | |
|           content.window.open(path + "onpageshow_message.html", "", "noopener")
 | |
|         );
 | |
| 
 | |
|         is(e1.data, "pageshow", "Got page show");
 | |
| 
 | |
|         let e2 = await waitForMessage(_ => bc.postMessage("createiframe"));
 | |
|         is(e2.data.framesLength, 1, "Here we should have an iframe");
 | |
| 
 | |
|         let e3 = await waitForMessage(_ => bc.postMessage("nextpage"));
 | |
| 
 | |
|         is(e3.data.event, "load");
 | |
|         is(e3.data.framesLength, 0, "Here there shouldn't be an iframe");
 | |
| 
 | |
|         // Return to the previous document. N.B. we expect to trigger
 | |
|         // BFCache here, hence we wait for pageshow.
 | |
|         let e4 = await waitForMessage(_ => bc.postMessage("back"));
 | |
| 
 | |
|         is(e4.data, "pageshow");
 | |
| 
 | |
|         let e5 = await waitForMessage(_ => bc.postMessage("queryframes"));
 | |
|         is(e5.data.framesLength, 1, "And again there should be an iframe");
 | |
| 
 | |
|         is(e5.outerWindowId, e2.outerWindowId, "BF cache cached outer window");
 | |
|         is(e5.browsingContextId, e2.browsingContextId, "BF cache cached BC");
 | |
| 
 | |
|         let e6 = await waitForMessage(_ => bc.postMessage("close"));
 | |
|         is(e6.data, "closed");
 | |
| 
 | |
|         bc.close();
 | |
|       });
 | |
|     }
 | |
|   );
 | |
| });
 | 
