Bug 1389784: Recover gracefully when we fail to create a tab browser. r?mystor draft
authorKris Maglione <maglione.k@gmail.com>
Tue, 03 Oct 2017 12:56:24 -0700
changeset 674459 100b36b89b1c09087230f5e5cb4d6822e18e6daf
parent 673982 4d4e89492b76f33cea17e294661d7a519d4379c5
child 734340 c523d293f36848220b36947b81ef722c472966b8
push id82847
push usermaglione.k@gmail.com
push dateTue, 03 Oct 2017 20:01:48 +0000
reviewersmystor
bugs1389784
milestone58.0a1
Bug 1389784: Recover gracefully when we fail to create a tab browser. r?mystor There are some cases where we fail to create a tab's browser due to the sanity checks in _createBrowser(). While in theory those should never fail, in practice they seem to. And when they do, they leave the browser in an inconsistent state. This change should both prevent the worst effects of these failures, and also give use better error reporting so that we can properly debug them. MozReview-Commit-ID: EZjKN9URw5X
browser/base/content/tabbrowser.xml
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -2692,98 +2692,111 @@
               }, 0, this.tabContainer);
             }
 
             // invalidate cache
             this._visibleTabs = null;
 
             this.tabContainer.appendChild(t);
 
-            // If this new tab is owned by another, assert that relationship
-            if (aOwner)
-              t.owner = aOwner;
-
-            var position = this.tabs.length - 1;
-            t._tPos = position;
-            this.tabContainer._setPositionalAttributes();
-
-            this.tabContainer.updateVisibility();
-
-            // If we don't have a preferred remote type, and we have a remote
-            // opener, use the opener's remote type.
-            if (!aPreferredRemoteType && aOpenerBrowser) {
-              aPreferredRemoteType = aOpenerBrowser.remoteType;
-            }
-
-            // If URI is about:blank and we don't have a preferred remote type,
-            // then we need to use the referrer, if we have one, to get the
-            // correct remote type for the new tab.
-            if (uriIsAboutBlank && !aPreferredRemoteType && aReferrerURI) {
-              aPreferredRemoteType =
-                E10SUtils.getRemoteTypeForURI(aReferrerURI.spec,
-                                              gMultiProcessBrowser);
-            }
-
-            let remoteType =
-              aForceNotRemote ? E10SUtils.NOT_REMOTE
-              : E10SUtils.getRemoteTypeForURI(aURI, gMultiProcessBrowser,
-                                              aPreferredRemoteType);
-
+            let usingPreloadedContent = false;
             let b;
-            let usingPreloadedContent = false;
-
-            // If we open a new tab with the newtab URL in the default
-            // userContext, check if there is a preloaded browser ready.
-            // Private windows are not included because both the label and the
-            // icon for the tab would be set incorrectly (see bug 1195981).
-            if (aURI == BROWSER_NEW_TAB_URL &&
-                !aUserContextId &&
-                !PrivateBrowsingUtils.isWindowPrivate(window)) {
-              b = this._getPreloadedBrowser();
-              if (b) {
-                usingPreloadedContent = true;
-              }
-            }
-
-            if (!b) {
-              // No preloaded browser found, create one.
-              b = this._createBrowser({ remoteType,
-                                        uriIsAboutBlank,
-                                        userContextId: aUserContextId,
-                                        sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
-                                        openerWindow: aOpener,
-                                        isPrerendered: aIsPrerendered,
-                                        nextTabParentId: aNextTabParentId,
-                                        name: aName });
-            }
-
-            t.linkedBrowser = b;
-
-            if (aFocusUrlBar) {
-              b._urlbarFocused = true;
-            }
-
-            this._tabForBrowser.set(b, t);
-            t.permanentKey = b.permanentKey;
-            t._browserParams = { uriIsAboutBlank,
-                                 remoteType,
-                                 usingPreloadedContent };
-
-            // If the caller opts in, create a lazy browser.
-            if (aCreateLazyBrowser) {
-              this._createLazyBrowser(t);
-
-              if (lazyBrowserURI) {
-                // Lazy browser must be explicitly registered so tab will appear as
-                // a switch-to-tab candidate in autocomplete.
-                this._unifiedComplete.registerOpenPage(lazyBrowserURI, aUserContextId);
-                b.registeredOpenURI = lazyBrowserURI;
-              }
-            } else {
-              this._insertBrowser(t, true);
+
+            try {
+              // If this new tab is owned by another, assert that relationship
+              if (aOwner)
+                t.owner = aOwner;
+
+              var position = this.tabs.length - 1;
+              t._tPos = position;
+              this.tabContainer._setPositionalAttributes();
+
+              this.tabContainer.updateVisibility();
+
+              // If we don't have a preferred remote type, and we have a remote
+              // opener, use the opener's remote type.
+              if (!aPreferredRemoteType && aOpenerBrowser) {
+                aPreferredRemoteType = aOpenerBrowser.remoteType;
+              }
+
+              // If URI is about:blank and we don't have a preferred remote type,
+              // then we need to use the referrer, if we have one, to get the
+              // correct remote type for the new tab.
+              if (uriIsAboutBlank && !aPreferredRemoteType && aReferrerURI) {
+                aPreferredRemoteType =
+                  E10SUtils.getRemoteTypeForURI(aReferrerURI.spec,
+                                                gMultiProcessBrowser);
+              }
+
+              let remoteType =
+                aForceNotRemote ? E10SUtils.NOT_REMOTE
+                : E10SUtils.getRemoteTypeForURI(aURI, gMultiProcessBrowser,
+                                                aPreferredRemoteType);
+
+              // If we open a new tab with the newtab URL in the default
+              // userContext, check if there is a preloaded browser ready.
+              // Private windows are not included because both the label and the
+              // icon for the tab would be set incorrectly (see bug 1195981).
+              if (aURI == BROWSER_NEW_TAB_URL &&
+                  !aUserContextId &&
+                  !PrivateBrowsingUtils.isWindowPrivate(window)) {
+                b = this._getPreloadedBrowser();
+                if (b) {
+                  usingPreloadedContent = true;
+                }
+              }
+
+              if (!b) {
+                // No preloaded browser found, create one.
+                b = this._createBrowser({ remoteType,
+                                          uriIsAboutBlank,
+                                          userContextId: aUserContextId,
+                                          sameProcessAsFrameLoader: aSameProcessAsFrameLoader,
+                                          openerWindow: aOpener,
+                                          isPrerendered: aIsPrerendered,
+                                          nextTabParentId: aNextTabParentId,
+                                          name: aName });
+              }
+
+              t.linkedBrowser = b;
+
+              if (aFocusUrlBar) {
+                b._urlbarFocused = true;
+              }
+
+              this._tabForBrowser.set(b, t);
+              t.permanentKey = b.permanentKey;
+              t._browserParams = { uriIsAboutBlank,
+                                   remoteType,
+                                   usingPreloadedContent };
+
+              // If the caller opts in, create a lazy browser.
+              if (aCreateLazyBrowser) {
+                this._createLazyBrowser(t);
+
+                if (lazyBrowserURI) {
+                  // Lazy browser must be explicitly registered so tab will appear as
+                  // a switch-to-tab candidate in autocomplete.
+                  this._unifiedComplete.registerOpenPage(lazyBrowserURI, aUserContextId);
+                  b.registeredOpenURI = lazyBrowserURI;
+                }
+              } else {
+                this._insertBrowser(t, true);
+              }
+            } catch (e) {
+              Cu.reportError("Failed to create tab");
+              Cu.reportError(e);
+              t.remove();
+              if (t.linkedBrowser) {
+                this._tabFilters.delete(t);
+                this._tabListeners.delete(t);
+                let notificationbox = this.getNotificationBox(t.linkedBrowser);
+                notificationbox.remove();
+              }
+              throw e;
             }
 
             // Dispatch a new tab notification.  We do this once we're
             // entirely done, so that things are in a consistent state
             // even if the event listener opens or closes tabs.
             var detail = aEventDetail || {};
             var evt = new CustomEvent("TabOpen", { bubbles: true, detail });
             t.dispatchEvent(evt);