const { PromiseUtils } = ChromeUtils.import( "resource://gre/modules/PromiseUtils.jsm" ); let dir = getChromeDir(getResolvedURI(gTestPath)); dir.append("file_dummy.html"); const uriString = Services.io.newFileURI(dir).spec; add_task(async function() { await BrowserTestUtils.withNewTab("https://example.com", async function( browser ) { // Override the browser's `prepareToChangeRemoteness` so that we can delay // the process switch for an indefinite amount of time. This will allow us // to control the timing of the resolve call to trigger the bug. let prepareToChangeCalled = PromiseUtils.defer(); let finishSwitch = PromiseUtils.defer(); let oldPrepare = browser.prepareToChangeRemoteness; browser.prepareToChangeRemoteness = async () => { prepareToChangeCalled.resolve(); await oldPrepare.call(browser); await finishSwitch.promise; }; // Begin a process switch, which should cause `prepareToChangeRemoteness` to // be called. We do this from the content process to make sure the frontend // has no chance to trigger an eager process switch. info("Beginning process switch into file URI process"); let browserLoaded = BrowserTestUtils.browserLoaded(browser); await SpecialPowers.spawn(browser, [uriString], uri => { content.location = uri; }); await prepareToChangeCalled.promise; // The tab we opened is now midway through process switching. Open another // browser within the same tab, and immediately close it after the load // finishes. info("Creating new tab loaded in file URI process"); let fileProcess; let browserParentDestroyed = PromiseUtils.defer(); await BrowserTestUtils.withNewTab(uriString, async function(otherBrowser) { let remoteTab = otherBrowser.frameLoader.remoteTab; fileProcess = remoteTab.contentProcessId; info("Loaded test URI in pid: " + fileProcess); browserParentDestroyed.resolve( TestUtils.topicObserved( "ipc:browser-destroyed", subject => subject === remoteTab ) ); }); await browserParentDestroyed.promise; // This browser has now been closed, which could cause the file content // process to begin shutting down, despite us process switching into it. // We can now allow the process switch to finish, and wait for the load to // finish as well. info("BrowserParent has been destroyed, finishing process switch"); finishSwitch.resolve(); await browserLoaded; info("Load complete"); is( browser.frameLoader.remoteTab.contentProcessId, fileProcess, "Should have loaded in the same file URI process" ); }); });