Merge mozilla-central and ux
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Thu, 26 Sep 2013 10:26:16 +0200
changeset 170370 91a937dfb947145bbc2250fbff2cd58b6f4833eb
parent 162551 e85b0372cece1bb73a37bd89a8c053971021c835 (current diff)
parent 170369 814c3eb60842b50ce0cb7b763090b0c17888c700 (diff)
child 170371 af53342e5e4d35f3ef5d42c018e4be93e283f0c1
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.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
Merge mozilla-central and ux
browser/app/profile/firefox.js
browser/base/content/browser-appmenu.inc
browser/base/content/test/general/browser_addon_bar.js
browser/base/content/test/general/browser_addon_bar_aomlistener.js
browser/base/content/test/general/browser_addon_bar_close_button.js
browser/base/content/test/general/browser_addon_bar_shortcut.js
browser/base/content/test/general/browser_bug598923.js
browser/base/content/test/general/browser_bug599325.js
browser/base/content/test/general/browser_bug616836.js
browser/base/content/test/general/browser_customize.js
browser/base/content/test/general/browser_disablechrome.js
browser/base/content/test/general/disablechrome.html
browser/components/nsBrowserGlue.js
browser/themes/linux/places/pageStarred.png
browser/themes/linux/places/starPage.png
browser/themes/osx/Toolbar-lion.png
browser/themes/osx/Toolbar-lion@2x.png
browser/themes/osx/social/share-button-active.png
browser/themes/osx/social/share-button-active@2x.png
browser/themes/osx/social/share-button.png
browser/themes/osx/social/share-button@2x.png
browser/themes/osx/tabbrowser/tab-bottom-hover-active.png
browser/themes/osx/tabbrowser/tab-bottom-normal-active.png
browser/themes/osx/tabbrowser/tab-bottom-selected-active.png
browser/themes/osx/tabbrowser/tab-top-hover-active.png
browser/themes/osx/tabbrowser/tab-top-hover-active@2x.png
browser/themes/osx/tabbrowser/tab-top-normal-active.png
browser/themes/osx/tabbrowser/tab-top-normal-active@2x.png
browser/themes/osx/tabbrowser/tab-top-selected-active.png
browser/themes/osx/tabbrowser/tab-top-selected-active@2x.png
browser/themes/windows/appmenu-dropmarker.png
browser/themes/windows/appmenu-icons.png
browser/themes/windows/places/editBookmark.png
browser/themes/windows/privatebrowsing-dark.png
browser/themes/windows/privatebrowsing-light.png
browser/themes/windows/social/share-button-active.png
browser/themes/windows/social/share-button.png
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/style/nsCSSKeywordList.h
layout/style/nsCSSProps.cpp
modules/libpref/src/init/all.js
toolkit/themes/linux/global/icons/notloading_16.png
toolkit/themes/osx/global/icons/notloading_16.png
toolkit/themes/windows/global/icons/notloading_16.png
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.mm
widget/windows/nsWindow.cpp
--- a/accessible/tests/mochitest/events/test_focus_general.html
+++ b/accessible/tests/mochitest/events/test_focus_general.html
@@ -91,17 +91,17 @@
       gQueue = new eventQueue();
 
       gQueue.push(new synthFocus("editablearea"));
       gQueue.push(new synthFocus("navarea"));
       gQueue.push(new synthTab("navarea", new focusChecker(frameDoc)));
       gQueue.push(new focusElmWhileSubdocIsFocused("link"));
 
       gQueue.push(new synthTab(editableDoc, new focusChecker(editableDoc)));
-      if (WIN) {
+      if (WIN || LINUX) {
         // Alt key is used to active menubar and focus menu item on Windows,
         // other platforms requires setting a ui.key.menuAccessKeyFocuses
         // preference.
         gQueue.push(new toggleTopMenu(editableDoc, new topMenuChecker()));
         gQueue.push(new toggleTopMenu(editableDoc, new focusChecker(editableDoc)));
       }
       gQueue.push(new synthContextMenu(editableDoc, new contextMenuChecker()));
       gQueue.push(new synthDownKey(editableDoc, new focusContextMenuItemChecker()));
--- a/accessible/tests/mochitest/events/test_menu.xul
+++ b/accessible/tests/mochitest/events/test_menu.xul
@@ -151,17 +151,17 @@
 
       gQueue.push(new openFileMenu());
       gQueue.push(new openEditMenu());
       gQueue.push(new closeEditMenu());
 
       // Alt key is used to active menubar and focus menu item on Windows,
       // other platforms requires setting a ui.key.menuAccessKeyFocuses
       // preference.
-      if (WIN) {
+      if (WIN || LINUX) {
         gQueue.push(new focusFileMenu());
         gQueue.push(new focusEditMenu());
         gQueue.push(new leaveMenubar());
       }
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -428,21 +428,20 @@ pref("browser.tabs.warnOnCloseOtherTabs"
 pref("browser.tabs.warnOnOpen", true);
 pref("browser.tabs.maxOpenBeforeWarn", 15);
 pref("browser.tabs.loadInBackground", true);
 pref("browser.tabs.opentabfor.middleclick", true);
 pref("browser.tabs.loadDivertedInBackground", false);
 pref("browser.tabs.loadBookmarksInBackground", false);
 pref("browser.tabs.tabClipWidth", 140);
 pref("browser.tabs.animate", true);
-pref("browser.tabs.onTop", true);
-#ifdef XP_WIN
+#ifdef UNIX_BUT_NOT_MAC
+pref("browser.tabs.drawInTitlebar", false);
+#else
 pref("browser.tabs.drawInTitlebar", true);
-#else
-pref("browser.tabs.drawInTitlebar", false);
 #endif
 
 // Where to show tab close buttons:
 // 0  on active tab only
 // 1  on all tabs until tabClipWidth is reached, then active tab only
 // 2  no close buttons at all
 // 3  at the end of the tabstrip
 pref("browser.tabs.closeButtons", 1);
@@ -1301,8 +1300,11 @@ pref("plain_text.wrap_long_lines", true)
 pref("dom.debug.propagate_gesture_events_through_content", false);
 
 // The request URL of the GeoLocation backend.
 pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
 
 // Necko IPC security checks only needed for app isolation for cookies/cache/etc:
 // currently irrelevant for desktop e10s
 pref("network.disable.ipc.security", true);
+
+// CustomizableUI debug logging.
+pref("browser.uiCustomization.debug", false);
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -173,60 +173,16 @@ const gXPInstallObserver = {
 
       PopupNotifications.show(browser, notificationID, messageString, anchorID,
                               action, null, options);
       break;
     }
   }
 };
 
-/*
- * When addons are installed/uninstalled, check and see if the number of items
- * on the add-on bar changed:
- * - If an add-on was installed, incrementing the count, show the bar.
- * - If an add-on was uninstalled, and no more items are left, hide the bar.
- */
-let AddonsMgrListener = {
-  get addonBar() document.getElementById("addon-bar"),
-  get statusBar() document.getElementById("status-bar"),
-  getAddonBarItemCount: function() {
-    // Take into account the contents of the status bar shim for the count.
-    var itemCount = this.statusBar.childNodes.length;
-
-    var defaultOrNoninteractive = this.addonBar.getAttribute("defaultset")
-                                      .split(",")
-                                      .concat(["separator", "spacer", "spring"]);
-    for (let item of this.addonBar.currentSet.split(",")) {
-      if (defaultOrNoninteractive.indexOf(item) == -1)
-        itemCount++;
-    }
-
-    return itemCount;
-  },
-  onInstalling: function(aAddon) {
-    this.lastAddonBarCount = this.getAddonBarItemCount();
-  },
-  onInstalled: function(aAddon) {
-    if (this.getAddonBarItemCount() > this.lastAddonBarCount)
-      setToolbarVisibility(this.addonBar, true);
-  },
-  onUninstalling: function(aAddon) {
-    this.lastAddonBarCount = this.getAddonBarItemCount();
-  },
-  onUninstalled: function(aAddon) {
-    if (this.getAddonBarItemCount() == 0)
-      setToolbarVisibility(this.addonBar, false);
-  },
-  onEnabling: function(aAddon) this.onInstalling(),
-  onEnabled: function(aAddon) this.onInstalled(),
-  onDisabling: function(aAddon) this.onUninstalling(),
-  onDisabled: function(aAddon) this.onUninstalled(),
-};
-
-
 var LightWeightThemeWebInstaller = {
   handleEvent: function (event) {
     switch (event.type) {
       case "InstallBrowserTheme":
       case "PreviewBrowserTheme":
       case "ResetBrowserThemePreview":
         // ignore requests from background tabs
         if (event.target.ownerDocument.defaultView.top != content)
@@ -410,8 +366,65 @@ var LightWeightThemeWebInstaller = {
     return pm.testPermission(uri, "install") == pm.ALLOW_ACTION;
   },
 
   _getThemeFromNode: function (node) {
     return this._manager.parseTheme(node.getAttribute("data-browsertheme"),
                                     node.baseURI);
   }
 }
+
+/*
+ * Listen for Lightweight Theme styling changes and update the browser's theme accordingly.
+ */
+let LightweightThemeListener = {
+  _modifiedStyles: [],
+
+  init: function () {
+    XPCOMUtils.defineLazyGetter(this, "styleSheet", function() {
+      for (let i = document.styleSheets.length - 1; i >= 0; i--) {
+        let sheet = document.styleSheets[i];
+        if (sheet.href == "chrome://browser/skin/browser-lightweightTheme.css")
+          return sheet;
+      }
+    });
+
+    Services.obs.addObserver(this, "lightweight-theme-styling-update", false);
+    if (document.documentElement.hasAttribute("lwtheme"))
+      this.updateStyleSheet(document.documentElement.style.backgroundImage);
+  },
+
+  uninit: function () {
+    Services.obs.removeObserver(this, "lightweight-theme-styling-update");
+  },
+
+  /**
+   * Append the headerImage to the background-image property of all rulesets in
+   * browser-lightweightTheme.css.
+   *
+   * @param headerImage - a string containing a CSS image for the lightweight theme header.
+   */
+  updateStyleSheet: function(headerImage) {
+    if (!this.styleSheet)
+      return;
+    for (let i = 0; i < this.styleSheet.cssRules.length; i++) {
+      let rule = this.styleSheet.cssRules[i];
+      if (!rule.style.backgroundImage)
+        continue;
+
+      if (!this._modifiedStyles[i])
+        this._modifiedStyles[i] = { backgroundImage: rule.style.backgroundImage };
+
+      rule.style.backgroundImage = this._modifiedStyles[i].backgroundImage + ", " + headerImage;
+    }
+  },
+
+  // nsIObserver
+  observe: function (aSubject, aTopic, aData) {
+    if (aTopic != "lightweight-theme-styling-update" || !this.styleSheet)
+      return;
+
+    let themeData = JSON.parse(aData);
+    if (!themeData)
+      return;
+    this.updateStyleSheet("url(" + themeData.headerURL + ")");
+  },
+};
deleted file mode 100644
--- a/browser/base/content/browser-appmenu.inc
+++ /dev/null
@@ -1,406 +0,0 @@
-# -*- Mode: HTML -*-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-<menupopup id="appmenu-popup"
-           onpopupshowing="if (event.target == this) {
-                             updateEditUIVisibility();
-#ifdef MOZ_SERVICES_SYNC
-                             gSyncUI.updateUI();
-#endif
-                             return;
-                           }
-                           updateCharacterEncodingMenuState();
-                           if (event.target.parentNode.parentNode.parentNode.parentNode == this)
-                             this._currentPopup = event.target;">
-  <hbox>
-    <vbox id="appmenuPrimaryPane">
-      <splitmenu id="appmenu_newTab"
-                 label="&tabCmd.label;"
-                 command="cmd_newNavigatorTab">
-          <menupopup>
-            <menuitem id="appmenu_newTab_popup"
-                      label="&tabCmd.label;"
-                      command="cmd_newNavigatorTab"
-                      key="key_newNavigatorTab"/>
-            <menuitem id="appmenu_newNavigator"
-                      label="&newNavigatorCmd.label;"
-                      command="cmd_newNavigator"
-                      key="key_newNavigator"/>
-            <menuseparator/>
-            <menuitem id="appmenu_openFile"
-                      label="&openFileCmd.label;"
-                      command="Browser:OpenFile"
-                      key="openFileKb"/>
-          </menupopup>
-      </splitmenu>
-      <menuitem id="appmenu_newPrivateWindow"
-                class="menuitem-iconic menuitem-iconic-tooltip"
-                label="&newPrivateWindow.label;"
-                command="Tools:PrivateBrowsing"
-                key="key_privatebrowsing"/>
-      <menuitem label="&goOfflineCmd.label;"
-                id="appmenu_offlineModeRecovery"
-                type="checkbox"
-                observes="workOfflineMenuitemState"
-                oncommand="BrowserOffline.toggleOfflineStatus();"/>
-      <menuseparator class="appmenu-menuseparator"/>
-      <hbox>
-        <menuitem id="appmenu-edit-label"
-                  label="&appMenuEdit.label;"
-                  disabled="true"/>
-        <toolbarbutton id="appmenu-cut"
-                       class="appmenu-edit-button"
-                       command="cmd_cut"
-                       onclick="if (!this.disabled) hidePopup();"
-                       tooltiptext="&cutButton.tooltip;"/>
-        <toolbarbutton id="appmenu-copy"
-                       class="appmenu-edit-button"
-                       command="cmd_copy"
-                       onclick="if (!this.disabled) hidePopup();"
-                       tooltiptext="&copyButton.tooltip;"/>
-        <toolbarbutton id="appmenu-paste"
-                       class="appmenu-edit-button"
-                       command="cmd_paste"
-                       onclick="if (!this.disabled) hidePopup();"
-                       tooltiptext="&pasteButton.tooltip;"/>
-        <spacer flex="1"/>
-        <menu id="appmenu-editmenu">
-          <menupopup id="appmenu-editmenu-menupopup">
-            <menuitem id="appmenu-editmenu-cut"
-                      class="menuitem-iconic"
-                      label="&cutCmd.label;"
-                      key="key_cut"
-                      command="cmd_cut"/>
-            <menuitem id="appmenu-editmenu-copy"
-                      class="menuitem-iconic"
-                      label="&copyCmd.label;"
-                      key="key_copy"
-                      command="cmd_copy"/>
-            <menuitem id="appmenu-editmenu-paste"
-                      class="menuitem-iconic"
-                      label="&pasteCmd.label;"
-                      key="key_paste"
-                      command="cmd_paste"/>
-            <menuseparator/>
-            <menuitem id="appmenu-editmenu-undo"
-                      label="&undoCmd.label;"
-                      key="key_undo"
-                      command="cmd_undo"/>
-            <menuitem id="appmenu-editmenu-redo"
-                      label="&redoCmd.label;"
-                      key="key_redo"
-                      command="cmd_redo"/>
-            <menuseparator/>
-            <menuitem id="appmenu-editmenu-selectAll"
-                      label="&selectAllCmd.label;"
-                      key="key_selectAll"
-                      command="cmd_selectAll"/>
-            <menuseparator/>
-            <menuitem id="appmenu-editmenu-delete"
-                      label="&deleteCmd.label;"
-                      key="key_delete"
-                      command="cmd_delete"/>
-          </menupopup>
-        </menu>
-      </hbox>
-      <menuitem id="appmenu_find"
-                class="menuitem-tooltip"
-                label="&appMenuFind.label;"
-                command="cmd_find"
-                key="key_find"/>
-      <menuseparator class="appmenu-menuseparator"/>
-      <menuitem id="appmenu_savePage"
-                class="menuitem-tooltip"
-                label="&savePageCmd.label;"
-                command="Browser:SavePage"
-                key="key_savePage"/>
-      <menuitem id="appmenu_sendLink"
-                label="&emailPageCmd.label;"
-                command="Browser:SendLink"/>
-      <splitmenu id="appmenu_print"
-                 iconic="true"
-                 label="&printCmd.label;"
-                 command="cmd_print">
-          <menupopup>
-            <menuitem id="appmenu_print_popup"
-                      class="menuitem-iconic"
-                      label="&printCmd.label;"
-                      command="cmd_print"
-                      key="printKb"/>
-            <menuitem id="appmenu_printPreview"
-                      label="&printPreviewCmd.label;"
-                      command="cmd_printPreview"/>
-            <menuitem id="appmenu_printSetup"
-                      label="&printSetupCmd.label;"
-                      command="cmd_pageSetup"/>
-          </menupopup>
-      </splitmenu>
-      <menuseparator class="appmenu-menuseparator"/>
-      <splitmenu id="appmenu_webDeveloper"
-                 command="Tools:DevToolbox"
-                 label="&appMenuWebDeveloper.label;">
-        <menupopup id="appmenu_webDeveloper_popup">
-          <menuitem id="appmenu_devToolbox"
-                    observes="devtoolsMenuBroadcaster_DevToolbox"/>
-          <menuseparator id="appmenu_devtools_separator"/>
-          <menuitem id="appmenu_devToolbar"
-                    observes="devtoolsMenuBroadcaster_DevToolbar"/>
-          <menuitem id="appmenu_devAppMgr"
-                    observes="devtoolsMenuBroadcaster_DevAppMgr"/>
-          <menuitem id="appmenu_chromeDebugger"
-                    observes="devtoolsMenuBroadcaster_ChromeDebugger"/>
-          <menuitem id="appmenu_browserConsole"
-                    observes="devtoolsMenuBroadcaster_BrowserConsole"/>
-          <menuitem id="appmenu_responsiveUI"
-                    observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
-          <menuitem id="appmenu_scratchpad"
-                    observes="devtoolsMenuBroadcaster_Scratchpad"/>
-          <menuitem id="appmenu_pageSource"
-                    observes="devtoolsMenuBroadcaster_PageSource"/>
-          <menuitem id="appmenu_errorConsole"
-                    observes="devtoolsMenuBroadcaster_ErrorConsole"/>
-          <menuitem id="appmenu_devtools_connect"
-                    observes="devtoolsMenuBroadcaster_connect"/>
-          <menuseparator id="appmenu_devToolsEndSeparator"/>
-          <menuitem id="appmenu_getMoreDevtools"
-                    observes="devtoolsMenuBroadcaster_GetMoreTools"/>
-          <menuseparator/>
-#define ID_PREFIX appmenu_developer_
-#define OMIT_ACCESSKEYS
-#include browser-charsetmenu.inc
-#undef ID_PREFIX
-#undef OMIT_ACCESSKEYS
-          <menuitem label="&goOfflineCmd.label;"
-                    type="checkbox"
-                    observes="workOfflineMenuitemState"
-                    oncommand="BrowserOffline.toggleOfflineStatus();"/>
-        </menupopup>
-      </splitmenu>
-      <menuseparator class="appmenu-menuseparator"/>
-#define ID_PREFIX appmenu_
-#define OMIT_ACCESSKEYS
-#include browser-charsetmenu.inc
-#undef ID_PREFIX
-#undef OMIT_ACCESSKEYS
-      <menuitem id="appmenu_fullScreen"
-                class="menuitem-tooltip"
-                label="&fullScreenCmd.label;"
-                type="checkbox"
-                observes="View:FullScreen"
-                key="key_fullScreen"/>
-#ifdef MOZ_SERVICES_SYNC
-      <!-- only one of sync-setup or sync-syncnow will be showing at once -->
-      <menuitem id="sync-setup-appmenu"
-                label="&syncSetup.label;"
-                observes="sync-setup-state"
-                oncommand="gSyncUI.openSetup()"/>
-      <menuitem id="sync-syncnowitem-appmenu"
-                label="&syncSyncNowItem.label;"
-                observes="sync-syncnow-state"
-                oncommand="gSyncUI.doSync(event);"/>
-#endif
-      <menuitem id="appmenu-quit"
-                class="menuitem-iconic"
-#ifdef XP_WIN
-                label="&quitApplicationCmdWin.label;"
-#else
-                label="&quitApplicationCmd.label;"
-#endif
-                command="cmd_quitApplication"/>
-    </vbox>
-    <vbox id="appmenuSecondaryPane">
-      <splitmenu id="appmenu_bookmarks"
-                 iconic="true"
-                 label="&bookmarksMenu.label;"
-                 command="Browser:ShowAllBookmarks">
-          <menupopup id="appmenu_bookmarksPopup"
-                     placespopup="true"
-                     context="placesContext"
-                     openInTabs="children"
-                     oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);"
-                     onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);"
-                     onpopupshowing="BookmarkingUI.onPopupShowing(event);
-                                     if (!this.parentNode._placesView)
-                                       new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
-                     tooltip="bhTooltip"
-                     popupsinherittooltip="true">
-            <menuitem id="appmenu_showAllBookmarks"
-                      label="&showAllBookmarks2.label;"
-                      command="Browser:ShowAllBookmarks"
-                      context=""
-                      key="manBookmarkKb"/>
-            <menuseparator/>
-            <menuitem id="appmenu_bookmarkThisPage"
-                      class="menuitem-iconic"
-                      label="&bookmarkThisPageCmd.label;"
-                      command="Browser:AddBookmarkAs"
-                      key="addBookmarkAsKb"/>
-            <menuitem id="appmenu_subscribeToPage"
-                      class="menuitem-iconic"
-                      label="&subscribeToPageMenuitem.label;"
-                      oncommand="return FeedHandler.subscribeToFeed(null, event);"
-                      onclick="checkForMiddleClick(this, event);"
-                      observes="singleFeedMenuitemState"/>
-            <menu id="appmenu_subscribeToPageMenu"
-                  class="menu-iconic"
-                  label="&subscribeToPageMenupopup.label;"
-                  observes="multipleFeedsMenuState">
-              <menupopup id="appmenu_subscribeToPageMenupopup"
-                         onpopupshowing="return FeedHandler.buildFeedList(event.target);"
-                         oncommand="return FeedHandler.subscribeToFeed(null, event);"
-                         onclick="checkForMiddleClick(this, event);"/>
-            </menu>
-            <menuseparator/>
-            <menu id="appmenu_bookmarksToolbar"
-                  placesanonid="toolbar-autohide"
-                  class="menu-iconic bookmark-item"
-                  label="&personalbarCmd.label;"
-                  container="true">
-              <menupopup id="appmenu_bookmarksToolbarPopup"
-                         placespopup="true"
-                         context="placesContext"
-                         onpopupshowing="if (!this.parentNode._placesView)
-                                           new PlacesMenu(event, 'place:folder=TOOLBAR');"/>
-            </menu>
-            <menuseparator/>
-            <!-- Bookmarks menu items -->
-            <menuseparator builder="end"
-                           class="hide-if-empty-places-result"/>
-            <menuitem id="appmenu_unsortedBookmarks"
-                      label="&appMenuUnsorted.label;"
-                      oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"
-                      class="menuitem-iconic"/>
-          </menupopup>
-      </splitmenu>
-      <splitmenu id="appmenu_history"
-                 iconic="true"
-                 label="&historyMenu.label;"
-                 command="Browser:ShowAllHistory">
-          <menupopup id="appmenu_historyMenupopup"
-                     placespopup="true"
-                     oncommand="this.parentNode._placesView._onCommand(event);"
-                     onclick="checkForMiddleClick(this, event);"
-                     onpopupshowing="if (!this.parentNode._placesView)
-                                       new HistoryMenu(event);"
-                     tooltip="bhTooltip"
-                     popupsinherittooltip="true">
-            <menuitem id="appmenu_showAllHistory"
-                      label="&showAllHistoryCmd2.label;"
-                      command="Browser:ShowAllHistory"
-                      key="showAllHistoryKb"/>
-            <menuseparator/>
-            <menuitem id="appmenu_sanitizeHistory"
-                      label="&clearRecentHistory.label;"
-                      key="key_sanitize"
-                      command="Tools:Sanitize"/>
-            <menuseparator class="hide-if-empty-places-result"/>
-#ifdef MOZ_SERVICES_SYNC
-            <menuitem id="appmenu_sync-tabs"
-                      class="syncTabsMenuItem"
-                      label="&syncTabsMenu2.label;"
-                      oncommand="BrowserOpenSyncTabs();"
-                      disabled="true"/>
-#endif
-            <menuitem id="appmenu_restoreLastSession"
-                      label="&historyRestoreLastSession.label;"
-                      command="Browser:RestoreLastSession"/>
-            <menu id="appmenu_recentlyClosedTabsMenu"
-                  class="recentlyClosedTabsMenu"
-                  label="&historyUndoMenu.label;"
-                  disabled="true">
-              <menupopup id="appmenu_recentlyClosedTabsMenupopup"
-                         onpopupshowing="document.getElementById('appmenu_history')._placesView.populateUndoSubmenu();"/>
-            </menu>
-            <menu id="appmenu_recentlyClosedWindowsMenu"
-                  class="recentlyClosedWindowsMenu"
-                  label="&historyUndoWindowMenu.label;"
-                  disabled="true">
-              <menupopup id="appmenu_recentlyClosedWindowsMenupopup"
-                         onpopupshowing="document.getElementById('appmenu_history')._placesView.populateUndoWindowSubmenu();"/>
-            </menu>
-            <menuseparator/>
-          </menupopup>
-      </splitmenu>
-      <menuitem id="appmenu_downloads"
-                class="menuitem-tooltip"
-                label="&downloads.label;"
-                command="Tools:Downloads"
-                key="key_openDownloads"/>
-      <spacer id="appmenuSecondaryPane-spacer"/>
-      <menuitem id="appmenu_addons"
-                class="menuitem-iconic menuitem-iconic-tooltip"
-                label="&addons.label;"
-                command="Tools:Addons"
-                key="key_openAddons"/>
-      <splitmenu id="appmenu_customize"
-#ifdef XP_UNIX
-                 label="&preferencesCmdUnix.label;"
-#else
-                 label="&preferencesCmd2.label;"
-#endif
-                 oncommand="openPreferences();">
-          <menupopup id="appmenu_customizeMenu"
-                     onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('appmenu_toggleToolbarsSeparator'));">
-            <menuitem id="appmenu_preferences"
-#ifdef XP_UNIX
-                      label="&preferencesCmdUnix.label;"
-#else
-                      label="&preferencesCmd2.label;"
-#endif
-                      oncommand="openPreferences();"/>
-            <menuseparator/>
-            <menuseparator id="appmenu_toggleToolbarsSeparator"/>
-            <menuitem id="appmenu_toggleTabsOnTop"
-                      label="&viewTabsOnTop.label;"
-                      type="checkbox"
-                      command="cmd_ToggleTabsOnTop"/>
-            <menuitem id="appmenu_toolbarLayout"
-                      label="&appMenuToolbarLayout.label;"
-                      command="cmd_CustomizeToolbars"/>
-          </menupopup>
-      </splitmenu>
-      <splitmenu id="appmenu_help"
-                 label="&helpMenu.label;"
-                 oncommand="openHelpLink('firefox-help')">
-          <menupopup id="appmenu_helpMenupopup">
-            <menuitem id="appmenu_openHelp"
-                      label="&helpMenu.label;"
-                      oncommand="openHelpLink('firefox-help')"
-                      onclick="checkForMiddleClick(this, event);"/>
-            <menuitem id="appmenu_gettingStarted"
-                      label="&appMenuGettingStarted.label;"
-                      oncommand="gBrowser.loadOneTab('https://www.mozilla.org/firefox/central/', {inBackground: false});"
-                      onclick="checkForMiddleClick(this, event);"/>
-            <menuitem id="appmenu_keyboardShortcuts"
-                      label="&helpKeyboardShortcuts.label;"
-                      oncommand="openHelpLink('keyboard-shortcuts')"
-                      onclick="checkForMiddleClick(this, event);"/>
-#ifdef MOZ_SERVICES_HEALTHREPORT
-            <menuitem id="appmenu_healthReport"
-                      label="&healthReport.label;"
-                      oncommand="openHealthReport()"
-                      onclick="checkForMiddleClick(this, event);"/>
-#endif
-            <menuitem id="appmenu_troubleshootingInfo"
-                      label="&helpTroubleshootingInfo.label;"
-                      oncommand="openTroubleshootingPage()"
-                      onclick="checkForMiddleClick(this,event);"/>
-            <menuitem id="appmenu_feedbackPage"
-                      label="&helpFeedbackPage.label;"
-                      oncommand="openFeedbackPage()"
-                      onclick="checkForMiddleClick(this, event);"/>
-            <menuseparator/>
-            <menuitem id="appmenu_safeMode"
-                      label="&appMenuSafeMode.label;"
-                      oncommand="safeModeRestart();"/>
-            <menuseparator/>
-            <menuitem id="appmenu_about"
-                      label="&aboutProduct.label;"
-                      oncommand="openAboutDialog();"/>
-          </menupopup>
-      </splitmenu>
-    </vbox>
-  </hbox>
-</menupopup>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/browser-customization.js
@@ -0,0 +1,97 @@
+# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+ * Customization handler prepares this browser window for entering and exiting
+ * customization mode by handling customizationstarting and customizationending
+ * events.
+ */
+let CustomizationHandler = {
+  handleEvent: function(aEvent) {
+    switch(aEvent.type) {
+      case "customizationstarting":
+        this._customizationStarting();
+        break;
+      case "customizationending":
+        this._customizationEnding(aEvent.detail);
+        break;
+    }
+  },
+
+  isCustomizing: function() {
+    return document.documentElement.hasAttribute("customizing") ||
+           document.documentElement.hasAttribute("customize-exiting");
+  },
+
+  _customizationStarting: function() {
+    // Disable the toolbar context menu items
+    let menubar = document.getElementById("main-menubar");
+    for (let childNode of menubar.childNodes)
+      childNode.setAttribute("disabled", true);
+
+    let cmd = document.getElementById("cmd_CustomizeToolbars");
+    cmd.setAttribute("disabled", "true");
+
+    let splitter = document.getElementById("urlbar-search-splitter");
+    if (splitter) {
+      splitter.parentNode.removeChild(splitter);
+    }
+
+    CombinedStopReload.uninit();
+    PlacesToolbarHelper.customizeStart();
+    BookmarkingUI.customizeStart();
+    DownloadsButton.customizeStart();
+  },
+
+  _customizationEnding: function(aDetails) {
+    // Update global UI elements that may have been added or removed
+    if (aDetails.changed) {
+      gURLBar = document.getElementById("urlbar");
+
+      gProxyFavIcon = document.getElementById("page-proxy-favicon");
+      gHomeButton.updateTooltip();
+      gIdentityHandler._cacheElements();
+      XULBrowserWindow.init();
+
+#ifndef XP_MACOSX
+      updateEditUIVisibility();
+#endif
+
+      // Hacky: update the PopupNotifications' object's reference to the iconBox,
+      // if it already exists, since it may have changed if the URL bar was
+      // added/removed.
+      if (!window.__lookupGetter__("PopupNotifications")) {
+        PopupNotifications.iconBox =
+          document.getElementById("notification-popup-box");
+      }
+
+    }
+
+    PlacesToolbarHelper.customizeDone();
+    BookmarkingUI.customizeDone();
+    DownloadsButton.customizeDone();
+
+    // The url bar splitter state is dependent on whether stop/reload
+    // and the location bar are combined, so we need this ordering
+    CombinedStopReload.init();
+    UpdateUrlbarSearchSplitterState();
+
+    // Update the urlbar
+    if (gURLBar) {
+      URLBarSetURI();
+      XULBrowserWindow.asyncUpdateUI();
+      BookmarkingUI.updateStarState();
+    }
+
+    // Re-enable parts of the UI we disabled during the dialog
+    let menubar = document.getElementById("main-menubar");
+    for (let childNode of menubar.childNodes)
+      childNode.setAttribute("disabled", false);
+    let cmd = document.getElementById("cmd_CustomizeToolbars");
+    cmd.removeAttribute("disabled");
+
+    gBrowser.selectedBrowser.focus();
+  }
+}
--- a/browser/base/content/browser-feeds.js
+++ b/browser/base/content/browser-feeds.js
@@ -3,85 +3,72 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 /**
  * The Feed Handler object manages discovery of RSS/ATOM feeds in web pages
  * and shows UI when they are discovered.
  */
 var FeedHandler = {
-  /**
-   * The click handler for the Feed icon in the toolbar. Opens the
-   * subscription page if user is not given a choice of feeds.
-   * (Otherwise the list of available feeds will be presented to the
-   * user in a popup menu.)
-   */
-  onFeedButtonClick: function(event) {
-    event.stopPropagation();
-
-    let feeds = gBrowser.selectedBrowser.feeds || [];
-    // If there are multiple feeds, the menu will open, so no need to do
-    // anything. If there are no feeds, nothing to do either.
-    if (feeds.length != 1)
-      return;
-
-    if (event.eventPhase == Event.AT_TARGET &&
-        (event.button == 0 || event.button == 1)) {
-      this.subscribeToFeed(feeds[0].href, event);
-    }
-  },
-
- /** Called when the user clicks on the Subscribe to This Page... menu item.
+  /** Called when the user clicks on the Subscribe to This Page... menu item,
+   * or when the user clicks the feed button when the page contains multiple
+   * feeds.
    * Builds a menu of unique feeds associated with the page, and if there
    * is only one, shows the feed inline in the browser window.
-   * @param   menuPopup
-   *          The feed list menupopup to be populated.
-   * @returns true if the menu should be shown, false if there was only
+   * @param   container
+   *          The feed list container (menupopup or subview) to be populated.
+   * @param   isSubview
+   *          Whether we're creating a subview (true) or menu (false/undefined)
+   * @returns true if the menu/subview should be shown, false if there was only
    *          one feed and the feed should be shown inline in the browser
-   *          window (do not show the menupopup).
+   *          window (do not show the menupopup/subview).
    */
-  buildFeedList: function(menuPopup) {
+  buildFeedList: function(container, isSubview) {
     var feeds = gBrowser.selectedBrowser.feeds;
-    if (feeds == null) {
+    if (!isSubview && feeds == null) {
       // XXX hack -- menu opening depends on setting of an "open"
       // attribute, and the menu refuses to open if that attribute is
       // set (because it thinks it's already open).  onpopupshowing gets
       // called after the attribute is unset, and it doesn't get unset
       // if we return false.  so we unset it here; otherwise, the menu
       // refuses to work past this point.
-      menuPopup.parentNode.removeAttribute("open");
+      container.parentNode.removeAttribute("open");
       return false;
     }
 
-    while (menuPopup.firstChild)
-      menuPopup.removeChild(menuPopup.firstChild);
+    while (container.firstChild)
+      container.removeChild(container.firstChild);
 
-    if (feeds.length <= 1)
+    if (!feeds || feeds.length <= 1)
       return false;
 
     // Build the menu showing the available feed choices for viewing.
+    var itemNodeType = isSubview ? "toolbarbutton" : "menuitem";
     for (let feedInfo of feeds) {
-      var menuItem = document.createElement("menuitem");
+      var item = document.createElement(itemNodeType);
       var baseTitle = feedInfo.title || feedInfo.href;
       var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew", [baseTitle]);
-      menuItem.setAttribute("class", "feed-menuitem");
-      menuItem.setAttribute("label", labelStr);
-      menuItem.setAttribute("feed", feedInfo.href);
-      menuItem.setAttribute("tooltiptext", feedInfo.href);
-      menuItem.setAttribute("crop", "center");
-      menuPopup.appendChild(menuItem);
+      item.setAttribute("class", "feed-" + itemNodeType);
+      item.setAttribute("label", labelStr);
+      item.setAttribute("feed", feedInfo.href);
+      item.setAttribute("tooltiptext", feedInfo.href);
+      item.setAttribute("crop", "center");
+      if (isSubview) {
+        item.setAttribute("tabindex", "0");
+      }
+      container.appendChild(item);
     }
     return true;
   },
 
   /**
    * Subscribe to a given feed.  Called when
    *   1. Page has a single feed and user clicks feed icon in location bar
    *   2. Page has a single feed and user selects Subscribe menu item
-   *   3. Page has multiple feeds and user selects from feed icon popup
+   *   3. Page has multiple feeds and user selects from feed icon popup (or subview)
    *   4. Page has multiple feeds and user selects from Subscribe submenu
    * @param   href
    *          The feed to subscribe to. May be null, in which case the
    *          event target's feed attribute is examined.
    * @param   event
    *          The event this method is handling. Used to decide where
    *          to open the preview UI. (Optional, unless href is null)
    */
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -12,17 +12,17 @@ var FullScreen = {
   toggle: function (event) {
     var enterFS = window.fullScreen;
 
     // We get the fullscreen event _before_ the window transitions into or out of FS mode.
     if (event && event.type == "fullscreen")
       enterFS = !enterFS;
 
     // Toggle the View:FullScreen command, which controls elements like the
-    // fullscreen menuitem, menubars, and the appmenu.
+    // fullscreen menuitem, and menubars.
     let fullscreenCommand = document.getElementById("View:FullScreen");
     if (enterFS) {
       fullscreenCommand.setAttribute("checked", enterFS);
     } else {
       fullscreenCommand.removeAttribute("checked");
     }
 
 #ifdef XP_MACOSX
@@ -512,50 +512,33 @@ var FullScreen = {
   showXULChrome: function(aTag, aShow)
   {
     var els = document.getElementsByTagNameNS(this._XULNS, aTag);
 
     for (let el of els) {
       // XXX don't interfere with previously collapsed toolbars
       if (el.getAttribute("fullscreentoolbar") == "true") {
         if (!aShow) {
-
-          var toolbarMode = el.getAttribute("mode");
-          if (toolbarMode != "text") {
-            el.setAttribute("saved-mode", toolbarMode);
-            el.setAttribute("saved-iconsize", el.getAttribute("iconsize"));
-            el.setAttribute("mode", "icons");
-            el.setAttribute("iconsize", "small");
-          }
-
           // Give the main nav bar and the tab bar the fullscreen context menu,
           // otherwise remove context menu to prevent breakage
           el.setAttribute("saved-context", el.getAttribute("context"));
           if (el.id == "nav-bar" || el.id == "TabsToolbar")
             el.setAttribute("context", "autohide-context");
           else
             el.removeAttribute("context");
 
           // Set the inFullscreen attribute to allow specific styling
           // in fullscreen mode
           el.setAttribute("inFullscreen", true);
         }
         else {
-          var restoreAttr = function restoreAttr(attrName) {
-            var savedAttr = "saved-" + attrName;
-            if (el.hasAttribute(savedAttr)) {
-              el.setAttribute(attrName, el.getAttribute(savedAttr));
-              el.removeAttribute(savedAttr);
-            }
+          if (el.hasAttribute("saved-context")) {
+            el.setAttribute("context", el.getAttribute("saved-context"));
+            el.removeAttribute("saved-context");
           }
-
-          restoreAttr("mode");
-          restoreAttr("iconsize");
-          restoreAttr("context");
-
           el.removeAttribute("inFullscreen");
         }
       } else {
         // use moz-collapsed so it doesn't persist hidden/collapsed,
         // so that new windows don't have missing toolbars
         if (aShow)
           el.removeAttribute("moz-collapsed");
         else
@@ -566,21 +549,19 @@ var FullScreen = {
     if (aShow) {
       gNavToolbox.removeAttribute("inFullscreen");
       document.documentElement.removeAttribute("inFullscreen");
     } else {
       gNavToolbox.setAttribute("inFullscreen", true);
       document.documentElement.setAttribute("inFullscreen", true);
     }
 
-    // In tabs-on-top mode, move window controls to the tab bar,
-    // and in tabs-on-bottom mode, move them back to the navigation toolbar.
     var fullscreenctls = document.getElementById("window-controls");
     var navbar = document.getElementById("nav-bar");
-    var ctlsOnTabbar = window.toolbar.visible && (navbar.collapsed || TabsOnTop.enabled);
+    var ctlsOnTabbar = window.toolbar.visible;
     if (fullscreenctls.parentNode == navbar && ctlsOnTabbar) {
       fullscreenctls.removeAttribute("flex");
       document.getElementById("TabsToolbar").appendChild(fullscreenctls);
     }
     else if (fullscreenctls.parentNode.id == "TabsToolbar" && !ctlsOnTabbar) {
       fullscreenctls.setAttribute("flex", "1");
       navbar.appendChild(fullscreenctls);
     }
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -396,16 +396,17 @@ var FullZoom = {
 
   /**
    * Saves the zoom level of the page in the given browser to the content
    * prefs store.
    *
    * @param browser  The zoom of this browser will be saved.  Required.
    */
   _applyZoomToPref: function FullZoom__applyZoomToPref(browser) {
+    Services.obs.notifyObservers(null, "browser-fullZoom:zoomChange", "");
     if (!this.siteSpecific ||
         gInPrintPreviewMode ||
         browser.contentDocument.mozSyntheticDocument)
       return;
 
     this._cps2.set(browser.currentURI.spec, this.name,
                    ZoomManager.getZoomForBrowser(browser),
                    this._loadContextFromWindow(browser.contentWindow), {
@@ -416,16 +417,17 @@ var FullZoom = {
   },
 
   /**
    * Removes from the content prefs store the zoom level of the given browser.
    *
    * @param browser  The zoom of this browser will be removed.  Required.
    */
   _removePref: function FullZoom__removePref(browser) {
+    Services.obs.notifyObservers(null, "browser-fullZoom:zoomReset", "");
     if (browser.contentDocument.mozSyntheticDocument)
       return;
     let ctxt = this._loadContextFromWindow(browser.contentWindow);
     this._cps2.removeByDomainAndName(browser.currentURI.spec, this.name, ctxt, {
       handleCompletion: function () {
         this._isNextContentPrefChangeInternal = true;
       }.bind(this),
     });
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -180,21 +180,16 @@
                   accesskey="&viewMenu.accesskey;">
               <menupopup id="menu_viewPopup"
                          onpopupshowing="updateCharacterEncodingMenuState();">
                 <menu id="viewToolbarsMenu"
                       label="&viewToolbarsMenu.label;"
                       accesskey="&viewToolbarsMenu.accesskey;">
                   <menupopup onpopupshowing="onViewToolbarsPopupShowing(event);">
                     <menuseparator/>
-                    <menuitem id="menu_tabsOnTop"
-                              command="cmd_ToggleTabsOnTop"
-                              type="checkbox"
-                              label="&viewTabsOnTop.label;"
-                              accesskey="&viewTabsOnTop.accesskey;"/>
                     <menuitem id="menu_customizeToolbars"
                               label="&viewCustomizeToolbar.label;"
                               accesskey="&viewCustomizeToolbar.accesskey;"
                               command="cmd_CustomizeToolbars"/>
                   </menupopup>
                 </menu>
                 <menu id="viewSidebarMenuMenu"
                       label="&viewSidebarMenu.label;"
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -129,19 +129,16 @@ var StarUI = {
       this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition);
       return;
     }
 
     this._overlayLoading = true;
     document.loadOverlay(
       "chrome://browser/content/places/editBookmarkOverlay.xul",
       (function (aSubject, aTopic, aData) {
-        //XXX We just caused localstore.rdf to be re-applied (bug 640158)
-        retrieveToolbarIconsizesFromTheme();
-
         // Move the header (star, title, button) into the grid,
         // so that it aligns nicely with the other items (bug 484022).
         let header = this._element("editBookmarkPanelHeader");
         let rows = this._element("editBookmarkPanelGrid").lastChild;
         rows.insertBefore(header, rows.firstChild);
         header.hidden = false;
 
         this._overlayLoading = false;
@@ -825,19 +822,20 @@ var BookmarksEventHandler = {
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 //// PlacesMenuDNDHandler
 
 // Handles special drag and drop functionality for Places menus that are not
 // part of a Places view (e.g. the bookmarks menu in the menubar).
 var PlacesMenuDNDHandler = {
-  _springLoadDelay: 350, // milliseconds
+  _springLoadDelayMs: 350,
+  _closeDelayMs: 500,
   _loadTimer: null,
-  _closerTimer: null,
+  _closeTimer: null,
 
   /**
    * Called when the user enters the <menu> element during a drag.
    * @param   event
    *          The DragEnter event that spawned the opening. 
    */
   onDragEnter: function PMDH_onDragEnter(event) {
     // Opening menus in a Places popup is handled by the view itself.
@@ -848,30 +846,31 @@ var PlacesMenuDNDHandler = {
     if (this._loadTimer || popup.state === "showing" || popup.state === "open")
       return;
 
     this._loadTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     this._loadTimer.initWithCallback(() => {
       this._loadTimer = null;
       popup.setAttribute("autoopened", "true");
       popup.showPopup(popup);
-    }, this._springLoadDelay, Ci.nsITimer.TYPE_ONE_SHOT);
+    }, this._springLoadDelayMs, Ci.nsITimer.TYPE_ONE_SHOT);
     event.preventDefault();
     event.stopPropagation();
   },
 
   /**
    * Handles dragleave on the <menu> element.
    * @returns true if the element is a container element (menu or 
    *          menu-toolbarbutton), false otherwise.
    */
   onDragLeave: function PMDH_onDragLeave(event) {
     // Handle menu-button separate targets.
     if (event.relatedTarget === event.currentTarget ||
-        event.relatedTarget.parentNode === event.currentTarget)
+        (event.relatedTarget &&
+         event.relatedTarget.parentNode === event.currentTarget))
       return;
 
     // Closing menus in a Places popup is handled by the view itself.
     if (!this._isStaticContainer(event.target))
       return;
 
     let popup = event.target.lastChild;
 
@@ -887,17 +886,17 @@ var PlacesMenuDNDHandler = {
       while (node && !inHierarchy) {
         inHierarchy = node == event.target;
         node = node.parentNode;
       }
       if (!inHierarchy && popup && popup.hasAttribute("autoopened")) {
         popup.removeAttribute("autoopened");
         popup.hidePopup();
       }
-    }, this._springLoadDelay, Ci.nsITimer.TYPE_ONE_SHOT);
+    }, this._closeDelayMs, Ci.nsITimer.TYPE_ONE_SHOT);
   },
 
   /**
    * Determines if a XUL element represents a static container.
    * @returns true if the element is a container element (menu or 
    *`         menu-toolbarbutton), false otherwise.
    */
   _isStaticContainer: function PMDH__isContainer(node) {
@@ -955,83 +954,107 @@ let PlacesToolbarHelper = {
     return document.getElementById("PlacesToolbar");
   },
 
   init: function PTH_init() {
     let viewElt = this._viewElt;
     if (!viewElt || viewElt._placesView)
       return;
 
-    // If the bookmarks toolbar item is hidden because the parent toolbar is
-    // collapsed or hidden (i.e. in a popup), spare the initialization.  Also,
-    // there is no need to initialize the toolbar if customizing because
-    // init() will be called when the customization is done.
-    let toolbar = viewElt.parentNode.parentNode;
-    if (toolbar.collapsed ||
-        getComputedStyle(toolbar, "").display == "none" ||
-        this._isCustomizing)
+    // If the bookmarks toolbar item is:
+    // - not in a toolbar, or;
+    // - the toolbar is collapsed, or;
+    // - the toolbar is hidden some other way:
+    // don't initialize.  Also, there is no need to initialize the toolbar if
+    // customizing, because that will happen when the customization is done.
+    let toolbar = this._getParentToolbar(viewElt);
+    if (!toolbar || toolbar.collapsed || this._isCustomizing ||
+        getComputedStyle(toolbar, "").display == "none")
       return;
 
     new PlacesToolbar(this._place);
   },
 
   customizeStart: function PTH_customizeStart() {
-    let viewElt = this._viewElt;
-    if (viewElt && viewElt._placesView)
-      viewElt._placesView.uninit();
-
-    this._isCustomizing = true;
+    try {
+      let viewElt = this._viewElt;
+      if (viewElt && viewElt._placesView)
+        viewElt._placesView.uninit();
+    } finally {
+      this._isCustomizing = true;
+    }
   },
 
   customizeDone: function PTH_customizeDone() {
     this._isCustomizing = false;
     this.init();
+  },
+
+  onPlaceholderCommand: function () {
+    let widgetGroup = CustomizableUI.getWidget("personal-bookmarks");
+    let widget = widgetGroup.forWindow(window);
+    if (widget.overflowed ||
+        widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
+      PlacesCommandHook.showPlacesOrganizer("BookmarksToolbar");
+    }
+  },
+
+  _getParentToolbar: function(element) {
+    while (element) {
+      if (element.localName == "toolbar") {
+        return element;
+      }
+      element = element.parentNode;
+    }
+    return null;
   }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 //// BookmarkingUI
 
 /**
- * Handles the bookmarks star button in the URL bar, as well as the bookmark
- * menu button.
+ * Handles the bookmarks menu-button in the toolbar.
  */
 
 let BookmarkingUI = {
   get button() {
-    if (!this._button) {
-      this._button = document.getElementById("bookmarks-menu-button");
+    let widgetGroup = CustomizableUI.getWidget("bookmarks-menu-button");
+    if (widgetGroup.areaType == CustomizableUI.TYPE_TOOLBAR) {
+      return widgetGroup.forWindow(window).node;
     }
-    return this._button;
+    return null;
   },
 
   get star() {
-    if (!this._star) {
-      this._star = document.getElementById("star-button");
-    }
-    return this._star;
+    let button = this.button;
+    return button && document.getAnonymousElementByAttribute(button, "anonid",
+                                                             "button");
   },
 
   get anchor() {
-    if (this.star && isElementVisible(this.star)) {
-      // Anchor to the icon, so the panel looks more natural.
-      return this.star;
-    }
-    return null;
+    let widget = CustomizableUI.getWidget("bookmarks-menu-button")
+                               .forWindow(window);
+    if (widget.overflowed)
+      return widget.anchor;
+
+    let star = this.star;
+    return star && document.getAnonymousElementByAttribute(star, "class",
+                                                           "toolbarbutton-icon");
   },
 
   STATUS_UPDATING: -1,
   STATUS_UNSTARRED: 0,
   STATUS_STARRED: 1,
   get status() {
     if (this._pendingStmt)
       return this.STATUS_UPDATING;
-    return this.star &&
-           this.star.hasAttribute("starred") ? this.STATUS_STARRED
-                                             : this.STATUS_UNSTARRED;
+    let button = this.button;
+    return button && button.hasAttribute("starred") ? this.STATUS_STARRED
+                                                    : this.STATUS_UNSTARRED;
   },
 
   get _starredTooltip()
   {
     delete this._starredTooltip;
     return this._starredTooltip =
       gNavigatorBundle.getString("starButtonOn.tooltip");
   },
@@ -1054,97 +1077,100 @@ let BookmarkingUI = {
     this._popupNeedsUpdate = true;
   },
 
   onPopupShowing: function BUI_onPopupShowing(event) {
     // Don't handle events for submenus.
     if (event.target != event.currentTarget)
       return;
 
+    let widget = CustomizableUI.getWidget("bookmarks-menu-button")
+                               .forWindow(window);
+    if (widget.overflowed) {
+      // Don't open a popup in the overflow popup, rather just open the Library.
+      event.preventDefault();
+      widget.node.removeAttribute("noautoclose");
+      PlacesCommandHook.showPlacesOrganizer("BookmarksMenu");
+      return;
+    }
+
     if (!this._popupNeedsUpdate)
       return;
     this._popupNeedsUpdate = false;
 
     let popup = event.target;
     let getPlacesAnonymousElement =
       aAnonId => document.getAnonymousElementByAttribute(popup.parentNode,
                                                          "placesanonid",
                                                          aAnonId);
 
     let viewToolbarMenuitem = getPlacesAnonymousElement("view-toolbar");
     if (viewToolbarMenuitem) {
       // Update View bookmarks toolbar checkbox menuitem.
       let personalToolbar = document.getElementById("PersonalToolbar");
       viewToolbarMenuitem.setAttribute("checked", !personalToolbar.collapsed);
     }
-
-    let toolbarMenuitem = getPlacesAnonymousElement("toolbar-autohide");
-    if (toolbarMenuitem) {
-      // If bookmarks items are visible, hide Bookmarks Toolbar menu and the
-      // separator after it.
-      toolbarMenuitem.collapsed = toolbarMenuitem.nextSibling.collapsed =
-        isElementVisible(document.getElementById("personal-bookmarks"));
-    }
   },
 
   /**
    * Handles star styling based on page proxy state changes.
    */
   onPageProxyStateChanged: function BUI_onPageProxyStateChanged(aState) {
     if (!this.star) {
       return;
     }
 
     if (aState == "invalid") {
       this.star.setAttribute("disabled", "true");
-      this.star.removeAttribute("starred");
+      this.button.removeAttribute("starred");
+      this.button.setAttribute("buttontooltiptext", "");
     }
     else {
       this.star.removeAttribute("disabled");
     }
+    this._updateToolbarStyle();
   },
 
   _updateToolbarStyle: function BUI__updateToolbarStyle() {
-    if (!this.button) {
+    let button = this.button;
+    if (!button)
       return;
-    }
 
     let personalToolbar = document.getElementById("PersonalToolbar");
-    let onPersonalToolbar = this.button.parentNode == personalToolbar ||
-                            this.button.parentNode.parentNode == personalToolbar;
+    let onPersonalToolbar = button.parentNode == personalToolbar ||
+                            button.parentNode.parentNode == personalToolbar;
 
     if (onPersonalToolbar) {
-      this.button.classList.add("bookmark-item");
-      this.button.classList.remove("toolbarbutton-1");
+      button.classList.add("bookmark-item");
+      button.classList.remove("toolbarbutton-1");
     }
     else {
-      this.button.classList.remove("bookmark-item");
-      this.button.classList.add("toolbarbutton-1");
+      button.classList.remove("bookmark-item");
+      button.classList.add("toolbarbutton-1");
     }
   },
 
   _uninitView: function BUI__uninitView() {
     // When an element with a placesView attached is removed and re-inserted,
     // XBL reapplies the binding causing any kind of issues and possible leaks,
     // so kill current view and let popupshowing generate a new one.
-    if (this.button && this.button._placesView) {
-      this.button._placesView.uninit();
-    }
+    let button = this.button;
+    if (button && button._placesView)
+      button._placesView.uninit();
   },
 
   customizeStart: function BUI_customizeStart() {
     this._uninitView();
   },
 
   customizeChange: function BUI_customizeChange() {
     this._updateToolbarStyle();
   },
 
   customizeDone: function BUI_customizeDone() {
-    delete this._button;
     this.onToolbarVisibilityChange();
     this._updateToolbarStyle();
   },
 
   _hasBookmarksObserver: false,
   uninit: function BUI_uninit() {
     this._uninitView();
 
@@ -1154,17 +1180,17 @@ let BookmarkingUI = {
 
     if (this._pendingStmt) {
       this._pendingStmt.cancel();
       delete this._pendingStmt;
     }
   },
 
   updateStarState: function BUI_updateStarState() {
-    if (!this.star || (this._uri && gBrowser.currentURI.equals(this._uri))) {
+    if (!this.button || (this._uri && gBrowser.currentURI.equals(this._uri))) {
       return;
     }
 
     // Reset tracked values.
     this._uri = gBrowser.currentURI;
     this._itemIds = [];
 
     if (this._pendingStmt) {
@@ -1203,63 +1229,127 @@ let BookmarkingUI = {
         }
       }
 
       delete this._pendingStmt;
     }, this);
   },
 
   _updateStar: function BUI__updateStar() {
-    if (!this.star) {
+    let button = this.button;
+    if (!button)
       return;
-    }
 
     if (this._itemIds.length > 0) {
-      this.star.setAttribute("starred", "true");
-      this.star.setAttribute("tooltiptext", this._starredTooltip);
+      button.setAttribute("starred", "true");
+      button.setAttribute("buttontooltiptext", this._starredTooltip);
     }
     else {
-      this.star.removeAttribute("starred");
-      this.star.setAttribute("tooltiptext", this._unstarredTooltip);
+      button.removeAttribute("starred");
+      button.setAttribute("buttontooltiptext", this._unstarredTooltip);
     }
   },
 
   onCommand: function BUI_onCommand(aEvent) {
     if (aEvent.target != aEvent.currentTarget) {
       return;
     }
+
+    // Handle special case when the button is in the panel.
+    let widgetGroup = CustomizableUI.getWidget("bookmarks-menu-button");
+    let widget = widgetGroup.forWindow(window);
+    if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
+      let view = document.getElementById("PanelUI-bookmarks");
+      view.addEventListener("ViewShowing", this.onPanelMenuViewShowing);
+      view.addEventListener("ViewHiding", this.onPanelMenuViewHiding);
+      widget.node.setAttribute("noautoclose", "true");
+      PanelUI.showSubView("PanelUI-bookmarks", widget.node,
+                          CustomizableUI.AREA_PANEL);
+      return;
+    }
+    else if (widget.overflowed) {
+      // Allow to close the panel if the page is already bookmarked, cause
+      // we are going to open the edit bookmark panel.
+      if (this._itemIds.length > 0)
+        widget.node.removeAttribute("noautoclose");
+      else
+        widget.node.setAttribute("noautoclose", "true");
+    }
+
     // Ignore clicks on the star if we are updating its state.
     if (!this._pendingStmt) {
       PlacesCommandHook.bookmarkCurrentPage(this._itemIds.length > 0);
     }
   },
 
+  onPanelMenuViewShowing: function BUI_onViewShowing(aEvent) {
+    // Update checked status of the toolbar toggle.
+    let viewToolbar = document.getElementById("panelMenu_viewBookmarksToolbar");
+    let personalToolbar = document.getElementById("PersonalToolbar");
+    if (personalToolbar.collapsed)
+      viewToolbar.removeAttribute("checked");
+    else
+      viewToolbar.setAttribute("checked", "true");
+    // Setup the Places view.
+    this._panelMenuView = new PlacesPanelMenuView("place:folder=BOOKMARKS_MENU",
+                                                  "panelMenu_bookmarksMenu",
+                                                  "panelMenu_bookmarksMenu");
+  },
+
+  onPanelMenuViewHiding: function BUI_onViewHiding(aEvent) {
+    this._panelMenuView.uninit();
+    delete this._panelMenuView;
+  },
+
+  onPanelMenuViewCommand: function BUI_onPanelMenuViewCommand(aEvent, aView) {
+    let target = aEvent.originalTarget;
+    if (!target._placesNode)
+      return;
+    if (PlacesUtils.nodeIsContainer(target._placesNode))
+      PlacesCommandHook.showPlacesOrganizer([ "BookmarksMenu", target._placesNode.itemId ]);
+    else
+      PlacesUIUtils.openNodeWithEvent(target._placesNode, aEvent, aView);
+    PanelUI.hide();
+  },
+
   // nsINavBookmarkObserver
   onItemAdded: function BUI_onItemAdded(aItemId, aParentId, aIndex, aItemType,
                                         aURI) {
+    if (!this.button) {
+      return;
+    }
+
     if (aURI && aURI.equals(this._uri)) {
       // If a new bookmark has been added to the tracked uri, register it.
       if (this._itemIds.indexOf(aItemId) == -1) {
         this._itemIds.push(aItemId);
         this._updateStar();
       }
     }
   },
 
   onItemRemoved: function BUI_onItemRemoved(aItemId) {
+    if (!this.button) {
+      return;
+    }
+
     let index = this._itemIds.indexOf(aItemId);
     // If one of the tracked bookmarks has been removed, unregister it.
     if (index != -1) {
       this._itemIds.splice(index, 1);
       this._updateStar();
     }
   },
 
   onItemChanged: function BUI_onItemChanged(aItemId, aProperty,
                                             aIsAnnotationProperty, aNewValue) {
+    if (!this.button) {
+      return;
+    }
+
     if (aProperty == "uri") {
       let index = this._itemIds.indexOf(aItemId);
       // If the changed bookmark was tracked, check if it is now pointing to
       // a different uri and unregister it.
       if (index != -1 && aNewValue != this._uri.spec) {
         this._itemIds.splice(index, 1);
         this._updateStar();
       }
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -27,17 +27,16 @@
     <command id="Browser:SendLink"
              oncommand="MailIntegration.sendLinkForWindow(window.content);"/>
 
     <command id="cmd_pageSetup" oncommand="PrintUtils.showPageSetup();"/>
     <command id="cmd_print" oncommand="PrintUtils.print();"/>
     <command id="cmd_printPreview" oncommand="PrintUtils.printPreview(PrintPreviewListener);"/>
     <command id="cmd_close" oncommand="BrowserCloseTabOrWindow()"/>
     <command id="cmd_closeWindow" oncommand="BrowserTryToCloseWindow()"/>
-    <command id="cmd_ToggleTabsOnTop" oncommand="TabsOnTop.toggle()"/>
     <command id="cmd_CustomizeToolbars" oncommand="BrowserCustomizeToolbar()"/>
     <command id="cmd_quitApplication" oncommand="goQuitApplication()"/>
 
 
     <commandset id="editMenuCommands"/>
 
     <command id="View:PageSource" oncommand="BrowserViewSourceOfDocument(content.document);" observes="isImage"/>
     <command id="View:PageInfo" oncommand="BrowserPageInfo();"/>
@@ -104,23 +103,23 @@
     <command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
     <command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)" disabled="true" hidden="true"/>
     <command id="Tools:Sanitize"
      oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
     <command id="Tools:PrivateBrowsing"
       oncommand="OpenBrowserWindow({private: true});"/>
     <command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
     <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
-    <command id="Browser:ToggleAddonBar" oncommand="toggleAddonBar();"/>
     <command id="Social:SharePage" oncommand="SocialShare.sharePage();" disabled="true"/>
     <command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();" hidden="true"/>
     <command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();" hidden="true"/>
     <command id="Social:FocusChat" oncommand="SocialChatBar.focus();" hidden="true" disabled="true"/>
     <command id="Social:Toggle" oncommand="Social.toggle();" hidden="true"/>
     <command id="Social:Addons" oncommand="BrowserOpenAddonsMgr('addons://list/service');"/>
+    <command id="MenuPanel:Toggle" oncommand="PanelUI.toggle(event);"/>
   </commandset>
 
   <commandset id="placesCommands">
     <command id="Browser:ShowAllBookmarks"
              oncommand="PlacesCommandHook.showPlacesOrganizer('AllBookmarks');"/>
     <command id="Browser:ShowAllHistory"
              oncommand="PlacesCommandHook.showPlacesOrganizer('History');"/>
   </commandset>
@@ -407,33 +406,38 @@
     <key id="key_quitApplication" key="&quitApplicationCmdUnix.key;" command="cmd_quitApplication" modifiers="accel"/>
 #endif
 
 #ifdef FULL_BROWSER_WINDOW
     <key id="key_undoCloseTab" command="History:UndoCloseTab" key="&tabCmd.commandkey;" modifiers="accel,shift"/>
 #endif
     <key id="key_undoCloseWindow" command="History:UndoCloseWindow" key="&newNavigatorCmd.key;" modifiers="accel,shift"/>
 
+    <key id="key_menuButton" command="MenuPanel:Toggle"
+#ifdef XP_MACOSX
+         key="&toggleMenuPanelMac.key;" modifiers="accel,shift"/>
+#else
+         key="&toggleMenuPanel.key;" modifiers="accel"/>
+#endif
+
 #ifdef XP_GNOME
 #define NUM_SELECT_TAB_MODIFIER alt
 #else
 #define NUM_SELECT_TAB_MODIFIER accel
 #endif
 
 #expand    <key id="key_selectTab1" oncommand="gBrowser.selectTabAtIndex(0, event);" key="1" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 #expand    <key id="key_selectTab2" oncommand="gBrowser.selectTabAtIndex(1, event);" key="2" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 #expand    <key id="key_selectTab3" oncommand="gBrowser.selectTabAtIndex(2, event);" key="3" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 #expand    <key id="key_selectTab4" oncommand="gBrowser.selectTabAtIndex(3, event);" key="4" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 #expand    <key id="key_selectTab5" oncommand="gBrowser.selectTabAtIndex(4, event);" key="5" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 #expand    <key id="key_selectTab6" oncommand="gBrowser.selectTabAtIndex(5, event);" key="6" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 #expand    <key id="key_selectTab7" oncommand="gBrowser.selectTabAtIndex(6, event);" key="7" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 #expand    <key id="key_selectTab8" oncommand="gBrowser.selectTabAtIndex(7, event);" key="8" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 #expand    <key id="key_selectLastTab" oncommand="gBrowser.selectTabAtIndex(-1, event);" key="9" modifiers="__NUM_SELECT_TAB_MODIFIER__"/>
 
-    <key id="key_toggleAddonBar" command="Browser:ToggleAddonBar" key="&toggleAddonBarCmd.key;" modifiers="accel"/>
-
   </keyset>
 
 # Used by baseMenuOverlay
 #ifdef XP_MACOSX
   <commandset id="baseMenuCommandSet" />
 #endif
   <keyset id="baseMenuKeyset" />
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -783,19 +783,17 @@ SocialShare = {
       }, true);
     }
     // always ensure that origin belongs to the endpoint
     let uri = Services.io.newURI(shareEndpoint, null, null);
     iframe.setAttribute("origin", provider.origin);
     iframe.setAttribute("src", shareEndpoint);
 
     let navBar = document.getElementById("nav-bar");
-    let anchor = navBar.getAttribute("mode") == "text" ?
-                   document.getAnonymousElementByAttribute(this.shareButton, "class", "toolbarbutton-text") :
-                   document.getAnonymousElementByAttribute(this.shareButton, "class", "toolbarbutton-icon");
+    let anchor = document.getAnonymousElementByAttribute(this.shareButton, "class", "toolbarbutton-icon");
     this.panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
     Social.setErrorListener(iframe, this.setErrorMessage.bind(this));
   }
 };
 
 SocialMenu = {
   populate: function SocialMenu_populate() {
     let submenu = document.getElementById("menu_social-statusarea-popup");
@@ -1109,19 +1107,17 @@ SocialToolbar = {
           setTimeout(function() {
             dispatchPanelEvent("socialFrameShow");
           }, 0);
         }, true);
       }
     });
 
     let navBar = document.getElementById("nav-bar");
-    let anchor = navBar.getAttribute("mode") == "text" ?
-                   document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-text") :
-                   document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-badge-container");
+    let anchor = document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-badge-container");
     // Bug 849216 - open the popup in a setTimeout so we avoid the auto-rollup
     // handling from preventing it being opened in some cases.
     setTimeout(function() {
       panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
     }, 0);
   },
 
   setPanelErrorMessage: function SocialToolbar_setPanelErrorMessage(aNotificationFrame) {
--- a/browser/base/content/browser-tabview.js
+++ b/browser/base/content/browser-tabview.js
@@ -413,26 +413,23 @@ let TabView = {
   _addToolbarButton: function TabView__addToolbarButton() {
     let buttonId = "tabview-button";
 
     if (document.getElementById(buttonId))
       return;
 
     let toolbar = document.getElementById("TabsToolbar");
     let currentSet = toolbar.currentSet.split(",");
-
     let alltabsPos = currentSet.indexOf("alltabs-button");
     if (-1 == alltabsPos)
       return;
 
-    currentSet[alltabsPos] += "," + buttonId;
-    currentSet = currentSet.join(",");
-    toolbar.currentSet = currentSet;
-    toolbar.setAttribute("currentset", currentSet);
-    document.persist(toolbar.id, "currentset");
+    let allTabsBtn = document.getElementById("alltabs-button");
+    let nextItem = allTabsBtn.nextSibling;
+    toolbar.insertItem(buttonId, nextItem);
   },
 
   // ----------
   // Function: updateGroupNumberBroadcaster
   // Updates the group number broadcaster.
   updateGroupNumberBroadcaster: function TabView_updateGroupNumberBroadcaster(number) {
     let groupsNumber = document.getElementById("tabviewGroupsNumber");
     groupsNumber.setAttribute("groups", number);
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -16,16 +16,73 @@
 searchbar {
   -moz-binding: url("chrome://browser/content/search/search.xml#searchbar");
 }
 
 .browserStack > browser[remote="true"] {
   -moz-binding: url("chrome://global/content/bindings/remote-browser.xml#remote-browser");
 }
 
+toolbar[customizable="true"] {
+  -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar");
+}
+
+%ifdef XP_MACOSX
+#toolbar-menubar {
+  -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-menubar-stub");
+}
+
+toolbar[customizable="true"]:not([nowindowdrag="true"]) {
+  -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-drag");
+}
+%endif
+
+#toolbar-menubar[autohide="true"] {
+  -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-menubar-autohide");
+}
+
+#addon-bar {
+  -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#addonbar-delegating");
+  visibility: visible;
+  margin: 0;
+  height: 0 !important;
+  overflow: hidden;
+  padding: 0;
+  border: 0 none;
+}
+
+#addonbar-closebutton {
+  visibility: visible;
+  height: 0 !important;
+}
+
+#status-bar {
+  height: 0 !important;
+  -moz-binding: none;
+  padding: 0;
+  margin: 0;
+}
+
+panelmultiview {
+  -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelmultiview");
+}
+
+panelview {
+  -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelview");
+  -moz-box-orient: vertical;
+}
+
+.panel-mainview {
+  transition: transform 150ms;
+}
+
+panelview:not([mainview]):not([current]) {
+  display: none;
+}
+
 tabbrowser {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
 }
 
 .tabbrowser-tabs {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs");
 }
 
@@ -42,31 +99,29 @@ tabbrowser {
 }
 
 .tabbrowser-tab {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab");
 }
 
 .tabbrowser-tab:not([pinned]) {
   -moz-box-flex: 100;
-  max-width: 250px;
+  max-width: 180px;
   min-width: 100px;
   width: 0;
   transition: min-width 200ms ease-out,
-              max-width 250ms ease-out,
-              opacity 50ms ease-out 20ms /* hide the tab for the first 20ms of the max-width transition */;
+              max-width 230ms ease-out;
 }
 
 .tabbrowser-tab:not([pinned]):not([fadein]) {
   max-width: 0.1px;
   min-width: 0.1px;
-  opacity: 0 !important;
+  visibility: hidden;
   transition: min-width 200ms ease-out,
-              max-width 250ms ease-out,
-              opacity 50ms ease-out 180ms /* hide the tab for the last 20ms of the max-width transition */;
+              max-width 230ms ease-out;
 }
 
 .tab-throbber:not([fadein]):not([pinned]),
 .tab-label:not([fadein]):not([pinned]),
 .tab-icon-image:not([fadein]):not([pinned]),
 .tab-close-button:not([fadein]):not([pinned]) {
   display: none;
 }
@@ -89,30 +144,23 @@ tabbrowser {
 #alltabs-popup {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
 }
 
 toolbar[printpreview="true"] {
   -moz-binding: url("chrome://global/content/printPreviewBindings.xml#printpreviewtoolbar");
 }
 
-#toolbar-menubar {
-  -moz-box-ordinal-group: 5;
+toolbar[overflowable] > .customization-target {
+  overflow: hidden;
 }
 
-#navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
-  -moz-box-ordinal-group: 50;
-}
-
-#TabsToolbar {
-  -moz-box-ordinal-group: 100;
-}
-
-#TabsToolbar[tabsontop="true"] {
-  -moz-box-ordinal-group: 10;
+toolbar:not([overflowing]) > .overflow-button,
+toolbar[customizing] > .overflow-button {
+  display: none;
 }
 
 %ifdef CAN_DRAW_IN_TITLEBAR
 #main-window[inFullscreen] > #titlebar,
 #main-window[inFullscreen] .titlebar-placeholder,
 #main-window:not([tabsintitlebar]) .titlebar-placeholder {
   display: none;
 }
@@ -120,53 +168,75 @@ toolbar[printpreview="true"] {
 #titlebar {
   -moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox");
 }
 
 #titlebar-spacer {
   pointer-events: none;
 }
 
-#main-window[tabsintitlebar] #appmenu-button-container,
 #main-window[tabsintitlebar] #titlebar-buttonbox {
   position: relative;
 }
+
+#titlebar-buttonbox {
+  -moz-appearance: -moz-window-button-box;
+}
+
+%ifdef XP_MACOSX
+#titlebar-fullscreen-button {
+  -moz-appearance: -moz-mac-fullscreen-button;
+}
 %endif
 
-.bookmarks-toolbar-customize,
-#wrapper-personal-bookmarks > #personal-bookmarks > #PlacesToolbar > hbox > #PlacesToolbarItems {
+%ifdef XP_WIN
+#main-window[sizemode="maximized"] #titlebar-buttonbox {
+  -moz-appearance: -moz-window-button-box-maximized;
+}
+%endif
+
+%endif
+
+#bookmarks-toolbar-placeholder,
+toolbarpaletteitem > #personal-bookmarks > #PlacesToolbar,
+#personal-bookmarks[customizableui-areatype="menu-panel"] > #PlacesToolbar,
+#personal-bookmarks[customizableui-areatype="toolbar"].overflowedItem > #PlacesToolbar {
   display: none;
 }
 
-#wrapper-personal-bookmarks[place="toolbar"] > #personal-bookmarks > #PlacesToolbar > .bookmarks-toolbar-customize {
+toolbarpaletteitem > #personal-bookmarks > #bookmarks-toolbar-placeholder,
+#personal-bookmarks[customizableui-areatype="menu-panel"] > #bookmarks-toolbar-placeholder,
+#personal-bookmarks[customizableui-areatype="toolbar"].overflowedItem > #bookmarks-toolbar-placeholder {
   display: -moz-box;
 }
 
-#main-window[disablechrome] #navigator-toolbox[tabsontop="true"] > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
+#wrapper-urlbar-container > #urlbar-container > #urlbar-wrapper > #urlbar > toolbarbutton,
+#urlbar-reload-button:not([displaystop]) + #urlbar-stop-button,
+#urlbar-reload-button[displaystop] {
   visibility: collapse;
 }
 
-#wrapper-urlbar-container #urlbar-container > #urlbar > toolbarbutton,
-#urlbar-container:not([combined]) > #urlbar > toolbarbutton,
-#urlbar-container[combined] + #reload-button + #stop-button,
-#urlbar-container[combined] + #reload-button,
-toolbar:not([mode="icons"]) > #urlbar-container > #urlbar > toolbarbutton,
-toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button:not([displaystop]) + #urlbar-stop-button,
-toolbar[mode="icons"] > #urlbar-container > #urlbar > #urlbar-reload-button[displaystop],
-toolbar[mode="icons"] > #reload-button:not([displaystop]) + #stop-button,
-toolbar[mode="icons"] > #reload-button[displaystop] {
-  visibility: collapse;
+#PanelUI-feeds > .feed-toolbarbutton:-moz-locale-dir(rtl) {
+  direction: rtl;
 }
 
-#feed-button > .toolbarbutton-menu-dropmarker {
-  display: none;
+#panelMenu_bookmarksMenu {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+#panelMenu_bookmarksMenu > .bookmark-item {
+  max-width: none;
 }
 
-#feed-menu > .feed-menuitem:-moz-locale-dir(rtl) {
-  direction: rtl;
+#urlbar-container {
+  min-width: 50ch;
+}
+
+#search-container {
+  min-width: 25ch;
 }
 
 #main-window:-moz-lwtheme {
   background-repeat: no-repeat;
   background-position: top right;
 }
 
 %ifdef XP_MACOSX
@@ -175,59 +245,26 @@ toolbar[mode="icons"] > #reload-button[d
 }
 %endif
 
 #browser-bottombox[lwthemefooter="true"] {
   background-repeat: no-repeat;
   background-position: bottom left;
 }
 
-splitmenu {
-  -moz-binding: url("chrome://browser/content/urlbarBindings.xml#splitmenu");
-}
-
-.splitmenu-menuitem {
-  -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem");
-  list-style-image: inherit;
-  -moz-image-region: inherit;
-}
-
-.splitmenu-menuitem[iconic="true"] {
-  -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
-}
-
-.splitmenu-menu > .menu-text,
-:-moz-any(.splitmenu-menu, .splitmenu-menuitem) > .menu-accel-container,
-#appmenu-editmenu > .menu-text,
-#appmenu-editmenu > .menu-accel-container {
-  display: none;
-}
-
 .menuitem-tooltip {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-tooltip");
 }
 
 .menuitem-iconic-tooltip,
 .menuitem-tooltip[type="checkbox"],
 .menuitem-tooltip[type="radio"] {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#menuitem-iconic-tooltip");
 }
 
-%ifdef MENUBAR_CAN_AUTOHIDE
-%ifndef CAN_DRAW_IN_TITLEBAR
-#appmenu-toolbar-button > .toolbarbutton-text {
-  display: -moz-box;
-}
-%endif
-
-#appmenu_offlineModeRecovery:not([checked=true]) {
-  display: none;
-}
-%endif
-
 /* Hide menu elements intended for keyboard access support */
 #main-menubar[openedwithkey=false] .show-only-for-keyboard {
   display: none;
 }
 
 /* ::::: location bar ::::: */
 #urlbar {
   -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
@@ -252,32 +289,30 @@ panel[noactions] > richlistbox > richlis
 panel[noactions] > richlistbox > richlistitem[type~="action"] > .ac-url-box > .ac-url > .ac-url-text {
   visibility: visible;
 }
 
 #urlbar:not([actiontype]) > #urlbar-display-box {
   display: none;
 }
 
-#wrapper-urlbar-container > #urlbar-container > #urlbar {
+#wrapper-urlbar-container > #urlbar-container > #urlbar-wrapper > #urlbar {
   -moz-user-input: disabled;
   cursor: -moz-grab;
 }
 
 #PopupAutoComplete {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup");
 }
 
 #PopupAutoCompleteRichResult {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-rich-result-popup");
 }
 
-#urlbar-container[combined] > #urlbar > #urlbar-icons > #go-button,
-#urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon:not(#go-button),
-#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button,
+#urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon,
 #urlbar[pageproxystate="invalid"][focused="true"] > #urlbar-go-button ~ toolbarbutton,
 #urlbar[pageproxystate="valid"] > #urlbar-go-button,
 #urlbar:not([focused="true"]) > #urlbar-go-button {
   visibility: collapse;
 }
 
 #urlbar[pageproxystate="invalid"] > #identity-box > #identity-icon-labels {
   visibility: collapse;
@@ -311,28 +346,30 @@ panel[noactions] > richlistbox > richlis
 .unified-nav-current {
   font-weight: bold;
 }
 
 toolbarbutton.bookmark-item {
   max-width: 13em;
 }
 
-%ifdef MENUBAR_CAN_AUTOHIDE
-#toolbar-menubar:not([autohide="true"]) ~ toolbar > #bookmarks-menu-button,
-#toolbar-menubar:not([autohide="true"]) > #bookmarks-menu-button {
-  display: none;
-}
-%endif
-
 #editBMPanel_tagsSelector {
   /* override default listbox width from xul.css */
   width: auto;
 }
 
+/* The star doesn't make sense as text */
+toolbar[mode="text"] #bookmarks-menu-button > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
+  display: -moz-box !important;
+}
+toolbar[mode="text"] #bookmarks-menu-button > .toolbarbutton-menubutton-button > .toolbarbutton-text,
+toolbar[mode="full"] #bookmarks-menu-button.bookmark-item > .toolbarbutton-menubutton-button > .toolbarbutton-text {
+  display: none;
+}
+
 menupopup[emptyplacesresult="true"] > .hide-if-empty-places-result {
   display: none;
 }
 
 menuitem.spell-suggestion {
   font-weight: bold;
 }
 
@@ -347,17 +384,16 @@ window[sizemode="maximized"] #content .n
 
 /* Hide extension toolbars that neglected to set the proper class */
 window[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar),
 window[chromehidden~="toolbar"] toolbar:not(.toolbar-primary):not(.chromeclass-menubar) {
   display: none;
 }
 
 #navigator-toolbox ,
-#status-bar ,
 #mainPopupSet {
   min-width: 1px;
 }
 
 %ifdef MOZ_SERVICES_SYNC
 /* Sync notification UI */
 #sync-notifications {
   -moz-binding: url("chrome://browser/content/sync/notification.xml#notificationbox");
@@ -446,24 +482,16 @@ window[chromehidden~="toolbar"] toolbar:
 
 #full-screen-domain-text,
 #full-screen-remember-decision > .checkbox-label-box > .checkbox-label {
   word-wrap: break-word;
   /* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */
   min-width: 1px;
 }
 
-#nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-icon {
-  display: -moz-box;
-}
-
-#nav-bar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-text {
-  display: none;
-}
-
 /* ::::: Ctrl-Tab Panel ::::: */
 
 .ctrlTab-preview > html|img,
 .ctrlTab-preview > html|canvas {
   min-width: inherit;
   max-width: inherit;
   min-height: inherit;
   max-height: inherit;
@@ -518,27 +546,16 @@ window[chromehidden~="toolbar"] toolbar:
 #click-to-play-plugins-notification {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
 }
 
 .plugin-popupnotification-centeritem {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#plugin-popupnotification-center-item");
 }
 
-/* override hidden="true" for the status bar compatibility shim
-   in case it was persisted for the real status bar */
-#status-bar {
-  display: -moz-box;
-}
-
-/* Remove the resizer from the statusbar compatibility shim */
-#status-bar[hideresizer] > .statusbar-resizerpanel {
-  display: none;
-}
-
 browser[tabmodalPromptShowing] {
   -moz-user-focus: none !important;
 }
 
 /* Status panel */
 
 statuspanel {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#statuspanel");
@@ -731,8 +748,19 @@ chatbox:-moz-full-screen-ancestor > .cha
   font-weight: bold;
   /* color: menutext used to overwrite the disabled color */
   color: menutext;
 }
 
 .contentSelectDropdown-ingroup {
   -moz-margin-start: 2em;
 }
+
+/* Give this menupopup an arrow panel styling */
+#BMB_bookmarksPopup {
+  -moz-appearance: none;
+  -moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-arrow");
+  background: transparent;
+  border: none;
+  transition: opacity 300ms;
+  /* The popup inherits -moz-image-region from the button, must reset it */
+  -moz-image-region: auto;
+}
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -79,16 +79,22 @@ this.__defineGetter__("PluralForm", func
 this.__defineSetter__("PluralForm", function (val) {
   delete this.PluralForm;
   return this.PluralForm = val;
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
   "resource://gre/modules/TelemetryStopwatch.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "gCustomizeMode", function() {
+  let scope = {};
+  Cu.import("resource:///modules/CustomizeMode.jsm", scope);
+  return new scope.CustomizeMode(window);
+});
+
 #ifdef MOZ_SERVICES_SYNC
 XPCOMUtils.defineLazyModuleGetter(this, "Weave",
   "resource://services-sync/main.js");
 #endif
 
 XPCOMUtils.defineLazyGetter(this, "PopupNotifications", function () {
   let tmp = {};
   Cu.import("resource://gre/modules/PopupNotifications.jsm", tmp);
@@ -147,16 +153,17 @@ let gInitialPages = [
   "about:newtab",
   "about:home",
   "about:privatebrowsing",
   "about:welcomeback",
   "about:sessionrestore"
 ];
 
 #include browser-addons.js
+#include browser-customization.js
 #include browser-feeds.js
 #include browser-fullScreen.js
 #include browser-fullZoom.js
 #include browser-places.js
 #include browser-plugins.js
 #include browser-safebrowsing.js
 #include browser-social.js
 #include browser-tabPreviews.js
@@ -309,39 +316,32 @@ function SetClickAndHoldHandlers() {
     }
   }
 
   function _addClickAndHoldListenersOnElement(aElm) {
     aElm.addEventListener("mousedown", mousedownHandler, true);
     aElm.addEventListener("click", clickHandler, true);
   }
 
-  // Bug 414797: Clone unified-back-forward-button's context menu into both the
-  // back and the forward buttons.
-  var unifiedButton = document.getElementById("unified-back-forward-button");
-  if (unifiedButton && !unifiedButton._clickHandlersAttached) {
-    unifiedButton._clickHandlersAttached = true;
-
-    let popup = document.getElementById("backForwardMenu").cloneNode(true);
-    popup.removeAttribute("id");
-    // Prevent the context attribute on unified-back-forward-button from being
-    // inherited.
-    popup.setAttribute("context", "");
-
-    let backButton = document.getElementById("back-button");
-    backButton.setAttribute("type", "menu");
-    backButton.appendChild(popup);
-    _addClickAndHoldListenersOnElement(backButton);
-
-    let forwardButton = document.getElementById("forward-button");
-    popup = popup.cloneNode(true);
-    forwardButton.setAttribute("type", "menu");
-    forwardButton.appendChild(popup);
-    _addClickAndHoldListenersOnElement(forwardButton);
-  }
+  // Bug 414797: Clone the back/forward buttons' context menu into both buttons.
+  let popup = document.getElementById("backForwardMenu").cloneNode(true);
+  popup.removeAttribute("id");
+  // Prevent the back/forward buttons' context attributes from being inherited.
+  popup.setAttribute("context", "");
+
+  let backButton = document.getElementById("back-button");
+  backButton.setAttribute("type", "menu");
+  backButton.appendChild(popup);
+  _addClickAndHoldListenersOnElement(backButton);
+
+  let forwardButton = document.getElementById("forward-button");
+  popup = popup.cloneNode(true);
+  forwardButton.setAttribute("type", "menu");
+  forwardButton.appendChild(popup);
+  _addClickAndHoldListenersOnElement(forwardButton);
 }
 
 const gSessionHistoryObserver = {
   observe: function(subject, topic, data)
   {
     if (topic != "browser:purge-session-history")
       return;
 
@@ -917,38 +917,29 @@ var gBrowserInit = {
         // border.  Use 28px as a guess (titlebar + bottom window border)
         defaultHeight -= 28;
 #endif
       }
       document.documentElement.setAttribute("width", defaultWidth);
       document.documentElement.setAttribute("height", defaultHeight);
     }
 
-    if (!gShowPageResizers)
-      document.getElementById("status-bar").setAttribute("hideresizer", "true");
-
     if (!window.toolbar.visible) {
       // adjust browser UI for popups
       if (gURLBar) {
         gURLBar.setAttribute("readonly", "true");
         gURLBar.setAttribute("enablehistory", "false");
       }
       goSetCommandEnabled("cmd_newNavigatorTab", false);
     }
 
-#ifdef MENUBAR_CAN_AUTOHIDE
-    updateAppButtonDisplay();
-#endif
-
     // Misc. inits.
     CombinedStopReload.init();
-    TabsOnTop.init();
     gPrivateBrowsingUI.init();
     TabsInTitlebar.init();
-    retrieveToolbarIconsizesFromTheme();
 
     // Wait until chrome is painted before executing code not critical to making the window visible
     this._boundDelayedStartup = this._delayedStartup.bind(this, mustLoadSidebar);
     window.addEventListener("MozAfterPaint", this._boundDelayedStartup);
 
     this._loadHandled = true;
   },
 
@@ -1040,17 +1031,22 @@ var gBrowserInit = {
     Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
     Services.obs.addObserver(gFormSubmitObserver, "invalidformsubmit", false);
 
     BrowserOffline.init();
     OfflineApps.init();
     IndexedDBPromptHelper.init();
     gFormSubmitObserver.init();
     SocialUI.init();
-    AddonManager.addAddonListener(AddonsMgrListener);
+
+    // Initialize the full zoom setting.
+    // We do this before the session restore service gets initialized so we can
+    // apply full zoom settings to tabs restored by the session restore service.
+    FullZoom.init();
+    LightweightThemeListener.init();
     WebrtcIndicator.init();
 
     // Ensure login manager is up and running.
     Services.logins;
 
 #ifdef MOZ_CRASHREPORTER
     if (gMultiProcessBrowser)
       TabCrashReporter.init();
@@ -1091,21 +1087,16 @@ var gBrowserInit = {
       document.getElementById("textfieldDirection-swap").hidden = false;
     }
 
     // Setup click-and-hold gestures access to the session history
     // menus if global click-and-hold isn't turned on
     if (!getBoolPref("ui.click_hold_context_menus", false))
       SetClickAndHoldHandlers();
 
-    // Initialize the full zoom setting.
-    // We do this before the session restore service gets initialized so we can
-    // apply full zoom settings to tabs restored by the session restore service.
-    FullZoom.init();
-
     // Bug 666804 - NetworkPrioritizer support for e10s
     if (!gMultiProcessBrowser) {
       let NP = {};
       Cu.import("resource:///modules/NetworkPrioritizer.jsm", NP);
       NP.trackBrowserWindow(window);
     }
 
     PlacesToolbarHelper.init();
@@ -1177,54 +1168,25 @@ var gBrowserInit = {
 #endif
 
 #ifdef MOZ_DATA_REPORTING
     gDataNotificationInfoBar.init();
 #endif
 
     gBrowserThumbnails.init();
 
-    setUrlAndSearchBarWidthForConditionalForwardButton();
-    window.addEventListener("resize", function resizeHandler(event) {
-      if (event.target == window)
-        setUrlAndSearchBarWidthForConditionalForwardButton();
-    });
-
-#ifdef MENUBAR_CAN_AUTOHIDE
-    // If the user (or the locale) hasn't enabled the top-level "Character
-    // Encoding" menu via the "browser.menu.showCharacterEncoding" preference,
-    // hide it.
-    if ("true" != gPrefService.getComplexValue("browser.menu.showCharacterEncoding",
-                                               Ci.nsIPrefLocalizedString).data)
-      document.getElementById("appmenu_charsetMenu").hidden = true;
-#endif
-
     // Add Devtools menuitems and listeners
     gDevToolsBrowser.registerBrowserWindow(window);
 
-    let appMenuButton = document.getElementById("appmenu-button");
-    let appMenuPopup = document.getElementById("appmenu-popup");
-    if (appMenuButton && appMenuPopup) {
-      let appMenuOpening = null;
-      appMenuButton.addEventListener("mousedown", function(event) {
-        if (event.button == 0)
-          appMenuOpening = new Date();
-      }, false);
-      appMenuPopup.addEventListener("popupshown", function(event) {
-        if (event.target != appMenuPopup || !appMenuOpening)
-          return;
-        let duration = new Date() - appMenuOpening;
-        appMenuOpening = null;
-        Services.telemetry.getHistogramById("FX_APP_MENU_OPEN_MS").add(duration);
-      }, false);
-    }
-
     window.addEventListener("mousemove", MousePosTracker, false);
     window.addEventListener("dragover", MousePosTracker, false);
 
+    gNavToolbox.addEventListener("customizationstarting", CustomizationHandler);
+    gNavToolbox.addEventListener("customizationending", CustomizationHandler);
+
     // End startup crash tracking after a delay to catch crashes while restoring
     // tabs and to postpone saving the pref to disk.
     try {
       const startupCrashEndDelay = 30 * 1000;
       setTimeout(Services.startup.trackStartupCrashEnd, startupCrashEndDelay);
     } catch (ex) {
       Cu.reportError("Could not end startup crash tracking: " + ex);
     }
@@ -1315,18 +1277,16 @@ var gBrowserInit = {
     try {
       gBrowser.removeProgressListener(window.XULBrowserWindow);
       gBrowser.removeTabsProgressListener(window.TabsProgressListener);
     } catch (ex) {
     }
 
     BookmarkingUI.uninit();
 
-    TabsOnTop.uninit();
-
     TabsInTitlebar.uninit();
 
     var enumerator = Services.wm.getEnumerator(null);
     enumerator.getNext();
     if (!enumerator.hasMoreElements()) {
       document.persist("sidebar-box", "sidebarcommand");
       document.persist("sidebar-box", "width");
       document.persist("sidebar-box", "src");
@@ -1367,18 +1327,19 @@ var gBrowserInit = {
         Services.prefs.removeObserver(prefName, gMetroPrefs);
       });
 #endif
 #endif
 
       BrowserOffline.uninit();
       OfflineApps.uninit();
       IndexedDBPromptHelper.uninit();
-      AddonManager.removeAddonListener(AddonsMgrListener);
       SocialUI.uninit();
+      LightweightThemeListener.uninit();
+      PanelUI.uninit();
     }
 
     // Final window teardown, do this last.
     window.XULBrowserWindow = null;
     window.QueryInterface(Ci.nsIInterfaceRequestor)
           .getInterface(Ci.nsIWebNavigation)
           .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
           .QueryInterface(Ci.nsIInterfaceRequestor)
@@ -1393,17 +1354,17 @@ var gBrowserInit = {
   // macBrowserOverlay
   nonBrowserWindowStartup: function() {
     // Disable inappropriate commands / submenus
     var disabledItems = ['Browser:SavePage',
                          'Browser:SendLink', 'cmd_pageSetup', 'cmd_print', 'cmd_find', 'cmd_findAgain',
                          'viewToolbarsMenu', 'viewSidebarMenuMenu', 'Browser:Reload',
                          'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen',
                          'viewHistorySidebar', 'Browser:AddBookmarkAs', 'Browser:BookmarkAllTabs',
-                         'View:PageInfo', 'Browser:ToggleTabView', 'Browser:ToggleAddonBar'];
+                         'View:PageInfo', 'Browser:ToggleTabView'];
     var element;
 
     for (let disabledItem of disabledItems) {
       element = document.getElementById(disabledItem);
       if (element)
         element.setAttribute("disabled", "true");
     }
 
@@ -2192,60 +2153,47 @@ function losslessDecodeURI(aURI) {
   return value;
 }
 
 function UpdateUrlbarSearchSplitterState()
 {
   var splitter = document.getElementById("urlbar-search-splitter");
   var urlbar = document.getElementById("urlbar-container");
   var searchbar = document.getElementById("search-container");
-  var stop = document.getElementById("stop-button");
+
+  // If the splitter is already in the right place, we don't need to do anything:
+  if (splitter &&
+      ((splitter.nextSibling == searchbar && splitter.previousSibling == urlbar) ||
+       (splitter.nextSibling == urlbar && splitter.previousSibling == searchbar))) {
+    return;
+  }
 
   var ibefore = null;
   if (urlbar && searchbar) {
-    if (urlbar.nextSibling == searchbar ||
-        urlbar.getAttribute("combined") &&
-        stop && stop.nextSibling == searchbar)
+    if (urlbar.nextSibling == searchbar)
       ibefore = searchbar;
     else if (searchbar.nextSibling == urlbar)
       ibefore = urlbar;
   }
 
   if (ibefore) {
     if (!splitter) {
       splitter = document.createElement("splitter");
       splitter.id = "urlbar-search-splitter";
       splitter.setAttribute("resizebefore", "flex");
       splitter.setAttribute("resizeafter", "flex");
       splitter.setAttribute("skipintoolbarset", "true");
+      splitter.setAttribute("overflows", "false");
       splitter.className = "chromeclass-toolbar-additional";
     }
     urlbar.parentNode.insertBefore(splitter, ibefore);
   } else if (splitter)
     splitter.parentNode.removeChild(splitter);
 }
 
-function setUrlAndSearchBarWidthForConditionalForwardButton() {
-  // Workaround for bug 694084: Showing/hiding the conditional forward button resizes
-  // the search bar when the url/search bar splitter hasn't been used.
-  var urlbarContainer = document.getElementById("urlbar-container");
-  var searchbarContainer = document.getElementById("search-container");
-  if (!urlbarContainer ||
-      !searchbarContainer ||
-      urlbarContainer.hasAttribute("width") ||
-      searchbarContainer.hasAttribute("width") ||
-      urlbarContainer.parentNode != searchbarContainer.parentNode)
-    return;
-  urlbarContainer.style.width = searchbarContainer.style.width = "";
-  var urlbarWidth = urlbarContainer.clientWidth;
-  var searchbarWidth = searchbarContainer.clientWidth;
-  urlbarContainer.style.width = urlbarWidth + "px";
-  searchbarContainer.style.width = searchbarWidth + "px";
-}
-
 function UpdatePageProxyState()
 {
   if (gURLBar && gURLBar.value != gLastValidURLStr)
     SetPageProxyState("invalid");
 }
 
 function SetPageProxyState(aState)
 {
@@ -2639,35 +2587,30 @@ var PrintPreviewListener = {
     if (gInPrintPreviewMode)
       this._hideChrome();
     else
       this._showChrome();
 
     if (this._chromeState.sidebarOpen)
       toggleSidebar(this._sidebarCommand);
 
-#ifdef MENUBAR_CAN_AUTOHIDE
-    updateAppButtonDisplay();
-#endif
+    TabsInTitlebar.allowedBy("print-preview", !gInPrintPreviewMode);
   },
   _hideChrome: function () {
     this._chromeState = {};
 
     var sidebar = document.getElementById("sidebar-box");
     this._chromeState.sidebarOpen = !sidebar.hidden;
     this._sidebarCommand = sidebar.getAttribute("sidebarcommand");
 
     var notificationBox = gBrowser.getNotificationBox();
     this._chromeState.notificationsOpen = !notificationBox.notificationsHidden;
     notificationBox.notificationsHidden = true;
 
     document.getElementById("sidebar").setAttribute("src", "about:blank");
-    var addonBar = document.getElementById("addon-bar");
-    this._chromeState.addonBarOpen = !addonBar.collapsed;
-    addonBar.collapsed = true;
     gBrowser.updateWindowResizers();
 
     this._chromeState.findOpen = gFindBarInitialized && !gFindBar.hidden;
     if (gFindBarInitialized)
       gFindBar.close();
 
     var globalNotificationBox = document.getElementById("global-notificationbox");
     this._chromeState.globalNotificationsOpen = !globalNotificationBox.notificationsHidden;
@@ -2679,21 +2622,16 @@ var PrintPreviewListener = {
       this._chromeState.syncNotificationsOpen = !syncNotifications.notificationsHidden;
       syncNotifications.notificationsHidden = true;
     }
   },
   _showChrome: function () {
     if (this._chromeState.notificationsOpen)
       gBrowser.getNotificationBox().notificationsHidden = false;
 
-    if (this._chromeState.addonBarOpen) {
-      document.getElementById("addon-bar").collapsed = false;
-      gBrowser.updateWindowResizers();
-    }
-
     if (this._chromeState.findOpen)
       gFindBar.open();
 
     if (this._chromeState.globalNotificationsOpen)
       document.getElementById("global-notificationbox").notificationsHidden = false;
 
     if (this._chromeState.syncNotificationsOpen)
       document.getElementById("sync-notifications").notificationsHidden = false;
@@ -2760,45 +2698,16 @@ function openHomeDialog(aURL)
       gPrefService.setComplexValue("browser.startup.homepage",
                                    Components.interfaces.nsISupportsString, str);
     } catch (ex) {
       dump("Failed to set the home page.\n"+ex+"\n");
     }
   }
 }
 
-var bookmarksButtonObserver = {
-  onDrop: function (aEvent)
-  {
-    let name = { };
-    let url = browserDragAndDrop.drop(aEvent, name);
-    try {
-      PlacesUIUtils.showBookmarkDialog({ action: "add"
-                                       , type: "bookmark"
-                                       , uri: makeURI(url)
-                                       , title: name
-                                       , hiddenRows: [ "description"
-                                                     , "location"
-                                                     , "loadInSidebar"
-                                                     , "keyword" ]
-                                       }, window);
-    } catch(ex) { }
-  },
-
-  onDragOver: function (aEvent)
-  {
-    browserDragAndDrop.dragOver(aEvent);
-    aEvent.dropEffect = "link";
-  },
-
-  onDragExit: function (aEvent)
-  {
-  }
-}
-
 var newTabButtonObserver = {
   onDragOver: function (aEvent)
   {
     browserDragAndDrop.dragOver(aEvent);
   },
 
   onDragExit: function (aEvent)
   {
@@ -3306,163 +3215,28 @@ function OpenBrowserWindow(options)
   else // forget about the charset information.
   {
     win = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no" + extraFeatures, defaultArgs);
   }
 
   return win;
 }
 
-var gCustomizeSheet = false;
+//XXXunf Are these still useful to keep around?
 function BrowserCustomizeToolbar() {
-  // Disable the toolbar context menu items
-  var menubar = document.getElementById("main-menubar");
-  for (let childNode of menubar.childNodes)
-    childNode.setAttribute("disabled", true);
-
-  var cmd = document.getElementById("cmd_CustomizeToolbars");
-  cmd.setAttribute("disabled", "true");
-
-  var splitter = document.getElementById("urlbar-search-splitter");
-  if (splitter)
-    splitter.parentNode.removeChild(splitter);
-
-  CombinedStopReload.uninit();
-
-  PlacesToolbarHelper.customizeStart();
-  BookmarkingUI.customizeStart();
-  DownloadsButton.customizeStart();
-
-  TabsInTitlebar.allowedBy("customizing-toolbars", false);
-
-  var customizeURL = "chrome://global/content/customizeToolbar.xul";
-  gCustomizeSheet = getBoolPref("toolbar.customization.usesheet", false);
-
-  if (gCustomizeSheet) {
-    let sheetFrame = document.createElement("iframe");
-    let panel = document.getElementById("customizeToolbarSheetPopup");
-    sheetFrame.id = "customizeToolbarSheetIFrame";
-    sheetFrame.toolbox = gNavToolbox;
-    sheetFrame.panel = panel;
-    sheetFrame.setAttribute("style", panel.getAttribute("sheetstyle"));
-    panel.appendChild(sheetFrame);
-
-    // Open the panel, but make it invisible until the iframe has loaded so
-    // that the user doesn't see a white flash.
-    panel.style.visibility = "hidden";
-    gNavToolbox.addEventListener("beforecustomization", function onBeforeCustomization() {
-      gNavToolbox.removeEventListener("beforecustomization", onBeforeCustomization, false);
-      panel.style.removeProperty("visibility");
-    }, false);
-
-    sheetFrame.setAttribute("src", customizeURL);
-
-    panel.openPopup(gNavToolbox, "after_start", 0, 0);
-  } else {
-    window.openDialog(customizeURL,
-                      "CustomizeToolbar",
-                      "chrome,titlebar,toolbar,location,resizable,dependent",
-                      gNavToolbox);
-  }
+  gCustomizeMode.enter();
 }
 
 function BrowserToolboxCustomizeDone(aToolboxChanged) {
-  if (gCustomizeSheet) {
-    document.getElementById("customizeToolbarSheetPopup").hidePopup();
-    let iframe = document.getElementById("customizeToolbarSheetIFrame");
-    iframe.parentNode.removeChild(iframe);
-  }
-
-  // Update global UI elements that may have been added or removed
-  if (aToolboxChanged) {
-    gURLBar = document.getElementById("urlbar");
-
-    gProxyFavIcon = document.getElementById("page-proxy-favicon");
-    gHomeButton.updateTooltip();
-    gIdentityHandler._cacheElements();
-    window.XULBrowserWindow.init();
-
-#ifndef XP_MACOSX
-    updateEditUIVisibility();
-#endif
-
-    // Hacky: update the PopupNotifications' object's reference to the iconBox,
-    // if it already exists, since it may have changed if the URL bar was
-    // added/removed.
-    if (!window.__lookupGetter__("PopupNotifications"))
-      PopupNotifications.iconBox = document.getElementById("notification-popup-box");
-  }
-
-  PlacesToolbarHelper.customizeDone();
-  BookmarkingUI.customizeDone();
-  DownloadsButton.customizeDone();
-
-  // The url bar splitter state is dependent on whether stop/reload
-  // and the location bar are combined, so we need this ordering
-  CombinedStopReload.init();
-  UpdateUrlbarSearchSplitterState();
-  setUrlAndSearchBarWidthForConditionalForwardButton();
-
-  // Update the urlbar
-  if (gURLBar) {
-    URLBarSetURI();
-    XULBrowserWindow.asyncUpdateUI();
-    BookmarkingUI.updateStarState();
-    SocialUI.updateState();
-  }
-
-  TabsInTitlebar.allowedBy("customizing-toolbars", true);
-
-  // Re-enable parts of the UI we disabled during the dialog
-  var menubar = document.getElementById("main-menubar");
-  for (let childNode of menubar.childNodes)
-    childNode.setAttribute("disabled", false);
-  var cmd = document.getElementById("cmd_CustomizeToolbars");
-  cmd.removeAttribute("disabled");
-
-  // make sure to re-enable click-and-hold
-  if (!getBoolPref("ui.click_hold_context_menus", false))
-    SetClickAndHoldHandlers();
-
-  gBrowser.selectedBrowser.focus();
+  gCustomizeMode.exit(aToolboxChanged);
 }
 
 function BrowserToolboxCustomizeChange(aType) {
-  switch (aType) {
-    case "iconsize":
-    case "mode":
-      retrieveToolbarIconsizesFromTheme();
-      break;
-    default:
-      gHomeButton.updatePersonalToolbarStyle();
-      BookmarkingUI.customizeChange();
-  }
-}
-
-/**
- * Allows themes to override the "iconsize" attribute on toolbars.
- */
-function retrieveToolbarIconsizesFromTheme() {
-  function retrieveToolbarIconsize(aToolbar) {
-    if (aToolbar.localName != "toolbar")
-      return;
-
-    // The theme indicates that it wants to override the "iconsize" attribute
-    // by specifying a special value for the "counter-reset" property on the
-    // toolbar. A custom property cannot be used because getComputedStyle can
-    // only return the values of standard CSS properties.
-    let counterReset = getComputedStyle(aToolbar).counterReset;
-    if (counterReset == "smallicons 0")
-      aToolbar.setAttribute("iconsize", "small");
-    else if (counterReset == "largeicons 0")
-      aToolbar.setAttribute("iconsize", "large");
-  }
-
-  Array.forEach(gNavToolbox.childNodes, retrieveToolbarIconsize);
-  gNavToolbox.externalToolbars.forEach(retrieveToolbarIconsize);
+  gHomeButton.updatePersonalToolbarStyle();
+  BookmarksMenuButton.customizeChange();
 }
 
 /**
  * Update the global flag that tracks whether or not any edit UI (the Edit menu,
  * edit-related items in the context menu, and edit-related toolbar buttons
  * is visible, then update the edit commands' enabled state accordingly.  We use
  * this flag to skip updating the edit commands on focus or selection changes
  * when no UI is visible to improve performance (including pageload performance,
@@ -3481,36 +3255,27 @@ function retrieveToolbarIconsizesFromThe
  * is a no op.
  */
 function updateEditUIVisibility()
 {
 #ifndef XP_MACOSX
   let editMenuPopupState = document.getElementById("menu_EditPopup").state;
   let contextMenuPopupState = document.getElementById("contentAreaContextMenu").state;
   let placesContextMenuPopupState = document.getElementById("placesContext").state;
-#ifdef MENUBAR_CAN_AUTOHIDE
-  let appMenuPopupState = document.getElementById("appmenu-popup").state;
-#endif
 
   // The UI is visible if the Edit menu is opening or open, if the context menu
   // is open, or if the toolbar has been customized to include the Cut, Copy,
   // or Paste toolbar buttons.
   gEditUIVisible = editMenuPopupState == "showing" ||
                    editMenuPopupState == "open" ||
                    contextMenuPopupState == "showing" ||
                    contextMenuPopupState == "open" ||
                    placesContextMenuPopupState == "showing" ||
                    placesContextMenuPopupState == "open" ||
-#ifdef MENUBAR_CAN_AUTOHIDE
-                   appMenuPopupState == "showing" ||
-                   appMenuPopupState == "open" ||
-#endif
-                   document.getElementById("cut-button") ||
-                   document.getElementById("copy-button") ||
-                   document.getElementById("paste-button") ? true : false;
+                   document.getElementById("edit-controls") ? true : false;
 
   // If UI is visible, update the edit commands' enabled state to reflect
   // whether or not they are actually enabled for the current focus/selection.
   if (gEditUIVisible)
     goUpdateGlobalEditMenuItems();
 
   // Otherwise, enable all commands, so that keyboard shortcuts still work,
   // then lazily determine their actual enabled state when the user presses
@@ -3530,44 +3295,29 @@ function updateEditUIVisibility()
 
 /**
  * Makes the Character Encoding menu enabled or disabled as appropriate.
  * To be called when the View menu or the app menu is opened.
  */
 function updateCharacterEncodingMenuState()
 {
   let charsetMenu = document.getElementById("charsetMenu");
-  let appCharsetMenu = document.getElementById("appmenu_charsetMenu");
-  let appDevCharsetMenu =
-    document.getElementById("appmenu_developer_charsetMenu");
   // gBrowser is null on Mac when the menubar shows in the context of
   // non-browser windows. The above elements may be null depending on
   // what parts of the menubar are present. E.g. no app menu on Mac.
   if (gBrowser &&
       gBrowser.docShell &&
       gBrowser.docShell.mayEnableCharacterEncodingMenu) {
     if (charsetMenu) {
       charsetMenu.removeAttribute("disabled");
     }
-    if (appCharsetMenu) {
-      appCharsetMenu.removeAttribute("disabled");
-    }
-    if (appDevCharsetMenu) {
-      appDevCharsetMenu.removeAttribute("disabled");
-    }
   } else {
     if (charsetMenu) {
       charsetMenu.setAttribute("disabled", "true");
     }
-    if (appCharsetMenu) {
-      appCharsetMenu.setAttribute("disabled", "true");
-    }
-    if (appDevCharsetMenu) {
-      appDevCharsetMenu.setAttribute("disabled", "true");
-    }
   }
 }
 
 /**
  * Returns true if |aMimeType| is text-based, false otherwise.
  *
  * @param aMimeType
  *        The MIME type to check.
@@ -3589,18 +3339,18 @@ function mimeTypeIsTextBased(aMimeType)
 var XULBrowserWindow = {
   // Stored Status, Link and Loading values
   status: "",
   defaultStatus: "",
   overLink: "",
   startTime: 0,
   statusText: "",
   isBusy: false,
-  inContentWhitelist: ["about:addons", "about:downloads", "about:permissions",
-                       "about:sync-progress", "about:preferences"],
+  // Left here for add-on compatibility, see bug 752434
+  inContentWhitelist: [],
 
   QueryInterface: function (aIID) {
     if (aIID.equals(Ci.nsIWebProgressListener) ||
         aIID.equals(Ci.nsIWebProgressListener2) ||
         aIID.equals(Ci.nsISupportsWeakReference) ||
         aIID.equals(Ci.nsIXULBrowserWindow) ||
         aIID.equals(Ci.nsISupports))
       return this;
@@ -3619,18 +3369,16 @@ var XULBrowserWindow = {
     return gBrowser.getStatusPanel();
   },
   get isImage () {
     delete this.isImage;
     return this.isImage = document.getElementById("isImage");
   },
 
   init: function () {
-    this.throbberElement = document.getElementById("navigator-throbber");
-
     // Initialize the security button's state and tooltip text.
     var securityUI = gBrowser.securityUI;
     this.onSecurityChange(null, null, securityUI.state);
   },
 
   setJSStatus: function () {
     // unsupported
   },
@@ -3744,20 +3492,16 @@ var XULBrowserWindow = {
         gBrowser.selectedBrowser.engines = null;
       }
 
       this.isBusy = true;
 
       if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
         this._busyUI = true;
 
-        // Turn the throbber on.
-        if (this.throbberElement)
-          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) {
       // This (thanks to the filter) is a network stop or the last
       // request stop outside of loading the document, stop throbbers
@@ -3792,20 +3536,16 @@ var XULBrowserWindow = {
           this.isImage.setAttribute('disabled', 'true');
       }
 
       this.isBusy = false;
 
       if (this._busyUI) {
         this._busyUI = false;
 
-        // Turn the throbber off.
-        if (this.throbberElement)
-          this.throbberElement.removeAttribute("busy");
-
         this.stopCommand.setAttribute("disabled", "true");
         CombinedStopReload.switchToReload(aRequest instanceof Ci.nsIRequest);
       }
     }
   },
 
   onLocationChange: function (aWebProgress, aRequest, aLocationURI, aFlags) {
     var location = aLocationURI ? aLocationURI.spec : "";
@@ -3862,26 +3602,16 @@ var XULBrowserWindow = {
       if (gURLBar) {
         URLBarSetURI(aLocationURI);
 
         // Update starring UI
         BookmarkingUI.updateStarState();
         SocialUI.updateState();
       }
 
-      // Show or hide browser chrome based on the whitelist
-      if (this.hideChromeForLocation(location)) {
-        document.documentElement.setAttribute("disablechrome", "true");
-      } else {
-        if (SessionStore.getTabValue(gBrowser.selectedTab, "appOrigin"))
-          document.documentElement.setAttribute("disablechrome", "true");
-        else
-          document.documentElement.removeAttribute("disablechrome");
-      }
-
       // Utility functions for disabling find
       var shouldDisableFind = function shouldDisableFind(aDocument) {
         let docElt = aDocument.documentElement;
         return docElt && docElt.getAttribute("disablefastfind") == "true";
       }
 
       var disableFindCommands = function disableFindCommands(aDisable) {
         let findCommands = [document.getElementById("cmd_find"),
@@ -3912,16 +3642,27 @@ var XULBrowserWindow = {
           if (content.document.readyState == "interactive" || content.document.readyState == "complete")
             disableFindCommands(shouldDisableFind(content.document));
           else {
             content.document.addEventListener("readystatechange", onContentRSChange);
           }
         }
       } else
         disableFindCommands(false);
+
+      // Try not to instantiate gCustomizeMode as much as possible,
+      // so don't use CustomizeMode.jsm to check for URI or customizing.
+      let customizingURI = "about:customizing";
+      if (location == customizingURI &&
+          !CustomizationHandler.isCustomizing()) {
+        gCustomizeMode.enter();
+      } else if (location != customizingURI &&
+                 CustomizationHandler.isCustomizing()) {
+        gCustomizeMode.exit();
+      }
     }
     UpdateBackForwardCommands(gBrowser.webNavigation);
 
     gGestureSupport.restoreRotationState();
 
     // See bug 358202, when tabs are switched during a drag operation,
     // timers don't fire on windows (bug 203573)
     if (aRequest)
@@ -3929,22 +3670,18 @@ var XULBrowserWindow = {
     else
       this.asyncUpdateUI();
   },
 
   asyncUpdateUI: function () {
     FeedHandler.updateFeeds();
   },
 
-  hideChromeForLocation: function(aLocation) {
-    aLocation = aLocation.toLowerCase();
-    return this.inContentWhitelist.some(function(aSpec) {
-      return aSpec == aLocation;
-    });
-  },
+  // Left here for add-on compatibility, see bug 752434
+  hideChromeForLocation: function() {},
 
   onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
     this.status = aMessage;
     this.updateStatusField();
   },
 
   // Properties used to cache security state used to update the UI
   _state: null,
@@ -4072,31 +3809,18 @@ var LinkTargetDisplay = {
   }
 };
 
 var CombinedStopReload = {
   init: function () {
     if (this._initialized)
       return;
 
-    var urlbar = document.getElementById("urlbar-container");
-    var reload = document.getElementById("reload-button");
-    var stop = document.getElementById("stop-button");
-
-    if (urlbar) {
-      if (urlbar.parentNode.getAttribute("mode") != "icons" ||
-          !reload || urlbar.nextSibling != reload ||
-          !stop || reload.nextSibling != stop)
-        urlbar.removeAttribute("combined");
-      else {
-        urlbar.setAttribute("combined", "true");
-        reload = document.getElementById("urlbar-reload-button");
-        stop = document.getElementById("urlbar-stop-button");
-      }
-    }
+    let reload = document.getElementById("urlbar-reload-button");
+    let stop = document.getElementById("urlbar-stop-button");
     if (!stop || !reload || reload.nextSibling != stop)
       return;
 
     this._initialized = true;
     if (XULBrowserWindow.stopCommand.getAttribute("disabled") != "true")
       reload.setAttribute("displaystop", "true");
     stop.addEventListener("click", this, false);
     this.reload = reload;
@@ -4417,31 +4141,29 @@ function onViewToolbarsPopupShowing(aEve
     var deadItem = popup.childNodes[i];
     if (deadItem.hasAttribute("toolbarId"))
       popup.removeChild(deadItem);
   }
 
   var firstMenuItem = aInsertPoint || popup.firstChild;
 
   let toolbarNodes = Array.slice(gNavToolbox.childNodes);
-  toolbarNodes.push(document.getElementById("addon-bar"));
 
   for (let toolbar of toolbarNodes) {
     let toolbarName = toolbar.getAttribute("toolbarname");
     if (toolbarName) {
       let menuItem = document.createElement("menuitem");
       let hidingAttribute = toolbar.getAttribute("type") == "menubar" ?
                             "autohide" : "collapsed";
       menuItem.setAttribute("id", "toggle_" + toolbar.id);
       menuItem.setAttribute("toolbarId", toolbar.id);
       menuItem.setAttribute("type", "checkbox");
       menuItem.setAttribute("label", toolbarName);
       menuItem.setAttribute("checked", toolbar.getAttribute(hidingAttribute) != "true");
-      if (popup.id != "appmenu_customizeMenu")
-        menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
+      menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
       if (popup.id != "toolbar-context-menu")
         menuItem.setAttribute("key", toolbar.getAttribute("key"));
 
       popup.insertBefore(menuItem, firstMenuItem);
 
       menuItem.addEventListener("command", onViewToolbarCommand, false);
     }
   }
@@ -4455,210 +4177,300 @@ function onViewToolbarCommand(aEvent) {
 }
 
 function setToolbarVisibility(toolbar, isVisible) {
   var hidingAttribute = toolbar.getAttribute("type") == "menubar" ?
                         "autohide" : "collapsed";
 
   toolbar.setAttribute(hidingAttribute, !isVisible);
   document.persist(toolbar.id, hidingAttribute);
+  let eventParams = {
+    detail: {
+      visible: isVisible
+    },
+    bubbles: true
+  };
+  let event = new CustomEvent("toolbarvisibilitychange", eventParams);
+  toolbar.dispatchEvent(event);
 
   PlacesToolbarHelper.init();
   BookmarkingUI.onToolbarVisibilityChange();
   gBrowser.updateWindowResizers();
-
-#ifdef MENUBAR_CAN_AUTOHIDE
-  updateAppButtonDisplay();
-#endif
-}
-
-var TabsOnTop = {
-  init: function TabsOnTop_init() {
-    Services.prefs.addObserver(this._prefName, this, false);
-
-    // Only show the toggle UI if the user disabled tabs on top.
-    if (Services.prefs.getBoolPref(this._prefName)) {
-      for (let item of document.querySelectorAll("menuitem[command=cmd_ToggleTabsOnTop]"))
-        item.parentNode.removeChild(item);
-    }
-  },
-
-  uninit: function TabsOnTop_uninit() {
-    Services.prefs.removeObserver(this._prefName, this);
-  },
-
-  toggle: function () {
-    this.enabled = !Services.prefs.getBoolPref(this._prefName);
-  },
-
-  syncUI: function () {
-    let userEnabled = Services.prefs.getBoolPref(this._prefName);
-    let enabled = userEnabled && gBrowser.tabContainer.visible;
-
-    document.getElementById("cmd_ToggleTabsOnTop")
-            .setAttribute("checked", userEnabled);
-
-    document.documentElement.setAttribute("tabsontop", enabled);
-    document.getElementById("navigator-toolbox").setAttribute("tabsontop", enabled);
-    document.getElementById("TabsToolbar").setAttribute("tabsontop", enabled);
-    document.getElementById("nav-bar").setAttribute("tabsontop", enabled);
-    gBrowser.tabContainer.setAttribute("tabsontop", enabled);
-    TabsInTitlebar.allowedBy("tabs-on-top", enabled);
-  },
-
-  get enabled () {
-    return gNavToolbox.getAttribute("tabsontop") == "true";
-  },
-
-  set enabled (val) {
-    Services.prefs.setBoolPref(this._prefName, !!val);
-    return val;
-  },
-
-  observe: function (subject, topic, data) {
-    if (topic == "nsPref:changed")
-      this.syncUI();
-  },
-
-  _prefName: "browser.tabs.onTop"
 }
 
 var TabsInTitlebar = {
   init: function () {
 #ifdef CAN_DRAW_IN_TITLEBAR
     this._readPref();
     Services.prefs.addObserver(this._prefName, this, false);
 
-    // Don't trust the initial value of the sizemode attribute; wait for
-    // the resize event (handled in tabbrowser.xml).
-    this.allowedBy("sizemode", false);
-
+    // We need to update the appearance of the titlebar when the menu changes
+    // from the active to the inactive state. We can't, however, rely on
+    // DOMMenuBarInactive, because the menu fires this event and then removes
+    // the inactive attribute after an event-loop spin.
+    //
+    // Because updating the appearance involves sampling the heights and margins
+    // of various elements, it's important that the layout be more or less
+    // settled before updating the titlebar. So instead of listening to
+    // DOMMenuBarActive and DOMMenuBarInactive, we use a MutationObserver to
+    // watch the "invalid" attribute directly.
+    let menu = document.getElementById("toolbar-menubar");
+    this._menuObserver = new MutationObserver(this._onMenuMutate);
+    this._menuObserver.observe(menu, {attributes: true});
+
+    gNavToolbox.addEventListener("customization-transitionend", this);
     this._initialized = true;
 #endif
   },
 
   allowedBy: function (condition, allow) {
 #ifdef CAN_DRAW_IN_TITLEBAR
     if (allow) {
       if (condition in this._disallowed) {
         delete this._disallowed[condition];
-        this._update();
+        this._update(true);
       }
     } else {
       if (!(condition in this._disallowed)) {
         this._disallowed[condition] = null;
-        this._update();
+        this._update(true);
       }
     }
 #endif
   },
 
+  updateAppearance: function updateAppearance(aForce) {
+#ifdef CAN_DRAW_IN_TITLEBAR
+    this._update(aForce);
+#endif
+  },
+
   get enabled() {
     return document.documentElement.getAttribute("tabsintitlebar") == "true";
   },
 
 #ifdef CAN_DRAW_IN_TITLEBAR
   observe: function (subject, topic, data) {
     if (topic == "nsPref:changed")
       this._readPref();
   },
 
+  handleEvent: function(ev) {
+    if (ev.type == "customization-transitionend") {
+      this._update(true);
+    }
+  },
+
+  _onMenuMutate: function (aMutations) {
+    for (let mutation of aMutations) {
+      if (mutation.attributeName == "inactive" ||
+          mutation.attributeName == "autohide") {
+        TabsInTitlebar._update(true);
+        return;
+      }
+    }
+  },
+
   _initialized: false,
   _disallowed: {},
   _prefName: "browser.tabs.drawInTitlebar",
+  _lastSizeMode: null,
 
   _readPref: function () {
     this.allowedBy("pref",
                    Services.prefs.getBoolPref(this._prefName));
   },
 
-  _update: function () {
+  _update: function (aForce=false) {
     function $(id) document.getElementById(id);
     function rect(ele) ele.getBoundingClientRect();
+    function verticalMargins(cstyle) parseInt(cstyle.marginBottom, 10) + parseInt(cstyle.marginTop, 10);
 
     if (!this._initialized || window.fullScreen)
       return;
 
     let allowed = true;
+
+    if (!aForce) {
+      // _update is called on resize events, because the window is not ready
+      // after sizemode events. However, we only care about the event when the
+      // sizemode is different from the last time we updated the appearance of
+      // the tabs in the titlebar.
+      let sizemode = document.documentElement.getAttribute("sizemode");
+      if (this._lastSizeMode == sizemode) {
+        return;
+      }
+      this._lastSizeMode = sizemode;
+    }
+
     for (let something in this._disallowed) {
       allowed = false;
       break;
     }
 
-    if (allowed == this.enabled)
-      return;
-
     let titlebar = $("titlebar");
+    let titlebarContent = $("titlebar-content");
+    let menubar = $("toolbar-menubar");
 
     if (allowed) {
-      let tabsToolbar       = $("TabsToolbar");
-
-#ifdef MENUBAR_CAN_AUTOHIDE
-      let appmenuButtonBox  = $("appmenu-button-container");
-      this._sizePlaceholder("appmenu-button", rect(appmenuButtonBox).width);
+      // We set the tabsintitlebar attribute first so that our CSS for
+      // tabsintitlebar manifests before we do our measurements.
+      document.documentElement.setAttribute("tabsintitlebar", "true");
+      updateTitlebarDisplay();
+
+      // Try to avoid reflows in this code by calculating dimensions first and
+      // then later set the properties affecting layout together in a batch.
+
+      // Buttons first:
+      let captionButtonsBoxWidth = rect($("titlebar-buttonbox")).width;
+#ifdef XP_MACOSX
+      let fullscreenButtonWidth = rect($("titlebar-fullscreen-button")).width;
+      // No need to look up the menubar stuff on OS X:
+      let menuHeight = 0;
+      let fullMenuHeight = 0;
+#else
+      // Otherwise, get the height and margins separately for the menubar
+      let menuHeight = rect(menubar).height;
+      let menuStyles = window.getComputedStyle(menubar);
+      let fullMenuHeight = verticalMargins(menuStyles) + menuHeight;
 #endif
-      let captionButtonsBox = $("titlebar-buttonbox");
-      this._sizePlaceholder("caption-buttons", rect(captionButtonsBox).width);
-
-      let tabsToolbarRect = rect(tabsToolbar);
-      let titlebarTop = rect($("titlebar-content")).top;
-      titlebar.style.marginBottom = - Math.min(tabsToolbarRect.top - titlebarTop,
-                                               tabsToolbarRect.height) + "px";
-
-      document.documentElement.setAttribute("tabsintitlebar", "true");
-
-      if (!this._draghandle) {
+      // Get the full height of the tabs toolbar:
+      let tabsToolbar = $("TabsToolbar");
+      let tabsStyles = window.getComputedStyle(tabsToolbar);
+      let fullTabsHeight = rect(tabsToolbar).height + verticalMargins(tabsStyles);
+
+      // If the navbar overlaps the tabbar using negative margins, we need to take those into
+      // account so we don't overlap it
+      let navbarMarginTop = parseInt(window.getComputedStyle($("nav-bar")).marginTop, 10);
+      navbarMarginTop = Math.min(navbarMarginTop, 0);
+
+      // And get the height of what's in the titlebar:
+      let titlebarContentHeight = rect(titlebarContent).height;
+
+      // Padding surrounds the tab-view-deck when we are in customization mode,
+      // so take that into account:
+      let areCustomizing = document.documentElement.hasAttribute("customizing") ||
+                           document.documentElement.hasAttribute("customize-exiting");
+      let customizePadding = 0;
+      if (areCustomizing) {
+        let deckStyle = window.getComputedStyle($("tab-view-deck"));
+        customizePadding = parseInt(deckStyle.paddingTop, 10);
+      }
+
+      // Begin setting CSS properties which will cause a reflow
+
+      // If the menubar is around (menuHeight is non-zero), try to adjust
+      // its full height (i.e. including margins) to match the titlebar,
+      // by changing the menubar's bottom padding
+      if (menuHeight) {
+        // Calculate the difference between the titlebar's height and that of the menubar
+        let menuTitlebarDelta = titlebarContentHeight - fullMenuHeight;
+        let paddingBottom;
+        // The titlebar is bigger:
+        if (menuTitlebarDelta > 0) {
+          fullMenuHeight += menuTitlebarDelta;
+          // If there is already padding on the menubar, we need to add that
+          // to the difference so the total padding is correct:
+          if ((paddingBottom = menuStyles.paddingBottom)) {
+            menuTitlebarDelta += parseInt(paddingBottom, 10);
+          }
+          menubar.style.paddingBottom = menuTitlebarDelta + "px";
+        // The menubar is bigger, but has bottom padding we can remove:
+        } else if (menuTitlebarDelta < 0 && (paddingBottom = menuStyles.paddingBottom)) {
+          let existingPadding = parseInt(paddingBottom, 10);
+          // menuTitlebarDelta is negative; work out what's left, but don't set negative padding:
+          let desiredPadding = Math.max(0, existingPadding + menuTitlebarDelta);
+          menubar.style.paddingBottom = desiredPadding + "px";
+          // We've changed the menu height now:
+          fullMenuHeight += desiredPadding - existingPadding;
+        }
+      }
+
+      // Next, we calculate how much we need to stretch the titlebar down to
+      // go all the way to the bottom of the tab strip, if necessary.
+      let tabAndMenuHeight = fullTabsHeight + fullMenuHeight;
+      // Oh, and don't forget customization mode:
+      if (areCustomizing) {
+        tabAndMenuHeight += customizePadding;
+      }
+
+      if (tabAndMenuHeight > titlebarContentHeight) {
+        // We need to increase the titlebar content's outer height (ie including margins)
+        // to match the tab and menu height:
+        let extraMargin = tabAndMenuHeight - titlebarContentHeight;
+        // We need to reduce the height by the amount of navbar overlap
+        // (this value is 0 or negative):
+        extraMargin += navbarMarginTop;
+        titlebarContent.style.marginBottom = extraMargin + "px";
+        titlebarContentHeight += extraMargin;
+      }
+
+      // Then we bring up the titlebar by the same amount, but we add any negative margin:
+      titlebar.style.marginBottom = "-" + titlebarContentHeight + "px";
+
+
+      // Finally, size the placeholders:
+#ifdef XP_MACOSX
+      this._sizePlaceholder("fullscreen-button", fullscreenButtonWidth);
+#endif
+      this._sizePlaceholder("caption-buttons", captionButtonsBoxWidth);
+
+      if (!this._draghandles) {
+        this._draghandles = {};
         let tmp = {};
         Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
-        this._draghandle = new tmp.WindowDraggingElement(tabsToolbar);
-        this._draghandle.mouseDownCheck = function () {
+
+        let mouseDownCheck = function () {
           return !this._dragBindingAlive && TabsInTitlebar.enabled;
         };
+
+        this._draghandles.tabsToolbar = new tmp.WindowDraggingElement(tabsToolbar);
+        this._draghandles.tabsToolbar.mouseDownCheck = mouseDownCheck;
+
+        this._draghandles.navToolbox = new tmp.WindowDraggingElement(gNavToolbox);
+        this._draghandles.navToolbox.mouseDownCheck = mouseDownCheck;
       }
     } else {
       document.documentElement.removeAttribute("tabsintitlebar");
-
+      updateTitlebarDisplay();
+
+      // Reset the margins and padding that might have been modified:
+      titlebarContent.style.marginBottom = "";
       titlebar.style.marginBottom = "";
+      menubar.style.paddingBottom = "";
     }
   },
 
   _sizePlaceholder: function (type, width) {
     Array.forEach(document.querySelectorAll(".titlebar-placeholder[type='"+ type +"']"),
                   function (node) { node.width = width; });
   },
 #endif
 
   uninit: function () {
 #ifdef CAN_DRAW_IN_TITLEBAR
     this._initialized = false;
     Services.prefs.removeObserver(this._prefName, this);
+    this._menuObserver.disconnect();
 #endif
   }
 };
 
-#ifdef MENUBAR_CAN_AUTOHIDE
-function updateAppButtonDisplay() {
-  var displayAppButton =
-    !gInPrintPreviewMode &&
-    window.menubar.visible &&
-    document.getElementById("toolbar-menubar").getAttribute("autohide") == "true";
-
 #ifdef CAN_DRAW_IN_TITLEBAR
-  document.getElementById("titlebar").hidden = !displayAppButton;
-
-  if (displayAppButton)
+function updateTitlebarDisplay() {
+  document.getElementById("titlebar").hidden = !TabsInTitlebar.enabled;
+
+  if (TabsInTitlebar.enabled)
+#ifdef XP_WIN
     document.documentElement.setAttribute("chromemargin", "0,2,2,2");
+#else
+    document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
+#endif
   else
     document.documentElement.removeAttribute("chromemargin");
-
-  TabsInTitlebar.allowedBy("drawing-in-titlebar", displayAppButton);
-#else
-  document.getElementById("appmenu-toolbar-button").hidden =
-    !displayAppButton;
-#endif
 }
 #endif
 
 #ifdef CAN_DRAW_IN_TITLEBAR
 function onTitlebarMaxClick() {
   if (window.windowState == window.STATE_MAXIMIZED)
     window.restore();
   else
@@ -6910,39 +6722,32 @@ let gPrivateBrowsingUI = {
       return;
     }
 
     // Disable the Clear Recent History... menu item when in PB mode
     // temporary fix until bug 463607 is fixed
     document.getElementById("Tools:Sanitize").setAttribute("disabled", "true");
 
     if (window.location.href == getBrowserURL()) {
-#ifdef XP_MACOSX
-      if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
-        document.documentElement.setAttribute("drawintitlebar", true);
-      }
-#endif
-
       // Adjust the window's title
       let docElement = document.documentElement;
       if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
         docElement.setAttribute("title",
           docElement.getAttribute("title_privatebrowsing"));
         docElement.setAttribute("titlemodifier",
           docElement.getAttribute("titlemodifier_privatebrowsing"));
       }
       docElement.setAttribute("privatebrowsingmode",
         PrivateBrowsingUtils.permanentPrivateBrowsing ? "permanent" : "temporary");
       gBrowser.updateTitlebar();
 
       if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
         // Adjust the New Window menu entries
         [
           { normal: "menu_newNavigator", private: "menu_newPrivateWindow" },
-          { normal: "appmenu_newNavigator", private: "appmenu_newPrivateWindow" },
         ].forEach(function(menu) {
           let newWindow = document.getElementById(menu.normal);
           let newPrivateWindow = document.getElementById(menu.private);
           if (newWindow && newPrivateWindow) {
             newPrivateWindow.hidden = true;
             newWindow.label = newPrivateWindow.label;
             newWindow.accessKey = newPrivateWindow.accessKey;
             newWindow.command = newPrivateWindow.command;
@@ -7150,21 +6955,16 @@ function duplicateTabIn(aTab, where, del
       // A background tab has been opened, nothing else to do here.
       break;
     case "tab":
       gBrowser.selectedTab = newTab;
       break;
   }
 }
 
-function toggleAddonBar() {
-  let addonBar = document.getElementById("addon-bar");
-  setToolbarVisibility(addonBar, addonBar.collapsed);
-}
-
 var Scratchpad = {
   openScratchpad: function SP_openScratchpad() {
     return this.ScratchpadManager.openScratchpad();
   }
 };
 
 XPCOMUtils.defineLazyGetter(Scratchpad, "ScratchpadManager", function() {
   let tmp = {};
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -4,52 +4,64 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 <?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/customizableui/panelUIOverlay.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/browser-lightweightTheme.css" type="text/css"?>
 
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
 
 # All DTD information is stored in a separate file so that it can be shared by
 # hiddenWindow.xul.
 #include browser-doctype.inc
 
 <window id="main-window"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:svg="http://www.w3.org/2000/svg"
+        xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         onload="gBrowserInit.onLoad()" onunload="gBrowserInit.onUnload()" onclose="return WindowIsClosing();"
         title="&mainWindow.title;@PRE_RELEASE_SUFFIX@"
         title_normal="&mainWindow.title;@PRE_RELEASE_SUFFIX@"
 #ifdef XP_MACOSX
         title_privatebrowsing="&mainWindow.title;@PRE_RELEASE_SUFFIX@&mainWindow.titlemodifiermenuseparator;&mainWindow.titlePrivateBrowsingSuffix;"
         titledefault="&mainWindow.title;@PRE_RELEASE_SUFFIX@"
         titlemodifier=""
         titlemodifier_normal=""
         titlemodifier_privatebrowsing="&mainWindow.titlePrivateBrowsingSuffix;"
 #else
         title_privatebrowsing="&mainWindow.titlemodifier;@PRE_RELEASE_SUFFIX@ &mainWindow.titlePrivateBrowsingSuffix;"
         titlemodifier="&mainWindow.titlemodifier;@PRE_RELEASE_SUFFIX@"
         titlemodifier_normal="&mainWindow.titlemodifier;@PRE_RELEASE_SUFFIX@"
         titlemodifier_privatebrowsing="&mainWindow.titlemodifier;@PRE_RELEASE_SUFFIX@ &mainWindow.titlePrivateBrowsingSuffix;"
 #endif
+#ifdef CAN_DRAW_IN_TITLEBAR
+#ifdef XP_WIN
+        chromemargin="0,2,2,2"
+#else
+        chromemargin="0,-1,-1,-1"
+#endif
+        tabsintitlebar="true"
+#endif
         titlemenuseparator="&mainWindow.titlemodifiermenuseparator;"
         lightweightthemes="true"
         lightweightthemesfooter="browser-bottombox"
         windowtype="navigator:browser"
         macanimationtype="document"
         screenX="4" screenY="4"
         fullscreenbutton="true"
+        sizemode="normal"
         persist="screenX screenY width height sizemode">
 
 # All JS files which are not content (only) dependent that browser.xul
 # wishes to include *must* go into the global-scripts.inc file
 # so that they can be shared by macBrowserOverlay.xul.
 #include global-scripts.inc
 <script type="application/javascript" src="chrome://browser/content/nsContextMenu.js"/>
 
@@ -240,20 +252,16 @@
            rolluponmousewheel="true"
            consumeoutsideclicks="false"
            noautofocus="true"
            position="topcenter topright"/>
 
     <menupopup id="toolbar-context-menu"
                onpopupshowing="onViewToolbarsPopupShowing(event);">
       <menuseparator/>
-      <menuitem command="cmd_ToggleTabsOnTop"
-                type="checkbox"
-                label="&viewTabsOnTop.label;"
-                accesskey="&viewTabsOnTop.accesskey;"/>
       <menuitem command="cmd_CustomizeToolbars"
                 label="&viewCustomizeToolbar.label;"
                 accesskey="&viewCustomizeToolbar.accesskey;"/>
     </menupopup>
 
     <menupopup id="blockedPopupOptions"
                onpopupshowing="gPopupBlockerObserver.fillPopupList(event);"
                onpopuphiding="gPopupBlockerObserver.onPopupHiding(event);">
@@ -361,20 +369,16 @@
       <hbox pack="center">
         <button id="ctrlTab-showAll" class="ctrlTab-preview" noicon="true"/>
       </hbox>
     </panel>
 
     <!-- Bookmarks and history tooltip -->
     <tooltip id="bhTooltip"/>
 
-    <panel id="customizeToolbarSheetPopup"
-           noautohide="true"
-           sheetstyle="&dialog.dimensions;"/>
-
     <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
 
     <tooltip id="back-button-tooltip">
       <label class="tooltip-label" value="&backButton.tooltip;"/>
 #ifdef XP_MACOSX
       <label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
 #else
       <label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
@@ -387,39 +391,37 @@
       <label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
 #else
       <label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
 #endif
     </tooltip>
 
 #include popup-notifications.inc
 
+#include ../../components/customizableui/content/panelUI.inc.xul
   </popupset>
 
 #ifdef CAN_DRAW_IN_TITLEBAR
 <vbox id="titlebar">
   <hbox id="titlebar-content">
-#ifdef MENUBAR_CAN_AUTOHIDE
-    <hbox id="appmenu-button-container">
-      <button id="appmenu-button"
-              type="menu"
-              label="&brandShortName;"
-              style="-moz-user-focus: ignore;">
-#include browser-appmenu.inc
-      </button>
-    </hbox>
+    <spacer id="titlebar-spacer" flex="1"/>
+    <hbox id="titlebar-buttonbox-container" align="start"
+#ifdef XP_MACOSX
+          ordinal="0"
 #endif
-    <spacer id="titlebar-spacer" flex="1"/>
-    <hbox id="titlebar-buttonbox-container" align="start">
+    >
       <hbox id="titlebar-buttonbox">
         <toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
         <toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
         <toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/>
       </hbox>
     </hbox>
+#ifdef XP_MACOSX
+    <hbox id="titlebar-fullscreen-button" ordinal="1000"/>
+#endif
   </hbox>
 </vbox>
 #endif
 
 <deck flex="1" id="tab-view-deck">
 <vbox flex="1" id="browser-panel">
 
   <toolbox id="navigator-toolbox"
@@ -428,330 +430,456 @@
     <!-- Menu -->
     <toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
              defaultset="menubar-items"
              mode="icons" iconsize="small" defaulticonsize="small"
              lockiconsize="true"
 #ifdef MENUBAR_CAN_AUTOHIDE
              toolbarname="&menubarCmd.label;"
              accesskey="&menubarCmd.accesskey;"
+#ifdef XP_LINUX
+             autohide="true"
+#endif
 #endif
              context="toolbar-context-menu">
-      <toolbaritem id="menubar-items" align="center">
+      <toolbaritem id="menubar-items" align="center"
+                   customizableui-areatype="toolbar">
 # The entire main menubar is placed into browser-menubar.inc, so that it can be shared by
 # hiddenWindow.xul.
 #include browser-menubar.inc
       </toolbaritem>
 
 #ifdef CAN_DRAW_IN_TITLEBAR
-      <hbox class="titlebar-placeholder" type="appmenu-button" ordinal="0"/>
-      <hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"/>
+#ifndef XP_MACOSX
+      <hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"
+            id="titlebar-placeholder-on-menubar-for-caption-buttons" persist="width"
+            skipintoolbarset="true"/>
+#endif
+#endif
+    </toolbar>
+
+    <toolbar id="TabsToolbar"
+             class="toolbar-primary"
+             fullscreentoolbar="true"
+             customizable="true"
+             mode="icons" lockmode="true"
+             iconsize="small" defaulticonsize="small" lockiconsize="true"
+             aria-label="&tabsToolbar.label;"
+             context="toolbar-context-menu"
+             defaultset="tabbrowser-tabs,new-tab-button,alltabs-button,tabs-closebutton"
+             collapsed="true">
+
+      <tabs id="tabbrowser-tabs"
+            class="tabbrowser-tabs"
+            tabbrowser="content"
+            flex="1"
+            setfocus="false"
+            tooltip="tabbrowser-tab-tooltip"
+            customizableui-areatype="toolbar"
+            stopwatchid="FX_TAB_CLICK_MS">
+        <tab class="tabbrowser-tab" selected="true" fadein="true"/>
+      </tabs>
+
+      <toolbarbutton id="new-tab-button"
+                     class="toolbarbutton-1 chromeclass-toolbar-additional"
+                     label="&tabCmd.label;"
+                     command="cmd_newNavigatorTab"
+                     onclick="checkForMiddleClick(this, event);"
+                     tooltiptext="&newTabButton.tooltip;"
+                     ondrop="newTabButtonObserver.onDrop(event)"
+                     ondragover="newTabButtonObserver.onDragOver(event)"
+                     ondragenter="newTabButtonObserver.onDragOver(event)"
+                     ondragexit="newTabButtonObserver.onDragExit(event)"
+                     customizableui-areatype="toolbar"
+                     removable="true"/>
+
+      <toolbarbutton id="alltabs-button"
+                     class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button"
+                     type="menu"
+                     label="&listAllTabs.label;"
+                     tooltiptext="&listAllTabs.label;"
+                     removable="false">
+        <menupopup id="alltabs-popup"
+                   position="after_end">
+          <menuitem id="menu_tabview"
+                    class="menuitem-iconic"
+                    key="key_tabview"
+                    label="&viewTabGroups.label;"
+                    command="Browser:ToggleTabView"
+                    customizableui-areatype="toolbar"
+                    observes="tabviewGroupsNumber"/>
+          <menuseparator id="alltabs-popup-separator"/>
+        </menupopup>
+      </toolbarbutton>
+
+      <toolbarbutton id="tabs-closebutton"
+                     class="close-button tabs-closebutton close-icon"
+                     command="cmd_close"
+                     label="&closeTab.label;"
+                     customizableui-areatype="toolbar"
+                     tooltiptext="&closeTab.label;"/>
+
+#ifdef CAN_DRAW_IN_TITLEBAR
+      <hbox class="titlebar-placeholder" type="caption-buttons"
+            id="titlebar-placeholder-on-TabsToolbar-for-captions-buttons" persist="width"
+#ifndef XP_MACOSX
+            ordinal="1000"
+#endif
+            skipintoolbarset="true"/>
+
+#ifdef XP_MACOSX
+      <hbox class="titlebar-placeholder" type="fullscreen-button"
+            id="titlebar-placeholder-on-TabsToolbar-for-fullscreen-button" persist="width"
+            skipintoolbarset="true"/>
+#endif
 #endif
     </toolbar>
 
+    <!--
+           CAVEAT EMPTOR
+           Should you need to add items to the toolbar here, make sure to also add them
+           to the default placements of buttons in CustomizableUI.jsm, so the
+           customization code doesn't get confused.
+      -->
     <toolbar id="nav-bar" class="toolbar-primary chromeclass-toolbar"
-             toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;"
+             aria-label="&navbarCmd.label;"
              fullscreentoolbar="true" mode="icons" customizable="true"
              iconsize="large"
-             defaultset="unified-back-forward-button,urlbar-container,reload-button,stop-button,search-container,webrtc-status-button,bookmarks-menu-button,downloads-button,home-button,window-controls"
+             defaultset="urlbar-container,search-container,webrtc-status-button,bookmarks-menu-button,downloads-button,home-button,social-share-button,social-toolbar-item"
+             customizationtarget="nav-bar-customizationtarget"
+             overflowable="true"
+             overflowbutton="nav-bar-overflow-button"
+             overflowtarget="widget-overflow-list"
+             flex="501"
              context="toolbar-context-menu">
 
-      <toolbaritem id="unified-back-forward-button" class="chromeclass-toolbar-additional"
-                   context="backForwardMenu" removable="true"
-                   forwarddisabled="true"
-                   title="&backForwardItem.title;">
-        <toolbarbutton id="back-button" class="toolbarbutton-1"
-                       label="&backCmd.label;"
-                       command="Browser:BackOrBackDuplicate"
-                       onclick="checkForMiddleClick(this, event);"
-                       tooltip="back-button-tooltip"/>
-        <toolbarbutton id="forward-button" class="toolbarbutton-1"
-                       label="&forwardCmd.label;"
-                       command="Browser:ForwardOrForwardDuplicate"
-                       onclick="checkForMiddleClick(this, event);"
-                       tooltip="forward-button-tooltip"/>
-        <dummyobservertarget hidden="true"
-                             onbroadcast="if (this.getAttribute('disabled') == 'true')
-                                            this.parentNode.setAttribute('forwarddisabled', 'true');
-                                          else
-                                            this.parentNode.removeAttribute('forwarddisabled');">
-          <observes element="Browser:ForwardOrForwardDuplicate" attribute="disabled"/>
-        </dummyobservertarget>
-      </toolbaritem>
+      <hbox id="nav-bar-customizationtarget" class="customization-target" flex="1">
+        <toolbaritem id="urlbar-container" align="center" flex="400" persist="width"
+                     forwarddisabled="true" title="&locationItem.title;" removable="false"
+                     customizableui-areatype="toolbar"
+                     class="chromeclass-location" overflows="false">
+          <toolbarbutton id="back-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                         label="&backCmd.label;"
+                         command="Browser:BackOrBackDuplicate"
+                         onclick="checkForMiddleClick(this, event);"
+                         tooltip="back-button-tooltip"
+                         context="backForwardMenu"/>
+          <toolbarbutton id="forward-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                         label="&forwardCmd.label;"
+                         command="Browser:ForwardOrForwardDuplicate"
+                         onclick="checkForMiddleClick(this, event);"
+                         tooltip="forward-button-tooltip"
+                         context="backForwardMenu"/>
+          <dummyobservertarget hidden="true"
+                               onbroadcast="if (this.getAttribute('disabled') == 'true')
+                                              this.parentNode.setAttribute('forwarddisabled', 'true');
+                                            else
+                                              this.parentNode.removeAttribute('forwarddisabled');">
+            <observes element="Browser:ForwardOrForwardDuplicate" attribute="disabled"/>
+          </dummyobservertarget>
+          <hbox id="urlbar-wrapper" flex="1">
+            <textbox id="urlbar" flex="1"
+                     placeholder="&urlbar.placeholder2;"
+                     type="autocomplete"
+                     autocompletesearch="urlinline history"
+                     autocompletesearchparam="enable-actions"
+                     autocompletepopup="PopupAutoCompleteRichResult"
+                     completeselectedindex="true"
+                     tabscrolling="true"
+                     showcommentcolumn="true"
+                     showimagecolumn="true"
+                     enablehistory="true"
+                     maxrows="6"
+                     newlines="stripsurroundingwhitespace"
+                     oninput="gBrowser.userTypedValue = this.value;"
+                     ontextentered="this.handleCommand(param);"
+                     ontextreverted="return this.handleRevert();"
+                     pageproxystate="invalid"
+                     onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
+                     onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
+              <box id="notification-popup-box" hidden="true" align="center">
+                <image id="default-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="alert-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="plugin-install-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="pointerLock-notification-icon" class="notification-anchor-icon" role="button"/>
+                <image id="servicesInstall-notification-icon" class="notification-anchor-icon" role="button"/>
+              </box>
+              <!-- Use onclick instead of normal popup= syntax since the popup
+                   code fires onmousedown, and hence eats our favicon drag events.
+                   We only add the identity-box button to the tab order when the location bar
+                   has focus, otherwise pressing F6 focuses it instead of the location bar -->
+              <box id="identity-box" role="button"
+                   align="center"
+                   onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
+                   onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);"
+                   ondragstart="gIdentityHandler.onDragStart(event);">
+                <image id="page-proxy-favicon"
+                       onclick="PageProxyClickHandler(event);"
+                       pageproxystate="invalid"/>
+                <hbox id="identity-icon-labels">
+                  <label id="identity-icon-label" class="plain" flex="1"/>
+                  <label id="identity-icon-country-label" class="plain"/>
+                </hbox>
+              </box>
+              <box id="urlbar-display-box" align="center">
+                <label id="urlbar-display" value="&urlbar.switchToTab.label;"/>
+              </box>
+              <hbox id="urlbar-icons">
+                <image id="page-report-button"
+                       class="urlbar-icon"
+                       hidden="true"
+                       tooltiptext="&pageReportIcon.tooltip;"
+                       onclick="gPopupBlockerObserver.onReportButtonClick(event);"/>
+                <image id="star-button"
+                       class="urlbar-icon"
+                       onclick="BookmarkingUI.onCommand(event);"/>
+              </hbox>
+              <toolbarbutton id="urlbar-go-button"
+                             class="chromeclass-toolbar-additional"
+                             onclick="gURLBar.handleCommand(event);"
+                             tooltiptext="&goEndCap.tooltip;"/>
+              <toolbarbutton id="urlbar-reload-button"
+                             class="chromeclass-toolbar-additional"
+                             command="Browser:ReloadOrDuplicate"
+                             onclick="checkForMiddleClick(this, event);"
+                             tooltiptext="&reloadButton.tooltip;"/>
+              <toolbarbutton id="urlbar-stop-button"
+                             class="chromeclass-toolbar-additional"
+                             command="Browser:Stop"
+                             tooltiptext="&stopButton.tooltip;"/>
+            </textbox>
+          </hbox>
+        </toolbaritem>
 
-      <toolbaritem id="urlbar-container" align="center" flex="400" persist="width" combined="true"
-                   title="&locationItem.title;" class="chromeclass-location" removable="true">
-        <textbox id="urlbar" flex="1"
-                 placeholder="&urlbar.placeholder2;"
-                 type="autocomplete"
-                 autocompletesearch="urlinline history"
-                 autocompletesearchparam="enable-actions"
-                 autocompletepopup="PopupAutoCompleteRichResult"
-                 completeselectedindex="true"
-                 tabscrolling="true"
-                 showcommentcolumn="true"
-                 showimagecolumn="true"
-                 enablehistory="true"
-                 maxrows="6"
-                 newlines="stripsurroundingwhitespace"
-                 oninput="gBrowser.userTypedValue = this.value;"
-                 ontextentered="this.handleCommand(param);"
-                 ontextreverted="return this.handleRevert();"
-                 pageproxystate="invalid"
-                 onfocus="document.getElementById('identity-box').style.MozUserFocus= 'normal'"
-                 onblur="setTimeout(function() document.getElementById('identity-box').style.MozUserFocus = '', 0);">
-          <box id="notification-popup-box" hidden="true" align="center">
-            <image id="default-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="alert-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="plugin-install-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="pointerLock-notification-icon" class="notification-anchor-icon" role="button"/>
-            <image id="servicesInstall-notification-icon" class="notification-anchor-icon" role="button"/>
-          </box>
-          <!-- Use onclick instead of normal popup= syntax since the popup
-               code fires onmousedown, and hence eats our favicon drag events.
-               We only add the identity-box button to the tab order when the location bar
-               has focus, otherwise pressing F6 focuses it instead of the location bar -->
-          <box id="identity-box" role="button"
-               align="center"
-               onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
-               onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);"
-               ondragstart="gIdentityHandler.onDragStart(event);">
-            <image id="page-proxy-favicon"
-                   onclick="PageProxyClickHandler(event);"
-                   pageproxystate="invalid"/>
-            <hbox id="identity-icon-labels">
-              <label id="identity-icon-label" class="plain" flex="1"/>
-              <label id="identity-icon-country-label" class="plain"/>
-            </hbox>
-          </box>
-          <box id="urlbar-display-box" align="center">
-            <label id="urlbar-display" value="&urlbar.switchToTab.label;"/>
-          </box>
-          <hbox id="urlbar-icons">
-            <image id="page-report-button"
-                   class="urlbar-icon"
-                   hidden="true"
-                   tooltiptext="&pageReportIcon.tooltip;"
-                   onclick="gPopupBlockerObserver.onReportButtonClick(event);"/>
-            <image id="star-button"
-                   class="urlbar-icon"
-                   onclick="BookmarkingUI.onCommand(event);"/>
-            <image id="go-button"
-                   class="urlbar-icon"
-                   tooltiptext="&goEndCap.tooltip;"
-                   onclick="gURLBar.handleCommand(event);"/>
-          </hbox>
-          <toolbarbutton id="urlbar-go-button"
-                         class="chromeclass-toolbar-additional"
-                         onclick="gURLBar.handleCommand(event);"
-                         tooltiptext="&goEndCap.tooltip;"/>
-          <toolbarbutton id="urlbar-reload-button"
-                         class="chromeclass-toolbar-additional"
-                         command="Browser:ReloadOrDuplicate"
-                         onclick="checkForMiddleClick(this, event);"
-                         tooltiptext="&reloadButton.tooltip;"/>
-          <toolbarbutton id="urlbar-stop-button"
-                         class="chromeclass-toolbar-additional"
-                         command="Browser:Stop"
-                         tooltiptext="&stopButton.tooltip;"/>
-        </textbox>
-      </toolbaritem>
+        <toolbaritem id="search-container" title="&searchItem.title;"
+                     align="center" class="chromeclass-toolbar-additional"
+                     customizableui-areatype="toolbar"
+                     flex="100" persist="width" removable="true">
+          <searchbar id="searchbar" flex="1"/>
+        </toolbaritem>
 
-      <toolbarbutton id="reload-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&reloadCmd.label;" removable="true"
-                     command="Browser:ReloadOrDuplicate"
-                     onclick="checkForMiddleClick(this, event);"
-                     tooltiptext="&reloadButton.tooltip;"/>
-
-      <toolbarbutton id="stop-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&stopCmd.label;" removable="true"
-                     command="Browser:Stop"
-                     tooltiptext="&stopButton.tooltip;"/>
+        <toolbarbutton id="webrtc-status-button"
+                       class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       type="menu"
+                       hidden="true"
+                       orient="horizontal"
+                       label="&webrtcIndicatorButton.label;"
+                       tooltiptext="&webrtcIndicatorButton.tooltip;"
+                       customizableui-areatype="toolbar"
+                       overflows="false">
+          <menupopup onpopupshowing="WebrtcIndicator.fillPopup(this);"
+                     onpopuphiding="WebrtcIndicator.clearPopup(this);"
+                     oncommand="WebrtcIndicator.menuCommand(event.target);"/>
+        </toolbarbutton>
 
-      <toolbaritem id="search-container" title="&searchItem.title;"
-                   align="center" class="chromeclass-toolbar-additional"
-                   flex="100" persist="width" removable="true">
-        <searchbar id="searchbar" flex="1"/>
-      </toolbaritem>
-
-      <toolbarbutton id="webrtc-status-button"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     type="menu"
-                     hidden="true"
-                     orient="horizontal"
-                     label="&webrtcIndicatorButton.label;"
-                     tooltiptext="&webrtcIndicatorButton.tooltip;">
-        <menupopup onpopupshowing="WebrtcIndicator.fillPopup(this);"
-                   onpopuphiding="WebrtcIndicator.clearPopup(this);"
-                   oncommand="WebrtcIndicator.menuCommand(event.target);"/>
-      </toolbarbutton>
-
-      <toolbarbutton id="bookmarks-menu-button"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     persist="class"
-                     removable="true"
-                     type="menu"
-                     label="&bookmarksMenuButton.label;"
-                     tooltiptext="&bookmarksMenuButton.tooltip;"
-                     ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
-                     ondragover="PlacesMenuDNDHandler.onDragOver(event);"
-                     ondragleave="PlacesMenuDNDHandler.onDragLeave(event);"
-                     ondrop="PlacesMenuDNDHandler.onDrop(event);">
-        <menupopup id="BMB_bookmarksPopup"
-                   placespopup="true"
-                   context="placesContext"
-                   openInTabs="children"
-                   oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);"
-                   onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);"
-                   onpopupshowing="BookmarkingUI.onPopupShowing(event);
-                                   if (!this.parentNode._placesView)
-                                     new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
-                   tooltip="bhTooltip" popupsinherittooltip="true">
-          <menuitem id="BMB_viewBookmarksToolbar"
-                    placesanonid="view-toolbar"
-                    toolbarId="PersonalToolbar"
-                    type="checkbox"
-                    oncommand="onViewToolbarCommand(event)"
-                    label="&viewBookmarksToolbar.label;"/>
-          <menuseparator/>
-          <menuitem id="BMB_bookmarksShowAll"
-                    label="&showAllBookmarks2.label;"
-                    command="Browser:ShowAllBookmarks"
-                    key="manBookmarkKb"/>
-          <menuseparator/>
-          <menuitem id="BMB_bookmarkThisPage"
+        <toolbarbutton id="bookmarks-menu-button"
+                       class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       persist="class"
+                       removable="true"
+                       type="menu-button"
+                       label="&bookmarksMenuButton.label;"
+                       tooltiptext="&bookmarksMenuButton.tooltip;"
+                       ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
+                       ondragover="PlacesMenuDNDHandler.onDragOver(event);"
+                       ondragleave="PlacesMenuDNDHandler.onDragLeave(event);"
+                       ondrop="PlacesMenuDNDHandler.onDrop(event);"
+                       customizableui-areatype="toolbar"
+                       oncommand="BookmarkingUI.onCommand(event);">
+          <menupopup id="BMB_bookmarksPopup"
+                     placespopup="true"
+                     context="placesContext"
+                     openInTabs="children"
+                     anonanchorclass="toolbarbutton-menubutton-dropmarker"
+                     oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);"
+                     onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);"
+                     onpopupshowing="BookmarkingUI.onPopupShowing(event);
+                                     if (!this.parentNode._placesView)
+                                       new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
+                     tooltip="bhTooltip" popupsinherittooltip="true">
+            <menuitem id="BMB_bookmarksShowAll"
+                      label="&showAllBookmarks2.label;"
+                      command="Browser:ShowAllBookmarks"
+                      key="manBookmarkKb"/>
+            <menuitem id="BMB_viewBookmarksSidebar"
+                      label="&viewBookmarksSidebar2.label;"
+                      type="checkbox"
+                      oncommand="toggleSidebar('viewBookmarksSidebar');">
+              <observes element="viewBookmarksSidebar" attribute="checked"/>
+            </menuitem>
+            <menuseparator/>
+            <menuitem id="BMB_subscribeToPageMenuitem"
 #ifndef XP_MACOSX
-                    class="menuitem-iconic"
+                      class="menuitem-iconic"
 #endif
-                    label="&bookmarkThisPageCmd.label;"
-                    command="Browser:AddBookmarkAs"
-                    key="addBookmarkAsKb"/>
-          <menuitem id="BMB_subscribeToPageMenuitem"
+                      label="&subscribeToPageMenuitem.label;"
+                      oncommand="return FeedHandler.subscribeToFeed(null, event);"
+                      onclick="checkForMiddleClick(this, event);"
+                      observes="singleFeedMenuitemState"/>
+            <menu id="BMB_subscribeToPageMenupopup"
 #ifndef XP_MACOSX
-                    class="menuitem-iconic"
+                  class="menu-iconic"
 #endif
-                    label="&subscribeToPageMenuitem.label;"
-                    oncommand="return FeedHandler.subscribeToFeed(null, event);"
-                    onclick="checkForMiddleClick(this, event);"
-                    observes="singleFeedMenuitemState"/>
-          <menu id="BMB_subscribeToPageMenupopup"
-#ifndef XP_MACOSX
-                class="menu-iconic"
-#endif
-                label="&subscribeToPageMenupopup.label;"
-                observes="multipleFeedsMenuState">
-            <menupopup id="BMB_subscribeToPageSubmenuMenupopup"
-                       onpopupshowing="return FeedHandler.buildFeedList(event.target);"
-                       oncommand="return FeedHandler.subscribeToFeed(null, event);"
-                       onclick="checkForMiddleClick(this, event);"/>
-          </menu>
-          <menuseparator/>
-          <menu id="BMB_bookmarksToolbar"
-                placesanonid="toolbar-autohide"
-                class="menu-iconic bookmark-item"
-                label="&personalbarCmd.label;"
-                container="true">
-            <menupopup id="BMB_bookmarksToolbarPopup"
-                       placespopup="true"
-                       context="placesContext"
-                       onpopupshowing="if (!this.parentNode._placesView)
-                                         new PlacesMenu(event, 'place:folder=TOOLBAR');"/>
-          </menu>
-          <menuseparator/>
-          <!-- Bookmarks menu items -->
-          <menuseparator builder="end"
-                         class="hide-if-empty-places-result"/>
-          <menuitem id="BMB_unsortedBookmarks"
-                    label="&bookmarksMenuButton.unsorted.label;"
-                    oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"
-                    class="menuitem-iconic"/>
-        </menupopup>
-      </toolbarbutton>
+                  label="&subscribeToPageMenupopup.label;"
+                  observes="multipleFeedsMenuState">
+              <menupopup id="BMB_subscribeToPageSubmenuMenupopup"
+                         onpopupshowing="return FeedHandler.buildFeedList(event.target);"
+                         oncommand="return FeedHandler.subscribeToFeed(null, event);"
+                         onclick="checkForMiddleClick(this, event);"/>
+            </menu>
+            <menuseparator/>
+            <menu id="BMB_bookmarksToolbar"
+                  class="menu-iconic bookmark-item"
+                  label="&personalbarCmd.label;"
+                  container="true">
+              <menupopup id="BMB_bookmarksToolbarPopup"
+                         placespopup="true"
+                         context="placesContext"
+                         onpopupshowing="if (!this.parentNode._placesView)
+                                           new PlacesMenu(event, 'place:folder=TOOLBAR');">
+                <menuitem id="BMB_viewBookmarksToolbar"
+                          placesanonid="view-toolbar"
+                          toolbarId="PersonalToolbar"
+                          type="checkbox"
+                          oncommand="onViewToolbarCommand(event)"
+                          label="&viewBookmarksToolbar.label;"/>
+                <menuseparator/>
+                <!-- Bookmarks toolbar items -->
+              </menupopup>
+            </menu>
+            <menu id="BMB_unsortedBookmarks"
+                  class="menu-iconic bookmark-item"
+                  label="&bookmarksMenuButton.unsorted.label;"
+                  container="true">
+              <menupopup id="BMB_unsortedBookmarksPopup"
+                         placespopup="true"
+                         context="placesContext"
+                         onpopupshowing="if (!this.parentNode._placesView)
+                                           new PlacesMenu(event, 'place:folder=UNFILED_BOOKMARKS');"/>
+            </menu>
+            <menuseparator/>
+            <!-- Bookmarks menu items -->
+          </menupopup>
+        </toolbarbutton>
 
-      <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     persist="class" removable="true"
-                     label="&homeButton.label;"
-                     ondragover="homeButtonObserver.onDragOver(event)"
-                     ondragenter="homeButtonObserver.onDragOver(event)"
-                     ondrop="homeButtonObserver.onDrop(event)"
-                     ondragexit="homeButtonObserver.onDragExit(event)"
-                     onclick="BrowserGoHome(event);"
-                     aboutHomeOverrideTooltip="&abouthome.pageTitle;"/>
+        <!-- This is a placeholder for the Downloads Indicator.  It is visible
+             during the customization of the toolbar, in the palette, and before
+             the Downloads Indicator overlay is loaded. -->
+        <toolbarbutton id="downloads-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       oncommand="DownloadsIndicatorView.onCommand(event);"
+                       ondrop="DownloadsIndicatorView.onDrop(event);"
+                       ondragover="DownloadsIndicatorView.onDragOver(event);"
+                       ondragenter="DownloadsIndicatorView.onDragOver(event);"
+                       label="&downloads.label;"
+                       removable="true"
+                       customizableui-areatype="toolbar"
+                       tooltiptext="&downloads.tooltip;"/>
 
-      <toolbarbutton id="social-share-button"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     hidden="true"
-                     label="&sharePageCmd.label;"
-                     tooltiptext="&sharePageCmd.label;"
-                     command="Social:SharePage"/>
+        <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       persist="class" removable="true"
+                       label="&homeButton.label;"
+                       ondragover="homeButtonObserver.onDragOver(event)"
+                       ondragenter="homeButtonObserver.onDragOver(event)"
+                       ondrop="homeButtonObserver.onDrop(event)"
+                       ondragexit="homeButtonObserver.onDragExit(event)"
+                       onclick="BrowserGoHome(event);"
+                       customizableui-areatype="toolbar"
+                       aboutHomeOverrideTooltip="&abouthome.pageTitle;"/>
+
 
-      <toolbaritem id="social-toolbar-item"
-                   class="chromeclass-toolbar-additional"
-                   removable="false"
-                   title="&socialToolbar.title;"
-                   hidden="true"
-                   skipintoolbarset="true"
-                   observes="socialActiveBroadcaster">
+        <toolbarbutton id="social-share-button"
+                       class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       hidden="true"
+                       overflows="false"
+                       label="&sharePageCmd.label;"
+                       tooltiptext="&sharePageCmd.label;"
+                       customizableui-areatype="toolbar"
+                       command="Social:SharePage"/>
+
+        <toolbaritem id="social-toolbar-item"
+                     class="chromeclass-toolbar-additional"
+                     removable="false"
+                     title="&socialToolbar.title;"
+                     hidden="true"
+                     overflows="false"
+                     customizableui-areatype="toolbar"
+                     observes="socialActiveBroadcaster">
         <toolbarbutton id="social-notification-icon" class="default-notification-icon toolbarbutton-1 notification-anchor-icon"
                    oncommand="PopupNotifications._reshowNotifications(this,
                                 document.getElementById('social-sidebar-browser'));"/>
-        <toolbarbutton id="social-provider-button"
-                       class="toolbarbutton-1"
-                       type="menu">
-          <menupopup id="social-statusarea-popup">
-            <menuitem class="social-statusarea-user menuitem-iconic" pack="start" align="center"
-                      observes="socialBroadcaster_userDetails"
-                      oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();">
-              <image class="social-statusarea-user-portrait"
-                     observes="socialBroadcaster_userDetails"/>
-              <vbox>
-                <label class="social-statusarea-loggedInStatus"
+          <toolbarbutton id="social-provider-button"
+                         class="toolbarbutton-1"
+                         type="menu">
+            <menupopup id="social-statusarea-popup">
+              <menuitem class="social-statusarea-user menuitem-iconic" pack="start" align="center"
+                        observes="socialBroadcaster_userDetails"
+                        oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();">
+                <image class="social-statusarea-user-portrait"
                        observes="socialBroadcaster_userDetails"/>
-              </vbox>
-            </menuitem>
+                <vbox>
+                  <label class="social-statusarea-loggedInStatus"
+                         observes="socialBroadcaster_userDetails"/>
+                </vbox>
+              </menuitem>
 #ifndef XP_WIN
-            <menuseparator class="social-statusarea-separator"/>
+              <menuseparator class="social-statusarea-separator"/>
 #endif
-            <menuitem class="social-toggle-sidebar-menuitem"
-                      type="checkbox"
-                      autocheck="false"
-                      command="Social:ToggleSidebar"
-                      label="&social.toggleSidebar.label;"
-                      accesskey="&social.toggleSidebar.accesskey;"/>
-            <menuitem class="social-toggle-notifications-menuitem"
-                      type="checkbox"
-                      autocheck="false"
-                      command="Social:ToggleNotifications"
-                      label="&social.toggleNotifications.label;"
-                      accesskey="&social.toggleNotifications.accesskey;"/>
-            <menuitem class="social-toggle-menuitem" command="Social:Toggle"/>
-            <menuseparator/>
-            <menuseparator class="social-provider-menu" hidden="true"/>
-            <menuitem class="social-addons-menuitem" command="Social:Addons"
-                      label="&social.addons.label;"/>
-            <menuitem label="&social.learnMore.label;"
-                      accesskey="&social.learnMore.accesskey;"
-                      oncommand="SocialUI.showLearnMore();"/>
-          </menupopup>
-        </toolbarbutton>
+              <menuitem class="social-toggle-sidebar-menuitem"
+                        type="checkbox"
+                        autocheck="false"
+                        command="Social:ToggleSidebar"
+                        label="&social.toggleSidebar.label;"
+                        accesskey="&social.toggleSidebar.accesskey;"/>
+              <menuitem class="social-toggle-notifications-menuitem"
+                        type="checkbox"
+                        autocheck="false"
+                        command="Social:ToggleNotifications"
+                        label="&social.toggleNotifications.label;"
+                        accesskey="&social.toggleNotifications.accesskey;"/>
+              <menuitem class="social-toggle-menuitem" command="Social:Toggle"/>
+              <menuseparator/>
+              <menuseparator class="social-provider-menu" hidden="true"/>
+              <menuitem class="social-addons-menuitem" command="Social:Addons"
+                        label="&social.addons.label;"/>
+              <menuitem label="&social.learnMore.label;"
+                        accesskey="&social.learnMore.accesskey;"
+                        oncommand="SocialUI.showLearnMore();"/>
+            </menupopup>
+          </toolbarbutton>
+        </toolbaritem>
+      </hbox>
+
+      <toolbarbutton id="nav-bar-overflow-button"
+                     class="toolbarbutton-1 chromeclass-toolbar-additional chevron overflow-button"
+                     skipintoolbarset="true"
+                     tooltiptext="&navbarOverflow.label;"/>
+
+      <toolbaritem id="PanelUI-button"
+                   class="chromeclass-toolbar-additional"
+                   removable="false"
+                   title="&appmenu.title;">
+        <toolbarbutton id="PanelUI-menu-button"
+                       class="toolbarbutton-1"
+                       label="&brandShortName;"
+                       tooltiptext="&appmenu.title;"/>
       </toolbaritem>
 
-      <hbox id="window-controls" hidden="true" pack="end">
+      <hbox id="window-controls" hidden="true" pack="end" skipintoolbarset="true"
+            ordinal="1000">
         <toolbarbutton id="minimize-button"
                        tooltiptext="&fullScreenMinimize.tooltip;"
                        oncommand="window.minimize();"/>
 
         <toolbarbutton id="restore-button"
                        tooltiptext="&fullScreenRestore.tooltip;"
                        oncommand="BrowserFullScreen();"/>
 
@@ -767,28 +895,33 @@
              mode="icons" iconsize="small" defaulticonsize="small"
              lockiconsize="true"
              class="chromeclass-directories"
              context="toolbar-context-menu"
              defaultset="personal-bookmarks"
              toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"
              collapsed="true"
              customizable="true">
-      <toolbaritem flex="1" id="personal-bookmarks" title="&bookmarksItem.title;"
+      <toolbaritem id="personal-bookmarks"
+                   flex="1"
+                   title="&bookmarksToolbarItem.label;"
+                   customizableui-areatype="toolbar"
                    removable="true">
+        <toolbarbutton id="bookmarks-toolbar-placeholder"
+                       type="wrap"
+                       mousethrough="never"
+                       label="&bookmarksToolbarItem.label;"
+                       oncommand="PlacesToolbarHelper.onPlaceholderCommand();"/>
         <hbox flex="1"
               id="PlacesToolbar"
               context="placesContext"
               onclick="BookmarksEventHandler.onClick(event, this._placesView);"
               oncommand="BookmarksEventHandler.onCommand(event, this._placesView);"
               tooltip="bhTooltip"
               popupsinherittooltip="true">
-          <toolbarbutton class="bookmark-item bookmarks-toolbar-customize"
-                         mousethrough="never"
-                         label="&bookmarksToolbarItem.label;"/>
           <hbox flex="1">
             <hbox align="center">
               <image id="PlacesToolbarDropIndicator"
                      mousethrough="always"
                      collapsed="true"/>
             </hbox>
             <scrollbox orient="horizontal"
                        id="PlacesToolbarItems"
@@ -806,250 +939,111 @@
                          tooltip="bhTooltip" popupsinherittooltip="true"
                          context="placesContext"/>
             </toolbarbutton>
           </hbox>
         </hbox>
       </toolbaritem>
     </toolbar>
 
-#ifdef MENUBAR_CAN_AUTOHIDE
-#ifndef CAN_DRAW_IN_TITLEBAR
-#define APPMENU_ON_TABBAR
-#endif
-#endif
-
-
-    <toolbar id="TabsToolbar"
-             class="toolbar-primary"
-             fullscreentoolbar="true"
-             customizable="true"
-             mode="icons" lockmode="true"
-             iconsize="small" defaulticonsize="small" lockiconsize="true"
-             aria-label="&tabsToolbar.label;"
-             context="toolbar-context-menu"
-#ifdef APPMENU_ON_TABBAR
-             defaultset="appmenu-toolbar-button,tabbrowser-tabs,new-tab-button,alltabs-button,tabs-closebutton"
-#else
-             defaultset="tabbrowser-tabs,new-tab-button,alltabs-button,tabs-closebutton"
-#endif
-             collapsed="true">
-
-#ifdef APPMENU_ON_TABBAR
-      <toolbarbutton id="appmenu-toolbar-button"
-                     class="chromeclass-toolbar-additional"
-                     type="menu"
-                     label="&brandShortName;"
-                     tooltiptext="&appMenuButton.tooltip;">
-#include browser-appmenu.inc
-      </toolbarbutton>
-#endif
-
-      <tabs id="tabbrowser-tabs"
-            class="tabbrowser-tabs"
-            tabbrowser="content"
-            flex="1"
-            setfocus="false"
-            tooltip="tabbrowser-tab-tooltip"
-            stopwatchid="FX_TAB_CLICK_MS">
-        <tab class="tabbrowser-tab" selected="true" fadein="true"/>
-      </tabs>
-
-      <toolbarbutton id="new-tab-button"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&tabCmd.label;"
-                     command="cmd_newNavigatorTab"
-                     onclick="checkForMiddleClick(this, event);"
-                     tooltiptext="&newTabButton.tooltip;"
-                     ondrop="newTabButtonObserver.onDrop(event)"
-                     ondragover="newTabButtonObserver.onDragOver(event)"
-                     ondragenter="newTabButtonObserver.onDragOver(event)"
-                     ondragexit="newTabButtonObserver.onDragExit(event)"
-                     removable="true"/>
-
-      <toolbarbutton id="alltabs-button"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button"
-                     type="menu"
-                     label="&listAllTabs.label;"
-                     tooltiptext="&listAllTabs.label;"
-                     removable="true">
-        <menupopup id="alltabs-popup"
-                   position="after_end">
-          <menuitem id="menu_tabview"
-                    class="menuitem-iconic"
-                    key="key_tabview"
-                    label="&viewTabGroups.label;"
-                    command="Browser:ToggleTabView"
-                    observes="tabviewGroupsNumber"/>
-          <menuseparator id="alltabs-popup-separator"/>
-        </menupopup>
-      </toolbarbutton>
-
-      <toolbarbutton id="tabs-closebutton"
-                     class="close-button tabs-closebutton"
-                     command="cmd_close"
-                     label="&closeTab.label;"
-                     tooltiptext="&closeTab.label;"/>
-
-#ifdef CAN_DRAW_IN_TITLEBAR
-      <hbox class="titlebar-placeholder" type="appmenu-button" ordinal="0"/>
-      <hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"/>
-#endif
+    <!-- This is a shim which will go away ASAP. See bug 749804 for details -->
+    <toolbar id="addon-bar" toolbar-delegate="nav-bar">
+      <hbox id="addonbar-closebutton"/>
+      <statusbar id="status-bar"/>
     </toolbar>
-
     <toolbarpalette id="BrowserToolbarPalette">
 
 # Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding
 # or removing default items with the toolbarbutton-1 class.
 
       <toolbarbutton id="print-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&printButton.label;" command="cmd_print"
-                     tooltiptext="&printButton.tooltip;"/>
+#ifdef XP_MACOSX
+                     command="cmd_print"
+#else
+                     command="cmd_printPreview"
+#endif
+                     label="&printButton.label;" tooltiptext="&printButton.tooltip;"/>
 
-      <!-- This is a placeholder for the Downloads Indicator.  It is visible
-           during the customization of the toolbar, in the palette, and before
-           the Downloads Indicator overlay is loaded. -->
-      <toolbarbutton id="downloads-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     oncommand="DownloadsIndicatorView.onCommand(event);"
-                     ondrop="DownloadsIndicatorView.onDrop(event);"
-                     ondragover="DownloadsIndicatorView.onDragOver(event);"
-                     ondragenter="DownloadsIndicatorView.onDragOver(event);"
-                     label="&downloads.label;"
-                     tooltiptext="&downloads.tooltip;"/>
-
-      <toolbarbutton id="history-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     observes="viewHistorySidebar" label="&historyButton.label;"
-                     tooltiptext="&historyButton.tooltip;"/>
-
-      <toolbarbutton id="bookmarks-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     observes="viewBookmarksSidebar"
-                     tooltiptext="&bookmarksButton.tooltip;"
-                     ondrop="bookmarksButtonObserver.onDrop(event)"
-                     ondragover="bookmarksButtonObserver.onDragOver(event)"
-                     ondragenter="bookmarksButtonObserver.onDragOver(event)"
-                     ondragexit="bookmarksButtonObserver.onDragExit(event)"/>
 
       <toolbarbutton id="new-window-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&newNavigatorCmd.label;"
                      command="key_newNavigator"
                      tooltiptext="&newWindowButton.tooltip;"
                      ondrop="newWindowButtonObserver.onDrop(event)"
                      ondragover="newWindowButtonObserver.onDragOver(event)"
                      ondragenter="newWindowButtonObserver.onDragOver(event)"
                      ondragexit="newWindowButtonObserver.onDragExit(event)"/>
 
       <toolbarbutton id="fullscreen-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      observes="View:FullScreen"
                      type="checkbox"
                      label="&fullScreenCmd.label;"
                      tooltiptext="&fullScreenButton.tooltip;"/>
 
-      <toolbaritem id="zoom-controls" class="chromeclass-toolbar-additional"
-                   title="&zoomControls.label;">
-        <toolbarbutton id="zoom-out-button" class="toolbarbutton-1"
-                       label="&fullZoomReduceCmd.label;"
-                       command="cmd_fullZoomReduce"
-                       tooltiptext="&zoomOutButton.tooltip;"/>
-        <toolbarbutton id="zoom-in-button" class="toolbarbutton-1"
-                       label="&fullZoomEnlargeCmd.label;"
-                       command="cmd_fullZoomEnlarge"
-                       tooltiptext="&zoomInButton.tooltip;"/>
-      </toolbaritem>
-
-      <toolbarbutton id="feed-button"
-                     type="menu"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     disabled="true"
-                     label="&feedButton.label;"
-                     tooltiptext="&feedButton.tooltip;"
-                     onclick="return FeedHandler.onFeedButtonClick(event);">
-        <menupopup position="after_end"
-                   id="feed-menu"
-                   onpopupshowing="return FeedHandler.buildFeedList(this);"
-                   oncommand="return FeedHandler.subscribeToFeed(null, event);"
-                   onclick="checkForMiddleClick(this, event);"/>
-      </toolbarbutton>
-
-      <toolbarbutton id="cut-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&cutCmd.label;"
-                     command="cmd_cut"
-                     tooltiptext="&cutButton.tooltip;"/>
-
-      <toolbarbutton id="copy-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&copyCmd.label;"
-                     command="cmd_copy"
-                     tooltiptext="&copyButton.tooltip;"/>
-
-      <toolbarbutton id="paste-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&pasteCmd.label;"
-                     command="cmd_paste"
-                     tooltiptext="&pasteButton.tooltip;"/>
-
 #ifdef MOZ_SERVICES_SYNC
       <toolbarbutton id="sync-button"
                      class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&syncToolbarButton.label;"
                      oncommand="gSyncUI.handleToolbarButton()"/>
 #endif
 
-      <toolbaritem id="navigator-throbber" title="&throbberItem.title;" align="center" pack="center"
-                   mousethrough="always">
-        <image/>
-      </toolbaritem>
-
       <toolbarbutton id="tabview-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&tabGroupsButton.label;"
                      command="Browser:ToggleTabView"
                      tooltiptext="&tabGroupsButton.tooltip;"
                      observes="tabviewGroupsNumber"/>
     </toolbarpalette>
   </toolbox>
 
   <hbox id="fullscr-toggler" collapsed="true"/>
 
-  <hbox flex="1" id="browser">
-    <vbox id="browser-border-start" hidden="true" layer="true"/>
-    <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
-      <sidebarheader id="sidebar-header" align="center">
-        <label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
-        <image id="sidebar-throbber"/>
-        <toolbarbutton class="tabs-closebutton" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="toggleSidebar();"/>
-      </sidebarheader>
-      <browser id="sidebar" flex="1" autoscroll="false" disablehistory="true"
-                style="min-width: 14em; width: 18em; max-width: 36em;"/>
-    </vbox>
+  <deck id="content-deck" flex="1">
+    <hbox flex="1" id="browser">
+      <vbox id="browser-border-start" hidden="true" layer="true"/>
+      <vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">
+        <sidebarheader id="sidebar-header" align="center">
+          <label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
+          <image id="sidebar-throbber"/>
+          <toolbarbutton class="tabs-closebutton close-icon" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="toggleSidebar();"/>
+        </sidebarheader>
+        <browser id="sidebar" flex="1" autoscroll="false" disablehistory="true"
+                  style="min-width: 14em; width: 18em; max-width: 36em;"/>
+      </vbox>
 
-    <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
-    <vbox id="appcontent" flex="1">
-      <tabbrowser id="content" disablehistory="true"
-                  flex="1" contenttooltip="aHTMLTooltip"
-                  tabcontainer="tabbrowser-tabs"
-                  contentcontextmenu="contentAreaContextMenu"
-                  autocompletepopup="PopupAutoComplete"
-                  selectpopup="ContentSelectDropdown"/>
-      <chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
-    </vbox>
-    <splitter id="social-sidebar-splitter"
-              class="chromeclass-extrachrome sidebar-splitter"
-              observes="socialSidebarBroadcaster"/>
-    <vbox id="social-sidebar-box"
-          class="chromeclass-extrachrome"
-          observes="socialSidebarBroadcaster"
-          persist="width">
-      <browser id="social-sidebar-browser"
-               type="content"
-               context="contentAreaContextMenu"
-               disableglobalhistory="true"
-               tooltip="aHTMLTooltip"
+      <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
+      <vbox id="appcontent" flex="1">
+        <tabbrowser id="content" disablehistory="true"
+                    flex="1" contenttooltip="aHTMLTooltip"
+                    tabcontainer="tabbrowser-tabs"
+                    contentcontextmenu="contentAreaContextMenu"
+                    autocompletepopup="PopupAutoComplete"
+                    selectpopup="ContentSelectDropdown"
+                    onclick="contentAreaClick(event, false);"/>
+        <chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
+      </vbox>
+      <splitter id="social-sidebar-splitter"
+                class="chromeclass-extrachrome sidebar-splitter"
+                observes="socialSidebarBroadcaster"/>
+      <vbox id="social-sidebar-box"
+            class="chromeclass-extrachrome"
+            observes="socialSidebarBroadcaster"
+            persist="width">
+        <browser id="social-sidebar-browser"
+                 type="content"
+                 context="contentAreaContextMenu"
+                 disableglobalhistory="true"
+                 tooltip="aHTMLTooltip"
                popupnotificationanchor="social-notification-icon"
-               flex="1"
-               style="min-width: 14em; width: 18em; max-width: 36em;"/>
-    </vbox>
-    <vbox id="browser-border-end" hidden="true" layer="true"/>
-  </hbox>
+                 flex="1"
+                 style="min-width: 14em; width: 18em; max-width: 36em;"/>
+      </vbox>
+      <vbox id="browser-border-end" hidden="true" layer="true"/>
+    </hbox>
+#include ../../components/customizableui/content/customizeMode.inc.xul
+  </deck>
 
   <hbox id="full-screen-warning-container" hidden="true" fadeout="true">
     <hbox style="width: 100%;" pack="center"> <!-- Inner hbox needed due to bug 579776. -->
       <vbox id="full-screen-warning-message" align="center">
         <description id="full-screen-domain-text"/>
         <description class="full-screen-description" value="&fullscreenExitHint2.value;"/>
         <vbox id="full-screen-approval-pane" align="center">
           <hbox>
@@ -1096,66 +1090,43 @@
                          tooltiptext="&devToolbarToolsButton.tooltip;"/>
 #ifndef XP_MACOSX
           <toolbarbutton id="developer-toolbar-closebutton"
                          class="devtools-closebutton"
                          oncommand="DeveloperToolbar.hide();"
                          tooltiptext="&devToolbarCloseButton.tooltiptext;"/>
 #endif
    </toolbar>
-
-    <toolbar id="addon-bar"
-             toolbarname="&addonBarCmd.label;" accesskey="&addonBarCmd.accesskey;"
-             collapsed="true"
-             class="toolbar-primary chromeclass-toolbar"
-             context="toolbar-context-menu" toolboxid="navigator-toolbox"
-             mode="icons" iconsize="small" defaulticonsize="small"
-             lockiconsize="true"
-             defaultset="addonbar-closebutton,spring,status-bar"
-             customizable="true"
-             key="key_toggleAddonBar">
-      <toolbarbutton id="addonbar-closebutton"
-                     tooltiptext="&addonBarCloseButton.tooltip;"
-                     oncommand="setToolbarVisibility(this.parentNode, false);"/>
-      <statusbar id="status-bar" ordinal="1000"/>
-    </toolbar>
   </vbox>
 
+  <svg:svg height="0">
+    <svg:clipPath id="tab-curve-clip-path-start" clipPathUnits="objectBoundingBox">
+      <svg:path d="m 1,0.0625 0.05,0 0,0.938 -1,0 0,-0.028 C 0.32082458,0.95840561 0.4353096,0.81970962 0.48499998,0.5625 0.51819998,0.3905 0.535,0.0659 1,0.0625 z"/>
+    </svg:clipPath>
+    <svg:clipPath id="tab-curve-clip-path-end" clipPathUnits="objectBoundingBox">
+      <svg:path d="m 0,0.0625 -0.05,0 0,0.938 1,0 0,-0.028 C 0.67917542,0.95840561 0.56569036,0.81970962 0.51599998,0.5625 0.48279998,0.3905 0.465,0.0659 0,0.0625 z"/>
+    </svg:clipPath>
+
 #ifndef XP_UNIX
-  <svg:svg height="0">
     <svg:clipPath id="windows-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox">
       <svg:path d="M 0,0 C 0.16,0.11 0.28,0.29 0.28,0.5 0.28,0.71 0.16,0.89 0,1 L 1,1 1,0 0,0 z"/>
     </svg:clipPath>
     <svg:clipPath id="windows-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
-      <svg:path d="M 0,0 0,7.8 C 2.5,11 4,14 4,18 4,22 2.5,25 0,28 l 0,22 10000,0 0,-50 L 0,0 z"/>
+      <svg:path d="m 0,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22l10000,0 l 0,-50 l -10000,0 z"/>
     </svg:clipPath>
-  </svg:svg>
 #endif
 #ifdef XP_MACOSX
-  <svg:svg height="0">
     <svg:clipPath id="osx-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox">
       <svg:path d="M 0,0 C 0.15,0.12 0.25,0.3 0.25,0.5 0.25,0.7 0.15,0.88 0,1 L 1,1 1,0 0,0 z"/>
     </svg:clipPath>
     <svg:clipPath id="osx-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
-      <svg:path d="m 0,-5 0,4.03 C 3.6,1.8 6,6.1 6,11 6,16 3.6,20 0,23 l 0,27 10000,0 0,-55 L 0,-5 z"/>
-    </svg:clipPath>
-    <svg:clipPath id="osx-tab-ontop-left-curve-clip-path" clipPathUnits="userSpaceOnUse">
-      <svg:path d="M 9,0 C 7.3,0 6,1.3 6,3 l 0,14 c 0,3 -2.2,5 -5,5 l -1,0 0,1 12,0 0,-1 0,-19 0,-3 -3,0 z"/>
-    </svg:clipPath>
-    <svg:clipPath id="osx-tab-ontop-right-curve-clip-path" clipPathUnits="userSpaceOnUse">
-      <svg:path d="m 0,0 0,3 0,19 0,1 12,0 0,-1 -1,0 C 8.2,22 6,20 6,17 L 6,3 C 6,1.3 4.7,0 3,0 L 0,0 z"/>
+      <svg:path d="m -3,-10 l -0.1,7.7 c 6.6,1.8 8.8,7.6 8.8,12.5 c 0,5 -1.9,11.5 -8.25,13.25 l 0.05,25.75 l 10000,0 l 0,-55 l -10000,-4.2 z"/>
     </svg:clipPath>
-    <svg:clipPath id="osx-tab-onbottom-left-curve-clip-path" clipPathUnits="userSpaceOnUse">
-      <svg:path d="m 0,0 0,1 1,0 c 2.8,0 5,2.2 5,5 l 0,14 c 0,2 1.3,3 3,3 l 3,0 0,-3 L 12,1 12,0 0,0 z"/>
-    </svg:clipPath>
-    <svg:clipPath id="osx-tab-onbottom-right-curve-clip-path" clipPathUnits="userSpaceOnUse">
-      <svg:path d="m 0,0 0,1 0,19 0,3 3,0 c 1.7,0 3,-1 3,-3 L 6,6 C 6,3.2 8.2,1 11,1 L 12,1 12,0 0,0 z"/>
-    </svg:clipPath>
+#endif
   </svg:svg>
-#endif
 
 </vbox>
 # <iframe id="tab-view"> is dynamically appended as the 2nd child of #tab-view-deck.
 #     Introducing the iframe dynamically, as needed, was found to be better than
 #     starting with an empty iframe here in browser.xul from a Ts standpoint.
 </deck>
 
 </window>
--- a/browser/base/content/global-scripts.inc
+++ b/browser/base/content/global-scripts.inc
@@ -4,10 +4,11 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 <script type="application/javascript" src="chrome://global/content/printUtils.js"/>
 <script type="application/javascript" src="chrome://global/content/viewZoomOverlay.js"/>
 <script type="application/javascript" src="chrome://browser/content/places/browserPlacesViews.js"/>
 <script type="application/javascript" src="chrome://browser/content/browser.js"/>
 <script type="application/javascript" src="chrome://browser/content/downloads/downloads.js"/>
 <script type="application/javascript" src="chrome://browser/content/downloads/indicator.js"/>
+<script type="application/javascript" src="chrome://browser/content/customizableui/panelUI.js"/>
 <script type="application/javascript" src="chrome://global/content/inlineSpellCheckUI.js"/>
 <script type="application/javascript" src="chrome://global/content/viewSourceUtils.js"/>
--- a/browser/base/content/newtab/newTab.xul
+++ b/browser/base/content/newtab/newTab.xul
@@ -26,16 +26,17 @@
                      value="&newtab.undo.removedLabel;" />
           <xul:button id="newtab-undo-button" tabindex="-1"
                       label="&newtab.undo.undoButton;"
                       class="newtab-undo-button" />
           <xul:button id="newtab-undo-restore-button" tabindex="-1"
                       label="&newtab.undo.restoreButton;"
                       class="newtab-undo-button" />
           <xul:toolbarbutton id="newtab-undo-close-button" tabindex="-1"
+                             class="close-icon"
                              tooltiptext="&newtab.undo.closeTooltip;" />
         </div>
       </div>
 
       <div id="newtab-horizontal-margin">
         <div class="newtab-side-margin"/>
 
         <div id="newtab-grid">
--- a/browser/base/content/sync/notification.xml
+++ b/browser/base/content/sync/notification.xml
@@ -78,17 +78,17 @@
 
     </implementation>
   </binding>
 
   <binding id="notification" extends="chrome://global/content/bindings/notification.xml#notification">
     <content>
       <xul:hbox class="notification-inner outset" flex="1" xbl:inherits="type">
         <xul:toolbarbutton ondblclick="event.stopPropagation();"
-                           class="messageCloseButton tabbable"
+                           class="messageCloseButton close-icon tabbable"
                            xbl:inherits="hidden=hideclose"
                            tooltiptext="&closeNotification.tooltip;"
                            oncommand="document.getBindingParent(this).close()"/>
         <xul:hbox anonid="details" align="center" flex="1">
           <xul:image anonid="messageImage" class="messageImage" xbl:inherits="src=image"/>
           <xul:description anonid="messageText" class="messageText" xbl:inherits="xbl:text=label"/>
 
           <!-- The children are the buttons defined by the notification. -->
--- a/browser/base/content/tabbrowser.css
+++ b/browser/base/content/tabbrowser.css
@@ -36,16 +36,17 @@ tabpanels {
   background-color: transparent;
 }
 
 .tab-drop-indicator {
   position: relative;
   z-index: 2;
 }
 
+.tab-icon-image:not([src]):not([pinned]),
 .tab-throbber:not([busy]),
 .tab-throbber[busy] + .tab-icon-image {
   display: none;
 }
 
 .closing-tabs-spacer {
   pointer-events: none;
 }
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -202,18 +202,17 @@
         ]]></body>
       </method>
 
       <method name="updateWindowResizers">
         <body><![CDATA[
           if (!window.gShowPageResizers)
             return;
 
-          var show = document.getElementById("addon-bar").collapsed &&
-                     window.windowState == window.STATE_NORMAL;
+          var show = window.windowState == window.STATE_NORMAL;
           for (let i = 0; i < this.browsers.length; i++) {
             this.browsers[i].showWindowResizer = show;
           }
         ]]></body>
       </method>
 
       <method name="_setCloseKeyState">
         <parameter name="aEnabled"/>
@@ -994,17 +993,17 @@
 
             newBrowser.setAttribute("type", "content-primary");
             newBrowser.docShellIsActive =
               (window.windowState != window.STATE_MINIMIZED);
             this.mCurrentBrowser = newBrowser;
             this.mCurrentTab = this.tabContainer.selectedItem;
             this.showTab(this.mCurrentTab);
 
-            var backForwardContainer = document.getElementById("unified-back-forward-button");
+            var backForwardContainer = document.getElementById("urlbar-container");
             if (backForwardContainer) {
               backForwardContainer.setAttribute("switchingtabs", "true");
               window.addEventListener("MozAfterPaint", function removeSwitchingtabsAttr() {
                 window.removeEventListener("MozAfterPaint", removeSwitchingtabsAttr);
                 backForwardContainer.removeAttribute("switchingtabs");
               });
             }
 
@@ -1485,18 +1484,17 @@
             b.setAttribute("type", "content-targetable");
             b.setAttribute("message", "true");
             b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
             b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
 
             if (remote)
               b.setAttribute("remote", "true");
 
-            if (window.gShowPageResizers && document.getElementById("addon-bar").collapsed &&
-                window.windowState == window.STATE_NORMAL) {
+            if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
               b.setAttribute("showresizer", "true");
             }
 
             if (this.hasAttribute("autocompletepopup"))
               b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
 
             if (this.hasAttribute("selectpopup"))
               b.setAttribute("selectpopup", this.getAttribute("selectpopup"));
@@ -1890,16 +1888,21 @@
                 return null;
 
               newTab = true;
             }
 
             aTab.closing = true;
             this._removingTabs.push(aTab);
             this._visibleTabs = null; // invalidate cache
+
+            // Invalidate hovered tab state tracking for this closing tab.
+            if (this.tabContainer._hoveredTab == aTab)
+              aTab._mouseleave();
+
             if (newTab)
               this.addTab(BROWSER_NEW_TAB_URL, {skipAnimation: true});
             else
               this.tabContainer.updateVisibility();
 
             // We're committed to closing the tab now.
             // Dispatch a notification.
             // We dispatch it before any teardown so that event listeners can
@@ -3208,18 +3211,21 @@
         tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab,
                                               tabs.tabbrowser);
 
         tabs._positionPinnedTabs();
       ]]></handler>
       <handler event="overflow"><![CDATA[
         if (event.detail == 0)
           return; // Ignore vertical events
-
         var tabs = document.getBindingParent(this);
+        var numberOfTabs = tabs.tabbrowser.visibleTabs.length;
+        if (numberOfTabs == 1)
+          return;
+
         tabs.setAttribute("overflow", "true");
         tabs._positionPinnedTabs();
         tabs._handleTabSelect(false);
       ]]></handler>
     </handlers>
   </binding>
 
   <binding id="tabbrowser-tabs"
@@ -3306,16 +3312,17 @@
         document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox");
       </field>
 
       <field name="_firstTab">null</field>
       <field name="_lastTab">null</field>
       <field name="_afterSelectedTab">null</field>
       <field name="_beforeHoveredTab">null</field>
       <field name="_afterHoveredTab">null</field>
+      <field name="_hoveredTab">null</field>
 
       <method name="_setPositionalAttributes">
         <body><![CDATA[
           let visibleTabs = this.tabbrowser.visibleTabs;
 
           if (!visibleTabs.length)
             return;
 
@@ -3336,16 +3343,22 @@
           if (this._firstTab)
             this._firstTab.removeAttribute("first-visible-tab");
           this._firstTab = visibleTabs[0];
           this._firstTab.setAttribute("first-visible-tab", "true");
           if (this._lastTab)
             this._lastTab.removeAttribute("last-visible-tab");
           this._lastTab = visibleTabs[lastVisible];
           this._lastTab.setAttribute("last-visible-tab", "true");
+
+          let hoveredTab = this._hoveredTab;
+          if (hoveredTab) {
+            hoveredTab._mouseleave();
+            hoveredTab._mouseenter();
+          }
         ]]></body>
       </method>
 
       <field name="_prefObserver"><![CDATA[({
         tabContainer: this,
 
         observe: function (subject, topic, data) {
           switch (data) {
@@ -3414,20 +3427,16 @@
       <method name="_propagateVisibility">
         <body><![CDATA[
           let visible = this.visible;
 
           document.getElementById("menu_closeWindow").hidden = !visible;
           document.getElementById("menu_close").setAttribute("label",
             this.tabbrowser.mStringBundle.getString(visible ? "tabs.closeTab" : "tabs.close"));
 
-          goSetCommandEnabled("cmd_ToggleTabsOnTop", visible);
-
-          TabsOnTop.syncUI();
-
           TabsInTitlebar.allowedBy("tabs-visible", visible);
         ]]></body>
       </method>
 
       <method name="updateVisibility">
         <body><![CDATA[
           if (this.childNodes.length - this.tabbrowser._removingTabs.length == 1)
             this.visible = window.toolbar.visible;
@@ -3769,26 +3778,26 @@
           switch (aEvent.type) {
             case "load":
               this.updateVisibility();
               break;
             case "resize":
               if (aEvent.target != window)
                 break;
 
-              let sizemode = document.documentElement.getAttribute("sizemode");
-              TabsInTitlebar.allowedBy("sizemode",
-                                       sizemode == "maximized" || sizemode == "fullscreen");
-
-              var width = this.mTabstrip.boxObject.width;
-              if (width != this.mTabstripWidth) {
-                this.adjustTabstrip();
-                this._fillTrailingGap();
-                this._handleTabSelect();
-                this.mTabstripWidth = width;
+              TabsInTitlebar.updateAppearance();
+
+              if (this.tabbrowser.visibleTabs.length > 1) {
+                var width = this.mTabstrip.boxObject.width;
+                if (width != this.mTabstripWidth) {
+                  this.adjustTabstrip();
+                  this._fillTrailingGap();
+                  this._handleTabSelect();
+                  this.mTabstripWidth = width;
+                }
               }
 
               this.tabbrowser.updateWindowResizers();
               break;
             case "mouseout":
               // If the "related target" (the node to which the pointer went) is not
               // a child of the current document, the mouse just left the window.
               let relatedTarget = aEvent.relatedTarget;
@@ -4072,18 +4081,17 @@
         }
       ]]></handler>
 
       <handler event="dblclick"><![CDATA[
 #ifndef XP_MACOSX
         // When the tabbar has an unified appearance with the titlebar
         // and menubar, a double-click in it should have the same behavior
         // as double-clicking the titlebar
-        if (TabsInTitlebar.enabled ||
-            (TabsOnTop.enabled && this.parentNode._dragBindingAlive))
+        if (TabsInTitlebar.enabled || this.parentNode._dragBindingAlive)
           return;
 #endif
 
         if (event.button != 0 ||
             event.originalTarget.localName != "box")
           return;
 
         // See hack note in the tabbrowser-close-tab-button binding
@@ -4504,17 +4512,17 @@
          * with the tabbar as its event target (and explicit/originalTarget),
          * which treats that as a mouse gesture for opening a new tab.
          * In this context, we're manually blocking the dblclick event
          * (see dblclick handler).
          */
         var clickedOnce = false;
         function enableDblClick(event) {
           var target = event.originalTarget;
-          if (target.className == 'tab-close-button')
+          if (target.classList.contains("tab-close-button"))
             target._ignoredClick = true;
           if (!clickedOnce) {
             clickedOnce = true;
             return;
           }
           tabContainer._blockDblClick = false;
           tabContainer.removeEventListener("click", enableDblClick, true);
         }
@@ -4560,17 +4568,17 @@
                      validate="never"
                      role="presentation"/>
           <xul:label flex="1"
                      xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected"
                      class="tab-text tab-label"
                      role="presentation"/>
           <xul:toolbarbutton anonid="close-button"
                              xbl:inherits="fadein,pinned,selected"
-                             class="tab-close-button"/>
+                             class="tab-close-button close-icon"/>
         </xul:hbox>
       </xul:stack>
     </content>
 
     <implementation>
       <property name="pinned" readonly="true">
         <getter>
           return this.getAttribute("pinned") == "true";
@@ -4581,65 +4589,80 @@
           return this.getAttribute("hidden") == "true";
         </getter>
       </property>
 
       <field name="mOverCloseButton">false</field>
       <field name="mCorrespondingMenuitem">null</field>
       <field name="closing">false</field>
       <field name="lastAccessed">0</field>
+
+      <method name="_mouseenter">
+        <body><![CDATA[
+          if (this.closing)
+            return;
+
+          let tabContainer = this.parentNode;
+          let visibleTabs = tabContainer.tabbrowser.visibleTabs;
+          let tabIndex = visibleTabs.indexOf(this);
+          if (tabIndex == 0) {
+            tabContainer._beforeHoveredTab = null;
+          } else {
+            let candidate = visibleTabs[tabIndex - 1];
+            if (!candidate.selected) {
+              tabContainer._beforeHoveredTab = candidate;
+              candidate.setAttribute("beforehovered", "true");
+            }
+          }
+
+          if (tabIndex == visibleTabs.length - 1) {
+            tabContainer._afterHoveredTab = null;
+          } else {
+            let candidate = visibleTabs[tabIndex + 1];
+            if (!candidate.selected) {
+              tabContainer._afterHoveredTab = candidate;
+              candidate.setAttribute("afterhovered", "true");
+            }
+          }
+
+          tabContainer._hoveredTab = this;
+        ]]></body>
+      </method>
+
+      <method name="_mouseleave">
+        <body><![CDATA[
+          let tabContainer = this.parentNode;
+          if (tabContainer._beforeHoveredTab) {
+            tabContainer._beforeHoveredTab.removeAttribute("beforehovered");
+            tabContainer._beforeHoveredTab = null;
+          }
+          if (tabContainer._afterHoveredTab) {
+            tabContainer._afterHoveredTab.removeAttribute("afterhovered");
+            tabContainer._afterHoveredTab = null;
+          }
+
+          tabContainer._hoveredTab = null;
+        ]]></body>
+      </method>
     </implementation>
 
     <handlers>
       <handler event="mouseover"><![CDATA[
         let anonid = event.originalTarget.getAttribute("anonid");
         if (anonid == "close-button")
           this.mOverCloseButton = true;
 
-        let tab = event.target;
-        if (tab.closing)
-          return;
-
-        let tabContainer = this.parentNode;
-        let visibleTabs = tabContainer.tabbrowser.visibleTabs;
-        let tabIndex = visibleTabs.indexOf(tab);
-        if (tabIndex == 0) {
-          tabContainer._beforeHoveredTab = null;
-        } else {
-          let candidate = visibleTabs[tabIndex - 1];
-          if (!candidate.selected) {
-            tabContainer._beforeHoveredTab = candidate;
-            candidate.setAttribute("beforehovered", "true");
-          }
-        }
-
-        if (tabIndex == visibleTabs.length - 1) {
-          tabContainer._afterHoveredTab = null;
-        } else {
-          let candidate = visibleTabs[tabIndex + 1];
-          if (!candidate.selected) {
-            tabContainer._afterHoveredTab = candidate;
-            candidate.setAttribute("afterhovered", "true");
-          }
-        }
+        this._mouseenter();
       ]]></handler>
       <handler event="mouseout"><![CDATA[
         let anonid = event.originalTarget.getAttribute("anonid");
         if (anonid == "close-button")
           this.mOverCloseButton = false;
 
-        let tabContainer = this.parentNode;
-        if (tabContainer._beforeHoveredTab) {
-          tabContainer._beforeHoveredTab.removeAttribute("beforehovered");
-          tabContainer._beforeHoveredTab = null;
-        }
-        if (tabContainer._afterHoveredTab) {
-          tabContainer._afterHoveredTab.removeAttribute("afterhovered");
-          tabContainer._afterHoveredTab = null;
-        }
+        this._mouseleave();
       ]]></handler>
       <handler event="dragstart" phase="capturing">
         this.style.MozUserFocus = '';
       </handler>
       <handler event="mousedown" phase="capturing">
       <![CDATA[
         if (this.selected) {
           this.style.MozUserFocus = 'ignore';
--- a/browser/base/content/test/general/Makefile.in
+++ b/browser/base/content/test/general/Makefile.in
@@ -64,19 +64,16 @@ MOCHITEST_BROWSER_FILES = \
                  blockNoPlugins.xml \
                  blockPluginHard.xml \
                  blockPluginVulnerableNoUpdate.xml \
                  blockPluginVulnerableUpdatable.xml \
                  browser_aboutHealthReport.js \
                  browser_aboutHome.js \
                  browser_aboutSyncProgress.js \
                  browser_addKeywordSearch.js \
-                 browser_addon_bar_aomlistener.js \
-                 browser_addon_bar_close_button.js \
-                 browser_addon_bar_shortcut.js \
                  browser_alltabslistener.js \
                  browser_blob-channelname.js \
                  browser_bug304198.js \
                  browser_bug329212.js \
                  browser_bug356571.js \
                  browser_bug380960.js \
                  browser_bug386835.js \
                  browser_bug405137.js \
@@ -137,20 +134,17 @@ MOCHITEST_BROWSER_FILES = \
                  browser_bug585785.js \
                  browser_bug585830.js \
                  browser_bug590206.js \
                  browser_bug592338.js \
                  browser_bug594131.js \
                  browser_bug595507.js \
                  browser_bug596687.js \
                  browser_bug597218.js \
-                 browser_bug598923.js \
-                 browser_bug599325.js \
                  browser_bug609700.js \
-                 browser_bug616836.js \
                  browser_bug623155.js \
                  browser_bug623893.js \
                  browser_bug624734.js \
                  browser_bug647886.js \
                  browser_bug655584.js \
                  browser_bug664672.js \
                  browser_bug676619.js \
                  browser_bug678392-1.html \
@@ -190,18 +184,16 @@ MOCHITEST_BROWSER_FILES = \
                  browser_clearplugindata.js \
                  browser_contentAreaClick.js \
                  browser_contextSearchTabPosition.js \
                  browser_CTP_drag_drop.js \
                  browser_CTP_data_urls.js \
                  browser_CTP_resize.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
-                 browser_customize.js \
-                 browser_disablechrome.js \
                  browser_discovery.js \
                  browser_duplicateIDs.js \
                  browser_findbarClose.js \
                  browser_fullscreen-window-open.js \
                  browser_gestureSupport.js \
                  browser_getshortcutoruri.js \
                  browser_hide_removing.js \
                  browser_homeDrop.js \
@@ -262,27 +254,27 @@ MOCHITEST_BROWSER_FILES = \
                  browser_urlHighlight.js \
                  browser_utilityOverlay.js \
                  browser_visibleFindSelection.js \
                  browser_visibleTabs_bookmarkAllPages.js \
                  browser_visibleTabs_bookmarkAllTabs.js \
                  browser_visibleTabs_contextMenu.js \
                  browser_visibleTabs_tabPreview.js \
                  browser_visibleTabs.js \
+                 browser_windowopen_reflows.js \
                  browser_wyciwyg_urlbarCopying.js \
                  browser_zbug569342.js \
                  bug564387_video1.ogv \
                  bug564387_video1.ogv^headers^ \
                  bug564387.html \
                  bug592338.html \
                  bug792517-2.html \
                  bug792517.html \
                  bug792517.sjs \
                  bug839103.css \
-                 disablechrome.html \
                  discovery.html \
                  domplate_test.js \
                  download_page.html \
                  dummy_page.html \
                  feed_tab.html \
                  file_bug550565_favicon.ico \
                  file_bug550565_popup.html \
                  file_bug822367_1.html \
deleted file mode 100644
--- a/browser/base/content/test/general/browser_addon_bar.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function test() {
-  waitForExplicitFinish();
-
-  let addonbar = document.getElementById("addon-bar");
-  ok(addonbar.collapsed, "addon bar is collapsed by default");
-
-  let topMenu, toolbarMenu;
-
-  function onTopMenuShown(event) {
-    ok(1, "top menu popupshown listener called");
-    event.currentTarget.removeEventListener("popupshown", arguments.callee, false);
-    // open the customize or toolbars menu
-    toolbarMenu = document.getElementById("appmenu_customizeMenu") ||
-                      document.getElementById("viewToolbarsMenu").firstElementChild;
-    toolbarMenu.addEventListener("popupshown", onToolbarMenuShown, false);
-    toolbarMenu.addEventListener("popuphidden", onToolbarMenuHidden, false);
-    toolbarMenu.openPopup();
-  }
-
-  function onTopMenuHidden(event) {
-    ok(1, "top menu popuphidden listener called");
-    event.currentTarget.removeEventListener("popuphidden", arguments.callee, false);
-    finish();
-  }
-
-  function onToolbarMenuShown(event) {
-    ok(1, "sub menu popupshown listener called");
-    event.currentTarget.removeEventListener("popupshown", arguments.callee, false);
-
-    // test the menu item's default state
-    let menuitem = document.getElementById("toggle_addon-bar");
-    ok(menuitem, "found the menu item");
-    is(menuitem.getAttribute("checked"), "false", "menuitem is not checked by default");
-
-    // click on the menu item
-    // TODO: there's got to be a way to check+command in one shot
-    menuitem.setAttribute("checked", "true");
-    menuitem.click();
-
-    // now the addon bar should be visible and the menu checked
-    is(addonbar.getAttribute("collapsed"), "false", "addon bar is visible after executing the command");
-    is(menuitem.getAttribute("checked"), "true", "menuitem is checked after executing the command");
-
-    toolbarMenu.hidePopup();
-  }
-
-  function onToolbarMenuHidden(event) {
-    ok(1, "toolbar menu popuphidden listener called");
-    event.currentTarget.removeEventListener("popuphidden", arguments.callee, false);
-    topMenu.hidePopup();
-  }
-
-  // open the appmenu or view menu
-  topMenu = document.getElementById("appmenu-popup") ||
-            document.getElementById("menu_viewPopup");
-  topMenu.addEventListener("popupshown", onTopMenuShown, false);
-  topMenu.addEventListener("popuphidden", onTopMenuHidden, false);
-  topMenu.openPopup();
-}
deleted file mode 100644
--- a/browser/base/content/test/general/browser_addon_bar_aomlistener.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function test() {
-
-  let addonbar = document.getElementById("addon-bar");
-  ok(addonbar.collapsed, "addon bar is collapsed by default");
-
-  function addItem(id) {
-    let button = document.createElement("toolbarbutton");
-    button.id = id;
-    let palette = document.getElementById("navigator-toolbox").palette;
-    palette.appendChild(button);
-    addonbar.insertItem(id, null, null, false);
-  }
-
-  // call onInstalling
-  AddonsMgrListener.onInstalling();
-
-  // add item to the bar
-  let id = "testbutton";
-  addItem(id);
-
-  // call onInstalled
-  AddonsMgrListener.onInstalled();
-
-  // confirm bar is visible
-  ok(!addonbar.collapsed, "addon bar is not collapsed after toggle");
-
-  // call onUninstalling
-  AddonsMgrListener.onUninstalling();
-
-  // remove item from the bar
-  addonbar.currentSet = addonbar.currentSet.replace("," + id, "");
-
-  // call onUninstalled
-  AddonsMgrListener.onUninstalled();
-
-  // confirm bar is not visible
-  ok(addonbar.collapsed, "addon bar is collapsed after toggle");
-
-  // call onEnabling
-  AddonsMgrListener.onEnabling();
-
-  // add item to the bar
-  let id = "testbutton";
-  addItem(id);
-
-  // call onEnabled
-  AddonsMgrListener.onEnabled();
-
-  // confirm bar is visible
-  ok(!addonbar.collapsed, "addon bar is not collapsed after toggle");
-
-  // call onDisabling
-  AddonsMgrListener.onDisabling();
-
-  // remove item from the bar
-  addonbar.currentSet = addonbar.currentSet.replace("," + id, "");
-
-  // call onDisabled
-  AddonsMgrListener.onDisabled();
-
-  // confirm bar is not visible
-  ok(addonbar.collapsed, "addon bar is collapsed after toggle");
-}
deleted file mode 100644
--- a/browser/base/content/test/general/browser_addon_bar_close_button.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function test() {
-  let addonbar = document.getElementById("addon-bar");
-  ok(addonbar.collapsed, "addon bar is collapsed by default");
-
-  // make add-on bar visible
-  setToolbarVisibility(addonbar, true);
-  ok(!addonbar.collapsed, "addon bar is not collapsed after toggle");
-
-  // click the close button
-  let closeButton = document.getElementById("addonbar-closebutton");
-  EventUtils.synthesizeMouseAtCenter(closeButton, {});
-
-  // confirm addon bar is closed
-  ok(addonbar.collapsed, "addon bar is collapsed after clicking close button");
-}
deleted file mode 100644
--- a/browser/base/content/test/general/browser_addon_bar_shortcut.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function test() {
-  let addonbar = document.getElementById("addon-bar");
-  ok(addonbar.collapsed, "addon bar is collapsed by default");
-
-  // show the add-on bar
-  EventUtils.synthesizeKey("/", { accelKey: true }, window);
-  ok(!addonbar.collapsed, "addon bar is not collapsed after toggle");
-
-  // hide the add-on bar
-  EventUtils.synthesizeKey("/", { accelKey: true }, window);
-
-  // confirm addon bar is closed
-  ok(addonbar.collapsed, "addon bar is collapsed after toggle");
-}
--- a/browser/base/content/test/general/browser_bug462289.js
+++ b/browser/base/content/test/general/browser_bug462289.js
@@ -29,26 +29,19 @@ function step2()
   setTimeout(step3, 0);
 }
 
 function step3()
 {
   is(gBrowser.selectedTab, tab1, "2nd click on selected tab1 keeps tab selected");
   isnot(document.activeElement, tab1, "2nd click on selected tab1 does not activate tab");
 
-  if (gNavToolbox.getAttribute("tabsontop") == "true") {
-    ok(true, "[tabsontop=true] focusing URLBar then sending 1 Shift+Tab.");
-    gURLBar.focus();
-    EventUtils.synthesizeKey("VK_TAB", {shiftKey: true});
-  } else {
-    ok(true, "[tabsontop=false] focusing SearchBar then sending Tab(s) until out of nav-bar.");
-    document.getElementById("searchbar").focus();
-    while (focus_in_navbar())
-      EventUtils.synthesizeKey("VK_TAB", { });
-  }
+  ok(true, "focusing URLBar then sending 1 Shift+Tab.");
+  gURLBar.focus();
+  EventUtils.synthesizeKey("VK_TAB", {shiftKey: true});
   is(gBrowser.selectedTab, tab1, "tab key to selected tab1 keeps tab selected");
   is(document.activeElement, tab1, "tab key to selected tab1 activates tab");
 
   EventUtils.synthesizeMouseAtCenter(tab1, {});
   setTimeout(step4, 0);
 }
 
 function step4()
deleted file mode 100644
--- a/browser/base/content/test/general/browser_bug598923.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Test:
-// * if add-on is installed to the add-on bar, the bar is made visible.
-// * if add-on is uninstalled from the add-on bar, and no more add-ons there,
-//   the bar is hidden.
-
-function test() {
-  let aml = AddonsMgrListener;
-  ok(aml, "AddonsMgrListener exists");
-  // check is hidden
-  is(aml.addonBar.collapsed, true, "add-on bar is hidden initially");
-  // aob gets the count
-  AddonsMgrListener.onInstalling();
-  // add an item
-  let element = document.createElement("toolbaritem");
-  element.id = "bug598923-addon-item";
-  aml.addonBar.appendChild(element);
-  // aob checks the count, makes visible
-  AddonsMgrListener.onInstalled();
-  // check is visible
-  is(aml.addonBar.collapsed, false, "add-on bar has been made visible");
-  // aob gets the count
-  AddonsMgrListener.onUninstalling();
-  // remove an item
-  aml.addonBar.removeChild(element);
-  // aob checks the count, makes hidden
-  AddonsMgrListener.onUninstalled();
-  // check is hidden
-  is(aml.addonBar.collapsed, true, "add-on bar is hidden again");
-}
deleted file mode 100644
--- a/browser/base/content/test/general/browser_bug599325.js
+++ /dev/null
@@ -1,21 +0,0 @@
-function test() {
-  waitForExplicitFinish();
-
-  let addonBar = document.getElementById("addon-bar");
-  ok(addonBar, "got addon bar");
-  ok(!isElementVisible(addonBar), "addon bar initially hidden");
-
-  openToolbarCustomizationUI(function () {
-    ok(isElementVisible(addonBar),
-       "add-on bar is visible during toolbar customization");
-
-    closeToolbarCustomizationUI(onClose);
-  });
-
-  function onClose() {
-    ok(!isElementVisible(addonBar),
-       "addon bar is hidden after toolbar customization");
-
-    finish();
-  }
-}
deleted file mode 100644
--- a/browser/base/content/test/general/browser_bug616836.js
+++ /dev/null
@@ -1,4 +0,0 @@
-function test() {
-  is(document.querySelectorAll("#appmenu-popup [accesskey]").length, 0,
-     "there should be no items with access keys in the app menu popup");
-}
--- a/browser/base/content/test/general/browser_bug624734.js
+++ b/browser/base/content/test/general/browser_bug624734.js
@@ -1,23 +1,31 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Bug 624734 - Star UI has no tooltip until bookmarked page is visited
 
+function finishTest() {
+  is(BookmarkingUI.button.getAttribute("buttontooltiptext"),
+     BookmarkingUI._unstarredTooltip,
+     "Star icon should have the unstarred tooltip text");
+
+  gBrowser.removeCurrentTab();
+  finish();
+}
+
 function test() {
   waitForExplicitFinish();
 
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   tab.linkedBrowser.addEventListener("load", (function(event) {
     tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
 
-    is(BookmarkingUI.star.getAttribute("tooltiptext"),
-       BookmarkingUI._unstarredTooltip,
-       "Star icon should have the unstarred tooltip text");
-  
-    gBrowser.removeCurrentTab();
-    finish();
+    if (BookmarkingUI.status == BookmarkingUI.STATUS_UPDATING) {
+      waitForCondition(function() BookmarkingUI.status != BookmarkingUI.STATUS_UPDATING, finishTest, "BookmarkingUI was updating for too long");
+    } else {
+      finishTest();
+    }
   }), true);
 
   tab.linkedBrowser.loadURI("http://example.com/browser/browser/base/content/test/general/dummy_page.html");
 }
deleted file mode 100644
--- a/browser/base/content/test/general/browser_customize.js
+++ /dev/null
@@ -1,24 +0,0 @@
-function test() {
-  waitForExplicitFinish();
-
-  openToolbarCustomizationUI(customizationWindowLoaded);
-}
-
-function customizationWindowLoaded(win) {
-  let x = win.screenX;
-  let iconModeList = win.document.getElementById("modelist");
-
-  iconModeList.addEventListener("popupshown", function popupshown() {
-    iconModeList.removeEventListener("popupshown", popupshown, false);
-
-    executeSoon(function () {
-      is(win.screenX, x,
-         "toolbar customization window shouldn't move when the iconmode menulist is opened");
-      iconModeList.open = false;
-    
-      closeToolbarCustomizationUI(finish);
-    });
-  }, false);
-
-  iconModeList.open = true;
-}
deleted file mode 100644
--- a/browser/base/content/test/general/browser_disablechrome.js
+++ /dev/null
@@ -1,216 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// Tests that the disablechrome attribute gets propogated to the main UI
-
-const HTTPSRC = "http://example.com/browser/browser/base/content/test/general/";
-
-function is_element_hidden(aElement) {
-  var style = window.getComputedStyle(document.getElementById("nav-bar"), "");
-  if (style.visibility != "visible" || style.display == "none")
-    return true;
-
-  if (aElement.ownerDocument != aElement.parentNode)
-    return is_element_hidden(aElement.parentNode);
-
-  return false;
-}
-
-function is_chrome_hidden() {
-  is(document.documentElement.getAttribute("disablechrome"), "true", "Attribute should be set");
-  if (TabsOnTop.enabled)
-    ok(is_element_hidden(document.getElementById("nav-bar")), "Toolbar should be hidden");
-  else
-    ok(!is_element_hidden(document.getElementById("nav-bar")), "Toolbar should not be hidden");
-}
-
-function is_chrome_visible() {
-  isnot(document.getElementById("main-window").getAttribute("disablechrome"), "true", "Attribute should not be set");
-  ok(!is_element_hidden(document.getElementById("nav-bar")), "Toolbar should not be hidden");
-}
-
-function load_page(aURL, aCanHide, aCallback) {
-  gNewBrowser.addEventListener("pageshow", function() {
-    // Filter out about:blank loads
-    if (gNewBrowser.currentURI.spec != aURL)
-      return;
-
-    gNewBrowser.removeEventListener("pageshow", arguments.callee, false);
-
-    if (aCanHide)
-      is_chrome_hidden();
-    else
-      is_chrome_visible();
-
-    if (aURL == "about:addons") {
-      function check_after_init() {
-        if (aCanHide)
-          is_chrome_hidden();
-        else
-          is_chrome_visible();
-
-        aCallback();
-      }
-
-      if (gNewBrowser.contentWindow.gIsInitializing) {
-        gNewBrowser.contentDocument.addEventListener("Initialized", function() {
-          gNewBrowser.contentDocument.removeEventListener("Initialized", arguments.callee, false);
-
-          check_after_init();
-        }, false);
-      }
-      else {
-        check_after_init();
-      }
-    }
-    else {
-      executeSoon(aCallback);
-    }
-  }, false);
-  gNewBrowser.loadURI(aURL);
-}
-
-var gOldTab;
-var gNewTab;
-var gNewBrowser;
-
-function test() {
-  // Opening the add-ons manager and waiting for it to load the discovery pane
-  // takes more time in windows debug builds
-  requestLongerTimeout(2);
-
-  var gOldTabsOnTop = TabsOnTop.enabled;
-  registerCleanupFunction(function() {
-    TabsOnTop.enabled = gOldTabsOnTop;
-  });
-
-  waitForExplicitFinish();
-
-  gOldTab = gBrowser.selectedTab;
-  gNewTab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
-  gNewBrowser = gBrowser.selectedBrowser;
-
-  info("Tabs on top");
-  TabsOnTop.enabled = true;
-
-  run_http_test_1();
-}
-
-function end_test() {
-  gBrowser.removeTab(gNewTab);
-  finish();
-}
-
-function test_url(aURL, aCanHide, aNextTest) {
-  is_chrome_visible();
-  info("Page load");
-  load_page(aURL, aCanHide, function() {
-    info("Switch away");
-    gBrowser.selectedTab = gOldTab;
-    is_chrome_visible();
-
-    info("Switch back");
-    gBrowser.selectedTab = gNewTab;
-    if (aCanHide)
-      is_chrome_hidden();
-    else
-      is_chrome_visible();
-
-    gBrowser.removeTab(gNewTab);
-    gNewTab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
-    gNewBrowser = gBrowser.selectedBrowser;
-
-    gBrowser.selectedTab = gOldTab;
-
-    info("Background load");
-    load_page(aURL, false, function() {
-      info("Switch back");
-      gBrowser.selectedTab = gNewTab;
-      if (aCanHide)
-        is_chrome_hidden();
-      else
-        is_chrome_visible();
-
-      load_page("about:blank", false, aNextTest);
-    });
-  });
-}
-
-// Should never hide the chrome
-function run_http_test_1() {
-  info("HTTP tests");
-  test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test);
-}
-
-// Should hide the chrome
-function run_chrome_about_test() {
-  info("Chrome about: tests");
-  test_url("about:addons", true, function() {
-    info("Tabs on bottom");
-    TabsOnTop.enabled = false;
-    run_http_test_2();
-  });
-}
-
-// Should never hide the chrome
-function run_http_test_2() {
-  info("HTTP tests");
-  test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_2);
-}
-
-// Should not hide the chrome
-function run_chrome_about_test_2() {
-  info("Chrome about: tests");
-  test_url("about:addons", true, run_http_test3);
-}
-
-function run_http_test3() {
-  info("HTTP tests");
-  test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_3);
-}
-
-// Should not hide the chrome
-function run_chrome_about_test_3() {
-  info("Chrome about: tests");
-  test_url("about:Addons", true, function(){
-    info("Tabs on top");
-    TabsOnTop.enabled = true;
-    run_http_test4();
-  });
-}
-
-function run_http_test4() {
-  info("HTTP tests");
-  test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_4);
-}
-
-function run_chrome_about_test_4() {
-  info("Chrome about: tests");
-  test_url("about:Addons", true, run_http_test5);
- }
-
-function run_http_test5() {
-  info("HTTP tests");
-  test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_5);
-}
-
-// Should hide the chrome
-function run_chrome_about_test_5() {
-  info("Chrome about: tests");
-  test_url("about:preferences", true, function(){
-    info("Tabs on bottom");
-    TabsOnTop.enabled = false;
-    run_http_test6();
-  });
-}
-
-function run_http_test6() {
-  info("HTTP tests");
-  test_url(HTTPSRC + "disablechrome.html", false, run_chrome_about_test_6);
-}
-
-function run_chrome_about_test_6() {
-  info("Chrome about: tests");
-  test_url("about:preferences", true, end_test);
-}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_windowopen_reflows.js
@@ -0,0 +1,111 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const EXPECTED_REFLOWS = [
+  // handleEvent flushes layout to get the tabstrip width after a resize.
+  "handleEvent@chrome://browser/content/tabbrowser.xml|",
+
+  // Loading a tab causes a reflow.
+  "loadTabs@chrome://browser/content/tabbrowser.xml|" +
+    "loadOneOrMoreURIs@chrome://browser/content/browser.js|" +
+    "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|",
+
+  // Selecting the address bar causes a reflow.
+  "select@chrome://global/content/bindings/textbox.xml|" +
+    "focusAndSelectUrlBar@chrome://browser/content/browser.js|" +
+    "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|",
+
+  // Focusing the content area causes a reflow.
+  "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|",
+];
+
+if (Services.appinfo.OS == "Darwin") {
+  // TabsInTitlebar._update causes a reflow on OS X trying to do calculations
+  // since layout info is already dirty. This doesn't seem to happen before
+  // MozAfterPaint on other platforms.
+  EXPECTED_REFLOWS.push("rect@chrome://browser/content/browser.js|" +
+                          "TabsInTitlebar._update@chrome://browser/content/browser.js|" +
+                          "updateAppearance@chrome://browser/content/browser.js|" +
+                          "handleEvent@chrome://browser/content/tabbrowser.xml|");
+
+  // _onOverflow causes a reflow getting widths.
+  EXPECTED_REFLOWS.push("OverflowableToolbar.prototype._onOverflow@resource:///modules/CustomizableUI.jsm|" +
+                        "OverflowableToolbar.prototype.init@resource:///modules/CustomizableUI.jsm|" +
+                        "OverflowableToolbar.prototype.observe@resource:///modules/CustomizableUI.jsm|" +
+                        "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|");
+  // Same as above since in packaged builds there are no function names and the resource URI includes "app"
+  EXPECTED_REFLOWS.push("@resource://app/modules/CustomizableUI.jsm|" +
+                          "@resource://app/modules/CustomizableUI.jsm|" +
+                          "@resource://app/modules/CustomizableUI.jsm|" +
+                          "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|");
+}
+
+/*
+ * This test ensures that there are no unexpected
+ * uninterruptible reflows when opening new windows.
+ */
+function test() {
+  waitForExplicitFinish();
+
+  // Add a reflow observer and open a new window
+  let win = OpenBrowserWindow();
+  let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
+                    .getInterface(Ci.nsIWebNavigation)
+                    .QueryInterface(Ci.nsIDocShell);
+  docShell.addWeakReflowObserver(observer);
+
+  // Wait until the mozafterpaint event occurs.
+  waitForMozAfterPaint(win, function paintListener() {
+    // Remove reflow observer and clean up.
+    docShell.removeWeakReflowObserver(observer);
+    win.close();
+
+    finish();
+  });
+}
+
+let observer = {
+  reflow: function (start, end) {
+    // Gather information about the current code path.
+    let stack = new Error().stack;
+    let path = stack.split("\n").slice(1).map(line => {
+      return line.replace(/:\d+$/, "");
+    }).join("|");
+    let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|");
+
+    // Stack trace is empty. Reflow was triggered by native code.
+    if (path === "") {
+      return;
+    }
+
+    // Check if this is an expected reflow.
+    for (let expectedStack of EXPECTED_REFLOWS) {
+      if (path.startsWith(expectedStack) ||
+          // Accept an empty function name for gBrowserInit._delayedStartup or TabsInTitlebar._update to workaround bug 906578.
+          path.startsWith(expectedStack.replace(/(^|\|)(gBrowserInit\._delayedStartup|TabsInTitlebar\._update)@/, "$1@"))) {
+        ok(true, "expected uninterruptible reflow '" + expectedStack + "'");
+        return;
+      }
+    }
+
+    ok(false, "unexpected uninterruptible reflow '" + pathWithLineNumbers + "'");
+  },
+
+  reflowInterruptible: function (start, end) {
+    // We're not interested in interruptible reflows.
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver,
+                                         Ci.nsISupportsWeakReference])
+};
+
+function waitForMozAfterPaint(win, callback) {
+  win.addEventListener("MozAfterPaint", function onEnd(event) {
+    if (event.target != win)
+      return;
+    win.removeEventListener("MozAfterPaint", onEnd);
+    executeSoon(callback);
+  });
+}
deleted file mode 100644
--- a/browser/base/content/test/general/disablechrome.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<html>
-<body>
-</body>
-</html>
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -32,59 +32,37 @@ function updateTabContextMenu(tab) {
     tab = gBrowser.selectedTab;
   var evt = new Event("");
   tab.dispatchEvent(evt);
   menu.openPopup(tab, "end_after", 0, 0, true, false, evt);
   is(TabContextMenu.contextTab, tab, "TabContextMenu context is the expected tab");
   menu.hidePopup();
 }
 
-function findToolbarCustomizationWindow(aBrowserWin) {
-  if (!aBrowserWin)
-    aBrowserWin = window;
-
-  let iframe = aBrowserWin.document.getElementById("customizeToolbarSheetIFrame");
-  let win = iframe && iframe.contentWindow;
-  if (win)
-    return win;
-
-  win = findChromeWindowByURI("chrome://global/content/customizeToolbar.xul");
-  if (win && win.opener == aBrowserWin)
-    return win;
-
-  throw Error("Failed to find the customization window");
-}
-
 function openToolbarCustomizationUI(aCallback, aBrowserWin) {
   if (!aBrowserWin)
     aBrowserWin = window;
 
-  aBrowserWin.document.getElementById("cmd_CustomizeToolbars").doCommand();
-
-  aBrowserWin.gNavToolbox.addEventListener("beforecustomization", function UI_loaded() {
-    aBrowserWin.gNavToolbox.removeEventListener("beforecustomization", UI_loaded);
+  aBrowserWin.gCustomizeMode.enter();
 
-    let win = findToolbarCustomizationWindow(aBrowserWin);
-    waitForFocus(function () {
-      aCallback(win);
-    }, win);
+  aBrowserWin.gNavToolbox.addEventListener("customizationready", function UI_loaded() {
+    aBrowserWin.gNavToolbox.removeEventListener("customizationready", UI_loaded);
+    executeSoon(function() {
+      aCallback(aBrowserWin)
+    });
   });
 }
 
 function closeToolbarCustomizationUI(aCallback, aBrowserWin) {
-  let win = findToolbarCustomizationWindow(aBrowserWin);
-
-  win.addEventListener("unload", function unloaded() {
-    win.removeEventListener("unload", unloaded);
+  aBrowserWin.gNavToolbox.addEventListener("aftercustomization", function unloaded() {
+    aBrowserWin.gNavToolbox.removeEventListener("aftercustomization", unloaded);
     executeSoon(aCallback);
   });
 
-  let button = win.document.getElementById("donebutton");
-  button.focus();
-  button.doCommand();
+  aBrowserWin.gCustomizeMode.exit();
 }
 
 function waitForCondition(condition, nextTest, errorMsg) {
   var tries = 0;
   var interval = setInterval(function() {
     if (tries >= 30) {
       ok(false, errorMsg);
       moveOn();
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -932,26 +932,26 @@
                   pack="end" align="center">
           <xul:button anonid="button"
                       class="popup-notification-menubutton"
                       type="menu-button"
                       xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
             <xul:menupopup anonid="menupopup"
                            xbl:inherits="oncommand=menucommand">
               <children/>
-              <xul:menuitem class="menuitem-iconic popup-notification-closeitem"
+              <xul:menuitem class="menuitem-iconic popup-notification-closeitem close-icon"
                             label="&closeNotificationItem.label;"
                             xbl:inherits="oncommand=closeitemcommand"/>
             </xul:menupopup>
           </xul:button>
         </xul:hbox>
       </xul:vbox>
       <xul:vbox pack="start">
         <xul:toolbarbutton anonid="closebutton"
-                           class="messageCloseButton popup-notification-closebutton tabbable"
+                           class="messageCloseButton close-icon popup-notification-closebutton tabbable"
                            xbl:inherits="oncommand=closebuttoncommand"
                            tooltiptext="&closeNotification.tooltip;"/>
       </xul:vbox>
     </content>
     <implementation>
       <constructor><![CDATA[
         this.cancelbtn.setAttribute("tooltiptext", gNavigatorBundle.getString("addonDownloadCancelTooltip"));
 
@@ -1164,26 +1164,26 @@
                      style="visibility:hidden" width="16" height="16"/>
           <xul:button anonid="button"
                       type="menu-button"
                       class="popup-notification-menubutton"
                       xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
             <xul:menupopup anonid="menupopup"
                            xbl:inherits="oncommand=menucommand">
               <children/>
-              <xul:menuitem class="menuitem-iconic popup-notification-closeitem"
+              <xul:menuitem class="menuitem-iconic popup-notification-closeitem close-icon"
                             label="&closeNotificationItem.label;"
                             xbl:inherits="oncommand=closeitemcommand"/>
             </xul:menupopup>
           </xul:button>
         </xul:hbox>
       </xul:vbox>
       <xul:vbox pack="start">
         <xul:toolbarbutton anonid="closebutton"
-                           class="messageCloseButton popup-notification-closebutton tabbable"
+                           class="messageCloseButton close-icon popup-notification-closebutton tabbable"
                            xbl:inherits="oncommand=closebuttoncommand"
                            tooltiptext="&closeNotification.tooltip;"/>
       </xul:vbox>
     </content>
     <implementation>
       <constructor><![CDATA[
         // this.notification.options.identity is used to pass identity-specific info to the binding
         let origin = this.identity.origin
@@ -1503,17 +1503,17 @@
       <xul:vbox flex="1" align="stretch" class="popup-notification-main-box"
                 xbl:inherits="popupid">
         <xul:hbox class="click-to-play-plugins-notification-description-box" flex="1" align="start">
           <xul:description class="click-to-play-plugins-outer-description" flex="1">
             <html:span anonid="click-to-play-plugins-notification-description" />
             <xul:label class="text-link click-to-play-plugins-notification-link" anonid="click-to-play-plugins-notification-link" />
           </xul:description>
           <xul:toolbarbutton anonid="closebutton"
-                             class="messageCloseButton popup-notification-closebutton tabbable"
+                             class="messageCloseButton popup-notification-closebutton tabbable close-icon"
                              xbl:inherits="oncommand=closebuttoncommand"
                              tooltiptext="&closeNotification.tooltip;"/>
         </xul:hbox>
         <xul:grid anonid="click-to-play-plugins-notification-center-box"
                   class="click-to-play-plugins-notification-center-box">
           <xul:columns>
             <xul:column flex="1"/>
             <xul:column/>
@@ -2016,17 +2016,17 @@
         <xul:hbox align="center" flex="1">
           <xul:image class="panel-promo-icon"/>
           <xul:description anonid="promo-message" class="panel-promo-message" flex="1">
             <xul:description anonid="promo-link"
                              class="plain text-link inline-link"
                              onclick="document.getBindingParent(this).onLinkClick();"/>
           </xul:description>
         </xul:hbox>
-        <xul:toolbarbutton class="panel-promo-closebutton"
+        <xul:toolbarbutton class="panel-promo-closebutton close-icon"
                            oncommand="document.getBindingParent(this).onCloseButtonCommand();"
                            tooltiptext="&closeNotification.tooltip;"/>
       </xul:hbox>
     </content>
 
     <implementation implements="nsIDOMEventListener">
       <constructor><![CDATA[
         this._panel.addEventListener("popupshowing", this, false);
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -8,18 +8,17 @@ browser.jar:
 %  overlay chrome://global/content/console.xul chrome://browser/content/jsConsoleOverlay.xul
 %  overlay chrome://mozapps/content/update/updates.xul chrome://browser/content/softwareUpdateOverlay.xul
 #endif
 #ifdef XP_WIN
 %  overlay chrome://browser/content/browser.xul chrome://browser/content/win6BrowserOverlay.xul os=WINNT osversion>=6
 #endif
 %  overlay chrome://global/content/viewSource.xul chrome://browser/content/viewSourceOverlay.xul
 %  overlay chrome://global/content/viewPartialSource.xul chrome://browser/content/viewSourceOverlay.xul
-%  style chrome://global/content/customizeToolbar.xul chrome://browser/content/browser.css
-%  style chrome://global/content/customizeToolbar.xul chrome://browser/skin/
+
 *       content/browser/aboutDialog.xul               (content/aboutDialog.xul)
 *       content/browser/aboutDialog.js                (content/aboutDialog.js)
         content/browser/aboutDialog.css               (content/aboutDialog.css)
         content/browser/aboutRobots.xhtml             (content/aboutRobots.xhtml)
         content/browser/abouthome/aboutHome.xhtml     (content/abouthome/aboutHome.xhtml)
         content/browser/abouthome/aboutHome.js        (content/abouthome/aboutHome.js)
 *       content/browser/abouthome/aboutHome.css       (content/abouthome/aboutHome.css)
         content/browser/abouthome/noise.png           (content/abouthome/noise.png)
--- a/browser/branding/nightly/branding.nsi
+++ b/browser/branding/nightly/branding.nsi
@@ -3,17 +3,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # NSIS branding defines for nightly builds.
 # The official release build branding.nsi is located in other-license/branding/firefox/
 # The unofficial build branding.nsi is located in browser/branding/unofficial/
 
 # BrandFullNameInternal is used for some registry and file system values
 # instead of BrandFullName and typically should not be modified.
-!define BrandFullNameInternal "Nightly"
+!define BrandFullNameInternal "UX"
 !define CompanyName           "mozilla.org"
 !define URLInfoAbout          "http://www.mozilla.org"
 !define URLUpdateInfo         "http://www.mozilla.org/projects/firefox"
 
 !define URLStubDownload "http://download.mozilla.org/?product=firefox-nightly-latest&os=win&lang=${AB_CD}"
 !define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=nightly&installer_lang=${AB_CD}"
 !define Channel "nightly"
 
--- a/browser/branding/nightly/configure.sh
+++ b/browser/branding/nightly/configure.sh
@@ -1,5 +1,5 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-MOZ_APP_DISPLAYNAME=Nightly
+MOZ_APP_DISPLAYNAME=UX
--- a/browser/branding/nightly/locales/en-US/brand.dtd
+++ b/browser/branding/nightly/locales/en-US/brand.dtd
@@ -1,8 +1,8 @@
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
-<!ENTITY  brandShortName        "Nightly">
-<!ENTITY  brandFullName         "Nightly">
+<!ENTITY  brandShortName        "UX">
+<!ENTITY  brandFullName         "UX">
 <!ENTITY  vendorShortName       "Mozilla">
 <!ENTITY  trademarkInfo.part1   " ">
--- a/browser/branding/nightly/locales/en-US/brand.properties
+++ b/browser/branding/nightly/locales/en-US/brand.properties
@@ -1,9 +1,9 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-brandShortName=Nightly
-brandFullName=Nightly
+brandShortName=UX
+brandFullName=UX
 vendorShortName=Mozilla
 
 syncBrandShortName=Sync
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -87,16 +87,18 @@ static RedirEntry kRedirMap[] = {
   { "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
     nsIAboutModule::ALLOW_SCRIPT },
 #ifdef MOZ_SERVICES_HEALTHREPORT
   { "healthreport", "chrome://browser/content/abouthealthreport/abouthealth.xhtml",
     nsIAboutModule::ALLOW_SCRIPT },
 #endif
   { "app-manager", "chrome://browser/content/devtools/app-manager/index.xul",
     nsIAboutModule::ALLOW_SCRIPT },
+  { "customizing", "chrome://browser/content/customizableui/aboutCustomizing.xhtml",
+    nsIAboutModule::ALLOW_SCRIPT },
 };
 static const int kRedirTotal = NS_ARRAY_LENGTH(kRedirMap);
 
 static nsAutoCString
 GetAboutModuleName(nsIURI *aURI)
 {
   nsAutoCString path;
   aURI->GetPath(path);
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -105,16 +105,17 @@ static const mozilla::Module::ContractID
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "downloads", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #ifdef MOZ_SERVICES_HEALTHREPORT
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #endif
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "app-manager", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
+    { NS_ABOUT_MODULE_CONTRACTID_PREFIX "customizing", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #if defined(XP_WIN)
     { NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
 #elif defined(XP_MACOSX)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
 #endif
     { nullptr }
 };
 
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/aboutCustomizing.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html [
+  <!ENTITY % htmlDTD
+    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "DTD/xhtml1-strict.dtd">
+  %htmlDTD;
+  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+  %brandDTD;
+  <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
+  %browserDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      disablefastfind="true">
+	<head>
+		<title>&customizeMode.tabTitle;</title>
+	</head>
+	<body></body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/customizeMode.inc.xul
@@ -0,0 +1,28 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<hbox id="customization-container" flex="1" hidden="true">
+  <vbox flex="1" id="customization-palette-container">
+    <label id="customization-header" value="&customizeMode.menuAndToolbars.header;"/>
+    <vbox id="customization-palette" flex="1"/>
+    <hbox pack="start">
+      <button id="customization-reset-button" oncommand="gCustomizeMode.reset();" label="&customizeMode.restoreDefaults;" class="customizationmode-button"/>
+    </hbox>
+  </vbox>
+  <vbox id="customization-panel-container">
+    <vbox id="customization-panelWrapper">
+      <html:style html:type="text/html" scoped="scoped">
+        @import url(chrome://global/skin/popup.css);
+      </html:style>
+      <box class="panel-arrowbox">
+        <box flex="1"/>
+        <image class="panel-arrow" side="top"/>
+      </box>
+      <box class="panel-arrowcontent" flex="1">
+        <hbox id="customization-panelHolder"/>
+        <box class="panel-inner-arrowcontentfooter" hidden="true"/>
+      </box>
+    </vbox>
+  </vbox>
+</hbox>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/jar.mn
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+browser.jar:
+  content/browser/customizableui/aboutCustomizing.xhtml
+  content/browser/customizableui/panelUI.css
+  content/browser/customizableui/panelUI.js
+  content/browser/customizableui/panelUI.xml
+  content/browser/customizableui/toolbar.xml
+
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/moz.build
@@ -0,0 +1,6 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUI.css
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.panel-viewstack[viewtype="main"] > .panel-clickcapturer {
+  pointer-events: none;
+}
+
+.panel-mainview,
+.panel-viewcontainer,
+.panel-viewstack {
+  overflow: hidden;
+}
+
+.panel-viewstack {
+  position: relative;
+}
+
+.panel-subviews {
+  -moz-stack-sizing: ignore;
+  transform: translateX(0);
+  overflow-y: auto;
+}
+
+.panel-subviews[panelopen] {
+  transition: transform 150ms;
+}
+
+.panel-viewcontainer[panelopen]:-moz-any(:not([viewtype="main"]),[transitioning="true"]) {
+  transition: height 150ms;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -0,0 +1,154 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<panel id="PanelUI-popup"
+       role="group"
+       type="arrow"
+       level="top"
+       hidden="true"
+       consumeoutsideclicks="true"
+       noautofocus="true">
+  <panelmultiview id="PanelUI-multiView" mainViewId="PanelUI-mainView">
+    <panelview id="PanelUI-mainView" contextmenu="customizationPanelContextMenu">
+      <vbox id="PanelUI-contents-scroller">
+        <vbox id="PanelUI-contents"/>
+      </vbox>
+
+      <vbox id="PanelUI-mainView-spring"/>
+
+      <footer id="PanelUI-footer">
+        <!-- The parentNode is used so that the footer is presented as the anchor
+             instead of just the button being the anchor. -->
+        <toolbarbutton id="PanelUI-help" label="&helpMenu.label;" tabindex="0"
+                       oncommand="PanelUI.showHelpView(this.parentNode);"/>
+        <toolbarbutton id="PanelUI-customize" label="&appMenuCustomize.label;" tabindex="0"
+                       oncommand="gCustomizeMode.toggle();"/>
+        <toolbarbutton id="PanelUI-quit" tabindex="0"
+#ifdef XP_WIN
+                       label="&quitApplicationCmdWin.label;"
+#else
+#ifdef XP_MACOSX
+                       label="&quitApplicationCmdMac.label;"
+#else
+                       label="&quitApplicationCmd.label;"
+#endif
+#endif
+                       command="cmd_quitApplication"/>
+      </footer>
+    </panelview>
+
+    <panelview id="PanelUI-history" flex="1">
+      <label value="&appMenuHistory.label;"/>
+      <toolbarbutton id="appMenuClearRecentHistory" tabindex="0"
+                     label="&appMenuHistory.clearRecent.label;"
+                     command="Tools:Sanitize"/>
+      <toolbarbutton id="appMenuRestoreLastSession" tabindex="0"
+                     label="&appMenuHistory.restoreSession.label;"
+                     command="Browser:RestoreLastSession"/>
+      <vbox id="PanelUI-historyItems"/>
+      <label value="&appMenuHistory.showAll.label;"
+             id="PanelUI-historyMore"
+             class="text-link"
+             onclick="PlacesCommandHook.showPlacesOrganizer('History'); CustomizableUI.hidePanelForNode(this);"/>
+    </panelview>
+
+    <panelview id="PanelUI-bookmarks" flex="1">
+      <toolbarbutton id="panelMenuBookmarkThisPage"
+                     label="&bookmarkThisPageCmd.label;"
+                     command="Browser:AddBookmarkAs"
+                     onclick="PanelUI.hide();"/>
+      <toolbarseparator/>
+      <toolbarbutton id="panelMenu_showAllBookmarks"
+                     label="&showAllBookmarks2.label;"
+                     command="Browser:ShowAllBookmarks"
+                     onclick="PanelUI.hide();"/>
+      <toolbarbutton id="panelMenu_viewBookmarksSidebar"
+                     label="&viewBookmarksSidebar2.label;"
+                     oncommand="toggleSidebar('viewBookmarksSidebar'); PanelUI.hide();">
+        <observes element="viewBookmarksSidebar" attribute="checked"/>
+      </toolbarbutton>
+      <toolbarbutton id="panelMenu_viewBookmarksToolbar"
+                     label="&viewBookmarksToolbar.label;"
+                     type="checkbox"
+                     toolbarId="PersonalToolbar"
+                     oncommand="onViewToolbarCommand(event); PanelUI.hide();"/>
+      <toolbarseparator/>
+      <toolbarbutton id="panelMenu_bookmarksToolbar"
+                     label="&personalbarCmd.label;"
+                     oncommand="PlacesCommandHook.showPlacesOrganizer('BookmarksToolbar'); PanelUI.hide();"/>
+      <toolbarbutton id="panelMenu_unsortedBookmarks"
+                     label="&unsortedBookmarksCmd.label;"
+                     oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks'); PanelUI.hide();"/>
+      <toolbarseparator/>
+      <toolbaritem id="panelMenu_bookmarksMenu"
+                   flex="1"
+                   orient="vertical"
+                   smoothscroll="false"
+                   onclick="if (event.button == 1) BookmarkingUI.onPanelMenuViewCommand(event, this._placesView);"
+                   oncommand="BookmarkingUI.onPanelMenuViewCommand(event, this._placesView);"
+                   flatList="true"
+                   tooltip="bhTooltip">
+        <!-- bookmarks menu items -->
+      </toolbaritem>
+
+    </panelview>
+
+    <panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);"></panelview>
+
+    <panelview id="PanelUI-helpView" flex="1">
+      <label value="&helpMenu.label;"/>
+      <vbox id="PanelUI-helpItems"/>
+    </panelview>
+
+    <panelview id="PanelUI-developer" flex="1">
+      <label value="&webDeveloperMenu.label;"/>
+      <vbox id="PanelUI-developerItems"/>
+    </panelview>
+
+    <panelview id="PanelUI-characterEncodingView" flex="1">
+      <label value="&charsetMenu.label;"/>
+      <toolbarbutton label="&charsetCustomize.label;"
+                     oncommand="PanelUI.onCharsetCustomizeCommand();"/>
+
+      <vbox id="PanelUI-characterEncodingView-customlist"
+            class="PanelUI-characterEncodingView-list"/>
+      <vbox>
+        <label value="&charsetMenuAutodet.label;"/>
+        <vbox id="PanelUI-characterEncodingView-autodetect"
+              class="PanelUI-characterEncodingView-list"/>
+      </vbox>
+    </panelview>
+
+  </panelmultiview>
+  <popupset id="customizationContextMenus">
+    <menupopup id="customizationContextMenu">
+      <menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode)"
+                accesskey="&customizeMenu.addToToolbar.accesskey;"
+                label="&customizeMenu.addToToolbar.label;"/>
+      <menuitem oncommand="gCustomizeMode.removeFromPanel(document.popupNode)"
+                accesskey="&customizeMenu.removeFromMenu.accesskey;"
+                label="&customizeMenu.removeFromMenu.label;"/>
+      <menuseparator/>
+      <menuitem command="cmd_CustomizeToolbars"
+                accesskey="&viewCustomizeToolbar.accesskey;"
+                label="&viewCustomizeToolbar.label;"/>
+    </menupopup>
+
+    <menupopup id="customizationPanelContextMenu">
+      <menuitem command="cmd_CustomizeToolbars"
+                accesskey="&customizeMenu.addMoreItems.accesskey;"
+                label="&customizeMenu.addMoreItems.label;"/>
+    </menupopup>
+  </popupset>
+</panel>
+
+<panel id="widget-overflow"
+       role="group"
+       type="arrow"
+       level="top"
+       hidden="true"
+       consumeoutsideclicks="true">
+  <vbox id="widget-overflow-list">
+  </vbox>
+</panel>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUI.js
@@ -0,0 +1,407 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
+                                  "resource:///modules/CustomizableUI.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Promise",
+                                  "resource://gre/modules/Promise.jsm");
+/**
+ * Maintains the state and dispatches events for the main menu panel.
+ */
+
+const PanelUI = {
+  /** Panel events that we listen for. **/
+  get kEvents() ["popupshowing", "popupshown", "popuphiding", "popuphidden"],
+  /**
+   * Used for lazily getting and memoizing elements from the document. Lazy
+   * getters are set in init, and memoizing happens after the first retrieval.
+   */
+  get kElements() {
+    return {
+      contents: "PanelUI-contents",
+      mainView: "PanelUI-mainView",
+      multiView: "PanelUI-multiView",
+      helpView: "PanelUI-helpView",
+      menuButton: "PanelUI-menu-button",
+      panel: "PanelUI-popup",
+      scroller: "PanelUI-contents-scroller"
+    };
+  },
+
+  init: function() {
+    for (let [k, v] of Iterator(this.kElements)) {
+      // Need to do fresh let-bindings per iteration
+      let getKey = k;
+      let id = v;
+      this.__defineGetter__(getKey, function() {
+        delete this[getKey];
+        return this[getKey] = document.getElementById(id);
+      });
+    }
+
+    this.menuButton.addEventListener("mousedown", this);
+    this.menuButton.addEventListener("keypress", this);
+  },
+
+  _eventListenersAdded: false,
+  _ensureEventListenersAdded: function() {
+    if (this._eventListenersAdded)
+      return;
+    this._addEventListeners();
+  },
+
+  _addEventListeners: function() {
+    for (let event of this.kEvents) {
+      this.panel.addEventListener(event, this);
+    }
+
+    this.helpView.addEventListener("ViewShowing", this._onHelpViewShow, false);
+    this.helpView.addEventListener("ViewHiding", this._onHelpViewHide, false);
+    this._eventListenersAdded = true;
+  },
+
+  uninit: function() {
+    if (!this._eventListenersAdded) {
+      return;
+    }
+
+    for (let event of this.kEvents) {
+      this.panel.removeEventListener(event, this);
+    }
+    this.helpView.removeEventListener("ViewShowing", this._onHelpViewShow);
+    this.helpView.removeEventListener("ViewHiding", this._onHelpViewHide);
+    this.menuButton.removeEventListener("mousedown", this);
+    this.menuButton.removeEventListener("keypress", this);
+  },
+
+  /**
+   * Customize mode extracts the mainView and puts it somewhere else while the
+   * user customizes. Upon completion, this function can be called to put the
+   * panel back to where it belongs in normal browsing mode.
+   *
+   * @param aMainView
+   *        The mainView node to put back into place.
+   */
+  setMainView: function(aMainView) {
+    this._ensureEventListenersAdded();
+    this.multiView.setMainView(aMainView);
+  },
+
+  /**
+   * Opens the menu panel if it's closed, or closes it if it's
+   * open. If the event target has a child with the toolbarbutton-icon
+   * attribute, the panel will be anchored on that child. Otherwise, the panel
+   * is anchored on the event target itself.
+   *
+   * @param aEvent the event that triggers the toggle.
+   */
+  toggle: function(aEvent) {
+    // Don't show the panel if the window is in customization mode,
+    // since this button doubles as an exit path for the user in this case.
+    if (document.documentElement.hasAttribute("customizing")) {
+      return;
+    }
+    this._ensureEventListenersAdded();
+    if (this.panel.state == "open") {
+      this.hide();
+    } else if (this.panel.state == "closed") {
+      this.ensureReady().then(function() {
+        this.panel.hidden = false;
+        let editControlPlacement = CustomizableUI.getPlacementOfWidget("edit-controls");
+        if (editControlPlacement && editControlPlacement.area == CustomizableUI.AREA_PANEL) {
+          updateEditUIVisibility();
+        }
+
+        let anchor;
+        if (aEvent.type == "mousedown" ||
+            aEvent.type == "command") {
+          anchor = this.menuButton;
+        } else {
+          anchor = aEvent.target;
+        }
+        let iconAnchor =
+          document.getAnonymousElementByAttribute(anchor, "class",
+                                                  "toolbarbutton-icon");
+
+        // Only focus the panel if it's opened using the keyboard, so that
+        // cut/copy/paste buttons will work for mouse users.
+        let keyboardOpened = aEvent.sourceEvent &&
+                             aEvent.sourceEvent.target.localName == "key";
+        this.panel.setAttribute("noautofocus", !keyboardOpened);
+        this.panel.openPopup(iconAnchor || anchor, "bottomcenter topright");
+      }.bind(this));
+    }
+  },
+
+  /**
+   * If the menu panel is being shown, hide it.
+   */
+  hide: function() {
+    this.panel.hidePopup();
+  },
+
+  handleEvent: function(aEvent) {
+    switch (aEvent.type) {
+      case "popupshowing":
+        // Fall through
+      case "popupshown":
+        // Fall through
+      case "popuphiding":
+        // Fall through
+      case "popuphidden": {
+        this._updatePanelButton(aEvent.target);
+        break;
+      }
+      case "mousedown":
+        // Fall through
+      case "keypress":
+        this.toggle(aEvent);
+        break;
+    }
+  },
+
+  /**
+   * Registering the menu panel is done lazily for performance reasons. This
+   * method is exposed so that CustomizationMode can force panel-readyness in the
+   * event that customization mode is started before the panel has been opened
+   * by the user.
+   *
+   * @param aCustomizing (optional) set to true if this was called while entering
+   *        customization mode. If that's the case, we trust that customization
+   *        mode will handle calling beginBatchUpdate and endBatchUpdate.
+   *
+   * @return a Promise that resolves once the panel is ready to roll.
+   */
+  ensureReady: function(aCustomizing=false) {
+    return Task.spawn(function() {
+      if (!this._scrollWidth) {
+        // In order to properly center the contents of the panel, while ensuring
+        // that we have enough space on either side to show a scrollbar, we have to
+        // do a bit of hackery. In particular, we sample the system scrollbar width,
+        // and then use that to calculate a new width for the scroller.
+        this._scrollWidth = (yield this._sampleScrollbarWidth()) + "px";
+        let cstyle = window.getComputedStyle(this.scroller);
+        let widthStr = cstyle.width;
+        // Get the calculated padding on the left and right sides of
+        // the scroller too. We'll use that in our final calculation so
+        // that if a scrollbar appears, we don't have the contents right
+        // up against the edge of the scroller.
+        let paddingLeft = cstyle.paddingLeft;
+        let paddingRight = cstyle.paddingRight;
+        let calcStr = [widthStr, this._scrollWidth,
+                       paddingLeft, paddingRight].join(" + ");
+        this.scroller.style.width = "calc(" + calcStr + ")";
+      }
+
+      if (aCustomizing) {
+        CustomizableUI.registerMenuPanel(this.contents);
+      } else {
+        this.beginBatchUpdate();
+        CustomizableUI.registerMenuPanel(this.contents);
+        this.endBatchUpdate();
+      }
+    }.bind(this)).then(null, Cu.reportError);
+  },
+
+  /**
+   * Switch the panel to the main view if it's not already
+   * in that view.
+   */
+  showMainView: function() {
+    this._ensureEventListenersAdded();
+    this.multiView.showMainView();
+  },
+
+  /**
+   * Switch the panel to the help view if it's not already
+   * in that view.
+   */
+  showHelpView: function(aAnchor) {
+    this._ensureEventListenersAdded();
+    this.multiView.showSubView("PanelUI-helpView", aAnchor);
+  },
+
+  /**
+   * Shows a subview in the panel with a given ID.
+   *
+   * @param aViewId the ID of the subview to show.
+   * @param aAnchor the element that spawned the subview.
+   * @param aPlacementArea the CustomizableUI area that aAnchor is in.
+   */
+  showSubView: function(aViewId, aAnchor, aPlacementArea) {
+    this._ensureEventListenersAdded();
+    let viewNode = document.getElementById(aViewId);
+    if (!viewNode) {
+      Cu.reportError("Could not show panel subview with id: " + aViewId);
+      return;
+    }
+
+    if (!aAnchor) {
+      Cu.reportError("Expected an anchor when opening subview with id: " + aViewId);
+      return;
+    }
+
+    if (aPlacementArea == CustomizableUI.AREA_PANEL) {
+      this.multiView.showSubView(aViewId, aAnchor);
+    } else if (!aAnchor.open) {
+      aAnchor.open = true;
+      // Emit the ViewShowing event so that the widget definition has a chance
+      // to lazily populate the subview with things.
+      let evt = document.createEvent("CustomEvent");
+      evt.initCustomEvent("ViewShowing", true, true, viewNode);
+      viewNode.dispatchEvent(evt);
+      if (evt.defaultPrevented) {
+        return;
+      }
+
+      let tempPanel = document.createElement("panel");
+      tempPanel.setAttribute("type", "arrow");
+      tempPanel.setAttribute("id", "customizationui-widget-panel");
+      tempPanel.setAttribute("level", "top");
+      document.getElementById(CustomizableUI.AREA_NAVBAR).appendChild(tempPanel);
+
+      let multiView = document.createElement("panelmultiview");
+      tempPanel.appendChild(multiView);
+      multiView.setMainView(viewNode);
+      CustomizableUI.addPanelCloseListeners(tempPanel);
+
+      let panelRemover = function() {
+        tempPanel.removeEventListener("popuphidden", panelRemover);
+        CustomizableUI.removePanelCloseListeners(tempPanel);
+        let evt = new CustomEvent("ViewHiding", {detail: viewNode});
+        viewNode.dispatchEvent(evt);
+        aAnchor.open = false;
+
+        this.multiView.appendChild(viewNode);
+        tempPanel.parentElement.removeChild(tempPanel);
+      }.bind(this);
+      tempPanel.addEventListener("popuphidden", panelRemover);
+
+      let iconAnchor =
+        document.getAnonymousElementByAttribute(aAnchor, "class",
+                                                "toolbarbutton-icon");
+
+      tempPanel.openPopup(iconAnchor || aAnchor, "bottomcenter topright");
+    }
+  },
+
+  /**
+   * This function can be used as a command event listener for subviews
+   * so that the panel knows if and when to close itself.
+   */
+  onCommandHandler: function(aEvent) {
+    if (!aEvent.originalTarget.hasAttribute("noautoclose")) {
+      PanelUI.hide();
+    }
+  },
+
+  /**
+   * Open a dialog window that allow the user to customize listed character sets.
+   */
+  onCharsetCustomizeCommand: function() {
+    this.hide();
+    window.openDialog("chrome://global/content/customizeCharset.xul",
+                      "PrefWindow",
+                      "chrome,modal=yes,resizable=yes",
+                      "browser");
+  },
+
+  /** 
+   * Signal that we're about to make a lot of changes to the contents of the
+   * panels all at once. For performance, we ignore the mutations.
+   */
+  beginBatchUpdate: function() {
+    this._ensureEventListenersAdded();
+    this.multiView.ignoreMutations = true;
+  },
+
+  /**
+   * Signal that we're done making bulk changes to the panel. We now pay
+   * attention to mutations. This automatically synchronizes the multiview
+   * container with whichever view is displayed if the panel is open.
+   */
+  endBatchUpdate: function(aReason) {
+    this._ensureEventListenersAdded();
+    this.multiView.ignoreMutations = false;
+  },
+
+  /**
+   * Sets the anchor node into the open or closed state, depending
+   * on the state of the panel.
+   */
+  _updatePanelButton: function() {
+    this.menuButton.open = this.panel.state == "open" ||
+                           this.panel.state == "showing";
+  },
+
+  _onHelpViewShow: function(aEvent) {
+    // Call global menu setup function
+    buildHelpMenu();
+
+    let helpMenu = document.getElementById("menu_HelpPopup");
+    let items = this.getElementsByTagName("vbox")[0];
+    let attrs = ["oncommand", "onclick", "label", "key", "disabled"];
+    let NSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+    // Remove all buttons from the view
+    while (items.firstChild) {
+      items.removeChild(items.firstChild);
+    }
+
+    // Add the current set of menuitems of the Help menu to this view
+    let menuItems = Array.prototype.slice.call(helpMenu.getElementsByTagName("menuitem"));
+    let fragment = document.createDocumentFragment();
+    for (let node of menuItems) {
+      if (node.hidden)
+        continue;
+      let button = document.createElementNS(NSXUL, "toolbarbutton");
+      // Copy specific attributes from a menuitem of the Help menu
+      for (let attrName of attrs) {
+        if (!node.hasAttribute(attrName))
+          continue;
+        button.setAttribute(attrName, node.getAttribute(attrName));
+      }
+      fragment.appendChild(button);
+    }
+    items.appendChild(fragment);
+
+    this.addEventListener("command", PanelUI.onCommandHandler);
+  },
+
+  _onHelpViewHide: function(aEvent) {
+    this.removeEventListener("command", PanelUI.onCommandHandler);
+  },
+
+  _sampleScrollbarWidth: function() {
+    let deferred = Promise.defer();
+    let hwin = Services.appShell.hiddenDOMWindow;
+    let hdoc = hwin.document.documentElement;
+    let iframe = hwin.document.createElementNS("http://www.w3.org/1999/xhtml",
+                                               "html:iframe");
+    iframe.setAttribute("srcdoc", '<body style="overflow-y: scroll"></body>');
+    hdoc.appendChild(iframe);
+
+    let cwindow = iframe.contentWindow;
+    let utils = cwindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                       .getInterface(Ci.nsIDOMWindowUtils);
+
+    cwindow.addEventListener("load", function onLoad(aEvent) {
+      cwindow.removeEventListener("load", onLoad);
+      let sbWidth = {};
+      try {
+        utils.getScrollbarSize(true, sbWidth, {});
+      } catch(e) {
+        Components.utils.reportError("Could not sample scrollbar size: " + e +
+                                     " -- " + e.stack);
+        sbWidth.value = 0;
+      }
+      deferred.resolve(sbWidth.value);
+      iframe.remove();
+    });
+
+    return deferred.promise;
+  }
+};
+
+PanelUI.init();
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUI.xml
@@ -0,0 +1,342 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<bindings id="browserPanelUIBindings"
+          xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
+
+  <binding id="panelmultiview">
+    <resources>
+      <stylesheet src="chrome://browser/content/customizableui/panelUI.css"/>
+    </resources>
+    <content>
+      <xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,viewtype,transitioning">
+        <xul:stack anonid="viewStack" xbl:inherits="viewtype" viewtype="main" class="panel-viewstack">
+          <xul:vbox anonid="mainViewContainer" class="panel-mainview"/>
+
+          <!-- Used to capture click events over the PanelUI-mainView if we're in
+               subview mode. That way, any click on the PanelUI-mainView causes us
+               to revert to the mainView mode, whereupon PanelUI-click-capture then
+               allows click events to go through it. -->
+          <xul:vbox anonid="clickCapturer" class="panel-clickcapturer"/>
+
+          <!-- We manually set display: none (via a CSS attribute selector) on the
+               subviews that are not being displayed. We're using this over a deck
+               because a deck assumes the size of its largest child, regardless of
+               whether or not it is shown. That's not good for our case, since we
+               want to allow each subview to be uniquely sized. -->
+          <xul:vbox anonid="subViews" class="panel-subviews" xbl:inherits="panelopen">
+            <children includes="panelview"/>
+          </xul:vbox>
+        </xul:stack>
+      </xul:box>
+    </content>
+    <implementation implements="nsIDOMEventListener">
+      <field name="_clickCapturer" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "clickCapturer");
+      </field>
+      <field name="_viewContainer" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "viewContainer");
+      </field>
+      <field name="_mainViewContainer" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "mainViewContainer");
+      </field>
+      <field name="_subViews" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "subViews");
+      </field>
+      <field name="_viewStack" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "viewStack");
+      </field>
+      <field name="_panel" readonly="true">
+        this.parentNode;
+      </field>
+
+      <field name="_currentSubView">null</field>
+      <field name="_anchorElement">null</field>
+      <field name="_mainViewHeight">0</field>
+      <field name="_subViewObserver">null</field>
+      <field name="__transitioning">false</field>
+      <field name="_ignoreMutations">false</field>
+
+      <property name="showingSubView" readonly="true"
+                onget="return this._viewStack.getAttribute('viewtype') == 'subview'"/>
+      <property name="_mainViewId" onget="return this.getAttribute('mainViewId');" onset="this.setAttribute('mainViewId', val); return val;"/>
+      <property name="_mainView" readonly="true"
+                onget="return this._mainViewId ? document.getElementById(this._mainViewId) : null;"/>
+
+      <property name="ignoreMutations">
+        <getter>
+          return this._ignoreMutations;
+        </getter>
+        <setter><![CDATA[
+          this._ignoreMutations = val;
+          if (!val && this._panel.state == "open") {
+            if (this.showingSubView) {
+              this._syncContainerWithSubView();
+            } else {
+              this._syncContainerWithMainView();
+            }
+          }
+        ]]></setter>
+      </property>
+
+      <property name="_transitioning">
+        <getter>
+          return this.__transitioning;
+        </getter>
+        <setter><![CDATA[
+          this.__transitioning = val;
+          if (val) {
+            this.setAttribute("transitioning", "true");
+          } else {
+            this.removeAttribute("transitioning");
+          }
+        ]]></setter>
+      </property>
+      <constructor><![CDATA[
+        this._clickCapturer.addEventListener("click", this);
+        this._panel.addEventListener("popupshowing", this);
+        this._panel.addEventListener("popupshown", this);
+        this._panel.addEventListener("popuphidden", this);
+        this._subViews.addEventListener("overflow", this);
+        this._mainViewContainer.addEventListener("overflow", this);
+
+        // Get a MutationObserver ready to react to subview size changes. We
+        // only attach this MutationObserver when a subview is being displayed.
+        this._subViewObserver =
+          new MutationObserver(this._syncContainerWithSubView.bind(this));
+        this._mainViewObserver =
+          new MutationObserver(this._syncContainerWithMainView.bind(this));
+
+        this._mainViewContainer.setAttribute("panelid",
+                                             this._panel.id);
+
+        if (this._mainView) {
+          this.setMainView(this._mainView);
+        }
+        this.setAttribute("viewtype", "main");
+      ]]></constructor>
+
+      <destructor><![CDATA[
+        if (this._mainView) {
+          this._mainView.removeAttribute("mainview");
+        }
+        this._mainViewObserver.disconnect();
+        this._subViewObserver.disconnect();
+        this._panel.removeEventListener("popupshowing", this);
+        this._panel.removeEventListener("popupshown", this);
+        this._panel.removeEventListener("popuphidden", this);
+        this._subViews.removeEventListener("overflow", this);
+        this._mainViewContainer.removeEventListener("overflow", this);
+        this._clickCapturer.removeEventListener("click", this);
+      ]]></destructor>
+
+      <method name="setMainView">
+        <parameter name="aNewMainView"/>
+        <body><![CDATA[
+        if (this._mainView) {
+          this._mainViewObserver.disconnect();
+          this._subViews.appendChild(this._mainView);
+          this._mainView.removeAttribute("mainview");
+        }
+        this._mainViewId = aNewMainView.id;
+        aNewMainView.setAttribute("mainview", "true");
+        this._mainViewContainer.appendChild(aNewMainView);
+        ]]></body>
+      </method>
+
+      <method name="showMainView">
+        <body><![CDATA[
+          if (this.showingSubView) {
+            let viewNode = this._currentSubView;
+            let evt = document.createEvent("CustomEvent");
+            evt.initCustomEvent("ViewHiding", true, true, viewNode);
+            viewNode.dispatchEvent(evt);
+
+            viewNode.removeAttribute("current");
+            this._currentSubView = null;
+
+            this._subViewObserver.disconnect();
+
+            this._transitioning = true;
+
+            this._viewContainer.addEventListener("transitionend", function trans() {
+              this._viewContainer.removeEventListener("transitionend", trans);
+              this._transitioning = false;
+            }.bind(this));
+            this._viewContainer.style.height = this._mainViewHeight + "px";
+
+            this.setAttribute("viewtype", "main");
+          }
+
+          this._mainViewObserver.observe(this._mainView, {
+            attributes: true,
+            characterData: true,
+            childList: true,
+            subtree: true
+          });
+
+          this._shiftMainView();
+        ]]></body>
+      </method>
+
+      <method name="showSubView">
+        <parameter name="aViewId"/>
+        <parameter name="aAnchor"/>
+        <body><![CDATA[
+          let viewNode = this.querySelector("#" + aViewId);
+          viewNode.setAttribute("current", true);
+          // Emit the ViewShowing event so that the widget definition has a chance
+          // to lazily populate the subview with things.
+          let evt = document.createEvent("CustomEvent");
+          evt.initCustomEvent("ViewShowing", true, true, viewNode);
+          viewNode.dispatchEvent(evt);
+          if (evt.defaultPrevented) {
+            return;
+          }
+
+          this._currentSubView = viewNode;
+
+          // Now we have to transition to transition the panel. There are a few parts
+          // to this:
+          //
+          // 1) The main view content gets shifted so that the center of the anchor
+          //    node is at the left-most edge of the panel.
+          // 2) The subview deck slides in so that it takes up almost all of the
+          //    panel.
+          // 3) If the subview is taller then the main panel contents, then the panel
+          //    must grow to meet that new height. Otherwise, it must shrink.
+          //
+          // All three of these actions make use of CSS transformations, so they
+          // should all occur simultaneously.
+          this.setAttribute("viewtype", "subview");
+          this._shiftMainView(aAnchor);
+
+          this._mainViewHeight = this._viewStack.clientHeight;
+
+          this._transitioning = true;
+          this._viewContainer.addEventListener("transitionend", function trans() {
+            this._viewContainer.removeEventListener("transitionend", trans);
+            this._transitioning = false;
+          }.bind(this));
+          this._viewContainer.style.height = this._subViews.scrollHeight + "px";
+
+          this._subViewObserver.observe(viewNode, {
+            attributes: true,
+            characterData: true,
+            childList: true,
+            subtree: true
+          });
+        ]]></body>
+      </method>
+
+      <method name="_shiftMainView">
+        <parameter name="aAnchor"/>
+        <body><![CDATA[
+          if (aAnchor) {
+            // We need to find the edge of the anchor, relative to the main panel.
+            // Then we need to add half the width of the anchor. This is the target
+            // that we need to transition to.
+            let anchorRect = aAnchor.getBoundingClientRect();
+            let mainViewRect = this._mainViewContainer.getBoundingClientRect();
+            let center = aAnchor.clientWidth / 2;
+            let direction = aAnchor.ownerDocument.defaultView.getComputedStyle(aAnchor, null).direction;
+            let edge, target;
+            if (direction == "ltr") {
+              edge = anchorRect.left - mainViewRect.left;
+              target = "-" + (edge + center);
+            } else {
+              edge = mainViewRect.right - anchorRect.right;
+              target = edge + center;
+            }
+            this._mainViewContainer.style.transform = "translateX(" + target + "px)";
+            aAnchor.classList.add("panel-multiview-anchor");
+          } else {
+            this._mainViewContainer.style.transform = "";
+            if (this.anchorElement)
+              this.anchorElement.classList.remove("panel-multiview-anchor");
+          }
+          this.anchorElement = aAnchor;
+        ]]></body>
+      </method>
+
+      <method name="handleEvent">
+        <parameter name="aEvent"/>
+        <body><![CDATA[
+          switch(aEvent.type) {
+            case "click":
+              if (aEvent.originalTarget == this._clickCapturer) {
+                this.showMainView();
+              }
+              break;
+            case "overflow":
+              // Resize the right view on the next tick.
+              if (this.showingSubView) {
+                setTimeout(this._syncContainerWithSubView.bind(this), 0);
+              } else if (!this.transitioning) {
+                setTimeout(this._syncContainerWithMainView.bind(this), 0);
+              }
+              break;
+            case "popupshowing":
+              this.setAttribute("panelopen", "true");
+              this._syncContainerWithMainView();
+              break;
+            case "popupshown":
+              this._setMaxHeight();
+              break;
+            case "popuphidden":
+              this.removeAttribute("panelopen");
+              this._mainView.style.height = "";
+              this.showMainView();
+              break;
+          }
+        ]]></body>
+      </method>
+
+      <method name="_setMaxHeight">
+        <body><![CDATA[
+          // Ignore the mutation that'll fire when we set the height of
+          // the main view.
+          this.ignoreMutations = true;
+          this._mainView.style.height =
+            this.getBoundingClientRect().height + "px";
+          this.ignoreMutations = false;
+        ]]></body>
+      </method>
+      <method name="_syncContainerWithSubView">
+        <body><![CDATA[
+          if (!this.ignoreMutations && this.showingSubView) {
+            this._viewContainer.style.height =
+              this._subViews.scrollHeight + "px";
+          }
+        ]]></body>
+      </method>
+      <method name="_syncContainerWithMainView">
+        <body><![CDATA[
+          if (!this.ignoreMutations && !this.showingSubView && !this._transitioning) {
+            this._viewContainer.style.height =
+              this._mainView.scrollHeight + "px";
+          }
+        ]]></body>
+      </method>
+
+    </implementation>
+  </binding>
+
+  <binding id="panelview">
+    <implementation>
+      <property name="panelMultiView" readonly="true">
+        <getter><![CDATA[
+          if (this.parentNode.localName != "panelmultiview") {
+            return document.getBindingParent(this.parentNode);
+          }
+
+          return this.parentNode;
+        ]]></getter>
+      </property>
+    </implementation>
+  </binding>
+</bindings>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/toolbar.xml
@@ -0,0 +1,542 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<bindings id="browserToolbarBindings"
+          xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
+
+  <binding id="toolbar">
+    <resources>
+      <stylesheet src="chrome://global/skin/toolbar.css"/>
+    </resources>
+    <implementation implements="nsIAccessibleProvider">
+      <field name="_initialChildCount">0</field>
+
+      <property name="accessibleType" readonly="true">
+        <getter>
+          return Components.interfaces.nsIAccessibleProvider.XULToolbar;
+        </getter>
+      </property>
+
+      <constructor><![CDATA[
+          // Stash the initial child count so that later, after overlays are
+          // loaded, we can report to CustomizableUI's registerToolbar function
+          // whether or not we've been overlayed by comparing child counts.
+          this._initialChildCount = this.childElementCount;
+          if (document.readyState == "complete") {
+            this._init();
+          } else {
+            // Need to wait until XUL overlays are loaded. See bug 554279.
+            let self = this;
+            document.addEventListener("readystatechange", function onReadyStateChange() {
+              if (document.readyState != "complete")
+                return;
+              document.removeEventListener("readystatechange", onReadyStateChange, false);
+              self._init();
+            }, false);
+          }
+      ]]></constructor>
+
+      <method name="_init">
+        <body><![CDATA[
+          let scope = {};
+          Cu.import("resource:///modules/CustomizableUI.jsm", scope);
+          let CustomizableUI = scope.CustomizableUI;
+
+          // Searching for the toolbox palette in the toolbar binding because
+          // toolbars are constructed first.
+          let toolbox = this.toolbox;
+          if (toolbox && !toolbox.palette) {
+            for (let node of toolbox.children) {
+              if (node.localName == "toolbarpalette") {
+                // Hold on to the palette but remove it from the document.
+                toolbox.palette = node;
+                toolbox.removeChild(node);
+                break;
+              }
+            }
+          }
+
+          // If the child count does not match the child count that we recorded
+          // when the constructor fired, then we were overlayed.
+          let isOverlayed = this._initialChildCount != this.childElementCount;
+          CustomizableUI.registerToolbar(this, isOverlayed);
+        ]]></body>
+      </method>
+
+      <method name="insertItem">
+        <parameter name="aId"/>
+        <parameter name="aBeforeElt"/>
+        <parameter name="aWrapper"/>
+        <body><![CDATA[
+          if (aWrapper) {
+            Cu.reportError("Can't insert " + aId + ": using insertItem " +
+                           "no longer supports wrapper elements.");
+            return null;
+          }
+
+          // Hack, the customizable UI code makes this be the last position
+          let pos = null;
+          if (aBeforeElt) {
+            let beforeInfo = CustomizableUI.getPlacementOfWidget(aBeforeElt.id);
+            if (beforeInfo.area != this.id) {
+              Cu.reportError("Can't insert " + aId + " before " +
+                             aBeforeElt.id + " which isn't in this area (" +
+                             this.id + ").");
+              return null;
+            }
+            pos = beforeInfo.position;
+          }
+
+          CustomizableUI.addWidgetToArea(aId, this.id, pos);
+          return this.ownerDocument.getElementById(aId);
+        ]]></body>
+      </method>
+
+      <property name="toolbarName"
+                onget="return this.getAttribute('toolbarname');"
+                onset="this.setAttribute('toolbarname', val); return val;"/>
+
+      <property name="customizationTarget" readonly="true">
+        <getter><![CDATA[
+          if (this._customizationTarget)
+            return this._customizationTarget;
+
+          let id = this.getAttribute("customizationtarget");
+          if (id)
+            this._customizationTarget = document.getElementById(id);
+
+          if (this._customizationTarget)
+            this._customizationTarget.insertItem = this.insertItem.bind(this);
+          else
+            this._customizationTarget = this;
+
+          return this._customizationTarget;
+        ]]></getter>
+      </property>
+
+      <property name="toolbox" readonly="true">
+        <getter><![CDATA[
+          if (this._toolbox)
+            return this._toolbox;
+
+          let toolboxId = this.getAttribute("toolboxid");
+          if (toolboxId) {
+            let toolbox = document.getElementById(toolboxId);
+            if (toolbox) {
+              if (toolbox.externalToolbars.indexOf(this) == -1)
+                toolbox.externalToolbars.push(this);
+
+              this._toolbox = toolbox;
+            }
+          }
+
+          if (!this._toolbox && this.parentNode &&
+              this.parentNode.localName == "toolbox") {
+            this._toolbox = this.parentNode;
+          }
+
+          return this._toolbox;
+        ]]></getter>
+      </property>
+
+      <property name="currentSet">
+        <getter><![CDATA[
+          let currentWidgets = new Set();
+          for (let node of this.customizationTarget.children) {
+            let realNode = node.localName == "toolbarpaletteitem" ? node.firstChild : node;
+            if (realNode.getAttribute("skipintoolbarset") != "true") {
+              currentWidgets.add(realNode.id);
+            }
+          }
+          if (this.getAttribute("overflowing") == "true") {
+            let overflowTarget = this.getAttribute("overflowtarget");
+            let overflowList = this.ownerDocument.getElementById(overflowTarget);
+            for (let node of overflowList.children) {
+              let realNode = node.localName == "toolbarpaletteitem" ? node.firstChild : node;
+              if (realNode.getAttribute("skipintoolbarset") != "true") {
+                currentWidgets.add(realNode.id);
+              }
+            }
+          }
+          let orderedPlacements = CustomizableUI.getWidgetIdsInArea(this.id);
+          return orderedPlacements.filter((x) => currentWidgets.has(x)).join(',');
+        ]]></getter>
+        <setter><![CDATA[
+          // Get list of new and old ids:
+          let newVal = (val || '').split(',').filter(x => x);
+          let oldIds = CustomizableUI.getWidgetIdsInArea(this.id);
+
+          // Get a list of items only in the new list
+          let newIds = [id for (id of newVal) if (oldIds.indexOf(id) == -1)];
+          CustomizableUI.beginBatchUpdate();
+          for (let newId of newIds) {
+            oldIds = CustomizableUI.getWidgetIdsInArea(this.id);
+            let nextId = newId;
+            let pos;
+            do {
+              // Get the next item
+              nextId = newVal[newVal.indexOf(nextId) + 1];
+              // Figure out where it is in the old list
+              pos = oldIds.indexOf(nextId);
+              // If it's not in the old list, repeat:
+            } while (pos == -1 && nextId);
+            if (pos == -1) {
+              pos = null; // We didn't find anything, insert at the end
+            }
+            CustomizableUI.addWidgetToArea(newId, this.id, pos);
+          }
+
+          let currentIds = this.currentSet.split(',');
+          let removedIds = [id for (id of currentIds) if (newIds.indexOf(id) == -1 && newVal.indexOf(id) == -1)];
+          for (let removedId of removedIds) {
+            CustomizableUI.removeWidgetFromArea(removedId);
+          }
+          CustomizableUI.endBatchUpdate();
+        ]]></setter>
+      </property>
+
+
+    </implementation>
+  </binding>
+
+  <binding id="toolbar-menubar-stub">
+    <implementation>
+      <property name="toolbox" readonly="true">
+        <getter><![CDATA[
+          if (this._toolbox)
+            return this._toolbox;
+
+          if (this.parentNode && this.parentNode.localName == "toolbox") {
+            this._toolbox = this.parentNode;
+          }
+
+          return this._toolbox;
+        ]]></getter>
+      </property>
+      <property name="currentSet" readonly="true">
+        <getter><![CDATA[
+          return this.getAttribute("defaultset");
+        ]]></getter>
+      </property>
+      <method name="insertItem">
+        <body><![CDATA[
+          return null;
+        ]]></body>
+      </method>
+    </implementation>
+  </binding>
+
+  <!-- The toolbar-menubar-autohide and toolbar-drag bindings are almost
+       verbatim copies of their toolkit counterparts - they just inherit from
+       the customizableui's toolbar binding instead of toolkit's. We're currently
+       OK with the maintainance burden of having two copies of a binding, since
+       the long term goal is to move the customization framework into toolkit. -->
+
+  <binding id="toolbar-menubar-autohide"
+           extends="chrome://browser/content/customizableui/toolbar.xml#toolbar">
+    <implementation>
+      <constructor>
+        this._setInactive();
+      </constructor>
+      <destructor>
+        this._setActive();
+      </destructor>
+
+      <field name="_inactiveTimeout">null</field>
+
+      <field name="_contextMenuListener"><![CDATA[({
+        toolbar: this,
+        contextMenu: null,
+
+        get active () !!this.contextMenu,
+
+        init: function (event) {
+          let node = event.target;
+          while (node != this.toolbar) {
+            if (node.localName == "menupopup")
+              return;
+            node = node.parentNode;
+          }
+
+          let contextMenuId = this.toolbar.getAttribute("context");
+          if (!contextMenuId)
+            return;
+
+          this.contextMenu = document.getElementById(contextMenuId);
+          if (!this.contextMenu)
+            return;
+
+          this.contextMenu.addEventListener("popupshown", this, false);
+          this.contextMenu.addEventListener("popuphiding", this, false);
+          this.toolbar.addEventListener("mousemove", this, false);
+        },
+        handleEvent: function (event) {
+          switch (event.type) {
+            case "popupshown":
+              this.toolbar.removeEventListener("mousemove", this, false);
+              break;
+            case "popuphiding":
+            case "mousemove":
+              this.toolbar._setInactiveAsync();
+              this.toolbar.removeEventListener("mousemove", this, false);
+              this.contextMenu.removeEventListener("popuphiding", this, false);
+              this.contextMenu.removeEventListener("popupshown", this, false);
+              this.contextMenu = null;
+              break;
+          }
+        }
+      })]]></field>
+
+      <method name="_setInactive">
+        <body><![CDATA[
+          this.setAttribute("inactive", "true");
+        ]]></body>
+      </method>
+
+      <method name="_setInactiveAsync">
+        <body><![CDATA[
+          this._inactiveTimeout = setTimeout(function (self) {
+            if (self.getAttribute("autohide") == "true") {
+              self._inactiveTimeout = null;
+              self._setInactive();
+            }
+          }, 0, this);
+        ]]></body>
+      </method>
+
+      <method name="_setActive">
+        <body><![CDATA[
+          if (this._inactiveTimeout) {
+            clearTimeout(this._inactiveTimeout);
+            this._inactiveTimeout = null;
+          }
+          this.removeAttribute("inactive");
+        ]]></body>
+      </method>
+    </implementation>
+
+    <handlers>
+      <handler event="DOMMenuBarActive"     action="this._setActive();"/>
+      <handler event="popupshowing"         action="this._setActive();"/>
+      <handler event="mousedown" button="2" action="this._contextMenuListener.init(event);"/>
+      <handler event="DOMMenuBarInactive"><![CDATA[
+        if (!this._contextMenuListener.active)
+          this._setInactiveAsync();
+      ]]></handler>
+    </handlers>
+  </binding>
+
+  <binding id="toolbar-drag"
+           extends="chrome://browser/content/customizableui/toolbar.xml#toolbar">
+    <implementation>
+      <field name="_dragBindingAlive">true</field>
+      <constructor><![CDATA[
+        if (!this._draggableStarted) {
+          this._draggableStarted = true;
+          try {
+            let tmp = {};
+            Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
+            let draggableThis = new tmp.WindowDraggingElement(this);
+            draggableThis.mouseDownCheck = function(e) {
+              return this._dragBindingAlive;
+            };
+          } catch (e) {}
+        }
+      ]]></constructor>
+    </implementation>
+  </binding>
+
+
+<!-- This is a peculiar binding. It is here to deal with overlayed/inserted add-on content,
+      and immediately direct such content elsewhere. -->
+  <binding id="addonbar-delegating">
+    <implementation>
+      <field name="_initialChildCount">0</field>
+
+      <constructor><![CDATA[
+          // Reading these immediately so nobody messes with them anymore:
+          this._delegatingToolbar = this.getAttribute("toolbar-delegate");
+          // Stash the initial child count so that later, after overlays are
+          // loaded, we can report to CustomizableUI's registerToolbar function
+          // whether or not we've been overlayed by comparing child counts.
+          this._initialChildCount = this.childElementCount;
+          // Leaving those in here to unbreak some code:
+          if (document.readyState == "complete") {
+            this._init();
+          } else {
+            // Need to wait until XUL overlays are loaded. See bug 554279.
+            let self = this;
+            document.addEventListener("readystatechange", function onReadyStateChange() {
+              if (document.readyState != "complete")
+                return;
+              document.removeEventListener("readystatechange", onReadyStateChange, false);
+              self._init();
+            }, false);
+          }
+      ]]></constructor>
+
+      <method name="_init">
+        <body><![CDATA[
+          // Searching for the toolbox palette in the toolbar binding because
+          // toolbars are constructed first.
+          let toolbox = this.toolbox;
+          if (toolbox && !toolbox.palette) {
+            for (let node of toolbox.children) {
+              if (node.localName == "toolbarpalette") {
+                // Hold on to the palette but remove it from the document.
+                toolbox.palette = node;
+                toolbox.removeChild(node);
+              }
+            }
+          }
+
+          // If the child count does not match the child count that we recorded
+          // when the constructor fired, then we were overlayed.
+          let isOverlayed = this._initialChildCount != this.childElementCount;
+          CustomizableUI.registerToolbar(this, isOverlayed);
+          this.evictNodes();
+          // We can't easily use |this| or strong bindings for the observer fn here
+          // because that creates leaky circular references when the node goes away,
+          // and XBL destructors are unreliable.
+          let mutationObserver = new MutationObserver(function(mutations) {
+            if (!mutations.length) {
+              return;
+            }
+            let toolbar = mutations[0].target;
+            // Can't use our own attribute because we might not have one if we're set to
+            // collapsed
+            let areCustomizing = toolbar.ownerDocument.documentElement.getAttribute("customizing");
+            if (!toolbar._isModifying && !areCustomizing) {
+              toolbar.evictNodes();
+            }
+          });
+          mutationObserver.observe(this, {childList: true});
+        ]]></body>
+      </method>
+      <method name="evictNodes">
+        <body><![CDATA[
+          this._isModifying = true;
+          let i = this.childNodes.length;
+          while (i--) {
+            let node = this.childNodes[i];
+            if (this.childNodes[i].id) {
+              this.evictNode(this.childNodes[i]);
+            } else {
+              node.remove();
+            }
+          }
+          this._isModifying = false;
+        ]]></body>
+      </method>
+      <method name="evictNode">
+        <parameter name="aNode"/>
+        <body>
+        <![CDATA[
+          if (this._whiteListed.has(aNode.id) || CustomizableUI.isSpecialWidget(aNode.id)) {
+            return;
+          }
+          const kItemMaxWidth = 100;
+          let oldParent = aNode.parentNode;
+
+          try {
+            aNode.setAttribute("removable", "true");
+
+            let nodeWidth = aNode.getBoundingClientRect().width;
+            if (nodeWidth == 0 || nodeWidth > kItemMaxWidth) {
+              throw new Error(aNode.id + " is too big (" + nodeWidth +
+                              "px wide), moving to the palette");
+            }
+            CustomizableUI.addWidgetToArea(aNode.id, this._delegatingToolbar);
+          } catch (ex) {
+            Cu.reportError(ex);
+            // This will throw if the node is too big, or can't be moved there for
+            // some reason. Try to remove it anyway:
+            try {
+              CustomizableUI.removeWidgetFromArea(aNode.id);
+            } catch (ex) {
+              Cu.reportError(ex);
+              aNode.remove();
+            }
+          }
+
+          // Surprise: addWidgetToArea(palette) will get you nothing if the palette
+          // is not constructed yet. Fix:
+          if (aNode.parentNode == oldParent) {
+            let palette = this.toolbox.palette;
+            if (palette && oldParent != palette) {
+              palette.appendChild(aNode);
+            }
+          }
+        ]]></body>
+      </method>
+      <method name="insertItem">
+        <parameter name="aId"/>
+        <parameter name="aBeforeElt"/>
+        <parameter name="aWrapper"/>
+        <body><![CDATA[
+          if (aWrapper) {
+            Cu.reportError("Can't insert " + aId + ": using insertItem " +
+                           "no longer supports wrapper elements.");
+            return null;
+          }
+
+          let widget = CustomizableUI.getWidget(aId);
+          widget = widget && widget.forWindow(window);
+          let node = widget && widget.node;
+          if (!node) {
+            return null;
+          }
+
+          this._isModifying = true;
+          // Temporarily add it here so it can have a width, then ditch it:
+          this.appendChild(node);
+          this.evictNode(node);
+          this._isModifying = false;
+          // We will now have moved stuff around; kick off an aftercustomization event
+          // so add-ons know we've just moved their stuff:
+          if (window.gCustomizeMode) {
+            window.gCustomizeMode.dispatchToolboxEvent("aftercustomization");
+          }
+          return node;
+        ]]></body>
+      </method>
+      <property name="customizationTarget" readonly="true">
+        <getter><![CDATA[
+          return this;
+        ]]></getter>
+      </property>
+      <property name="currentSet">
+        <getter><![CDATA[
+          return [node.id for (node of this.children)].join(',');
+        ]]></getter>
+        <setter><![CDATA[
+          let v = val.split(',');
+          let newButtons = v.filter(x => x && (!this._whiteListed.has(x) &&
+                                               !CustomizableUI.isSpecialWidget(x) &&
+                                               !this._currentSetMigrated.has(x)));
+          for (x of newButtons) {
+            this._currentSetMigrated.add(x);
+            this.insertItem(x);
+          }
+        ]]></setter>
+      </property>
+      <property name="toolbox" readonly="true">
+        <getter><![CDATA[
+          if (!this._toolbox && this.parentNode &&
+              this.parentNode.localName == "toolbox") {
+            this._toolbox = this.parentNode;
+          }
+
+          return this._toolbox;
+        ]]></getter>
+      </property>
+      <field name="_whiteListed" readonly="true">new Set(["addonbar-closebutton", "status-bar"])</field>
+      <field name="_isModifying">false</field>
+      <field name="_currentSetMigrated">new Set()</field>
+    </implementation>
+  </binding>
+</bindings>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/moz.build
@@ -0,0 +1,12 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PARALLEL_DIRS += [
+		'content',
+		'src',
+]
+
+BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -0,0 +1,2489 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["CustomizableUI"];
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PanelWideWidgetTracker",
+  "resource:///modules/PanelWideWidgetTracker.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "CustomizableWidgets",
+  "resource:///modules/CustomizableWidgets.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
+  "resource://gre/modules/DeferredTask.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
+  "resource://gre/modules/PrivateBrowsingUtils.jsm");
+XPCOMUtils.defineLazyGetter(this, "gWidgetsBundle", function() {
+  const kUrl = "chrome://browser/locale/customizableui/customizableWidgets.properties";
+  return Services.strings.createBundle(kUrl);
+});
+XPCOMUtils.defineLazyServiceGetter(this, "gELS",
+  "@mozilla.org/eventlistenerservice;1", "nsIEventListenerService");
+
+const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+const kSpecialWidgetPfx = "customizableui-special-";
+
+const kCustomizationContextMenu = "customizationContextMenu";
+
+
+const kPrefCustomizationState        = "browser.uiCustomization.state";
+const kPrefCustomizationAutoAdd      = "browser.uiCustomization.autoAdd";
+const kPrefCustomizationDebug        = "browser.uiCustomization.debug";
+
+/**
+ * The keys are the handlers that are fired when the event type (the value)
+ * is fired on the subview. A widget that provides a subview has the option
+ * of providing onViewShowing and onViewHiding event handlers.
+ */
+const kSubviewEvents = [
+  "ViewShowing",
+  "ViewHiding"
+];
+
+/**
+ * gPalette is a map of every widget that CustomizableUI.jsm knows about, keyed
+ * on their IDs.
+ */
+let gPalette = new Map();
+
+/**
+ * gAreas maps area IDs to Sets of properties about those areas. An area is a
+ * place where a widget can be put.
+ */
+let gAreas = new Map();
+
+/**
+ * gPlacements maps area IDs to Arrays of widget IDs, indicating that the widgets
+ * are placed within that area (either directly in the area node, or in the
+ * customizationTarget of the node).
+ */
+let gPlacements = new Map();
+
+/**
+ * gFuturePlacements represent placements that will happen for areas that have
+ * not yet loaded (due to lazy-loading). This can occur when add-ons register
+ * widgets.
+ */
+let gFuturePlacements = new Map();
+
+//XXXunf Temporary. Need a nice way to abstract functions to build widgets
+//       of these types.
+let gSupportedWidgetTypes = new Set(["button", "view", "custom"]);
+
+/**
+ * gPanelsForWindow is a list of known panels in a window which we may need to close
+ * should command events fire which target them.
+ */
+let gPanelsForWindow = new WeakMap();
+
+/**
+ * gSeenWidgets remembers which widgets the user has seen for the first time
+ * before. This way, if a new widget is created, and the user has not seen it
+ * before, it can be put in its default location. Otherwise, it remains in the
+ * palette.
+ */
+let gSeenWidgets = new Set();
+
+/**
+ * gDirtyAreaCache is a set of area IDs for areas where items have been added,
+ * moved or removed at least once. This set is persisted, and is used to
+ * optimize building of toolbars in the default case where no toolbars should
+ * be "dirty".
+ */
+let gDirtyAreaCache = new Set();
+
+let gSavedState = null;
+let gRestoring = false;
+let gDirty = false;
+let gInBatchStack = 0;
+let gResetting = false;
+
+/**
+ * gBuildAreas maps area IDs to actual area nodes within browser windows.
+ */
+let gBuildAreas = new Map();
+
+/**
+ * gBuildWindows is a map of windows that have registered build areas, mapped
+ * to a Set of known toolboxes in that window.
+ */
+let gBuildWindows = new Map();
+
+let gNewElementCount = 0;
+let gGroupWrapperCache = new Map();
+let gSingleWrapperCache = new WeakMap();
+let gListeners = new Set();
+
+let gModuleName = "[CustomizableUI]";
+#include logging.js
+
+let CustomizableUIInternal = {
+  initialize: function() {
+    LOG("Initializing");
+
+    this.addListener(this);
+    this._defineBuiltInWidgets();
+    this.loadSavedState();
+
+    let panelPlacements = [
+      "edit-controls",
+      "zoom-controls",
+      "new-window-button",
+      "privatebrowsing-button",
+      "save-page-button",
+      "print-button",
+      "history-panelmenu",
+      "fullscreen-button",
+      "find-button",
+      "preferences-button",
+      "add-ons-button",
+    ];
+    let showCharacterEncoding = Services.prefs.getComplexValue(
+      "browser.menu.showCharacterEncoding",
+      Ci.nsIPrefLocalizedString
+    ).data;
+    if (showCharacterEncoding == "true") {
+      panelPlacements.push("characterencoding-button");
+    }
+
+    this.registerArea(CustomizableUI.AREA_PANEL, {
+      anchor: "PanelUI-menu-button",
+      type: CustomizableUI.TYPE_MENU_PANEL,
+      defaultPlacements: panelPlacements
+    });
+    PanelWideWidgetTracker.init();
+
+    this.registerArea(CustomizableUI.AREA_NAVBAR, {
+      legacy: true,
+      type: CustomizableUI.TYPE_TOOLBAR,
+      overflowable: true,
+      defaultPlacements: [
+        "urlbar-container",
+        "search-container",
+        "webrtc-status-button",
+        "bookmarks-menu-button",
+        "downloads-button",
+        "home-button",
+        "social-share-button",
+        "social-toolbar-item",
+      ]
+    });
+#ifndef XP_MACOSX
+    this.registerArea(CustomizableUI.AREA_MENUBAR, {
+      legacy: true,
+      type: CustomizableUI.TYPE_TOOLBAR,
+      defaultPlacements: [
+        "menubar-items",
+      ]
+    });
+#endif
+    this.registerArea(CustomizableUI.AREA_TABSTRIP, {
+      legacy: true,
+      type: CustomizableUI.TYPE_TOOLBAR,
+      defaultPlacements: [
+        "tabbrowser-tabs",
+        "new-tab-button",
+        "alltabs-button",
+        "tabs-closebutton",
+      ]
+    });
+    this.registerArea(CustomizableUI.AREA_BOOKMARKS, {
+      legacy: true,
+      type: CustomizableUI.TYPE_TOOLBAR,
+      defaultPlacements: [
+        "personal-bookmarks",
+      ]
+    });
+
+    this.registerArea(CustomizableUI.AREA_ADDONBAR, {
+      type: CustomizableUI.TYPE_TOOLBAR,
+      legacy: true,
+      defaultPlacements: ["addonbar-closebutton", "status-bar"]
+    });
+  },
+
+  _defineBuiltInWidgets: function() {
+    //XXXunf Need to figure out how to auto-add new builtin widgets in new
+    //       app versions to already customized areas.
+    for (let widgetDefinition of CustomizableWidgets) {
+      this.createBuiltinWidget(widgetDefinition);
+    }
+  },
+
+  wrapWidget: function(aWidgetId) {
+    if (gGroupWrapperCache.has(aWidgetId)) {
+      return gGroupWrapperCache.get(aWidgetId);
+    }
+
+    let provider = this.getWidgetProvider(aWidgetId);
+    if (!provider) {
+      return null;
+    }
+
+    if (provider == CustomizableUI.PROVIDER_API) {
+      let widget = gPalette.get(aWidgetId);
+      if (!widget.wrapper) {
+        widget.wrapper = new WidgetGroupWrapper(widget);
+        gGroupWrapperCache.set(aWidgetId, widget.wrapper);
+      }
+      return widget.wrapper;
+    }
+
+    // PROVIDER_SPECIAL gets treated the same as PROVIDER_XUL.
+    let wrapper = new XULWidgetGroupWrapper(aWidgetId);
+    gGroupWrapperCache.set(aWidgetId, wrapper);
+    return wrapper;
+  },
+
+  registerArea: function(aName, aProperties) {
+    if (typeof aName != "string" || !/^[a-z0-9-_]{1,}$/i.test(aName)) {
+      throw new Error("Invalid area name");
+    }
+    if (gAreas.has(aName)) {
+      throw new Error("Area already registered");
+    }
+
+    let props = new Map();
+    for (let key in aProperties) {
+      //XXXgijs for special items, we need to make sure they have an appropriate ID
+      // so we aren't perpetually in a non-default state:
+      if (key == "defaultPlacements" && Array.isArray(aProperties[key])) {
+        props.set(key, aProperties[key].map(x => this.isSpecialWidget(x) ? this.ensureSpecialWidgetId(x) : x ));
+      } else {
+        props.set(key, aProperties[key]);
+      }
+    }
+    gAreas.set(aName, props);
+
+    if (props.get("legacy")) {
+      // Guarantee this area exists in gFuturePlacements, to avoid checking it in
+      // various places elsewhere.
+      gFuturePlacements.set(aName, new Set());
+    } else {
+      this.restoreStateForArea(aName);
+    }
+  },
+
+  unregisterArea: function(aName) {
+    if (typeof aName != "string" || !/^[a-z0-9-_]{1,}$/i.test(aName)) {
+      throw new Error("Invalid area name");
+    }
+    if (!gAreas.has(aName)) {
+      throw new Error("Area not registered");
+    }
+
+    // Move all the widgets out
+    this.beginBatchUpdate();
+    let placements = gPlacements.get(aName);
+    placements.forEach(this.removeWidgetFromArea, this);
+
+    // Delete all remaining traces.
+    gAreas.delete(aName);
+    gPlacements.delete(aName);
+    gFuturePlacements.delete(aName);
+    gBuildAreas.delete(aName);
+    this.endBatchUpdate(true);
+  },
+
+  registerToolbar: function(aToolbar, aIsOverlayed) {
+    let area = aToolbar.id;
+    if (gBuildAreas.has(area) && gBuildAreas.get(area).has(aToolbar)) {
+      return;
+    }
+    this.beginBatchUpdate();
+    let document = aToolbar.ownerDocument;
+    let areaProperties = gAreas.get(area);
+
+    if (!areaProperties) {
+      throw new Error("Unknown customization area: " + area);
+    }
+
+    let placements = gPlacements.get(area);
+    if (!placements && areaProperties.has("legacy")) {
+      let legacyState = aToolbar.getAttribute("currentset");
+      if (legacyState) {
+        legacyState = legacyState.split(",").filter(s => s);
+      }
+
+      // Manually restore the state here, so the legacy state can be converted. 
+      this.restoreStateForArea(area, legacyState);
+      placements = gPlacements.get(area);
+    }
+
+    // If the number of children of this toolbar exceeds the length of the
+    // placements, then an add-on probably overlayed the toolbar, so we mark
+    // it dirty.
+    if (aIsOverlayed) {
+      gDirtyAreaCache.add(area);
+    }
+
+    if (areaProperties.has("overflowable")) {
+      aToolbar.overflowable = new OverflowableToolbar(aToolbar);
+    }
+
+    this.registerBuildArea(area, aToolbar);
+
+    // We only build the toolbar if it's been marked as "dirty". Dirty means
+    // one of the following things:
+    // 1) Items have been added, moved or removed from this toolbar before.
+    // 2) The number of children of the toolbar does not match the length of
+    //    the placements array for that area.
+    //
+    // This notion of being "dirty" is stored in a cache which is persisted
+    // in the saved state.
+    if (gDirtyAreaCache.has(area)) {
+      this.buildArea(area, placements, aToolbar);
+    }
+    aToolbar.setAttribute("currentset", placements.join(","));
+    this.endBatchUpdate();
+  },
+
+  buildArea: function(aArea, aPlacements, aAreaNode) {
+    let document = aAreaNode.ownerDocument;
+    let window = document.defaultView;
+    let inPrivateWindow = PrivateBrowsingUtils.isWindowPrivate(window);
+    let container = aAreaNode.customizationTarget;
+
+    if (!container) {
+      throw new Error("Expected area " + aArea
+                      + " to have a customizationTarget attribute.");
+    }
+
+    this.beginBatchUpdate();
+
+    let currentNode = container.firstChild;
+    let placementsToRemove = new Set();
+    for (let id of aPlacements) {
+      while (currentNode && currentNode.getAttribute("skipintoolbarset") == "true") {
+        currentNode = currentNode.nextSibling;
+      }
+
+      if (currentNode && currentNode.id == id) {
+        currentNode = currentNode.nextSibling;
+        continue;
+      }
+
+      let [provider, node] = this.getWidgetNode(id, window);
+      if (!node) {
+        LOG("Unknown widget: " + id);
+        continue;
+      }
+
+      // If the placements have items in them which are (now) no longer removable,
+      // we shouldn't be moving them:
+      if (node.parentNode != container && !this.isWidgetRemovable(node)) {
+        placementsToRemove.add(id);
+        continue;
+      }
+
+      if (inPrivateWindow && provider == CustomizableUI.PROVIDER_API) {
+        let widget = gPalette.get(id);
+        if (!widget.showInPrivateBrowsing && inPrivateWindow) {
+          continue;
+        }
+      }
+
+      this.ensureButtonContextMenu(node, aArea == CustomizableUI.AREA_PANEL);
+      if (node.localName == "toolbarbutton" && aArea == CustomizableUI.AREA_PANEL) {
+        node.setAttribute("tabindex", "0");
+        if (!node.hasAttribute("type")) {
+          node.setAttribute("type", "wrap");
+        }
+      }
+
+      this.notifyListeners("onWidgetBeforeDOMChange", node, currentNode, container);
+      this.insertWidgetBefore(node, currentNode, container, aArea);
+      this._addParentFlex(node);
+      this.notifyListeners("onWidgetAfterDOMChange", node, currentNode, container);
+      if (gResetting) {
+        this.notifyListeners("onWidgetReset", id);
+      }
+    }
+
+    if (currentNode) {
+      let palette = aAreaNode.toolbox ? aAreaNode.toolbox.palette : null;
+      let limit = currentNode.previousSibling;
+      let node = container.lastChild;
+      while (node && node != limit) {
+        let previousSibling = node.previousSibling;
+        // Nodes opt-in to removability. If they're removable, and we haven't
+        // seen them in the placements array, then we toss them into the palette
+        // if one exists. If no palette exists, we just remove the node. If the
+        // node is not removable, we leave it where it is. However, we can only
+        // safely touch elements that have an ID - both because we depend on
+        // IDs, and because such elements are not intended to be widgets
+        // (eg, titlebar-placeholder elements).
+        if (node.id && node.getAttribute("skipintoolbarset") != "true") {
+          if (this.isWidgetRemovable(node)) {
+            if (palette) {
+              palette.appendChild(node);
+              this.removeLocationAttributes(node);
+            } else {
+              container.removeChild(node);
+            }
+          } else {
+            this.setLocationAttributes(currentNode, aArea);
+            node.setAttribute("removable", false);
+            LOG("Adding non-removable widget to placements of " + aArea + ": " +
+                node.id);
+            gPlacements.get(aArea).push(node.id);
+            gDirty = true;
+          }
+        }
+        node = previousSibling;
+      }
+    }
+
+    // If there are placements in here which aren't removable from their original area,
+    // we remove them from this area's placement array. They will (have) be(en) added
+    // to their original area's placements array in the block above this one.
+    if (placementsToRemove.size) {
+      let placementAry = gPlacements.get(aArea);
+      for (let id of placementsToRemove) {
+        let index = placementAry.indexOf(id);
+        placementAry.splice(index, 1);
+      }
+    }
+
+    this.endBatchUpdate();
+  },
+
+  addPanelCloseListeners: function(aPanel) {
+    gELS.addSystemEventListener(aPanel, "click", this, false);
+    gELS.addSystemEventListener(aPanel, "keypress", this, false);
+    let win = aPanel.ownerDocument.defaultView;
+    if (!gPanelsForWindow.has(win)) {
+      gPanelsForWindow.set(win, new Set());
+    }
+    gPanelsForWindow.get(win).add(this._getPanelForNode(aPanel));
+  },
+
+  removePanelCloseListeners: function(aPanel) {
+    gELS.removeSystemEventListener(aPanel, "click", this, false);
+    gELS.removeSystemEventListener(aPanel, "keypress", this, false);
+    let win = aPanel.ownerDocument.defaultView;
+    let panels = gPanelsForWindow.get(win);
+    if (panels) {
+      panels.delete(this._getPanelForNode(aPanel));
+    }
+  },
+
+  ensureButtonContextMenu: function(aNode, aShouldHaveCustomizationMenu) {
+    let currentContextMenu = aNode.getAttribute("context") ||
+                             aNode.getAttribute("contextmenu");
+    if (aShouldHaveCustomizationMenu) {
+      if (!currentContextMenu)
+        aNode.setAttribute("context", kCustomizationContextMenu);
+    } else {
+      if (currentContextMenu == kCustomizationContextMenu)
+        aNode.removeAttribute("context");
+    }
+  },
+
+  getWidgetProvider: function(aWidgetId) {
+    if (this.isSpecialWidget(aWidgetId)) {
+      return CustomizableUI.PROVIDER_SPECIAL;
+    }
+    if (gPalette.has(aWidgetId)) {
+      return CustomizableUI.PROVIDER_API;
+    }
+    // If this was an API widget that was destroyed, return null:
+    if (gSeenWidgets.has(aWidgetId)) {
+      return null;
+    }
+
+    // We fall back to the XUL provider, but we don't know for sure (at this
+    // point) whether it exists there either. So the API is technically lying.
+    // Ideally, it would be able to return an error value (or throw an
+    // exception) if it really didn't exist. Our code calling this function
+    // handles that fine, but this is a public API.
+    return CustomizableUI.PROVIDER_XUL;
+  },
+
+  getWidgetNode: function(aWidgetId, aWindow) {
+    let document = aWindow.document;
+
+    if (this.isSpecialWidget(aWidgetId)) {
+      let widgetNode = document.getElementById(aWidgetId) ||
+                       this.createSpecialWidget(aWidgetId, document);
+      return [ CustomizableUI.PROVIDER_SPECIAL, widgetNode];
+    }
+
+    let widget = gPalette.get(aWidgetId);
+    if (widget) {
+      // If we have an instance of this widget already, just use that.
+      if (widget.instances.has(document)) {
+        LOG("An instance of widget " + aWidgetId + " already exists in this "
+            + "document. Reusing.");
+        return [ CustomizableUI.PROVIDER_API,
+                 widget.instances.get(document) ];
+      }
+
+      return [ CustomizableUI.PROVIDER_API,
+               this.buildWidget(document, widget) ];
+    }
+
+    LOG("Searching for " + aWidgetId + " in toolbox.");
+    let node = this.findWidgetInWindow(aWidgetId, aWindow);
+    if (node) {
+      return [ CustomizableUI.PROVIDER_XUL, node ];
+    }
+
+    LOG("No node for " + aWidgetId + " found.");
+    return [];
+  },
+
+  registerMenuPanel: function(aPanel) {
+    if (gBuildAreas.has(CustomizableUI.AREA_PANEL) &&
+        gBuildAreas.get(CustomizableUI.AREA_PANEL).has(aPanel)) {
+      return;
+    }
+
+    let document = aPanel.ownerDocument;
+
+    for (let btn of aPanel.querySelectorAll("toolbarbutton")) {
+      btn.setAttribute("tabindex", "0");
+      this.ensureButtonContextMenu(btn, true);
+      if (!btn.hasAttribute("type")) {
+        btn.setAttribute("type", "wrap");
+      }
+    }
+
+    aPanel.toolbox = document.getElementById("navigator-toolbox");
+    aPanel.customizationTarget = aPanel;
+
+    this.addPanelCloseListeners(aPanel);
+
+    let placements = gPlacements.get(CustomizableUI.AREA_PANEL);
+    this.buildArea(CustomizableUI.AREA_PANEL, placements, aPanel);
+    this.registerBuildArea(CustomizableUI.AREA_PANEL, aPanel);
+  },
+
+  onWidgetAdded: function(aWidgetId, aArea, aPosition) {
+    let areaNodes = gBuildAreas.get(aArea);
+    if (!areaNodes) {
+      return;
+    }
+
+    let placements = gPlacements.get(aArea);
+    if (!placements) {
+      ERROR("Could not find any placements for " + aArea +
+            " when adding a widget.");
+      return;
+    }
+
+    let area = gAreas.get(aArea);
+    let showInPrivateBrowsing = gPalette.has(aWidgetId)
+                              ? gPalette.get(aWidgetId).showInPrivateBrowsing
+                              : true;
+    let nextNodeId = placements[aPosition + 1];
+
+    // Go through each of the nodes associated with this area and move the
+    // widget to the requested location.
+    for (let areaNode of areaNodes) {
+      let window = areaNode.ownerDocument.defaultView;
+      if (!showInPrivateBrowsing && PrivateBrowsingUtils.isWindowPrivate(window)) {
+        continue;
+      }
+
+      let container = areaNode.customizationTarget;
+      let [provider, widgetNode] = this.getWidgetNode(aWidgetId, window);
+
+
+      this.ensureButtonContextMenu(widgetNode, aArea == CustomizableUI.AREA_PANEL);
+      if (widgetNode.localName == "toolbarbutton" && aArea == CustomizableUI.AREA_PANEL) {
+        widgetNode.setAttribute("tabindex", "0");
+        if (!widgetNode.hasAttribute("type")) {
+          widgetNode.setAttribute("type", "wrap");
+        }
+      }
+
+      let nextNode = nextNodeId ? container.querySelector(idToSelector(nextNodeId))
+                                : null;
+
+      this.notifyListeners("onWidgetBeforeDOMChange", widgetNode, nextNode, container);
+      this.insertWidgetBefore(widgetNode, nextNode, container, aArea);
+      this._addParentFlex(widgetNode);
+      this.notifyListeners("onWidgetAfterDOMChange", widgetNode, nextNode, container);
+
+      if (area.get("type") == CustomizableUI.TYPE_TOOLBAR) {
+        areaNode.setAttribute("currentset", areaNode.currentSet);
+      }
+
+    }
+  },
+
+  onWidgetRemoved: function(aWidgetId, aArea) {
+    let areaNodes = gBuildAreas.get(aArea);
+    if (!areaNodes) {
+      return;
+    }
+
+    let area = gAreas.get(aArea);
+    let showInPrivateBrowsing = gPalette.has(aWidgetId)
+                              ? gPalette.get(aWidgetId).showInPrivateBrowsing
+                              : true;
+
+    for (let areaNode of areaNodes) {
+      let window = areaNode.ownerDocument.defaultView;
+      if (!showInPrivateBrowsing &&
+          PrivateBrowsingUtils.isWindowPrivate(window)) {
+        continue;
+      }
+
+      let container = areaNode.customizationTarget;
+      let widgetNode = container.ownerDocument.getElementById(aWidgetId);
+      if (!widgetNode) {
+        ERROR("Widget not found, unable to remove");
+        continue;
+      }
+
+      this.notifyListeners("onWidgetBeforeDOMChange", widgetNode, null, container);
+      this._removeParentFlex(widgetNode);
+
+      if (gPalette.has(aWidgetId) || this.isSpecialWidget(aWidgetId)) {
+        container.removeChild(widgetNode);
+      } else {
+        this.removeLocationAttributes(widgetNode);
+        widgetNode.removeAttribute("tabindex");
+        if (widgetNode.getAttribute("type") == "wrap") {
+          widgetNode.removeAttribute("type");
+        }
+        //XXXgijs: this won't work when removing widgets from the panel (fix in bug 902100)
+        areaNode.toolbox.palette.appendChild(widgetNode);
+      }
+      this.notifyListeners("onWidgetAfterDOMChange", widgetNode, null, container);
+
+      if (area.get("type") == CustomizableUI.TYPE_TOOLBAR) {
+        areaNode.setAttribute("currentset", areaNode.currentSet);
+      }
+
+      let windowCache = gSingleWrapperCache.get(window);
+      if (windowCache) {
+        windowCache.delete(aWidgetId);
+      }
+    }
+  },
+
+  onWidgetMoved: function(aWidgetId, aArea, aOldPosition, aNewPosition) {
+    let areaNodes = gBuildAreas.get(aArea);
+    if (!areaNodes) {
+      return;
+    }
+
+    let placements = gPlacements.get(aArea);
+    if (!placements) {
+      ERROR("Could not find any placements for " + aArea +
+            " when moving a widget.");
+      return;
+    }
+
+    let area = gAreas.get(aArea);
+    let showInPrivateBrowsing = gPalette.has(aWidgetId)
+                              ? gPalette.get(aWidgetId).showInPrivateBrowsing
+                              : true;
+
+    let nextNodeId = placements[aNewPosition + 1];
+
+    for (let areaNode of areaNodes) {
+      let window = areaNode.ownerDocument.defaultView;
+      if (!showInPrivateBrowsing &&
+          PrivateBrowsingUtils.isWindowPrivate(window)) {
+        continue;
+      }
+
+      let container = areaNode.customizationTarget;
+      let [provider, widgetNode] = this.getWidgetNode(aWidgetId, window);
+      if (!widgetNode) {
+        ERROR("Widget not found, unable to move");
+        continue;
+      }
+
+      let nextNode = nextNodeId ? container.querySelector(idToSelector(nextNodeId))
+                                : null;
+
+      this.notifyListeners("onWidgetBeforeDOMChange", widgetNode, nextNode, container);
+      this.insertWidgetBefore(widgetNode, nextNode, container, aArea);
+      this.notifyListeners("onWidgetAfterDOMChange", widgetNode, nextNode, container);
+
+      if (area.get("type") == CustomizableUI.TYPE_TOOLBAR) {
+        areaNode.setAttribute("currentset", areaNode.currentSet);
+      }
+
+    }
+  },
+
+  registerBuildArea: function(aArea, aNode) {
+    // We ensure that the window is registered to have its customization data
+    // cleaned up when unloading.
+    let window = aNode.ownerDocument.defaultView;
+    if (window.closed) {
+      return;
+    }
+    this.registerBuildWindow(window);
+
+    // Also register this build area's toolbox.
+    if (aNode.toolbox) {
+      gBuildWindows.get(window).add(aNode.toolbox);
+    }
+
+    if (!gBuildAreas.has(aArea)) {
+      gBuildAreas.set(aArea, new Set());
+    }
+
+    gBuildAreas.get(aArea).add(aNode);
+  },
+
+  registerBuildWindow: function(aWindow) {
+    if (!gBuildWindows.has(aWindow)) {
+      gBuildWindows.set(aWindow, new Set());
+
+      aWindow.addEventListener("unload", this);
+      aWindow.addEventListener("command", this, true);
+    }
+  },
+
+  unregisterBuildWindow: function(aWindow) {
+    aWindow.removeEventListener("unload", this);
+    aWindow.removeEventListener("command", this, true);
+    gPanelsForWindow.delete(aWindow);
+    gBuildWindows.delete(aWindow);
+    gSingleWrapperCache.delete(aWindow);
+    let document = aWindow.document;
+
+    for (let [areaId, areaNodes] of gBuildAreas) {
+      let areaProperties = gAreas.get(areaId);
+      for (let node of areaNodes) {
+        if (node.ownerDocument == document) {
+          if (areaProperties.has("overflowable")) {
+            node.overflowable.uninit();
+            node.overflowable = null;
+          }
+          areaNodes.delete(node);
+        }
+      }
+    }
+
+    for (let [,widget] of gPalette) {
+      widget.instances.delete(document);
+      this.notifyListeners("onWidgetInstanceRemoved", widget.id, document);
+    }
+  },
+
+  setLocationAttributes: function(aNode, aArea) {
+    let props = gAreas.get(aArea);
+    if (!props) {
+      throw new Error("Expected area " + aArea + " to have a properties Map " +
+                      "associated with it.");
+    }
+
+    aNode.setAttribute("customizableui-areatype", props.get("type") || "");
+    let anchor = props.get("anchor");
+    if (anchor) {
+      aNode.setAttribute("customizableui-anchorid", anchor);
+    }
+  },
+
+  removeLocationAttributes: function(aNode) {
+    aNode.removeAttribute("customizableui-areatype");
+    aNode.removeAttribute("customizableui-anchorid");
+  },
+
+  insertWidgetBefore: function(aNode, aNextNode, aContainer, aArea) {
+    this.setLocationAttributes(aNode, aArea);
+    aContainer.insertBefore(aNode, aNextNode);
+  },
+
+  handleEvent: function(aEvent) {
+    switch (aEvent.type) {
+      case "command":
+        if (!this._originalEventInPanel(aEvent)) {
+          break;
+        }
+        aEvent = aEvent.sourceEvent;
+        // Fall through
+      case "click":
+      case "keypress":
+        this.maybeAutoHidePanel(aEvent);
+        break;
+      case "unload":
+        this.unregisterBuildWindow(aEvent.currentTarget);
+        break;
+    }
+  },
+
+  _originalEventInPanel: function(aEvent) {
+    let e = aEvent.sourceEvent;
+    if (!e) {
+      return false;
+    }
+    let node = this._getPanelForNode(e.target);
+    if (!node) {
+      return false;
+    }
+    let win = e.view;
+    let panels = gPanelsForWindow.get(win);
+    return !!panels && panels.has(node);
+  },
+
+  isSpecialWidget: function(aId) {
+    return (aId.startsWith(kSpecialWidgetPfx) ||
+            aId.startsWith("separator") ||
+            aId.startsWith("spring") ||
+            aId.startsWith("spacer"));
+  },
+
+  ensureSpecialWidgetId: function(aId) {
+    let nodeType = aId.match(/spring|spacer|separator/)[0];
+    // If the ID we were passed isn't a generated one, generate one now:
+    if (nodeType == aId) {
+      // Due to timers resolution Date.now() can be the same for
+      // elements created in small timeframes.  So ids are
+      // differentiated through a unique count suffix.
+      return kSpecialWidgetPfx + aId + Date.now() + (++gNewElementCount);
+    }
+    return aId;
+  },
+
+  createSpecialWidget: function(aId, aDocument) {
+    let nodeName = "toolbar" + aId.match(/spring|spacer|separator/)[0];
+    let node = aDocument.createElementNS(kNSXUL, nodeName);
+    node.id = this.ensureSpecialWidgetId(aId);
+    if (nodeName == "toolbarspring") {
+      node.flex = 1;
+    }
+    return node;
+  },
+
+  /* Find a XUL-provided widget in a window. Don't try to use this
+   * for an API-provided widget or a special widget.
+   */
+  findWidgetInWindow: function(aId, aWindow) {
+    if (!gBuildWindows.has(aWindow)) {
+      throw new Error("Build window not registered");
+    }
+
+    if (!aId) {
+      ERROR("findWidgetInWindow was passed an empty string.");
+      return null;
+    }
+
+    let document = aWindow.document;
+
+    // look for a node with the same id, as the node may be
+    // in a different toolbar.
+    let node = document.getElementById(aId);
+    if (node) {
+      let parent = node.parentNode;
+      while (parent && !(parent.customizationTarget ||
+                         parent.localName == "toolbarpaletteitem")) {
+        parent = parent.parentNode;
+      }
+
+      if ((parent && parent.customizationTarget == node.parentNode &&
+           gBuildWindows.get(aWindow).has(parent.toolbox)) ||
+          (parent && parent.localName == "toolbarpaletteitem")) {
+        // Normalize the removable attribute. For backwards compat, if
+        // the widget is not defined in a toolbox palette then absence
+        // of the "removable" attribute means it is not removable.
+        if (!node.hasAttribute("removable")) {
+          // If we first see this in customization mode, it may be in the
+          // customization palette instead of the toolbox palette.
+          node.setAttribute("removable", !parent.customizationTarget);
+        }
+
+        return node;
+      }
+    }
+
+    let toolboxes = gBuildWindows.get(aWindow);
+    for (let toolbox of toolboxes) {
+      if (toolbox.palette) {
+        // Attempt to locate a node with a matching ID within
+        // the palette.
+        let node = toolbox.palette.querySelector(idToSelector(aId));
+        if (node) {
+          // Normalize the removable attribute. For backwards compat, this
+          // is optional if the widget is defined in the toolbox palette,
+          // and defaults to *true*, unlike if it was defined elsewhere.
+          if (!node.hasAttribute("removable")) {
+            node.setAttribute("removable", true);
+          }
+          return node;
+        }
+      }
+    }
+    return null;
+  },
+
+  buildWidget: function(aDocument, aWidget) {
+    if (typeof aWidget == "string") {
+      aWidget = gPalette.get(aWidget);
+    }
+    if (!aWidget) {
+      throw new Error("buildWidget was passed a non-widget to build.");
+    }
+
+    LOG("Building " + aWidget.id + " of type " + aWidget.type);
+
+    let node;
+    if (aWidget.type == "custom") {
+      if (aWidget.onBuild) {
+        try {
+          node = aWidget.onBuild(aDocument);
+        } catch (ex) {
+          ERROR("Custom widget with id " + aWidget.id + " threw an error: " + ex.message);
+        }
+      }
+      if (!node || !(node instanceof aDocument.defaultView.XULElement))
+        ERROR("Custom widget with id " + aWidget.id + " does not return a valid node");
+    }
+    else {
+      node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
+
+      node.setAttribute("id", aWidget.id);
+      node.setAttribute("widget-id", aWidget.id);
+      node.setAttribute("widget-type", aWidget.type);
+      if (aWidget.disabled) {
+        node.setAttribute("disabled", true);
+      }
+      node.setAttribute("removable", aWidget.removable);
+      node.setAttribute("overflows", aWidget.overflows);
+      node.setAttribute("label", this.getLocalizedProperty(aWidget, "label"));
+      node.setAttribute("tooltiptext", this.getLocalizedProperty(aWidget, "tooltiptext"));
+      //XXXunf Need to hook this up to a <key> element or something.
+      let shortcut = this.getLocalizedProperty(aWidget, "shortcut", null, "none");
+      if (shortcut != "none") {
+        node.setAttribute("acceltext", shortcut);
+      }
+      node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional");
+
+      let commandHandler = this.handleWidgetCommand.bind(this, aWidget, node);
+      node.addEventListener("command", commandHandler, false);
+      let clickHandler = this.handleWidgetClick.bind(this, aWidget, node);
+      node.addEventListener("click", clickHandler, false);
+
+      // If the widget has a view, and has view showing / hiding listeners,
+      // hook those up to this widget.
+      if (aWidget.type == "view" &&
+          (aWidget.onViewShowing || aWidget.onViewHiding)) {
+        LOG("Widget " + aWidget.id + " has a view with showing and hiding events. Auto-registering event handlers.");
+        let viewNode = aDocument.getElementById(aWidget.viewId);
+
+        if (viewNode) {
+          // PanelUI relies on the .PanelUI-subView class to be able to show only
+          // one sub-view at a time.
+          viewNode.classList.add("PanelUI-subView");
+
+          for (let eventName of kSubviewEvents) {
+            let handler = "on" + eventName;
+            if (typeof aWidget[handler] == "function") {
+              viewNode.addEventListener(eventName, aWidget[handler], false);
+            }
+          }
+
+          LOG("Widget " + aWidget.id + " showing and hiding event handlers set.");
+        } else {
+          ERROR("Could not find the view node with id: " + aWidget.viewId +
+                ", for widget: " + aWidget.id + ".");
+        }
+      }
+
+      if (aWidget.onCreated) {
+        aWidget.onCreated(node);
+      }
+    }
+
+    aWidget.instances.set(aDocument, node);
+    return node;
+  },
+
+  getLocalizedProperty: function(aWidget, aProp, aFormatArgs, aDef) {
+    if (typeof aWidget == "string") {
+      aWidget = gPalette.get(aWidget);
+    }
+    if (!aWidget) {
+      throw new Error("getLocalizedProperty was passed a non-widget to work with.");
+    }
+    let def, name;
+    // Let widgets pass their own string identifiers or strings, so that
+    // we can use strings which aren't the default (in case string ids change)
+    // and so that non-builtin-widgets can also provide labels, tooltips, etc.
+    if (aWidget[aProp]) {
+      name = aWidget[aProp];
+      // By using this as the default, if a widget provides a full string rather
+      // than a string ID for localization, we will fall back to that string
+      // and return that.
+      def = aDef || name;
+    } else {
+      name = aWidget.id + "." + aProp;
+      def = aDef || "";
+    }
+    try {
+      if (Array.isArray(aFormatArgs) && aFormatArgs.length) {
+        return gWidgetsBundle.formatStringFromName(name, aFormatArgs,
+          aFormatArgs.length) || def;
+      }
+      return gWidgetsBundle.GetStringFromName(name) || def;
+    } catch(ex) {
+      if (!def) {
+        ERROR("Could not localize property '" + name + "'.");
+      }
+    }
+    return def;
+  },
+
+  handleWidgetCommand: function(aWidget, aNode, aEvent) {
+    LOG("handleWidgetCommand");
+
+    if (aWidget.type == "button") {
+      this.maybeAutoHidePanel(aEvent);
+
+      if (aWidget.onCommand) {
+        try {
+          aWidget.onCommand.call(null, aEvent);
+        } catch (e) {
+          ERROR(e);
+        }
+      } else {
+        //XXXunf Need to think this through more, and formalize.
+        Services.obs.notifyObservers(aNode,
+                                     "customizedui-widget-command",
+                                     aWidget.id);
+      }
+    } else if (aWidget.type == "view") {
+      let ownerWindow = aNode.ownerDocument.defaultView;
+      ownerWindow.PanelUI.showSubView(aWidget.viewId, aNode,
+                                      this.getPlacementOfWidget(aNode.id).area);
+    }
+  },
+
+  handleWidgetClick: function(aWidget, aNode, aEvent) {
+    LOG("handleWidgetClick");
+    if (aWidget.type == "button") {
+      this.maybeAutoHidePanel(aEvent);
+    }
+
+    if (aWidget.onClick) {
+      try {
+        aWidget.onClick.call(null, aEvent);
+      } catch(e) {
+        Cu.reportError(e);
+      }
+    } else {
+      //XXXunf Need to think this through more, and formalize.
+      Services.obs.notifyObservers(aNode, "customizedui-widget-click", aWidget.id);
+    }
+  },
+
+  _getPanelForNode: function(aNode) {
+    let panel = aNode;
+    while (panel && panel.localName != "panel")
+      panel = panel.parentNode;
+    return panel;
+  },
+
+  /*
+   * If people put things in the panel which need more than single-click interaction,
+   * we don't want to close it. Right now we check for text inputs and menu buttons.
+   * Anything else we should take care of?
+   */
+  _isOnInteractiveElement: function(aEvent) {
+    let target = aEvent.originalTarget;
+    let panel = aEvent.currentTarget;
+    let inInput = false;
+    let inMenu = false;
+    while (!inInput && !inMenu && target != aEvent.currentTarget) {
+      inInput = target.localName == "input";
+      inMenu = target.type == "menu";
+      target = target.parentNode;
+    }
+    return inMenu || inInput;
+  },
+
+  hidePanelForNode: function(aNode) {
+    let panel = this._getPanelForNode(aNode);
+    if (panel) {
+      panel.hidePopup();
+    }
+  },
+
+  maybeAutoHidePanel: function(aEvent) {
+    if (aEvent.type == "keypress") {
+      if (aEvent.keyCode != aEvent.DOM_VK_ENTER &&
+          aEvent.keyCode != aEvent.DOM_VK_RETURN) {
+        return;
+      }
+      // If the user hit enter/return, we don't check preventDefault - it makes sense
+      // that this was prevented, but we probably still want to close the panel.
+      // If consumers don't want this to happen, they should specify noautoclose.
+
+    } else if (aEvent.type != "command") { // mouse events:
+      if (aEvent.defaultPrevented || aEvent.button != 0) {
+        return;
+      }
+      let isInteractive = this._isOnInteractiveElement(aEvent);
+      LOG("maybeAutoHidePanel: interactive ? " + isInteractive);
+      if (isInteractive) {
+        return;
+      }
+    }
+
+    if (aEvent.target.getAttribute("noautoclose") == "true" ||
+        aEvent.target.getAttribute("widget-type") == "view") {
+      return;
+    }
+
+    // If we get here, we can actually hide the popup:
+    this.hidePanelForNode(aEvent.target);
+  },
+
+  getUnusedWidgets: function(aWindowPalette) {
+    // We use a Set because there can be overlap between the widgets in
+    // gPalette and the items in the palette, especially after the first
+    // customization, since programmatically generated widgets will remain
+    // in the toolbox palette.
+    let widgets = new Set();
+
+    // It's possible that some widgets have been defined programmatically and
+    // have not been overlayed into the palette. We can find those inside
+    // gPalette.
+    for (let [id, widget] of gPalette) {
+      if (!widget.currentArea) {
+        widgets.add(id);
+      }
+    }
+
+    LOG("Iterating the actual nodes of the window palette");
+    for (let node of aWindowPalette.children) {
+      LOG("In palette children: " + node.id);
+      if (node.id && !this.getPlacementOfWidget(node.id)) {
+        widgets.add(node.id);
+      }
+    }
+
+    return [...widgets];
+  },
+
+  getPlacementOfWidget: function(aWidgetId, aOnlyRegistered) {
+    if (aOnlyRegistered && !this.widgetExists(aWidgetId)) {
+      return null;
+    }
+
+    for (let [area, placements] of gPlacements) {
+      let index = placements.indexOf(aWidgetId);
+      if (index != -1) {
+        return { area: area, position: index };
+      }
+    }
+
+    return null;
+  },
+
+  widgetExists: function(aWidgetId) {
+    if (gPalette.has(aWidgetId) || this.isSpecialWidget(aWidgetId)) {
+      return true;
+    }
+