browser_browsing_context_discarded.js (3654B)
1 "use strict"; 2 3 const TOPIC = "browsing-context-discarded"; 4 5 async function observeDiscarded(browsingContexts, callback) { 6 let discarded = new Map(); 7 8 let promise = BrowserUtils.promiseObserved(TOPIC, (subject, why) => { 9 ok(BrowsingContext.isInstance(subject), "subject to be a BrowsingContext"); 10 discarded.set(subject, why); 11 12 return browsingContexts.every(item => discarded.has(item)); 13 }); 14 await callback(); 15 await promise; 16 17 return discarded; 18 } 19 20 function check_reason(discardedContexts, expected) { 21 discardedContexts.forEach((why, browsingContext) => { 22 if (expected.has(browsingContext)) { 23 is(why, expected.get(browsingContext)); 24 } 25 }); 26 } 27 28 add_task(async function toplevelForNewWindow() { 29 const win = await BrowserTestUtils.openNewBrowserWindow(); 30 const browsingContext = win.gBrowser.selectedBrowser.browsingContext; 31 32 const expected = new Map([ 33 [win.browsingContext, "discard"], 34 [browsingContext, "discard"], 35 ]); 36 37 const discarded = await observeDiscarded([...expected.keys()], async () => { 38 await BrowserTestUtils.closeWindow(win); 39 }); 40 41 check_reason(discarded, expected); 42 }); 43 44 add_task(async function toplevelForNewTab() { 45 const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); 46 const browsingContext = tab.linkedBrowser.browsingContext; 47 48 const expected = new Map([[browsingContext, "discard"]]); 49 50 const discarded = await observeDiscarded([...expected.keys()], () => { 51 BrowserTestUtils.removeTab(tab); 52 }); 53 54 ok( 55 !discarded.has(window.browsingContext), 56 "no notification for the current window's chrome browsing context" 57 ); 58 59 check_reason(discarded, expected); 60 }); 61 62 add_task(async function subframe() { 63 const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); 64 const frameBrowsingContext = await SpecialPowers.spawn( 65 tab.linkedBrowser, 66 [], 67 () => { 68 const iframe = content.document.createElement("iframe"); 69 iframe.src = "https://example.com/"; 70 content.document.body.appendChild(iframe); 71 return iframe.browsingContext; 72 } 73 ); 74 75 const expected = new Map([[frameBrowsingContext, "discard"]]); 76 77 const discarded = await observeDiscarded([...expected.keys()], async () => { 78 await SpecialPowers.spawn(tab.linkedBrowser, [], () => { 79 let iframe = content.document.querySelector("iframe"); 80 iframe.remove(); 81 }); 82 }); 83 84 ok( 85 !discarded.has(tab.linkedBrowser.browsingContext), 86 "no notification for toplevel browsing context" 87 ); 88 ok( 89 !discarded.has(window.browsingContext), 90 "no notification for the current window's chrome browsing context" 91 ); 92 93 check_reason(discarded, expected); 94 95 BrowserTestUtils.removeTab(tab); 96 }); 97 98 add_task(async function replaceToplevel() { 99 const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); 100 101 // Force load about:blank such that BC::HasLoadedNonInitialDocument is true 102 // which means it's BFCache eligible and will be replaced 103 BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, "about:blank"); 104 await BrowserTestUtils.browserLoaded(tab.linkedBrowser, { 105 wantLoad: "about:blank", 106 }); 107 108 const browsingContext = tab.linkedBrowser.browsingContext; 109 110 const expected = new Map([[browsingContext, "replace"]]); 111 112 const discarded = await observeDiscarded([...expected.keys()], async () => { 113 await SpecialPowers.spawn(tab.linkedBrowser, [], () => { 114 content.location = "about:newtab"; 115 }); 116 }); 117 118 ok( 119 !discarded.has(window.browsingContext), 120 "no notification for the current window's chrome browsing context" 121 ); 122 123 check_reason(discarded, expected); 124 125 BrowserTestUtils.removeTab(tab); 126 });