Bug 899348 - Dispatch an event when an out-of-process browser crashes and display an error page when that occurs. r=bz
authorFelipe Gomes <felipc@gmail.com>
Tue, 03 Sep 2013 19:11:22 -0300
changeset 145815 04aa8c1ab6bb7f715ae7334a074d882f54ae25d5
parent 145737 e3785e299ab6ea4c4f6f318ff601d73c6be9198c
child 145816 7298863a7a28d239dc8f4025aeb25ec75e74e53c
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbz
bugs899348
milestone26.0a1
Bug 899348 - Dispatch an event when an out-of-process browser crashes and display an error page when that occurs. r=bz
browser/base/content/tabbrowser.xml
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
dom/ipc/TabParent.cpp
dom/locales/en-US/chrome/appstrings.properties
js/xpconnect/src/xpc.msg
xpcom/base/ErrorList.h
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3113,16 +3113,32 @@
             return;
 
           var tab = this._getTabForContentWindow(contentWin);
           var titleChanged = this.setTabTitle(tab);
           if (titleChanged && !tab.selected && !tab.hasAttribute("busy"))
             tab.setAttribute("titlechanged", "true");
         ]]>
       </handler>
+      <handler event="oop-browser-crashed">
+        <![CDATA[
+          if (!event.isTrusted)
+            return;
+
+          let browser = event.originalTarget;
+          let title = browser.contentTitle;
+          let uri = browser.currentURI;
+
+          this._updateBrowserRemoteness(browser, false);
+
+          browser.setAttribute("crashedPageTitle", title);
+          browser.docShell.displayLoadError(Cr.NS_ERROR_CONTENT_CRASHED, uri, null);
+          browser.removeAttribute("crashedPageTitle");
+        ]]>
+      </handler>
     </handlers>
   </binding>
 
   <binding id="tabbrowser-tabbox"
            extends="chrome://global/content/bindings/tabbox.xml#tabbox">
     <implementation>
       <property name="tabs" readonly="true"
                 onget="return document.getBindingParent(this).tabContainer;"/>
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3977,17 +3977,17 @@ nsDocShell::ClearFrameHistory(nsISHEntry
 
 //-------------------------------------
 //-- Helper Method for Print discovery
 //-------------------------------------
 bool 
 nsDocShell::IsPrintingOrPP(bool aDisplayErrorDialog)
 {
   if (mIsPrintingOrPP && aDisplayErrorDialog) {
-    DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr);
+    DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
   }
 
   return mIsPrintingOrPP;
 }
 
 bool
 nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog)
 {
@@ -4133,17 +4133,17 @@ nsDocShell::LoadURI(const PRUnichar * aU
             // passed-in post data.
             postStream = fixupStream;
         }
     }
     // else no fixup service so just use the URI we created and see
     // what happens
 
     if (NS_ERROR_MALFORMED_URI == rv) {
-        DisplayLoadError(rv, uri, aURI);
+        DisplayLoadError(rv, uri, aURI, nullptr);
     }
 
     if (NS_FAILED(rv) || !uri)
         return NS_ERROR_FAILURE;
 
     PopupControlState popupState;
     if (aLoadFlags & LOAD_FLAGS_ALLOW_POPUPS) {
         popupState = openAllowed;
@@ -4348,16 +4348,25 @@ nsDocShell::DisplayLoadError(nsresult aE
                                    nsISecurityUITelemetry::WARNING_MALWARE_PAGE_TOP ;
         }
 
         if (errorPage.EqualsIgnoreCase("blocked"))
             mozilla::Telemetry::Accumulate(mozilla::Telemetry::SECURITY_UI,
                                            bucketId);
 
         cssClass.AssignLiteral("blacklist");
+    } else if (NS_ERROR_CONTENT_CRASHED == aError) {
+      errorPage.AssignLiteral("tabcrashed");
+      error.AssignLiteral("tabcrashed");
+
+      nsCOMPtr<EventTarget> handler = mChromeEventHandler;
+      if (handler) {
+        nsCOMPtr<Element> element = do_QueryInterface(handler);
+        element->GetAttribute(NS_LITERAL_STRING("crashedPageTitle"), messageStr);
+      }
     }
     else {
         // Errors requiring simple formatting
         switch (aError) {
         case NS_ERROR_MALFORMED_URI:
             // URI is malformed
             error.AssignLiteral("malformedURI");
             break;
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -515,19 +515,16 @@ protected:
     NS_IMETHOD GetChildOffset(nsIDOMNode * aChild, nsIDOMNode * aParent,
         int32_t * aOffset);
     nsIScrollableFrame* GetRootScrollFrame();
     NS_IMETHOD EnsureScriptEnvironment();
     NS_IMETHOD EnsureEditorData();
     nsresult   EnsureTransferableHookData();
     NS_IMETHOD EnsureFind();
     nsresult   RefreshURIFromQueue();
-    NS_IMETHOD DisplayLoadError(nsresult aError, nsIURI *aURI,
-                                const PRUnichar *aURL,
-                                nsIChannel* aFailedChannel = nullptr);
     NS_IMETHOD LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
                              const char *aErrorPage,
                              const PRUnichar *aErrorType,
                              const PRUnichar *aDescription,
                              const char *aCSSClass,
                              nsIChannel* aFailedChannel);
     bool IsNavigationAllowed(bool aDisplayPrintErrorDialog = true);
     bool IsPrintingOrPP(bool aDisplayErrorDialog = true);
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -37,17 +37,17 @@ interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
 interface nsIDOMStorage;
 interface nsIPrincipal;
 interface nsIWebBrowserPrint;
 interface nsIVariant;
 interface nsIPrivacyTransitionObserver;
 interface nsIReflowObserver;
 
-[scriptable, builtinclass, uuid(4bb2261b-4c13-44a4-ace3-fc2eec17cc34)]
+[scriptable, builtinclass, uuid(62f1b40d-1d15-4640-95dc-20caae775bd1)]
 interface nsIDocShell : nsIDocShellTreeItem
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -407,16 +407,32 @@ interface nsIDocShell : nsIDocShellTreeI
 
   /* Track whether we're currently restoring a document presentation. */
   readonly attribute boolean restoringDocument;
 
   /* attribute to access whether error pages are enabled */
   attribute boolean useErrorPages;
 
   /**
+   * Display a load error in a frame while keeping that frame's currentURI
+   * pointing correctly to the page where the error ocurred, rather than to
+   * the error document page. You must provide either the aURI or aURL parameter.
+   *
+   * @param  aError         The error code to be displayed
+   * @param  aURI           nsIURI of the page where the error happened
+   * @param  aURL           wstring of the page where the error happened
+   * @param  aFailedChannel The channel related to this error
+   */
+  void displayLoadError(in nsresult aError,
+                        in nsIURI aURI,
+                        in wstring aURL,
+                        [optional] in nsIChannel aFailedChannel);
+
+
+  /**
    * Keeps track of the previous SHTransaction index and the current
    * SHTransaction index at the time that the doc shell begins to load.
    * Used for ContentViewer eviction.
    */
   readonly attribute long previousTransIndex;
   readonly attribute long loadedTransIndex;
 
   /**
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -292,22 +292,26 @@ TabParent::ActorDestroy(ActorDestroyReas
     sEventCapturer = nullptr;
   }
   if (mIMETabParent == this) {
     mIMETabParent = nullptr;
   }
   nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (frameLoader) {
+    nsCOMPtr<Element> frameElement(mFrameElement);
     ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr);
     frameLoader->DestroyChild();
 
     if (why == AbnormalShutdown && os) {
       os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, frameLoader),
                           "oop-frameloader-crashed", nullptr);
+      nsContentUtils::DispatchTrustedEvent(frameElement->OwnerDoc(), frameElement,
+                                           NS_LITERAL_STRING("oop-browser-crashed"),
+                                           true, true);
     }
   }
 
   if (os) {
     os->NotifyObservers(NS_ISUPPORTS_CAST(nsITabParent*, this), "ipc:browser-destroyed", nullptr);
   }
 }
 
--- a/dom/locales/en-US/chrome/appstrings.properties
+++ b/dom/locales/en-US/chrome/appstrings.properties
@@ -28,8 +28,10 @@ externalProtocolPrompt=An external appli
 externalProtocolUnknown=<Unknown>
 externalProtocolChkMsg=Remember my choice for all links of this type.
 externalProtocolLaunchBtn=Launch application
 malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
 phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
 cspFrameAncestorBlocked=This page has a content security policy that prevents it from being embedded in this way.
 corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
 remoteXUL=This page uses an unsupported technology that is no longer available by default.
+#LOCALIZATION NOTE (tabcrashed): The following string is shown in the tab title if a page with a blank title has crashed. Current UX says that the tab title should remain blank
+tabcrashed=
--- a/js/xpconnect/src/xpc.msg
+++ b/js/xpconnect/src/xpc.msg
@@ -204,8 +204,12 @@ XPC_MSG_DEF(NS_ERROR_SIGNED_JAR_MANIFEST
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE , "No printers available.")
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND       , "The selected printer could not be found.")
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE  , "Failed to open output file for print to file.")
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_STARTDOC             , "Printing failed while starting the print job.")
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_ENDDOC               , "Printing failed while completing the print job.")
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_STARTPAGE            , "Printing failed while starting a new page.")
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY          , "Cannot print this document yet, it is still being loaded.")
 XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_NO_XUL               , "Printing XUL documents is not supported.") // bugs 136185 & 240490
+
+/* Codes related to content */
+XPC_MSG_DEF(NS_ERROR_CONTENT_CRASHED                  , "The process that hosted this content has crashed.")
+
--- a/xpcom/base/ErrorList.h
+++ b/xpcom/base/ErrorList.h
@@ -682,16 +682,18 @@
   ERROR(NS_ERROR_IMAGE_BLOCKED,                 FAILURE(5)),
   /* Error codes for content policy blocking */
   ERROR(NS_ERROR_CONTENT_BLOCKED,               FAILURE(6)),
   ERROR(NS_ERROR_CONTENT_BLOCKED_SHOW_ALT,      FAILURE(7)),
   /* Success variations of content policy blocking */
   ERROR(NS_PROPTABLE_PROP_NOT_THERE,            FAILURE(10)),
   /* Error code for XBL */
   ERROR(NS_ERROR_XBL_BLOCKED,                   FAILURE(15)),
+  /* Error code for when the content process crashed */
+  ERROR(NS_ERROR_CONTENT_CRASHED,               FAILURE(16)),
 
   /* XXX this is not really used */
   ERROR(NS_HTML_STYLE_PROPERTY_NOT_THERE,   SUCCESS(2)),
   ERROR(NS_CONTENT_BLOCKED,                 SUCCESS(8)),
   ERROR(NS_CONTENT_BLOCKED_SHOW_ALT,        SUCCESS(9)),
   ERROR(NS_PROPTABLE_PROP_OVERWRITTEN,      SUCCESS(11)),
   /* Error codes for FindBroadcaster in XULDocument.cpp */
   ERROR(NS_FINDBROADCASTER_NOT_FOUND,       SUCCESS(12)),