diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/content/tests/browser/browser_crash_previous_frameloader.js | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/toolkit/content/tests/browser/browser_crash_previous_frameloader.js b/toolkit/content/tests/browser/browser_crash_previous_frameloader.js new file mode 100644 index 0000000000..0fa2f17912 --- /dev/null +++ b/toolkit/content/tests/browser/browser_crash_previous_frameloader.js @@ -0,0 +1,131 @@ +"use strict"; + +/** + * Returns the id of the crash minidump. + * + * @param subject (nsISupports) + * The subject passed through the ipc:content-shutdown + * observer notification when a content process crash has + * occurred. + * @returns {String} The crash dump id. + */ +function getCrashDumpId(subject) { + Assert.ok( + subject instanceof Ci.nsIPropertyBag2, + "Subject needs to be a nsIPropertyBag2 to clean up properly" + ); + + return subject.getPropertyAsAString("dumpID"); +} + +/** + * Cleans up the .dmp and .extra file from a crash. + * + * @param id {String} The crash dump id. + */ +function cleanUpMinidump(id) { + let dir = Services.dirsvc.get("ProfD", Ci.nsIFile); + dir.append("minidumps"); + + let file = dir.clone(); + file.append(id + ".dmp"); + file.remove(true); + + file = dir.clone(); + file.append(id + ".extra"); + file.remove(true); +} + +/** + * This test ensures that if a remote frameloader crashes after + * the frameloader owner swaps it out for a new frameloader, + * that a oop-browser-crashed event is not sent to the new + * frameloader's browser element. + */ +add_task(async function test_crash_in_previous_frameloader() { + // On debug builds, crashing tabs results in much thinking, which + // slows down the test and results in intermittent test timeouts, + // so we'll pump up the expected timeout for this test. + requestLongerTimeout(2); + + if (!gMultiProcessBrowser) { + Assert.ok(false, "This test should only be run in multi-process mode."); + return; + } + + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: "http://example.com", + }, + async function (browser) { + // First, sanity check... + Assert.ok( + browser.isRemoteBrowser, + "This browser needs to be remote if this test is going to " + + "work properly." + ); + + // We will wait for the oop-browser-crashed event to have + // a chance to appear. That event is fired when RemoteTabs + // are destroyed, and that occurs _before_ ContentParents + // are destroyed, so we'll wait on the ipc:content-shutdown + // observer notification, which is fired when a ContentParent + // goes away. After we see this notification, oop-browser-crashed + // events should have fired. + let contentProcessGone = TestUtils.topicObserved("ipc:content-shutdown"); + let sawTabCrashed = false; + let onTabCrashed = () => { + sawTabCrashed = true; + }; + + browser.addEventListener("oop-browser-crashed", onTabCrashed); + + // The name of the game is to cause a crash in a remote browser, + // and then immediately swap out the browser for a non-remote one. + await SpecialPowers.spawn(browser, [], function () { + const { ctypes } = ChromeUtils.importESModule( + "resource://gre/modules/ctypes.sys.mjs" + ); + + let dies = function () { + ChromeUtils.privateNoteIntentionalCrash(); + let zero = new ctypes.intptr_t(8); + let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t)); + badptr.contents; + }; + + // When the parent flips the remoteness of the browser, the + // page should receive the pagehide event, which we'll then + // use to crash the frameloader. + docShell.chromeEventHandler.addEventListener("pagehide", function () { + dump("\nEt tu, Brute?\n"); + dies(); + }); + }); + + gBrowser.updateBrowserRemoteness(browser, { + remoteType: E10SUtils.NOT_REMOTE, + }); + info("Waiting for content process to go away."); + let [subject /* , data */] = await contentProcessGone; + + // If we don't clean up the minidump, the harness will + // complain. + let dumpID = getCrashDumpId(subject); + + Assert.ok(dumpID, "There should be a dumpID"); + if (dumpID) { + await Services.crashmanager.ensureCrashIsPresent(dumpID); + cleanUpMinidump(dumpID); + } + + info("Content process is gone!"); + Assert.ok( + !sawTabCrashed, + "Should not have seen the oop-browser-crashed event." + ); + browser.removeEventListener("oop-browser-crashed", onTabCrashed); + } + ); +}); |