Bug 1298219 - Regression test. r=billm
authorMike Conley <mconley@mozilla.com>
Thu, 01 Sep 2016 13:10:37 -0400
changeset 312998 bd4d11e10ee28439add0cbfbf7c99f25a662a82e
parent 312997 804c98e6fef45ffd4cbaef194e94fec3b578068f
child 312999 cfd5f330f1158682b0b109de50b679d3329f12fc
push id81509
push usercbook@mozilla.com
push dateWed, 07 Sep 2016 15:23:10 +0000
treeherdermozilla-inbound@80dccdd8c94a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1298219
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1298219 - Regression test. r=billm MozReview-Commit-ID: 5sDWL9NuTso
toolkit/content/tests/browser/browser.ini
toolkit/content/tests/browser/browser_crash_previous_frameloader.js
--- a/toolkit/content/tests/browser/browser.ini
+++ b/toolkit/content/tests/browser/browser.ini
@@ -15,16 +15,18 @@ support-files =
   file_multipleAudio.html
 [browser_bug295977_autoscroll_overflow.js]
 [browser_bug451286.js]
 skip-if = !e10s
 [browser_bug594509.js]
 [browser_bug982298.js]
 [browser_bug1198465.js]
 [browser_contentTitle.js]
+[browser_crash_previous_frameloader.js]
+run-if = e10s && crashreporter
 [browser_default_image_filename.js]
 [browser_f7_caret_browsing.js]
 [browser_findbar.js]
 [browser_label_textlink.js]
 [browser_isSynthetic.js]
 support-files =
   empty.png
 [browser_keyevents_during_autoscrolling.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/browser_crash_previous_frameloader.js
@@ -0,0 +1,114 @@
+"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
+      };
+
+      // Use a timeout to give the parent a little extra time
+      // to flip the remoteness of the browser. This has the
+      // potential to be a bit race-y, since in theory, the
+      // setTimeout could complete before the parent finishes
+      // the remoteness flip, which would mean we'd get the
+      // oop-browser-crashed event, and we'll fail here.
+      // Unfortunately, I can't find a way around that right
+      // now, since you cannot send a frameloader a message
+      // once its been replaced.
+      setTimeout(() => {
+        dump("\nEt tu, Brute?\n");
+        dies();
+      }, 0);
+    });
+
+    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);
+  });
+});