summaryrefslogtreecommitdiff
path: root/toolkit/content/tests/browser/browser_crash_previous_frameloader.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/content/tests/browser/browser_crash_previous_frameloader.js')
-rw-r--r--toolkit/content/tests/browser/browser_crash_previous_frameloader.js108
1 files changed, 108 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..bd50c6ffde
--- /dev/null
+++ b/toolkit/content/tests/browser/browser_crash_previous_frameloader.js
@@ -0,0 +1,108 @@
+"use strict";
+
+/**
+ * Cleans up the .dmp and .extra file from a crash.
+ *
+ * @param subject (nsISupports)
+ * The subject passed through the ipc:content-shutdown
+ * observer notification when a content process crash has
+ * occurred.
+ */
+function cleanUpMinidump(subject) {
+ Assert.ok(subject instanceof Ci.nsIPropertyBag2,
+ "Subject needs to be a nsIPropertyBag2 to clean up properly");
+ let dumpID = subject.getPropertyAsAString("dumpID");
+
+ Assert.ok(dumpID, "There should be a dumpID");
+ if (dumpID) {
+ let dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
+ dir.append("minidumps");
+
+ let file = dir.clone();
+ file.append(dumpID + ".dmp");
+ file.remove(true);
+
+ file = dir.clone();
+ file.append(dumpID + ".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(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;
+ }
+
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: "http://example.com",
+ }, 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 TabParents
+ // 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.
+ yield ContentTask.spawn(browser, null, function() {
+ const Cu = Components.utils;
+ Cu.import("resource://gre/modules/ctypes.jsm");
+ Cu.import("resource://gre/modules/Timer.jsm");
+
+ let dies = function() {
+ 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.
+ addEventListener("pagehide", function() {
+ dump("\nEt tu, Brute?\n");
+ dies();
+ });
+ });
+
+ gBrowser.updateBrowserRemoteness(browser, false);
+ info("Waiting for content process to go away.");
+ let [subject, data] = yield contentProcessGone;
+
+ // If we don't clean up the minidump, the harness will
+ // complain.
+ cleanUpMinidump(subject);
+
+ info("Content process is gone!");
+ Assert.ok(!sawTabCrashed,
+ "Should not have seen the oop-browser-crashed event.");
+ browser.removeEventListener("oop-browser-crashed", onTabCrashed);
+ });
+});