Bug 1585217 - Make the layout debugger with -autoclose handle content process crashes. r=heycam
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 01 Oct 2019 17:09:23 +0000
changeset 495785 ddfb38a12cdf889db6ab490cf05a93405171b93d
parent 495784 c6552f7ec6a0febfbcfbea6800df6aac76d94968
child 495786 b26f1c83ee031629b6a2fe5f2f24a184d4e9bab1
push id36638
push usershindli@mozilla.com
push dateWed, 02 Oct 2019 03:38:52 +0000
treeherdermozilla-central@cb9bbf38fa45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1585217
milestone71.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 1585217 - Make the layout debugger with -autoclose handle content process crashes. r=heycam This means that you can use it as a very light-weight crashtest harness by using: MOZ_GDB_SLEEP=0 ./mach run -layoutdebug <file> -autoclose Right now we just never exit otherwise. Differential Revision: https://phabricator.services.mozilla.com/D47715
layout/tools/layout-debug/ui/content/layoutdebug.js
--- a/layout/tools/layout-debug/ui/content/layoutdebug.js
+++ b/layout/tools/layout-debug/ui/content/layoutdebug.js
@@ -136,16 +136,42 @@ for (let [name, pref] of Object.entries(
 }
 
 for (let name of COMMANDS) {
   Debugger.prototype[name] = function() {
     this._sendMessage(name);
   };
 }
 
+const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+function autoCloseIfNeeded(aCrash) {
+  if (!gArgs.autoclose) {
+    return;
+  }
+  setTimeout(function() {
+    if (aCrash) {
+      let browser = document.createElementNS(XUL_NS, "browser");
+      // FIXME(emilio): we could use gBrowser if we bothered get the process switches right.
+      //
+      // Doesn't seem worth for this particular case.
+      document.documentElement.appendChild(browser);
+      browser.loadURI("about:crashparent", {
+        triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
+      });
+      return;
+    }
+    if (gArgs.profile && Services.profiler) {
+      dumpProfile();
+    } else {
+      Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
+    }
+  }, gArgs.delay * 1000);
+}
+
 function nsLDBBrowserContentListener() {
   this.init();
 }
 
 nsLDBBrowserContentListener.prototype = {
   init: function() {
     this.mStatusText = document.getElementById("status-text");
     this.mForwardButton = document.getElementById("forward-button");
@@ -169,29 +195,24 @@ nsLDBBrowserContentListener.prototype = 
       this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward);
       this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack);
       this.mStatusText.value = "loading...";
       this.mLoading = true;
     } else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
       this.setButtonEnabled(this.mStopButton, false);
       this.mStatusText.value = gURLBar.value + " loaded";
       this.mLoading = false;
-      if (gArgs.autoclose && gBrowser.currentURI.spec != "about:blank") {
+
+      if (gBrowser.currentURI.spec != "about:blank") {
         // We check for about:blank just to avoid one or two STATE_STOP
         // notifications that occur before the loadURI() call completes.
         // This does mean that --autoclose doesn't work when the URL on
         // the command line is about:blank (or not specified), but that's
         // not a big deal.
-        setTimeout(function() {
-          if (gArgs.profile && Services.profiler) {
-            dumpProfile();
-          } else {
-            Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
-          }
-        }, gArgs.delay * 1000);
+        autoCloseIfNeeded(false);
       }
     }
   },
 
   onProgressChange: function(
     aWebProgress,
     aRequest,
     aCurSelfProgress,
@@ -250,24 +271,44 @@ function parseArguments() {
       } else {
         throw `Unknown option ${arg}`;
       }
     }
   }
   return args;
 }
 
+const TabCrashedObserver = {
+  observe(subject, topic, data) {
+    switch (topic) {
+      case "ipc:content-shutdown":
+        subject.QueryInterface(Ci.nsIPropertyBag2);
+        if (!subject.get("abnormal")) {
+          return;
+        }
+        break;
+      case "oop-frameloader-crashed":
+        break;
+    }
+    autoCloseIfNeeded(true);
+  },
+};
+
+
 function OnLDBLoad() {
   gBrowser = document.getElementById("browser");
   gURLBar = document.getElementById("urlbar");
 
   gDebugger = new Debugger();
 
   checkPersistentMenus();
 
+  Services.obs.addObserver(TabCrashedObserver, "ipc:content-shutdown");
+  Services.obs.addObserver(TabCrashedObserver, "oop-frameloader-crashed");
+
   // Pretend slightly to be like a normal browser, so that SessionStore.jsm
   // doesn't get too confused.  The effect is that we'll never switch process
   // type when navigating, and for layout debugging purposes we don't bother
   // about getting that right.
   gBrowser.getTabForBrowser = function() {
     return null;
   };
 
@@ -357,16 +398,18 @@ function OnLDBBeforeUnload(event) {
     // timeout to avoid annoying the window manager if we're doing this in
     // response to clicking the window's close button.
     setTimeout(dumpProfile, 0);
   }
 }
 
 function OnLDBUnload() {
   gDebugger.detachBrowser();
+  Services.obs.removeObserver(TabCrashedObserver, "ipc:content-shutdown");
+  Services.obs.removeObserver(TabCrashedObserver, "oop-frameloader-crashed");
 }
 
 function toggle(menuitem) {
   // trim the initial "menu_"
   var feature = menuitem.id.substring(5);
   gDebugger[feature] = menuitem.getAttribute("checked") == "true";
 }