Bug 463384 - "Tabbed mode" is an unnecessary complication. r=mano
authorDão Gottwald <dao@mozilla.com>
Wed, 23 Mar 2011 12:31:35 +0100
changeset 63659 1d50cf645e9aed89d65cbf7535fa3f5d4a118b48
parent 63657 9c0816e8ad5664491b1a7d02ae23fd0d0335217e
child 63660 cd6080e941363b54731349f57ff1aa7b49171ccb
push idunknown
push userunknown
push dateunknown
reviewersmano
bugs463384
milestone2.0b13pre
Bug 463384 - "Tabbed mode" is an unnecessary complication. r=mano
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1391,16 +1391,17 @@ function prepareForStartup() {
   } catch (e) {
     alert("Error launching browser window:" + e);
     window.close(); // Give up.
     return;
   }
 
   // initialize observers and listeners
   // and give C++ access to gBrowser
+  gBrowser.init();
   XULBrowserWindow.init();
   window.QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(nsIWebNavigation)
         .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
         .QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIXULWindow)
         .XULBrowserWindow = window.XULBrowserWindow;
   window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
@@ -4251,24 +4252,20 @@ var XULBrowserWindow = {
           this.throbberElement.setAttribute("busy", "true");
 
         // XXX: This needs to be based on window activity...
         this.stopCommand.removeAttribute("disabled");
         CombinedStopReload.switchToStop();
       }
     }
     else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
-      if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
-        if (aWebProgress.DOMWindow == content) {
-          if (aRequest)
-            this.endDocumentLoad(aRequest, aStatus);
-          if (!gBrowser.mTabbedMode && !gBrowser.getIcon())
-            gBrowser.useDefaultIcon(gBrowser.selectedTab);
-        }
-      }
+      if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK &&
+          aWebProgress.DOMWindow == content &&
+          aRequest)
+        this.endDocumentLoad(aRequest, aStatus);
 
       // This (thanks to the filter) is a network stop or the last
       // request stop outside of loading the document, stop throbbers
       // and progress bars and such
       if (aRequest) {
         let msg = "";
         let location;
         // Get the URI either from a channel or a pseudo-object
@@ -4394,19 +4391,16 @@ var XULBrowserWindow = {
       if ((location == "about:blank" && !content.opener) ||
           location == "") {  // Second condition is for new tabs, otherwise
                              // reload function is enabled until tab is refreshed.
         this.reloadCommand.setAttribute("disabled", "true");
       } else {
         this.reloadCommand.removeAttribute("disabled");
       }
 
-      if (!gBrowser.mTabbedMode && aWebProgress.isLoadingDocument)
-        gBrowser.setIcon(gBrowser.selectedTab, null);
-
       if (gURLBar) {
         // Strip off "wyciwyg://" and passwords for the location bar
         let uri = aLocationURI;
         try {
           uri = this._uriFixup.createExposableURI(uri);
         } catch (e) {}
         URLBarSetURI(uri);
 
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -129,23 +129,20 @@
       </field>
       <field name="mProgressListeners">
         []
       </field>
       <field name="mTabsProgressListeners">
         []
       </field>
       <field name="mTabListeners">
-        new Array()
+        []
       </field>
       <field name="mTabFilters">
-        new Array()
-      </field>
-      <field name="mTabbedMode">
-        false
+        []
       </field>
       <field name="mIsBusy">
         false
       </field>
       <field name="arrowKeysShouldWrap" readonly="true">
 #ifdef XP_MACOSX
         true
 #else
@@ -1059,57 +1056,16 @@
             if (aTab.selected)
               this.updateTitlebar();
 
             return true;
           ]]>
         </body>
       </method>
 
-      <method name="enterTabbedMode">
-        <body>
-          <![CDATA[
-            if (this.mTabbedMode)
-              return;
-
-            this.mTabbedMode = true; // Welcome to multi-tabbed mode.
-
-            if (XULBrowserWindow.isBusy) {
-              this.mCurrentTab.setAttribute("busy", "true");
-              this.mIsBusy = true;
-              this.setTabTitleLoading(this.mCurrentTab);
-            } else {
-              this.setIcon(this.mCurrentTab, this.mCurrentBrowser.mIconURL);
-            }
-
-            var filter;
-            if (this.mTabFilters.length > 0) {
-              // Use the filter hooked up in our addProgressListener
-              filter = this.mTabFilters[0];
-            } else {
-              // create a filter and hook it up to our first browser
-              filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
-                                 .createInstance(Components.interfaces.nsIWebProgress);
-              this.mTabFilters[0] = filter;
-              this.mCurrentBrowser.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
-            }
-
-            // Remove all our progress listeners from the active browser's filter.
-            this.mProgressListeners.forEach(filter.removeProgressListener, filter);
-
-            // Wire up a progress listener to our filter.
-            const listener = this.mTabProgressListener(this.mCurrentTab,
-                                                       this.mCurrentBrowser,
-                                                       false);
-            filter.addProgressListener(listener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
-            this.mTabListeners[0] = listener;
-          ]]>
-        </body>
-      </method>
-
       <method name="loadOneTab">
         <parameter name="aURI"/>
         <parameter name="aReferrerURI"/>
         <parameter name="aCharset"/>
         <parameter name="aPostData"/>
         <parameter name="aLoadInBackground"/>
         <parameter name="aAllowThirdPartyFixup"/>
         <body>
@@ -1223,18 +1179,16 @@
               aAllowThirdPartyFixup = params.allowThirdPartyFixup;
               aFromExternal         = params.fromExternal;
               aRelatedToCurrent     = params.relatedToCurrent;
               aSkipAnimation        = params.skipAnimation;
             }
 
             this._browsers = null; // invalidate cache
 
-            this.enterTabbedMode();
-
             // if we're adding tabs, we're past interrupt mode, ditch the owner
             if (this.mCurrentTab.owner)
               this.mCurrentTab.owner = null;
 
             var t = document.createElementNS(
               "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                                              "tab");
 
@@ -1869,62 +1823,34 @@
         <parameter name="aMask"/>
         <body>
           <![CDATA[
             if (!this.mAddProgressListenerWasCalled) {
               this.mAddProgressListenerWasCalled = true;
               this.tabContainer.updateVisibility();
             }
 
-            if (this.mProgressListeners.length == 1) {
-              // If we are adding a 2nd progress listener, we need to enter tabbed mode
-              // because the browser status filter can only handle one progress listener.
-              // In tabbed mode, mTabProgressListener is used which will iterate over all listeners.
-              this.enterTabbedMode();
-            }
-
             this.mProgressListeners.push(aListener);
-
-            if (!this.mTabbedMode) {
-              // If someone does this:
-              // addProgressListener, removeProgressListener, addProgressListener
-              // don't create a new filter; reuse the existing filter.
-              if (this.mTabFilters.length == 0) {
-                // hook a filter up to our first browser
-                const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
-                                         .createInstance(Components.interfaces.nsIWebProgress);
-                this.mTabFilters[0] = filter;
-                this.mCurrentBrowser.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
-              }
-
-              // Directly hook the listener up to the filter for better performance
-              this.mTabFilters[0].addProgressListener(aListener, aMask);
-            }
           ]]>
         </body>
       </method>
 
       <method name="removeProgressListener">
         <parameter name="aListener"/>
         <body>
           <![CDATA[
             this.mProgressListeners =
               this.mProgressListeners.filter(function (l) l != aListener);
-
-            if (!this.mTabbedMode)
-              // Don't forget to remove it from the filter we hooked it up to
-              this.mTabFilters[0].removeProgressListener(aListener);
          ]]>
         </body>
       </method>
 
       <method name="addTabsProgressListener">
         <parameter name="aListener"/>
         <body>
-          this.enterTabbedMode();
           this.mTabsProgressListeners.push(aListener);
         </body>
       </method>
 
       <method name="removeTabsProgressListener">
         <parameter name="aListener"/>
         <body>
         <![CDATA[
@@ -2484,19 +2410,43 @@
 
           // set up the shared autoscroll popup
           this._autoScrollPopup = this.mCurrentBrowser._createAutoScrollPopup();
           this._autoScrollPopup.id = "autoscroller";
           this.appendChild(this._autoScrollPopup);
           this.mCurrentBrowser.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
           this.mCurrentBrowser.droppedLinkHandler = handleDroppedLink;
           this.updateWindowResizers();
+
+          // Hook up the event listeners to the first browser
+          var tabListener = this.mTabProgressListener(this.mCurrentTab, this.mCurrentBrowser, true);
+          const nsIWebProgress = Components.interfaces.nsIWebProgress;
+          const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
+                                   .createInstance(nsIWebProgress);
+          filter.addProgressListener(tabListener, nsIWebProgress.NOTIFY_ALL);
+          this.mTabListeners[0] = tabListener;
+          this.mTabFilters[0] = filter;
+          this.init();
         ]]>
       </constructor>
 
+      <method name="init">
+        <body><![CDATA[
+          if (!this._initialProgressListenerAdded) {
+            this._initialProgressListenerAdded = true;
+            try {
+              this.webProgress.addProgressListener(this.mTabFilters[0], Components.interfaces.nsIWebProgress.NOTIFY_ALL);
+            } catch (e) {
+              // The binding was constructed too early, need to try this again later. See bug 463384.
+              this._initialProgressListenerAdded = false;
+            }
+          }
+        ]]></body>
+      </method>
+
       <destructor>
         <![CDATA[
           for (var i = 0; i < this.mTabListeners.length; ++i) {
             let browser = this.getBrowserAtIndex(i);
             if (browser.registeredOpenURI) {
               this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI);
               delete browser.registeredOpenURI;
             }
@@ -2506,16 +2456,23 @@
             this.mTabListeners[i].destroy();
             this.mTabListeners[i] = null;
           }
           document.removeEventListener("keypress", this, false);
         ]]>
       </destructor>
 
       <!-- Deprecated stuff, implemented for backwards compatibility. -->
+      <method name="enterTabbedMode">
+        <body>
+          Application.console.log("enterTabbedMode is an obsolete method and " +
+                                  "will be removed in a future release.");
+        </body>
+      </method>
+      <field name="mTabbedMode" readonly="true">true</field>
       <method name="setStripVisibilityTo">
         <parameter name="aShow"/>
         <body>
           this.tabContainer.visible = aShow;
         </body>
       </method>
       <method name="getStripVisibility">
         <body>
@@ -2762,19 +2719,16 @@
       <property name="visible"
                 onget="return !this._container.collapsed;">
         <setter><![CDATA[
           if (val == this.visible)
             return val;
 
           this._container.collapsed = !val;
 
-          if (val)
-            this.tabbrowser.enterTabbedMode();
-
           document.getElementById("menu_closeWindow").hidden = !val;
           document.getElementById("menu_close").setAttribute("label",
             this.tabbrowser.mStringBundle.getString(val ? "tabs.closeTab" : "tabs.close"));
 
           if (window.TabsInTitlebar)
             TabsInTitlebar.allowedBy("tabs-visible", val);
 
           return val;