Mostly automated merge with https://hg.mozilla.org/mozilla-central
authorMike Conley <mconley@mozilla.com>
Mon, 13 May 2013 13:04:32 -0400
changeset 164314 fd52a4cb0d8454b1bb83979681bf1a596b796846
parent 138440 2e6cfac714f666381620f767bbe42f2595769f95 (current diff)
parent 164313 7c407cb365a0cf1eb569d6be752dcb72f49df290 (diff)
child 164315 56db3a7a5f94d0bcda5284d0ebcd842ed64e79ab
push idunknown
push userunknown
push dateunknown
milestone23.0a1
Mostly automated merge with https://hg.mozilla.org/mozilla-central
browser/app/profile/firefox.js
browser/base/content/browser-appmenu.inc
browser/base/content/browser-customization.js
browser/base/content/browser.css
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/test/Makefile.in
browser/base/content/test/browser_bug616836.js
browser/components/nsBrowserGlue.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/linux/browser.css
browser/themes/linux/jar.mn
browser/themes/osx/browser.css
browser/themes/osx/jar.mn
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/browser.css
browser/themes/windows/jar.mn
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -407,20 +407,20 @@ 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);
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -410,8 +410,63 @@ 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);
+    this.updateStyleSheet("url(" + themeData.headerURL + ")");
+  },
+};
deleted file mode 100644
--- a/browser/base/content/browser-appmenu.inc
+++ /dev/null
@@ -1,400 +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_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="BookmarksMenuButton.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('http://www.mozilla.com/firefox/central/', {inBackground: false});"
-                      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,102 @@
+# -*- 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 CustomizationStart and CustomizationEnd
+ * events.
+ */
+let CustomizationHandler = {
+  handleEvent: function(aEvent) {
+    switch(aEvent.type) {
+      case "CustomizationStart":
+        this._customizationStart();
+        break;
+      case "CustomizationEnd":
+        this._customizationEnd(aEvent.detail);
+        break;
+    }
+  },
+
+  _customizationStart: 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();
+    TabsInTitlebar.allowedBy("customizing-toolbars", false);
+  },
+
+  _customizationEnd: 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();
+    setUrlAndSearchBarWidthForConditionalForwardButton();
+
+    // Update the urlbar
+    if (gURLBar) {
+      URLBarSetURI();
+      XULBrowserWindow.asyncUpdateUI();
+      BookmarkingUI.updateStarState();
+      SocialMark.updateMarkState();
+    }
+
+    TabsInTitlebar.allowedBy("customizing-toolbars", true);
+
+    // 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");
+
+    // make sure to re-enable click-and-hold
+    if (!getBoolPref("ui.click_hold_context_menus", false)) {
+      SetClickAndHoldHandlers();
+    }
+
+    gBrowser.selectedBrowser.focus();
+  }
+}
--- 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.
     document.getElementById("View:FullScreen").setAttribute("checked", enterFS);
 
 #ifdef XP_MACOSX
     // Make sure the menu items are adjusted.
     document.getElementById("enterFullScreenItem").hidden = enterFS;
     document.getElementById("exitFullScreenItem").hidden = !enterFS;
 #endif
 
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -8,16 +8,30 @@
 searchbar {
   -moz-binding: url("chrome://browser/content/search/search.xml#searchbar");
 }
 
 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[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");
+}
+
 tabbrowser {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
 }
 
 .tabbrowser-tabs {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs");
 }
 
@@ -34,31 +48,31 @@ 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,
+              max-width 230ms ease-out,
               opacity 50ms ease-out 20ms /* hide the tab for the first 20ms of the max-width transition */;
 }
 
 .tabbrowser-tab:not([pinned]):not([fadein]) {
   max-width: 0.1px;
   min-width: 0.1px;
   opacity: 0 !important;
   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,
+              opacity 50ms ease-out 160ms /* hide the tab for the last 20ms of the max-width transition */;
 }
 
 .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;
 }
@@ -112,20 +126,36 @@ 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
+
+%ifdef XP_WIN
+#main-window[sizemode="maximized"] #titlebar-buttonbox {
+  -moz-appearance: -moz-window-button-box-maximized;
+}
+%endif
+
 %endif
 
 .bookmarks-toolbar-customize,
 #wrapper-personal-bookmarks > #personal-bookmarks > #PlacesToolbar > hbox > #PlacesToolbarItems {
   display: none;
 }
 
 #wrapper-personal-bookmarks[place="toolbar"] > #personal-bookmarks > #PlacesToolbar > .bookmarks-toolbar-customize {
@@ -135,91 +165,65 @@ toolbar[printpreview="true"] {
 #main-window[disablechrome] #navigator-toolbox[tabsontop="true"] > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
   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] {
+#urlbar-reload-button:not([displaystop]) + #urlbar-stop-button,
+#urlbar-reload-button[displaystop],
+#reload-button:not([displaystop]) + #stop-button,
+#reload-button[displaystop] {
   visibility: collapse;
 }
 
 #feed-button > .toolbarbutton-menu-dropmarker {
   display: 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
 #main-window[inFullscreen="true"] {
   padding-top: 0; /* override drawintitlebar="true" */
 }
 %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);
@@ -432,24 +436,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;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -87,16 +87,22 @@ this.__defineSetter__("PluralForm", func
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
   "resource://gre/modules/TelemetryStopwatch.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",
   "resource:///modules/AboutHomeUtils.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);
@@ -143,16 +149,17 @@ let gInitialPages = [
   "about:blank",
   "about:newtab",
   "about:home",
   "about:privatebrowsing",
   "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
@@ -932,18 +939,18 @@ var gBrowserInit = {
       // adjust browser UI for popups
       if (gURLBar) {
         gURLBar.setAttribute("readonly", "true");
         gURLBar.setAttribute("enablehistory", "false");
       }
       goSetCommandEnabled("cmd_newNavigatorTab", false);
     }
 
-#ifdef MENUBAR_CAN_AUTOHIDE
-    updateAppButtonDisplay();
+#ifdef CAN_DRAW_IN_TITLEBAR
+    updateTitlebarDisplay();
 #endif
 
     // Misc. inits.
     CombinedStopReload.init();
     TabsOnTop.init();
     gPrivateBrowsingUI.init();
     TabsInTitlebar.init();
     retrieveToolbarIconsizesFromTheme();
@@ -1027,17 +1034,19 @@ var gBrowserInit = {
     Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
     Services.obs.addObserver(gFormSubmitObserver, "invalidformsubmit", false);
 
     BrowserOffline.init();
     OfflineApps.init();
     IndexedDBPromptHelper.init();
     gFormSubmitObserver.init();
+    PanelUI.init();
     SocialUI.init();
+    LightweightThemeListener.init();
     AddonManager.addAddonListener(AddonsMgrListener);
     WebrtcIndicator.init();
 
     // Ensure login manager is up and running.
     Services.logins;
 
     if (mustLoadSidebar) {
       let sidebar = document.getElementById("sidebar");
@@ -1222,56 +1231,35 @@ var gBrowserInit = {
     // Enable DevTools connection screen, if the preference allows this.
     let devtoolsRemoteEnabled = gPrefService.getBoolPref("devtools.debugger.remote-enabled");
     if (devtoolsRemoteEnabled) {
       let cmd = document.getElementById("Tools:DevToolsConnect");
       cmd.removeAttribute("disabled");
       cmd.removeAttribute("hidden");
     }
 
-#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
-
     // Enable Responsive UI?
     let responsiveUIEnabled = gPrefService.getBoolPref("devtools.responsiveUI.enabled");
     if (responsiveUIEnabled) {
       let cmd = document.getElementById("Tools:ResponsiveUI");
       cmd.removeAttribute("disabled");
       cmd.removeAttribute("hidden");
     }
 
     // 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);
 
+    window.addEventListener("CustomizationStart", CustomizationHandler, false);
+    window.addEventListener("CustomizationEnd", CustomizationHandler, false);
+
+    gCustomizeMode.init();
+
     // 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);
     }
@@ -1357,16 +1345,19 @@ var gBrowserInit = {
         Cu.reportError(ex);
       }
 
       BrowserOffline.uninit();
       OfflineApps.uninit();
       IndexedDBPromptHelper.uninit();
       AddonManager.removeAddonListener(AddonsMgrListener);
       SocialUI.uninit();
+      LightweightThemeListener.uninit();
+      gCustomizeMode.uninit();
+      PanelUI.uninit();
     }
 
     // Final window teardown, do this last.
     window.XULBrowserWindow.destroy();
     window.XULBrowserWindow = null;
     window.QueryInterface(Ci.nsIInterfaceRequestor)
           .getInterface(Ci.nsIWebNavigation)
           .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
@@ -2640,18 +2631,18 @@ var PrintPreviewListener = {
     if (gInPrintPreviewMode)
       this._hideChrome();
     else
       this._showChrome();
 
     if (this._chromeState.sidebarOpen)
       toggleSidebar(this._sidebarCommand);
 
-#ifdef MENUBAR_CAN_AUTOHIDE
-    updateAppButtonDisplay();
+#ifdef CAN_DRAW_IN_TITLEBAR
+    updateTitlebarDisplay();
 #endif
   },
   _hideChrome: function () {
     this._chromeState = {};
 
     var sidebar = document.getElementById("sidebar-box");
     this._chromeState.sidebarOpen = !sidebar.hidden;
     this._sidebarCommand = sidebar.getAttribute("sidebarcommand");
@@ -3306,129 +3297,23 @@ 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();
-    SocialMark.updateMarkState();
-    SocialShare.update();
-  }
-
-  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;
@@ -3482,33 +3367,26 @@ 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;
 
   // 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();
@@ -3531,44 +3409,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,16 +3452,19 @@ function mimeTypeIsTextBased(aMimeType)
 var XULBrowserWindow = {
   // Stored Status, Link and Loading values
   status: "",
   defaultStatus: "",
   overLink: "",
   startTime: 0,
   statusText: "",
   isBusy: false,
+  // The pages in this array should be kept in sync with what pages that
+  // panelUIOverlay.xul is set to overlay in
+  // browser/components/customizableui/content/jar.mn
   inContentWhitelist: ["about:addons", "about:downloads", "about:permissions",
                        "about:sync-progress", "about:preferences"],
 
   QueryInterface: function (aIID) {
     if (aIID.equals(Ci.nsIWebProgressListener) ||
         aIID.equals(Ci.nsIWebProgressListener2) ||
         aIID.equals(Ci.nsISupportsWeakReference) ||
         aIID.equals(Ci.nsIXULBrowserWindow) ||
@@ -4150,18 +4016,17 @@ var CombinedStopReload = {
     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 ||
+      if (!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");
       }
     }
@@ -4476,18 +4341,16 @@ function onViewToolbarsPopupShowing(aEve
       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"));
       if (popup.id != "toolbar-context-menu")
         menuItem.setAttribute("key", toolbar.getAttribute("key"));
 
       popup.insertBefore(menuItem, firstMenuItem);
 
       menuItem.addEventListener("command", onViewToolbarCommand, false);
     }
   }
@@ -4506,18 +4369,18 @@ function setToolbarVisibility(toolbar, i
 
   toolbar.setAttribute(hidingAttribute, !isVisible);
   document.persist(toolbar.id, hidingAttribute);
 
   PlacesToolbarHelper.init();
   BookmarkingUI.onToolbarVisibilityChange();
   gBrowser.updateWindowResizers();
 
-#ifdef MENUBAR_CAN_AUTOHIDE
-  updateAppButtonDisplay();
+#ifdef CAN_DRAW_IN_TITLEBAR
+  updateTitlebarDisplay();
 #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.
@@ -4568,143 +4431,236 @@ var TabsOnTop = {
 }
 
 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});
     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();
   },
 
+  _onMenuMutate: function (aMutations) {
+    // We don't care about restored windows, since the menu shouldn't be
+    // pushing the tab-strip down.
+    if (document.documentElement.getAttribute("sizemode") == "normal") {
+      return;
+    }
+
+    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) {
     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;
-
     function $(id) document.getElementById(id);
+
     let titlebar = $("titlebar");
+    let titlebarContent = $("titlebar-content");
+    let menubar = $("toolbar-menubar");
+
+    // Reset the margins and padding that _update modifies so that we can take
+    // accurate measurements.
+    titlebarContent.style.marginBottom = "";
+    titlebar.style.marginBottom = "";
+    menubar.style.paddingBottom = "";
 
     if (allowed) {
+      // We set the tabsintitlebar attribute first so that our CSS for
+      // tabsintitlebar manifests before we do our measurements.
+      document.documentElement.setAttribute("tabsintitlebar", "true");
+
       function rect(ele)   ele.getBoundingClientRect();
 
-      let tabsToolbar       = $("TabsToolbar");
-
-#ifdef MENUBAR_CAN_AUTOHIDE
-      let appmenuButtonBox  = $("appmenu-button-container");
-      this._sizePlaceholder("appmenu-button", rect(appmenuButtonBox).width);
-#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) {
+#ifdef XP_MACOSX
+      let fullscreenButton  = $("titlebar-fullscreen-button");
+      this._sizePlaceholder("fullscreen-button", rect(fullscreenButton).width);
+#endif
+      let titlebarContentHeight = rect(titlebarContent).height;
+      let menuHeight = this._outerHeight(menubar);
+
+      // If the titlebar is taller than the menubar, add more padding to the
+      // bottom of the menubar so that it matches.
+      if (menuHeight && titlebarContentHeight > menuHeight) {
+        let menuTitlebarDelta = titlebarContentHeight - menuHeight;
+        menubar.style.paddingBottom = menuTitlebarDelta + "px";
+        menuHeight += menuTitlebarDelta;
+      }
+
+      // Next, we calculate how much we need to stretch the titlebar down to
+      // go all the way to the bottom of the tab strip.
+      let tabsToolbar = $("TabsToolbar");
+      let tabAndMenuHeight = this._outerHeight(tabsToolbar) + menuHeight;
+      titlebarContent.style.marginBottom = tabAndMenuHeight + "px";
+
+      // Finally, we have to determine how much to bring up the elements below
+      // the titlebar. We start with a baseHeight of tabAndMenuHeight, to offset
+      // the amount we added to the titlebar content. Then, we have two cases:
+      //
+      // 1) The titlebar is larger than the tabAndMenuHeight. This can happen in
+      //    large font mode with the menu autohidden. In this case, we want to
+      //    add tabAndMenuHeight, since this should line up the bottom of the
+      //    tabstrip with the bottom of the titlebar.
+      //
+      // 2) The titlebar is equal to or smaller than the tabAndMenuHeight. This
+      //    is the more common case, and occurs with normal font sizes. In this
+      //    case, we want to bring the menu and tabstrip right up to the top of
+      //    the titlebar, so we add the titlebarContentHeight to the baseHeight.
+      let baseHeight = tabAndMenuHeight;
+      baseHeight += (titlebarContentHeight > tabAndMenuHeight) ? tabAndMenuHeight
+                                                               : titlebarContentHeight;
+      titlebar.style.marginBottom = "-" + baseHeight + "px";
+
+      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");
-
-      titlebar.style.marginBottom = "";
     }
   },
 
   _sizePlaceholder: function (type, width) {
     Array.forEach(document.querySelectorAll(".titlebar-placeholder[type='"+ type +"']"),
                   function (node) { node.width = width; });
   },
+
+  /**
+   * Retrieve the height of an element, including its top and bottom
+   * margins.
+   *
+   * @param ele
+   *        The element to measure.
+   * @return
+   *        The height and margins as an integer. If the height of the element
+   *        is 0, then this returns 0, regardless of what the margins are.
+   */
+  _outerHeight: function (ele) {
+    let cstyle = document.defaultView.getComputedStyle(ele);
+    let margins = parseInt(cstyle.marginTop) + parseInt(cstyle.marginBottom);
+    let height = ele.getBoundingClientRect().height;
+    return height > 0 ? Math.abs(height + margins) : 0;
+  },
 #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 = gInPrintPreviewMode;
+
+  if (!gInPrintPreviewMode)
     document.documentElement.setAttribute("chromemargin", "0,2,2,2");
   else
     document.documentElement.removeAttribute("chromemargin");
 
-  TabsInTitlebar.allowedBy("drawing-in-titlebar", displayAppButton);
-#else
-  document.getElementById("appmenu-toolbar-button").hidden =
-    !displayAppButton;
-#endif
+  TabsInTitlebar.allowedBy("drawing-in-titlebar", !gInPrintPreviewMode);
 }
 #endif
 
 #ifdef CAN_DRAW_IN_TITLEBAR
 function onTitlebarMaxClick() {
   if (window.windowState == window.STATE_MAXIMIZED)
     window.restore();
   else
@@ -6731,39 +6687,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;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -4,39 +4,43 @@
 #
 # 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;"
+        chromemargin="0,-1,-1,-1"
 #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
         titlemenuseparator="&mainWindow.titlemodifiermenuseparator;"
         lightweightthemes="true"
@@ -426,39 +430,37 @@
         <separator/>
         <description id="mixed-content-blocked-moreinfo">&mixedContentBlocked.moreinfo;</description>
         <separator/>
         <label id="mixed-content-blocked-helplink" class="text-link"
                value="&mixedContentBlocked.helplink;"/>
       </popupnotificationcontent>
     </popupnotification>
 
+#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"
@@ -476,169 +478,395 @@
              context="toolbar-context-menu">
       <toolbaritem id="menubar-items" align="center">
 # 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"/>
+      <hbox class="titlebar-placeholder" type="caption-buttons"
+#ifdef XP_MACOSX
+            ordinal="0"
+#else
+            ordinal="1000"
+#endif
+      />
+
+#ifdef XP_MACOSX
+      <hbox class="titlebar-placeholder" type="fullscreen-button" ordinal="1000"/>
+#endif
 #endif
     </toolbar>
 
     <toolbar id="nav-bar" class="toolbar-primary chromeclass-toolbar"
              toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;"
              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"
+             customizationtarget="nav-bar-customizationtarget"
              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"
+      <hbox id="nav-bar-customizationtarget" class="customization-target" flex="0">
+        <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>
+
+        <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="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>
+
+        <toolbarbutton id="reload-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       label="&reloadCmd.label;" removable="true"
+                       command="Browser:ReloadOrDuplicate"
                        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>
+                       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;">
+          <menupopup onpopupshowing="WebrtcIndicator.fillPopup(this);"
+                     onpopuphiding="WebrtcIndicator.clearPopup(this);"
+                     oncommand="WebrtcIndicator.menuCommand(event.target);"/>
+        </toolbarbutton>
+
+        <toolbarbutton id="social-share-button"
+                       class="toolbarbutton-1 chromeclass-toolbar-additional"
+                       hidden="true"
+                       label="&sharePageCmd.label;"
+                       tooltiptext="&sharePageCmd.label;"
+                       command="Social:SharePage"/>
+
+        <toolbaritem id="social-toolbar-item"
+                     class="chromeclass-toolbar-additional"
+                     removable="false"
+                     title="&socialToolbar.title;"
+                     hidden="true"
+                     skipintoolbarset="true"
+                     observes="socialActiveBroadcaster">
+          <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"
+                         observes="socialBroadcaster_userDetails"/>
+                </vbox>
+              </menuitem>
+#ifndef XP_WIN
+              <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>
+          <toolbarbutton id="social-mark-button"
+                         class="toolbarbutton-1"
+                         hidden="true"
+                         disabled="true"
+                         command="Social:TogglePageMark"/>
+        </toolbaritem>
+      </hbox>
+
+      <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;"
+                       oncommand="PanelUI.toggle(event);"/>
       </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="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 id="window-controls" hidden="true" pack="end">
+        <toolbarbutton id="minimize-button"
+                       tooltiptext="&fullScreenMinimize.tooltip;"
+                       oncommand="window.minimize();"/>
+
+        <toolbarbutton id="restore-button"
+                       tooltiptext="&fullScreenRestore.tooltip;"
+                       oncommand="BrowserFullScreen();"/>
+
+        <toolbarbutton id="close-button"
+                       tooltiptext="&fullScreenClose.tooltip;"
+                       oncommand="BrowserTryToCloseWindow();"/>
+      </hbox>
+    </toolbar>
+
+    <toolbarset id="customToolbars" context="toolbar-context-menu"/>
+
+    <toolbar id="PersonalToolbar"
+             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;"
+                   removable="true">
+        <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>
-          </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);"/>
+            <scrollbox orient="horizontal"
+                       id="PlacesToolbarItems"
+                       flex="1"/>
+            <toolbarbutton type="menu"
+                           id="PlacesChevron"
+                           class="chevron"
+                           mousethrough="never"
+                           collapsed="true"
+                           tooltiptext="&bookmarksToolbarChevron.tooltip;"
+                           onpopupshowing="document.getElementById('PlacesToolbar')
+                                                   ._placesView._onChevronPopupShowing(event);">
+              <menupopup id="PlacesChevronPopup"
+                         placespopup="true"
+                         tooltip="bhTooltip" popupsinherittooltip="true"
+                         context="placesContext"/>
+            </toolbarbutton>
           </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>
+    </toolbar>
 
-      <toolbarbutton id="reload-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&reloadCmd.label;" removable="true"
-                     command="Browser:ReloadOrDuplicate"
+    <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"
+            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="&reloadButton.tooltip;"/>
+                     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="stop-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     label="&stopCmd.label;" removable="true"
-                     command="Browser:Stop"
-                     tooltiptext="&stopButton.tooltip;"/>
+      <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="caption-buttons"
+#ifdef XP_MACOSX
+            ordinal="0"
+#else
+            ordinal="1000"
+#endif
+      />
+
+#ifdef XP_MACOSX
+      <hbox class="titlebar-placeholder" type="fullscreen-button"
+            ordinal="1000"/>
+#endif
+#endif
+    </toolbar>
+
+    <toolbarpalette id="BrowserToolbarPalette">
+
+# Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding
+# or removing default items with the toolbarbutton-1 class.
 
       <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);"
@@ -721,230 +949,16 @@
                      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;"/>
 
-      <toolbarbutton id="social-share-button"
-                     class="toolbarbutton-1 chromeclass-toolbar-additional"
-                     hidden="true"
-                     label="&sharePageCmd.label;"
-                     tooltiptext="&sharePageCmd.label;"
-                     command="Social:SharePage"/>
-
-      <toolbaritem id="social-toolbar-item"
-                   class="chromeclass-toolbar-additional"
-                   removable="false"
-                   title="&socialToolbar.title;"
-                   hidden="true"
-                   skipintoolbarset="true"
-                   observes="socialActiveBroadcaster">
-        <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"
-                       observes="socialBroadcaster_userDetails"/>
-              </vbox>
-            </menuitem>
-#ifndef XP_WIN
-            <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>
-        <toolbarbutton id="social-mark-button"
-                       class="toolbarbutton-1"
-                       hidden="true"
-                       disabled="true"
-                       command="Social:TogglePageMark"/>
-      </toolbaritem>
-
-      <hbox id="window-controls" hidden="true" pack="end">
-        <toolbarbutton id="minimize-button"
-                       tooltiptext="&fullScreenMinimize.tooltip;"
-                       oncommand="window.minimize();"/>
-
-        <toolbarbutton id="restore-button"
-                       tooltiptext="&fullScreenRestore.tooltip;"
-                       oncommand="BrowserFullScreen();"/>
-
-        <toolbarbutton id="close-button"
-                       tooltiptext="&fullScreenClose.tooltip;"
-                       oncommand="BrowserTryToCloseWindow();"/>
-      </hbox>
-    </toolbar>
-
-    <toolbarset id="customToolbars" context="toolbar-context-menu"/>
-
-    <toolbar id="PersonalToolbar"
-             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;"
-                   removable="true">
-        <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"
-                       flex="1"/>
-            <toolbarbutton type="menu"
-                           id="PlacesChevron"
-                           class="chevron"
-                           mousethrough="never"
-                           collapsed="true"
-                           tooltiptext="&bookmarksToolbarChevron.tooltip;"
-                           onpopupshowing="document.getElementById('PlacesToolbar')
-                                                   ._placesView._onChevronPopupShowing(event);">
-              <menupopup id="PlacesChevronPopup"
-                         placespopup="true"
-                         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
-    </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;"/>
 
       <!-- 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"
@@ -1041,55 +1055,59 @@
                      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" 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"/>
-      <chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
-      <statuspanel id="statusbar-display" inactive="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"
-               flex="1"
-               style="min-width: 14em; width: 18em; max-width: 36em;"/>
-    </vbox>
-    <vbox id="browser-border-end" hidden="true" layer="true"/>
-  </hbox>
+      <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"
+                    onclick="contentAreaClick(event, false);"/>
+        <chatbar id="pinnedchats" layer="true" mousethrough="always" hidden="true"/>
+        <statuspanel id="statusbar-display" inactive="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"
+                 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="&fullscreenExitHint.value;"/>
         <vbox id="full-screen-approval-pane" align="center">
           <description class="full-screen-description" value="&fullscreenApproval.value;"/>
@@ -1140,57 +1158,52 @@
     <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.0645 C 0.5683,0.0679,0.51693,0.3764,0.4837,0.5484 c -0.0522,0.2702,-0.1425,0.4194,-0.4333,0.4194 L 0,1 H 1.0333 V 0.0645 z"/>
+    </svg:clipPath>
+    <svg:clipPath id="tab-curve-clip-path-end" clipPathUnits="objectBoundingBox">
+      <svg:path d="M -0.0333,0.0645 C 0.4317,0.0679,0.4831,0.3764,0.5163,0.5484 c 0.0522,0.2702,+0.1425,0.4194,0.4333,0.4194 L 1,1 H -0.033 V 0.0645 z"/>
+    </svg:clipPath>
+    <svg:clipPath id="tab-clip-path-outer" clipPathUnits="userSpaceOnUse">
+      <svg:path d="M 30,0 C 24,0 17.78,2.58 15.10,8.09 12.05,13.46 13.14,20.37 9.18,25.3 7.1,27.7 3.8,28 0.8,28 c -0.4,0.6 -2.09,1.11 -1.46,1.80 l 2.45,2.72 61.60,0 2.59,-3.06 C 65.15,28.96 64.57,27.80 63.5,28 60.13,28.13 56.33,27.03 54.74,23.78 51.85,18.44 52.65,11.81 49.09,6.73 45.88,1.65 39.54,-0.26 33.8,0 32.5,0 31.7,0 30,0 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: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: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/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
@@ -3479,19 +3479,17 @@
           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");
+              TabsInTitlebar.updateAppearance();
 
               var width = this.mTabstrip.boxObject.width;
               if (width != this.mTabstripWidth) {
                 this.adjustTabstrip();
                 this._fillTrailingGap();
                 this._handleTabSelect();
                 this.mTabstripWidth = width;
               }
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -132,17 +132,16 @@ endif
                  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_bug678392.js \
                  browser_bug678392-1.html \
--- a/browser/base/content/test/browser_addon_bar.js
+++ b/browser/base/content/test/browser_addon_bar.js
@@ -8,19 +8,18 @@ function test() {
   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;
+    // open the toolbars menu
+    toolbarMenu = 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);
@@ -49,15 +48,14 @@ function test() {
   }
 
   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");
+  // open the view menu
+  topMenu = 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/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/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1489,130 +1489,16 @@
         });
         if (item != null) {
           item.setAttribute("padbottom", "true");
         }
       ]]></constructor>
     </implementation>
   </binding>
 
-  <binding id="splitmenu">
-    <content>
-      <xul:hbox anonid="menuitem" flex="1"
-                class="splitmenu-menuitem"
-                xbl:inherits="iconic,label,disabled,onclick=oncommand,_moz-menuactive=active"/>
-      <xul:menu anonid="menu" class="splitmenu-menu"
-                xbl:inherits="disabled,_moz-menuactive=active"
-                oncommand="event.stopPropagation();">
-        <children includes="menupopup"/>
-      </xul:menu>
-    </content>
-
-    <implementation implements="nsIDOMEventListener">
-      <constructor><![CDATA[
-        this._parentMenupopup.addEventListener("DOMMenuItemActive", this, false);
-        this._parentMenupopup.addEventListener("popuphidden", this, false);
-      ]]></constructor>
-
-      <destructor><![CDATA[
-        this._parentMenupopup.removeEventListener("DOMMenuItemActive", this, false);
-        this._parentMenupopup.removeEventListener("popuphidden", this, false);
-      ]]></destructor>
-
-      <field name="menuitem" readonly="true">
-        document.getAnonymousElementByAttribute(this, "anonid", "menuitem");
-      </field>
-      <field name="menu" readonly="true">
-        document.getAnonymousElementByAttribute(this, "anonid", "menu");
-      </field>
-
-      <field name="_menuDelay">600</field>
-
-      <field name="_parentMenupopup"><![CDATA[
-        this._getParentMenupopup(this);
-      ]]></field>
-
-      <method name="_getParentMenupopup">
-        <parameter name="aNode"/>
-        <body><![CDATA[
-          let node = aNode.parentNode;
-          while (node) {
-            if (node.localName == "menupopup")
-              break;
-            node = node.parentNode;
-          }
-          return node;
-        ]]></body>
-      </method>
-
-      <method name="handleEvent">
-        <parameter name="event"/>
-        <body><![CDATA[
-          switch (event.type) {
-            case "DOMMenuItemActive":
-              if (this.getAttribute("active") == "true" &&
-                  event.target != this &&
-                  this._getParentMenupopup(event.target) == this._parentMenupopup)
-                this.removeAttribute("active");
-              break;
-            case "popuphidden":
-              if (event.target == this._parentMenupopup)
-                this.removeAttribute("active");
-              break;
-          }
-        ]]></body>
-      </method>
-    </implementation>
-
-    <handlers>
-      <handler event="mouseover"><![CDATA[
-        if (this.getAttribute("active") != "true") {
-          this.setAttribute("active", "true");
-
-          let event = document.createEvent("Events");
-          event.initEvent("DOMMenuItemActive", true, false);
-          this.dispatchEvent(event);
-
-          if (this.getAttribute("disabled") != "true") {
-            let self = this;
-            setTimeout(function () {
-              if (self.getAttribute("active") == "true")
-                self.menu.open = true;
-            }, this._menuDelay);
-          }
-        }
-      ]]></handler>
-
-      <handler event="popupshowing"><![CDATA[
-        if (event.target == this.firstChild &&
-            this._parentMenupopup._currentPopup)
-          this._parentMenupopup._currentPopup.hidePopup();
-      ]]></handler>
-
-      <handler event="click" phase="capturing"><![CDATA[
-        if (this.getAttribute("disabled") == "true") {
-          // Prevent the command from being carried out
-          event.stopPropagation();
-          return;
-        }
-
-        let node = event.originalTarget;
-        while (true) {
-          if (node == this.menuitem)
-            break;
-          if (node == this)
-            return;
-          node = node.parentNode;
-        }
-
-        this._parentMenupopup.hidePopup();
-      ]]></handler>
-    </handlers>
-  </binding>
-
   <binding id="menuitem-tooltip" extends="chrome://global/content/bindings/menu.xml#menuitem">
     <implementation>
       <constructor><![CDATA[
         this.setAttribute("tooltiptext", this.getAttribute("acceltext"));
         // TODO: Simplify this to this.setAttribute("acceltext", "") once bug
         // 592424 is fixed
         document.getAnonymousElementByAttribute(this, "anonid", "accel").firstChild.setAttribute("value", "");
       ]]></constructor>
--- 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
@@ -79,16 +79,18 @@ static RedirEntry kRedirMap[] = {
   { "preferences", "chrome://browser/content/preferences/in-content/preferences.xul",
     nsIAboutModule::ALLOW_SCRIPT },
   { "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
+  { "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
@@ -102,16 +102,17 @@ static const mozilla::Module::ContractID
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { 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 "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
     { NULL }
 };
 
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,29 @@
+<!-- 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">
+  <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 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>
+    <spacer flex="1"/>
+  </vbox>
+</hbox>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/jar.mn
@@ -0,0 +1,19 @@
+# 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/panelUIOverlay.xul
+  content/browser/customizableui/panelUIOverlay.js
+  content/browser/customizableui/toolbar.xml
+
+# These overlays should be kept in sync with what pages are in
+# XULBrowserWindow.inContentWhitelist in browser.js
+% overlay about:addons               chrome://browser/content/customizableui/panelUIOverlay.xul
+% overlay about:preferences          chrome://browser/content/customizableui/panelUIOverlay.xul
+% overlay about:permissions          chrome://browser/content/customizableui/panelUIOverlay.xul
+% overlay about:sync-progress        chrome://browser/content/customizableui/panelUIOverlay.xul
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,30 @@
+/* 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[view="main"] > .panel-clickcapturer {
+  pointer-events: none;
+}
+
+.panel-viewcontainer,
+.panel-viewstack {
+  overflow: hidden;
+}
+
+.panel-viewstack {
+  position: relative;
+}
+
+.panel-subviews {
+  -moz-stack-sizing: ignore;
+  transform: translateX(0);
+  overflow-y: hidden;
+}
+
+.panel-subviews[panelopen] {
+  transition: transform 150ms;
+}
+
+.panel-viewcontainer[panelopen] {
+  transition: height 150ms;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -0,0 +1,65 @@
+<!-- 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"
+       consumeoutsideclicks="true">
+  <panelmultiview id="PanelUI-multiView">
+    <panelmainview id="PanelUI-mainView">
+      <vbox class="PanelUI-pageControls" pack="center">
+        <hbox class="PanelUI-editControls">
+          <toolbarbutton id="PanelUI-cut-btn" flex="1"
+                         label="&cutCmd.label;"
+                         tooltiptext="&cutButton.tooltip;"
+                         command="cmd_cut"/>
+          <toolbarbutton id="PanelUI-copy-btn" flex="1"
+                         label="&copyCmd.label;"
+                         tooltiptext="&copyButton.tooltip;"
+                         command="cmd_copy"/>
+          <toolbarbutton id="PanelUI-paste-btn" flex="1"
+                         label="&pasteCmd.label;"
+                         tooltiptext="&pasteButton.tooltip;"
+                         command="cmd_paste"/>
+        </hbox>
+        <hbox class="PanelUI-zoomControls">
+          <toolbarbutton id="PanelUI-zoomOut-btn" flex="1"
+                         noautoclose="true" label="&fullZoomReduceCmd.label;"
+                         command="cmd_fullZoomReduce"
+                         tooltiptext="&zoomOutButton.tooltip;"/>
+          <toolbarbutton id="PanelUI-zoomReset-btn" flex="1"
+                         noautoclose="true" label="&zoomReset.label;"
+                         tooltiptext="&zoomReset.tooltip;"
+                         command="cmd_fullZoomReset"/>
+          <toolbarbutton id="PanelUI-zoomIn-btn" flex="1"
+                         noautoclose="true" label="&fullZoomEnlargeCmd.label;"
+                         command="cmd_fullZoomEnlarge"
+                         tooltiptext="&zoomInButton.tooltip;"/>
+        </hbox>
+      </vbox>
+
+      <vbox id="PanelUI-contents" type="grid"/>
+
+      <vbox id="PanelUI-mainView-spring" flex="1"/>
+
+      <footer class="PanelUI-footer" align="center">
+        <toolbarbutton id="PanelUI-help-btn" label="&helpMenu.label;"
+                       command="openHelpLink('firefox-help');"/>
+        <spacer flex="1"/>
+        <toolbarbutton id="PanelUI-customize-btn" label="&appMenuCustomize.label;"
+                       command="cmd_CustomizeToolbars"/>
+      </footer>
+    </panelmainview>
+
+    <panelsubview id="PanelUI-history" flex="1">
+      <label value="&appMenuHistory.label;"/>
+      <vbox id="PanelUI-historyItems"/>
+      <label value="&appMenuHistoryMore.label;"
+             id="PanelUI-historyMore"
+             class="text-link"
+             onclick="PlacesCommandHook.showPlacesOrganizer('History'); PanelUI.hide();"/>
+    </panelsubview>
+  </panelmultiview>
+</panel>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUI.js
@@ -0,0 +1,175 @@
+/* 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");
+/**
+ * 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",
+      menuButton: "PanelUI-menu-button",
+      panel: "PanelUI-popup",
+    };
+  },
+
+  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);
+      });
+    }
+
+    for (let event of this.kEvents) {
+      this.panel.addEventListener(event, this);
+    }
+  },
+
+  uninit: function() {
+    for (let event of this.kEvents) {
+      this.panel.removeEventListener(event, 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.
+   */
+  replaceMainView: function(aMainView) {
+    this.multiView.insertBefore(aMainView, this.multiView.firstChild);
+  },
+
+  /**
+   * 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) {
+    if (this.panel.state == "open") {
+      this.hide();
+    } else if (this.panel.state == "closed") {
+      this.ensureRegistered();
+
+      let anchor = aEvent.target;
+      let iconAnchor =
+        document.getAnonymousElementByAttribute(anchor, "class",
+                                                "toolbarbutton-icon");
+      this.panel.openPopup(iconAnchor || anchor, "bottomcenter topright");
+    }
+  },
+
+  /**
+   * 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;
+      }
+    }
+  },
+
+  /**
+   * Registering the menu panel is done lazily for performance reasons. This
+   * method is exposed so that CustomizationMode can force registration in the
+   * event that customization mode is started before the panel has had a chance
+   * to register itself.
+   */
+  ensureRegistered: function() {
+    CustomizableUI.registerMenuPanel(this.contents);
+  },
+
+  /**
+   * Switch the panel to the main view if it's not already
+   * in that view.
+   */
+  showMainView: function() {
+    this.multiView.showMainView();
+  },
+
+  /**
+   * 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) {
+    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 {
+      // 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);
+
+      let tempPanel = document.createElement("panel");
+      tempPanel.appendChild(viewNode);
+      tempPanel.setAttribute("type", "arrow");
+      tempPanel.setAttribute("id", "customizationui-widget-panel");
+      document.getElementById(CustomizableUI.AREA_NAVBAR).appendChild(tempPanel);
+      tempPanel.addEventListener("popuphidden", function panelRemover() {
+        tempPanel.removeEventListener("popuphidden", panelRemover);
+        this.multiView.appendChild(viewNode);
+        tempPanel.parentElement.removeChild(tempPanel);
+      }.bind(this));
+
+      tempPanel.openPopup(aAnchor, "bottomcenter topright");
+    }
+  },
+
+  /**
+   * 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";
+  }
+};
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUI.xml
@@ -0,0 +1,236 @@
+<?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="toolbarbutton" display="xul:button"
+           extends="chrome://global/content/bindings/button.xml#button-base">
+    <resources>
+      <stylesheet src="chrome://global/skin/toolbarbutton.css"/>
+    </resources>
+    
+    <content>
+      <children includes="observes|template|menupopup|panel|tooltip"/>
+      <xul:hbox align="center" flex="1">
+	      <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label"/>
+	      <xul:vbox flex="1">
+	  	    <xul:label class="toolbarbutton-text" crop="right" flex="1"
+  	  	             xbl:inherits="value=label,accesskey,crop"/>
+  	  	  <xul:hbox pack="end">
+	  	  	  <xul:label class="toolbarbutton-acceltext" crop="middle"
+  		  	  	         xbl:inherits="value=acceltext"/>
+  		  	</xul:hbox>
+  		  </xul:vbox>
+  		</xul:hbox>
+    </content>
+    
+    <implementation implements="nsIAccessibleProvider">
+      <property name="accessibleType" readonly="true">
+        <getter>
+          return Components.interfaces.nsIAccessibleProvider.XULToolbarButton;
+        </getter>
+      </property>
+    </implementation>
+  </binding>
+
+  <binding id="panelmultiview">
+    <resources>
+      <stylesheet src="chrome://browser/content/customizableui/panelUI.css"/>
+    </resources>
+    <content>
+      <xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen">
+        <xul:stack anonid="viewStack" view="main" class="panel-viewstack">
+          <children includes="panelmainview"/>
+
+          <!-- 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="panelsubview"/>
+          </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="_mainView" readonly="true">
+        this.querySelector("panelmainview");
+      </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>
+
+      <property name="showingSubView" readonly="true"
+                onget="return this._viewStack.getAttribute('view') == 'subview'"/>
+
+      <constructor><![CDATA[
+        this._clickCapturer.addEventListener("click", this);
+        this._panel.addEventListener("popupshowing", this);
+        this._panel.addEventListener("popuphidden", 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._subViews.addEventListener("overflow", this);
+      ]]></constructor>
+
+      <destructor><![CDATA[
+        this._subViewObserver.disconnect();
+        this._panel.removeEventListener("popupshowing", this);
+        this._panel.removeEventListener("popuphidden", this);
+        this._clickCapturer.removeEventListener("click", this);
+      ]]></destructor>
+
+      <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._viewContainer.style.height = this._mainViewHeight + "px";
+            this._subViewObserver.disconnect();
+
+            this._viewStack.setAttribute("view", "main");
+          }
+
+          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);
+
+          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._viewStack.setAttribute("view", "subview");
+          this._shiftMainView(aAnchor);
+
+          this._mainViewHeight = this._viewStack.clientHeight;
+          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 left 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._mainView.getBoundingClientRect();
+            let leftEdge = anchorRect.left - mainViewRect.left;
+            let center = aAnchor.clientWidth / 2;
+            let target = leftEdge + center;
+            this._mainView.style.transform = "translateX(-" + target + "px)";
+            aAnchor.classList.add("panel-multiview-anchor");
+          } else {
+            this._mainView.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 subview on the next tick.
+              setTimeout(this._syncContainerWithSubView.bind(this), 0);
+              break;
+            case "popupshowing":
+              this.setAttribute("panelopen", "true");
+              this._syncContainerWithMainView();
+              break;
+            case "popuphidden":
+              this.removeAttribute("panelopen");
+              this.showMainView();
+              break;
+          }
+        ]]></body>
+      </method>
+
+      <method name="_syncContainerWithSubView">
+        <body><![CDATA[
+          this._viewContainer.style.height = this._subViews.scrollHeight + "px";
+        ]]></body>
+      </method>
+      <method name="_syncContainerWithMainView">
+        <body><![CDATA[
+          this._viewContainer.style.height = this._mainView.scrollHeight + "px";
+        ]]></body>
+      </method>
+
+    </implementation>
+  </binding>
+
+</bindings>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUIOverlay.js
@@ -0,0 +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/. */
+
+if (typeof XPCOMUtils == "undefined")
+  Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
+                                  "resource:///modules/CustomizableUI.jsm");
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/panelUIOverlay.xul
@@ -0,0 +1,26 @@
+<?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/. -->
+
+<!DOCTYPE overlay [
+  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
+  %brandDTD;
+  <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
+  %browserDTD;
+]>
+
+<?xml-stylesheet href="chrome://browser/skin/customizableui/panelUIOverlay.css" type="text/css"?>
+
+<overlay id="panelUIOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://browser/content/customizableui/panelUIOverlay.js"/>
+
+  <hbox id="app-extension-point-end">
+    <toolbarbutton id="PanelUI-menu-button"
+                   class="toolbarbutton-1"
+                   label="&brandShortName;"
+                   tooltiptext="&appmenu.title;"
+                   oncommand="CustomizableUI.showPanel(this);"/>
+  </hbox>
+</overlay>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/content/toolbar.xml
@@ -0,0 +1,236 @@
+<?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">
+      <property name="accessibleType" readonly="true">
+        <getter>
+          return Components.interfaces.nsIAccessibleProvider.XULToolbar;
+        </getter>
+      </property>
+
+      <constructor><![CDATA[
+          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);
+              }
+            }
+          }
+
+          CustomizableUI.registerToolbar(this);
+        ]]></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 = 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" readonly="true">
+        <getter><![CDATA[
+          if (!this._customizationTarget)
+            return "";
+
+          return [node.id for (node of this._customizationTarget.children)].join(',');
+        ]]></getter>
+      </property>
+
+
+    </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>
+
+      <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) {
+              // Don't move while customizing.
+              return this._dragBindingAlive &&
+                     this.getAttribute("customizing") != "true";
+            };
+          } catch (e) {}
+        }
+      ]]></constructor>
+    </implementation>
+  </binding>
+</bindings>
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/moz.build
@@ -0,0 +1,10 @@
+# -*- 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',
+]
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -0,0 +1,1770 @@
+/* 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/NetUtil.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+  "resource://gre/modules/PlacesUtils.jsm");
+
+const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+const kPrefCustomizationState        = "browser.uiCustomization.state";
+const kPrefCustomizationAutoAdd      = "browser.uiCustomization.autoAdd";
+const kPrefCustomizationDebug        = "browser.uiCustomization.debug";
+
+/**
+ * Lazily returns the definitions for the set of built-in widgets. This might
+ * not be the final resting place for this stuff, but it'll do for now.
+ */
+XPCOMUtils.defineLazyGetter(this, "gBuiltInWidgets", function() {
+  return [{
+    id: "history-panelmenu",
+    type: "view",
+    viewId: "PanelUI-history",
+    name: "History...",
+    description: "History repeats itself!",
+    defaultArea: CustomizableUI.AREA_PANEL,
+    allowedAreas: [CustomizableUI.AREA_PANEL, CustomizableUI.AREA_NAVBAR],
+    icons: {
+      "16": "chrome://branding/content/icon16.png",
+      "32": "chrome://branding/content/icon48.png",
+      "48": "chrome://branding/content/icon48.png"
+    },
+    onViewShowing: function(aEvent) {
+      // Populate our list of history
+      const kMaxResults = 15;
+      let doc = aEvent.detail.ownerDocument;
+
+      let options = PlacesUtils.history.getNewQueryOptions();
+      options.excludeQueries = true;
+      options.includeHidden = false;
+      options.resultType = options.RESULTS_AS_URI;
+      options.queryType = options.QUERY_TYPE_HISTORY;
+      options.sortingMode = options.SORT_BY_DATE_DESCENDING;
+      options.maxResults = kMaxResults;
+      let query = PlacesUtils.history.getNewQuery();
+
+      let items = doc.getElementById("PanelUI-historyItems");
+      // Clear previous history items.
+      while (items.firstChild) {
+        items.removeChild(items.firstChild);
+      }
+
+      PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
+                         .asyncExecuteLegacyQueries([query], 1, options, {
+        handleResult: function (aResultSet) {
+          let fragment = doc.createDocumentFragment();
+          for (let row, i = 0; (row = aResultSet.getNextRow()); i++) {
+            try {
+              let uri = row.getResultByIndex(1);
+              let title = row.getResultByIndex(2);
+              let icon = row.getResultByIndex(6);
+
+              let item = doc.createElementNS(kNSXUL, "toolbarbutton");
+              item.setAttribute("label", title || uri);
+              item.addEventListener("click", function(aEvent) {
+                if (aEvent.button == 0) {
+                  doc.defaultView.openUILink(uri, aEvent);
+                  doc.defaultView.PanelUI.hide();
+                }
+              });
+              if (icon)
+                item.setAttribute("image", "moz-anno:favicon:" + icon);
+              fragment.appendChild(item);
+            } catch (e) {
+              Cu.reportError("Error while showing history subview: " + e);
+            }
+          }
+          items.appendChild(fragment);
+        },
+        handleError: function (aError) {
+          LOG("History view tried to show but had an error: " + aError);
+        },
+        handleCompletion: function (aReason) {
+          LOG("History view is being shown!");
+        },
+      });
+    },
+    onViewHiding: function(aEvent) {
+      LOG("History view is being hidden!");
+    }
+  }, {
+    id: "privatebrowsing-button",
+    name: "Private Browsing\u2026",
+    description: "Open a new Private Browsing window",
+    defaultArea: CustomizableUI.AREA_PANEL,
+    allowedAreas: [CustomizableUI.AREA_PANEL],
+    icons: {
+      "16": "chrome://branding/content/icon16.png",
+      "32": "chrome://branding/content/icon48.png",
+      "48": "chrome://branding/content/icon48.png"
+    },
+    onCommand: function(e) {
+      if (e.target && e.target.ownerDocument && e.target.ownerDocument.defaultView) {
+        let win = e.target.ownerDocument.defaultView;
+        if (typeof win.OpenBrowserWindow == "function") {
+          win.OpenBrowserWindow({private: true});
+        }
+      }
+    }
+  }, {
+    id: "save-page-button",
+    name: "Save Page",
+    shortcut: "Ctrl+S",
+    description: "Save this page",
+    defaultArea: CustomizableUI.AREA_PANEL,
+    allowedAreas: [CustomizableUI.AREA_PANEL],
+    icons: {
+      "16": "chrome://branding/content/icon16.png",
+      "32": "chrome://branding/content/icon48.png",
+      "48": "chrome://branding/content/icon48.png"
+    },
+    onCommand: function(aEvent) {
+      let win = aEvent.target &&
+                aEvent.target.ownerDocument &&
+                aEvent.target.ownerDocument.defaultView;
+      if (win && typeof win.saveDocument == "function") {
+        win.saveDocument(win.content.document);
+      }
+    }
+  }, {
+    id: "find-button",
+    name: "Find",
+    shortcut: "Ctrl+F",
+    description: "Find in this page",
+    defaultArea: CustomizableUI.AREA_PANEL,
+    allowedAreas: [CustomizableUI.AREA_PANEL],
+    icons: {
+      "16": "chrome://branding/content/icon16.png",
+      "32": "chrome://branding/content/icon48.png",
+      "48": "chrome://branding/content/icon48.png"
+    },
+    onCommand: function(aEvent) {
+      let win = aEvent.target &&
+                aEvent.target.ownerDocument &&
+                aEvent.target.ownerDocument.defaultView;
+      if (win && win.gFindBar) {
+        win.gFindBar.onFindCommand();
+      }
+    }
+  }, {
+    id: "open-file-button",
+    name: "Open File",
+    shortcut: "Ctrl+O",
+    description: "Open file",
+    defaultArea: CustomizableUI.AREA_PANEL,
+    allowedAreas: [CustomizableUI.AREA_PANEL],
+    icons: {
+      "16": "chrome://branding/content/icon16.png",
+      "32": "chrome://branding/content/icon48.png",
+      "48": "chrome://branding/content/icon48.png"
+    },
+    onCommand: function(aEvent) {
+      let win = aEvent.target
+                && aEvent.target.ownerDocument
+                && aEvent.target.ownerDocument.defaultView;
+      if (win && typeof win.BrowserOpenFileWindow == "function") {
+        win.BrowserOpenFileWindow();
+      }
+    }
+  }, {
+    id: "developer-button",
+    name: "Developer",
+    shortcut: "Shift+F11",
+    description: "Toggle Developer Tools",
+    defaultArea: CustomizableUI.AREA_PANEL,
+    allowedAreas: [CustomizableUI.AREA_PANEL],
+    icons: {
+      "16": "chrome://branding/content/icon16.png",
+      "32": "chrome://branding/content/icon48.png",
+      "48": "chrome://branding/content/icon48.png"
+    },
+    onCommand: function(aEvent) {
+      let win = aEvent.target &&
+                aEvent.target.ownerDocument &&
+                aEvent.target.ownerDocument.defaultView;
+      if (win && win.gDevToolsBrowser) {
+        win.gDevToolsBrowser.toggleToolboxCommand(win.gBrowser);
+      }
+    }
+  }, {
+    id: "add-ons-button",
+    name: "Add-ons",
+    shortcut: "Ctrl+Shift+A",
+    description: "Add-ons Manager",
+    defaultArea: CustomizableUI.AREA_PANEL,
+    allowedAreas: [CustomizableUI.AREA_PANEL],
+    icons: {
+      "16": "chrome://branding/content/icon16.png",
+      "32": "chrome://branding/content/icon48.png",
+      "48": "chrome://branding/content/icon48.png"
+    },
+    onCommand: function(aEvent) {
+      let win = aEvent.target &&
+                aEvent.target.ownerDocument &&
+                aEvent.target.ownerDocument.defaultView;
+      if (win && typeof win.BrowserOpenAddonsMgr == "function") {
+        win.BrowserOpenAddonsMgr();
+      }
+    }
+  }, {
+    id: "preferences-button",
+    name: "Preferences",
+    shortcut: "Ctrl+Shift+O",
+    description: "Preferences\u2026",
+    defaultArea: CustomizableUI.AREA_PANEL,
+    allowedAreas: [CustomizableUI.AREA_PANEL],
+    icons: {
+      "16": "chrome://branding/content/icon16.png",
+      "32": "chrome://branding/content/icon48.png",
+      "48": "chrome://branding/content/icon48.png"
+    },
+    onCommand: function(aEvent) {
+      let win = aEvent.target &&
+                aEvent.target.ownerDocument &&
+                aEvent.target.ownerDocument.defaultView;
+      if (win && typeof win.openPreferences == "function") {
+        win.openPreferences();
+      }
+    }
+  }];
+});
+
+/**
+ * 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();
+
+/**
+ * If the user does not have any state saved, this is the default set of
+ * placements to use.
+ */
+let gDefaultPlacements = new Map([
+  ["toolbar-menubar", [
+    "menubar-items",
+  ]],
+  ["TabsToolbar", [
+    "tabbrowser-tabs",
+    "new-tab-button",
+    "alltabs-button",
+    "tabs-closebutton"
+  ]],
+  ["nav-bar", [
+    "unified-back-forward-button",
+    "urlbar-container",
+    "reload-button",
+    "stop-button",
+    "search-container",
+    "webrtc-status-button",
+    "bookmarks-menu-button-container",
+    "downloads-button",
+    "home-button",
+    "social-toolbar-button",
+  ]],
+  ["PersonalToolbar", [
+    "personal-bookmarks",
+  ]],
+  ["PanelUI-contents", [
+    "new-window-button",
+    "privatebrowsing-button",
+    "save-page-button",
+    "print-button",
+    "history-panelmenu",
+    "fullscreen-button",
+    "find-button",
+    "preferences-button",
+    "add-ons-button"
+  ]]
+]);
+
+//XXXunf Temporary. Need a nice way to abstract functions to build widgets
+//       of these types.
+let gSupportedWidgetTypes = new Set(["button", "view"]);
+
+/**
+ * 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();
+
+let gSavedState = null;
+let gRestoring = false;
+let gDirty = false;
+let gInBatch = false;
+
+/**
+ * gBuildAreas maps area IDs to actual area nodes within browser windows.
+ */
+let gBuildAreas = new Map();
+let gNewElementCount = 0;
+let gWrapperCache = new WeakMap();
+let gListeners = new Set();
+
+let gDebug = false;
+try {
+  gDebug = Services.prefs.getBoolPref(kPrefCustomizationDebug);
+} catch (e) {}
+
+function LOG(aMsg) {
+  if (gDebug) {
+    Services.console.logStringMessage("[CustomizableUI] " + aMsg);
+  }
+}
+function ERROR(aMsg) Cu.reportError("[CustomizableUI] " + aMsg);
+
+
+let CustomizableUIInternal = {
+  initialize: function() {
+    LOG("Initializing");
+
+    this.addListener(this);
+    this._defineBuiltInWidgets();
+    this.loadSavedState();
+
+    this.registerArea(CustomizableUI.AREA_PANEL);
+    this.registerArea(CustomizableUI.AREA_NAVBAR, ["legacy"]);
+    this.registerArea(CustomizableUI.AREA_MENUBAR, ["legacy"]);
+    this.registerArea(CustomizableUI.AREA_TABSTRIP, ["legacy"]);
+    this.registerArea(CustomizableUI.AREA_BOOKMARKS, ["legacy"]);
+  },
+
+  _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 gBuiltInWidgets) {
+      this.createBuiltinWidget(widgetDefinition);
+    }
+  },
+
+  wrapWidget: function(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);
+      }
+      return widget.wrapper;
+    }
+
+    // PROVIDER_SPECIAL gets treated the same as PROVIDER_XUL.
+    return new XULWidgetGroupWrapper(aWidgetId);
+  },
+
+  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 Set(aProperties);
+    gAreas.set(aName, props);
+
+    if (props.has("legacy")) {
+      // Guarantee this area exists in gFuturePlacements, to avoid checking it in
+      // various places elsewhere.
+      gFuturePlacements.set(aName, new Set());
+    } else {
+      this.restoreStateForArea(aName);
+    }
+  },
+
+  registerToolbar: function(aToolbar) {
+    let document = aToolbar.ownerDocument;
+    let area = aToolbar.id;
+
+    if (!gAreas.has(area)) {
+      throw new Error("Unknown customization area: " + area);
+    }
+
+    if (this.isBuildAreaRegistered(area, aToolbar)) {
+      return;
+    }
+
+    let areaProperties = gAreas.get(area);
+
+    if (!gPlacements.has(area) && areaProperties.has("legacy")) {
+      let legacyState = aToolbar.getAttribute("currentset");
+      if (legacyState) {
+        legacyState = legacyState.split(",");
+      }
+
+      // Manually restore the state here, so the legacy state can be converted. 
+      this.restoreStateForArea(area, legacyState);
+    }
+
+    this.registerBuildArea(area, aToolbar);
+
+    let placements = gPlacements.get(area);
+    this.buildArea(area, placements, aToolbar);
+    aToolbar.setAttribute("currentset", placements.join(","));
+
+    // We ensure that the window is registered to have its customization data
+    // cleaned up when unloading.
+    this.registerBuildWindow(document.defaultView);
+  },
+
+  buildArea: function(aArea, aPlacements, aAreaNode) {
+    let document = aAreaNode.ownerDocument;
+    let container = aAreaNode.customizationTarget;
+
+    if (!container) {
+      throw new Error("Expected area " + aArea
+                      + " to have a customizationTarget attribute.");
+    }
+
+    let currentNode = container.firstChild;
+    for (let id of aPlacements) {
+      if (currentNode && currentNode.id == id) {
+        this._addParentFlex(currentNode);
+        currentNode = currentNode.nextSibling;
+        continue;
+      }
+
+      let [provider, node] = this.getWidgetNode(id, document, aAreaNode.toolbox);
+      if (!node) {
+        LOG("Unknown widget: " + id);
+        continue;
+      }
+
+      if (provider == CustomizableUI.PROVIDER_XUL &&
+          aArea == CustomizableUI.AREA_PANEL) {
+        this.ensureButtonClosesPanel(node);
+      }
+
+      container.insertBefore(node, currentNode);
+      this._addParentFlex(node);
+    }
+
+    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.
+        if (node.getAttribute("removable") == "true") {
+          if (palette) {
+            palette.appendChild(node);
+          } else {
+            container.removeChild(node);
+          }
+        }
+        node = previousSibling;
+      }
+    }
+  },
+
+  ensureButtonClosesPanel: function(aNode) {
+    //XXXunf This seems kinda hacky, but I can't find any other reliable method.
+    //XXXunf Is it worth going to the effort to remove these when appropriate?
+    // The "command" event only gets fired if there's not an attached command
+    // (via the "command" attribute). For menus, this is handled natively, but
+    // since the panel isn't implemented as a menu, we have to handle it
+    // ourselves.
+
+    aNode.addEventListener("mouseup", this.maybeAutoHidePanel, false);
+    aNode.addEventListener("keypress", this.maybeAutoHidePanel, false);
+  },
+
+  getWidgetProvider: function(aWidgetId) {
+    if (this.isSpecialWidget(aWidgetId)) {
+      return CustomizableUI.PROVIDER_SPECIAL;
+    }
+    if (gPalette.has(aWidgetId)) {
+      return CustomizableUI.PROVIDER_API;
+    }
+
+    // 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, aDocument, aToolbox) {
+    if (this.isSpecialWidget(aWidgetId)) {
+      return [ CustomizableUI.PROVIDER_SPECIAL,
+               this.createSpecialWidget(aWidgetId, aDocument) ];
+    }
+
+    let widget = gPalette.get(aWidgetId);
+    if (widget) {
+      // If we have an instance of this widget already, just use that.
+      if (widget.instances.has(aDocument)) {
+        LOG("An instance of widget " + aWidgetId + " already exists in this "
+            + "document. Reusing.");
+        return [ CustomizableUI.PROVIDER_API,
+                 widget.instances.get(aDocument) ];
+      }
+
+      return [ CustomizableUI.PROVIDER_API,
+               this.buildWidget(aDocument, null, widget) ];
+    }
+
+    LOG("Searching for " + aWidgetId + " in toolbox.");
+    let node = this.findWidgetInToolbox(aWidgetId, aToolbox, aDocument);
+    if (node) {
+      return [ CustomizableUI.PROVIDER_XUL, node ];
+    }
+
+    return [];
+  },
+
+  registerMenuPanel: function(aPanel) {
+    if (this.isBuildAreaRegistered(CustomizableUI.AREA_PANEL, aPanel)) {
+      return;
+    }
+
+    let document = aPanel.ownerDocument;
+
+    for (let btn of aPanel.querySelectorAll("toolbarbutton")) {
+      if (!btn.hasAttribute("noautoclose")) {
+        this.ensureButtonClosesPanel(btn);
+      }
+    }
+
+    aPanel.toolbox = document.getElementById("navigator-toolbox");
+    aPanel.customizationTarget = 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) {
+      Cu.reportError("Could not find any placements for " + aArea +
+                     " when adding a widget.");
+      return;
+    }
+
+    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 container = areaNode.customizationTarget;
+      let [provider, widgetNode] = this.getWidgetNode(aWidgetId,
+                                                      container.ownerDocument,
+                                                      areaNode.toolbox);
+
+      if (provider == CustomizableUI.PROVIDER_XUL &&
+          aArea == CustomizableUI.AREA_PANEL) {
+        this.ensureButtonClosesPanel(widgetNode);
+      }
+
+      let nextNode = container.querySelector("#" + nextNodeId);
+      container.insertBefore(widgetNode, nextNode);
+      this._addParentFlex(widgetNode);
+    }
+  },
+
+  onWidgetRemoved: function(aWidgetId, aArea) {
+    let areaNodes = gBuildAreas.get(aArea);
+    if (!areaNodes) {
+      return;
+    }
+
+    for (let areaNode of areaNodes) {
+      let container = areaNode.customizationTarget;
+      let widgetNode = container.ownerDocument.getElementById(aWidgetId);
+      if (!widgetNode) {
+        ERROR("Widget not found, unable to remove");
+        continue;
+      }
+
+      this._removeParentFlex(widgetNode);
+
+      if (gPalette.has(aWidgetId) || this.isSpecialWidget(aWidgetId)) {
+        container.removeChild(widgetNode);
+      } else {
+        areaNode.toolbox.palette.appendChild(widgetNode);
+      }
+    }
+  },
+
+  onWidgetMoved: function(aWidgetId, aArea, aOldPosition, aNewPosition) {
+    let areaNodes = gBuildAreas.get(aArea);
+    if (!areaNodes) {
+      return;
+    }
+
+    let placements = gPlacements.get(aArea);
+    if (!placements) {
+      Cu.reportError("Could not find any placements for " + aArea +
+                     " when moving a widget.");
+      return;
+    }
+
+    let nextNodeId = placements[aNewPosition + 1];
+
+    for (let areaNode of areaNodes) {
+      let container = areaNode.customizationTarget;
+      let widgetNode = container.ownerDocument.getElementById(aWidgetId);
+      if (!widgetNode) {
+        ERROR("Widget not found, unable to move");
+        continue;
+      }
+
+      let nextNode = container.querySelector("#" + nextNodeId);
+      container.insertBefore(widgetNode, nextNode);
+    }
+  },
+
+  isBuildAreaRegistered: function(aArea, aInstance) {
+    if (!gBuildAreas.has(aArea)) {
+      return false;
+    }
+    return gBuildAreas.get(aArea).has(aInstance);
+  },
+
+  registerBuildArea: function(aArea, aNode) {
+    if (!gBuildAreas.has(aArea)) {
+      gBuildAreas.set(aArea, new Set());
+    }
+
+    gBuildAreas.get(aArea).add(aNode);
+  },
+
+  registerBuildWindow: function(aWindow) {
+    aWindow.addEventListener("unload", this, false);
+  },
+
+  unregisterBuildWindow: function(aWindow) {
+    let document = aWindow.document;
+
+    for (let [, area] of gBuildAreas) {
+      for (let node of area) {
+        if (node.ownerDocument == document) {
+          area.delete(node);
+        }
+      }
+    }
+
+    for (let [,widget] of gPalette)
+      widget.instances.delete(document);
+  },
+
+  handleEvent: function(aEvent) {
+    switch (aEvent.type) {
+      case "unload": {
+        let window = aEvent.target;
+        window.removeEventListener("unload", this);
+        this.unregisterBuildWindow(window);
+        break;
+      }
+    }
+  },
+
+  isSpecialWidget: function(aId) {
+    //XXXunf Need to double check these are getting handled correctly
+    //       everywhere, notably save/restore.
+    return (aId.startsWith("separator") ||
+            aId.startsWith("spring") ||
+            aId.startsWith("spacer"));
+  },
+
+  createSpecialWidget: function(aId, aDocument) {
+    let node = aDocument.createElementNS(kNSXUL, "toolbar" + 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.
+    node.id = aId + Date.now() + (++gNewElementCount);
+    if (aId == "spring") {
+      node.flex = 1;
+    }
+    return node;
+  },
+
+  findWidgetInToolbox: function(aId, aToolbox, aDocument) {
+    if (!aToolbox) {
+      return null;
+    }
+
+    // look for a node with the same id, as the node may be
+    // in a different toolbar.
+    let node = aDocument.getElementById(aId);
+    if (node) {
+      let parent = node.parentNode;
+      while (parent && parent.localName != "toolbar")
+        parent = parent.parentNode;
+
+      if (parent &&
+          parent.toolbox == aToolbox &&
+          parent.customizationTarget == node.parentNode) {
+        return node;
+      }
+    }
+
+    if (aToolbox.palette) {
+      // Attempt to locate a node with a matching ID within
+      // the palette.
+      return aToolbox.palette.querySelector("#" + aId);
+    }
+    return null;
+  },
+
+  // Depending on aMenu here is a hack that should be fixed.
+  buildWidget: function(aDocument, aMenu, 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);
+
+    let 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("label", aWidget.name);
+    node.setAttribute("tooltiptext", aWidget.description);
+    //XXXunf Need to hook this up to a <key> element or something.
+    if (aWidget.shortcut) {
+      node.setAttribute("acceltext", aWidget.shortcut);
+    }
+    node.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional");
+
+    if (aMenu) {
+      node.setAttribute("image", aWidget.icons["32"]);
+    } else {
+      node.setAttribute("image", aWidget.icons["16"]);
+    }
+
+    let handler = this.handleWidgetClick.bind(this, aWidget, node);
+    node.addEventListener("command", handler, 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) {
+        ERROR("Could not find the view node with id: " + aWidget.viewId);
+        throw new Error("Could not find the view node with id: " + aWidget.viewId);
+      }
+
+      // 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.");
+    }
+
+    aWidget.instances.set(aDocument, node);
+    return node;
+  },
+
+  handleWidgetClick: function(aWidget, aNode, aEvent) {
+    LOG("handleWidgetClick");
+
+    if (aWidget.type == "button") {
+      this.maybeAutoHidePanel(aEvent);
+
+      if (aWidget.onCommand) {
+        try {
+          aWidget.onCommand.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);
+      }
+    } else if (aWidget.type == "view") {
+      let ownerWindow = aNode.ownerDocument.defaultView;
+      ownerWindow.PanelUI.showSubView(aWidget.viewId, aNode,
+                                      this.getPlacementOfWidget(aNode.id).area);
+    }
+  },
+
+  maybeAutoHidePanel: function(aEvent) {
+    if (aEvent.type == "keypress" && 
+        !(aEvent.keyCode == aEvent.DOM_VK_ENTER ||
+          aEvent.keyCode == aEvent.DOM_VK_RETURN)) {
+      return;
+    }
+
+    if (aEvent.type == "mouseup" && aEvent.button != 0) {
+      return;
+    }
+
+    let ownerWindow = aEvent.target.ownerDocument.defaultView;
+    ownerWindow.PanelUI.hide();
+  },
+
+  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 [i for (i of widgets)];
+  },
+
+  getPlacementOfWidget: function(aWidgetId) {
+    let widget = gPalette.get(aWidgetId);
+
+    for (let [area, placements] of gPlacements) {
+      let index = placements.indexOf(aWidgetId);
+      if (index != -1) {
+        return { area: area, position: index };
+      }
+    }
+
+    return null;
+  },
+
+  addWidgetToArea: function(aWidgetId, aArea, aPosition) {
+    if (!gAreas.has(aArea)) {
+      throw new Error("Unknown customization area: " + aArea);
+    }
+
+    // If this is a lazy area that hasn't been restored yet, we can't yet modify
+    // it - would would at least like to add to it. So we keep track of it in
+    // gFuturePlacements,  and use that to add it when restoring the area. We
+    // throw away aPosition though, as that can only be bogus if the area hasn't
+    // yet been restorted (caller can't possibly know where its putting the
+    // widget in relation to other widgets).
+    if (this.isAreaLazy(aArea)) {
+      gFuturePlacements.get(aArea).set(aWidgetId);
+      return;
+    }
+
+    let oldPlacement = this.getPlacementOfWidget(aWidgetId);
+    if (oldPlacement && oldPlacement.area == aArea) {
+      this.moveWidgetWithinArea(aWidgetId, aPosition);
+      return;
+    }
+
+    if (oldPlacement) {
+      this.removeWidgetFromArea(aWidgetId);
+    }
+
+    if (!gPlacements.has(aArea)) {
+      gPlacements.set(aArea, [aWidgetId]);
+      aPosition = 0;
+    } else {
+      let placements = gPlacements.get(aArea);
+      if (typeof aPosition != "number") {
+        aPosition = placements.length;
+      }
+      if (aPosition < 0) {
+        aPosition = 0;
+      }
+      placements.splice(aPosition, 0, aWidgetId);
+    }
+
+    let widget = gPalette.get(aWidgetId);
+    if (widget) {
+      widget.currentArea = aArea;
+      widget.currentPosition = aPosition;
+    }
+
+    gDirty = true;
+    this.saveState();
+
+    this.notifyListeners("onWidgetAdded", aWidgetId, aArea, aPosition);
+  },
+
+  removeWidgetFromArea: function(aWidgetId) {
+    let oldPlacement = this.getPlacementOfWidget(aWidgetId);
+    if (!oldPlacement) {
+      return;
+    }
+
+    let placements = gPlacements.get(oldPlacement.area);
+    let position = placements.indexOf(aWidgetId);
+    if (position != -1) {
+      placements.splice(position, 1);
+    }
+
+    let widget = gPalette.get(aWidgetId);
+    if (widget) {
+      widget.currentArea = null;
+      widget.currentPosition = null;
+    }
+
+    gDirty = true;
+    this.saveState();
+
+    this.notifyListeners("onWidgetRemoved", aWidgetId, oldPlacement.area);
+  },
+
+  moveWidgetWithinArea: function(aWidgetId, aPosition) {
+    let oldPlacement = this.getPlacementOfWidget(aWidgetId);
+    if (!oldPlacement) {
+      return;
+    }
+
+    let placements = gPlacements.get(oldPlacement.area);
+    if (aPosition < 0) {
+      aPosition = 0;
+    } else if (aPosition > placements.length - 1) {
+      aPosition = placements.length - 1;
+    }
+
+    if (aPosition == oldPlacement.position) {
+      return;
+    }
+
+    placements.splice(oldPlacement.position, 1);
+    placements.splice(aPosition, 0, aWidgetId);
+
+    let widget = gPalette.get(aWidgetId);
+    if (widget) {
+      widget.currentPosition = aPosition;
+    }
+
+    gDirty = true;
+    this.saveState();
+
+    this.notifyListeners("onWidgetMoved", aWidgetId, oldPlacement.area,
+                         oldPlacement.position, aPosition);
+  },
+
+  // Note that this does not populate gPlacements, which is done lazily so that
+  // the legacy state can be migrated, which is only available once a browser
+  // window is openned.
+  // The panel area is an exception here, since it has no legacy state and is 
+  // built lazily - and therefore wouldn't otherwise result in restoring its
+  // state immediately when a browser window opens, which is important for
+  // other consumers of this API.
+  loadSavedState: function() {
+    let state = null;
+    try {
+      state = Services.prefs.getCharPref(kPrefCustomizationState);
+    } catch (e) {
+      LOG("No saved state found");
+      // This will fail if nothing has been customized, so silently fall back to
+      // the defaults.
+    }
+
+    if (!state) {
+      return;
+    }
+    try {
+      gSavedState = JSON.parse(state);
+    } catch(e) {
+      LOG("Error loading saved UI customization state, falling back to defaults.");
+    }
+
+    if (!("placements" in gSavedState)) {
+      gSavedState.placements = {};
+    }
+
+    gSeenWidgets = new Set(gSavedState.seen || []);
+  },
+
+  restoreStateForArea: function(aArea, aLegacyState) {
+    if (gPlacements.has(aArea)) {
+      // Already restored.
+      return;
+    }
+
+    this.beginBatchUpdate();
+    gRestoring = true;
+
+    let restored = false;
+    gPlacements.set(aArea, []);
+
+    if (gSavedState && aArea in gSavedState.placements) {
+      LOG("Restoring " + aArea + " from saved state");
+      let placements = gSavedState.placements[aArea];
+      for (let id of placements)
+        this.addWidgetToArea(id, aArea);
+      gDirty = false;
+      restored = true;
+    }
+
+    if (!restored && aLegacyState) {
+      LOG("Restoring " + aArea + " from legacy state");
+      for (let id of aLegacyState)
+        this.addWidgetToArea(id, aArea);
+      // Don't override dirty state, to ensure legacy state is saved here and
+      // therefore only used once.
+      restored = true;
+    }
+
+    if (!restored) {
+      LOG("Restoring " + aArea + " from default state");
+      if (gDefaultPlacements.has(aArea)) {
+        let defaults = gDefaultPlacements.get(aArea);
+        for (let id of defaults)
+          this.addWidgetToArea(id, aArea);
+      }
+      gDirty = false;
+    }
+
+    // Finally, add widgets to the area that were added before the it was able
+    // to be restored. This can occur when add-ons register widgets for a
+    // lazily-restored area before it's been restored.
+    if (gFuturePlacements.has(aArea)) {
+      for (let id of gFuturePlacements.get(aArea))
+        this.addWidgetToArea(id, aArea);
+    }
+
+    LOG("Placements for " + aArea + ":\n\t" + gPlacements.get(aArea).join("\n\t"));
+
+    gRestoring = false;
+    this.endBatchUpdate();
+  },
+
+  saveState: function() {
+    if (gInBatch || !gDirty) {
+      return;
+    }
+    let state = { placements: gPlacements,
+                  seen: gSeenWidgets };
+
+    LOG("Saving state.");
+    let serialized = JSON.stringify(state, this.serializerHelper);
+    LOG("State saved as: " + serialized);
+    Services.prefs.setCharPref(kPrefCustomizationState, serialized);
+    gDirty = false;
+  },
+
+  serializerHelper: function(aKey, aValue) {
+    if (typeof aValue == "object" && aValue.constructor.name == "Map") {
+      let result = {};
+      for (let [mapKey, mapValue] of aValue)
+        result[mapKey] = mapValue;
+      return result;
+    }
+
+    if (typeof aValue == "object" && aValue.constructor.name == "Set") {
+      return [i for (i of aValue)];
+    }
+
+    return aValue;
+  },
+
+  beginBatchUpdate: function() {
+    gInBatch = true;
+  },
+
+  endBatchUpdate: function(aForceSave) {
+    gInBatch = false;
+    if (aForceSave === true) {
+      gDirty = true;
+    }
+    this.saveState();
+  },
+
+  addListener: function(aListener) {
+    gListeners.add(aListener);
+  },
+
+  removeListener: function(aListener) {
+    if (aListener == this) {
+      return;
+    }
+
+    gListeners.delete(aListener);
+  },
+
+  notifyListeners: function(aEvent, ...aArgs) {
+    if (gRestoring) {
+      return;
+    }
+
+    for (let listener of gListeners) {
+      try {
+        if (aEvent in listener) {
+          listener[aEvent].apply(listener, aArgs);
+        }
+      } catch (e) {
+        Cu.reportError(e + " -- " + e.fileName + ":" + e.lineNumber);
+      }
+    }
+  },
+
+  createWidget: function(aProperties) {
+    let widget = this.normalizeWidget(aProperties, CustomizableUI.SOURCE_EXTERNAL);
+    //XXXunf This should probably throw.
+    if (!widget) {
+      return;
+    }
+
+    gPalette.set(widget.id, widget);
+    this.notifyListeners("onWidgetCreated", widget.id);
+
+    if (widget.defaultArea) {
+      let area = widget.defaultArea;
+      if (gDefaultPlacements.has(area)) {
+        gDefaultPlacements.get(area).push(widget.id);
+      } else {
+        gDefaultPlacements.set(area, [widget.id]);
+      }
+    }
+
+    // Look through previously saved state to see if we're restoring a widget.
+    let seenAreas = new Set();
+    for (let [area, placements] of gPlacements) {
+      seenAreas.add(area);
+      let index = gPlacements.get(area).indexOf(widget.id);
+      if (index != -1) {
+        widget.currentArea = area;
+        widget.currentPosition = index;
+        break;
+      }
+    }
+
+    // Also look at saved state data directly in areas that haven't yet been
+    // restored. Can't rely on this for restored areas, as they may have
+    // changed.
+    if (!widget.currentArea && gSavedState) {
+      for (let area of Object.keys(gSavedState.placements)) {
+        if (seenAreas.has(area)) {
+          continue;
+        }
+
+        let index = gSavedState.placements[area].indexOf(widget.id);
+        if (index != -1) {
+          widget.currentArea = area;
+          widget.currentPosition = index;
+          break;
+        }
+      }
+    }
+
+    // If we're restoring the widget to it's old placement, fire off the
+    // onWidgetAdded event - our own handler will take care of adding it to
+    // any build areas.
+    if (widget.currentArea) {
+      this.notifyListeners("onWidgetAdded", widget.id, widget.currentArea,
+                           widget.currentPosition);
+    } else {
+      let autoAdd = true;
+      try {
+        autoAdd = Services.prefs.getBoolPref(kPrefCustomizationAutoAdd);
+      } catch (e) {}
+
+      // If the widget doesn't have an existing placement, and it hasn't been
+      // seen before, then add it to its default area so it can be used.
+      if (autoAdd && !widget.currentArea && !gSeenWidgets.has(widget.id)) {
+        this.beginBatchUpdate();
+        gSeenWidgets.add(widget.id);
+
+        if (widget.defaultArea) {
+          if (this.isAreaLazy(widget.defaultArea)) {
+            gFuturePlacements.get(widget.defaultArea).set(widget.id);
+          } else {
+            this.addWidgetToArea(widget.id, widget.defaultArea);
+          }
+        }
+
+        this.endBatchUpdate(true);
+      }
+    }
+
+    return widget.id;
+  },
+
+  createBuiltinWidget: function(aData) {
+    // This should only ever be called on startup, before any windows are
+    // openned - so we know there's no build areas to handle. Also, builtin
+    // widgets are expected to be (mostly) static, so shouldn't affect the
+    // current placement settings.
+    let widget = this.normalizeWidget(aData, CustomizableUI.SOURCE_BUILTIN);
+    if (!widget) {
+      ERROR("Error creating builtin widget: " + aData.id);
+      return;
+    }
+
+    LOG("Creating built-in widget with id: " + widget.id);
+    gPalette.set(widget.id, widget);
+  },
+
+  // Returns true if the area will eventually lazily restore (but hasn't yet).
+  isAreaLazy: function(aArea) {
+    if (gPlacements.has(aArea)) {
+      return false;
+    }
+    return gAreas.get(aArea).has("legacy");
+  },
+
+  //XXXunf Log some warnings here, when the data provided isn't up to scratch.
+  normalizeWidget: function(aData, aSource) {
+    let widget = {
+      source: aSource || "addon",
+      instances: new Map(),
+      currentArea: null,
+      defaultArea: null,
+      allowedAreas: [],
+      shortcut: null,
+      description: null,
+      icons: {}
+    };
+
+    if (typeof aData.id != "string" || !/^[a-z0-9-_]{1,}$/i.test(aData.id)) {
+      ERROR("Given an illegal id in normalizeWidget: " + aData.id);
+      return null;
+    }
+
+    const kReqStringProps = ["id", "name"];
+    for (let prop of kReqStringProps) {
+      if (typeof aData[prop] != "string") {
+        return null;
+      }
+      widget[prop] = aData[prop];
+    }
+
+    const kOptStringProps = ["description", "shortcut"];
+    for (let prop of kOptStringProps) {
+      if (typeof aData[prop] == "string") {
+        widget[prop] = aData[prop];
+      }
+    }
+
+    if (aData.defaultArea && gAreas.has(aData.defaultArea)) {
+      widget.defaultArea = aData.defaultArea;
+    }
+
+    if (Array.isArray(aData.allowedAreas)) {
+      widget.allowedAreas =
+        [area for (area of aData.allowedAreas) if (gAreas.has(area))];
+    }
+
+    if ("type" in aData && gSupportedWidgetTypes.has(aData.type)) {
+      widget.type = aData.type;
+    } else {
+      widget.type = "button";
+    }
+
+    widget.disabled = aData.disabled === true;
+
+    if (typeof aData.icons == "object") {
+      let sizes = Object.keys(aData.icons);
+      for (let size of sizes) {
+        if (size == parseInt(size, 10)) {
+          widget.icons[size] = aData.icons[size];
+        }
+      }
+    }
+
+    if (widget.type == "button") {
+      widget.onCommand = typeof aData.onCommand == "function" ?
+                           aData.onCommand :
+                           null;
+    } else if (widget.type == "view") {
+      if (typeof aData.viewId != "string") {
+        ERROR("Expected a string for widget " + widget.id + " viewId, but got "
+              + aData.viewId);
+        return null;
+      }
+      widget.viewId = aData.viewId;
+
+      widget.onViewShowing = typeof aData.onViewShowing == "function" ?
+                                 aData.onViewShowing :
+                                 null;
+      widget.onViewHiding = typeof aData.onViewHiding == "function" ? 
+                                 aData.onViewHiding :
+                                 null;
+    }
+
+    if (gPalette.has(widget.id)) {
+      return null;
+    }
+
+    return widget;
+  },
+
+  destroyWidget: function(aWidgetId) {
+    let widget = gPalette.get(aWidgetId);
+    if (!widget) {
+      return;
+    }
+
+    // This will not remove the widget from gPlacements - we want to keep the
+    // setting so the widget gets put back in it's old position if/when it
+    // returns.
+
+    let area = widget.currentArea;
+    if (area) {
+      let buildArea = gBuildAreas.get(area);
+      for (let buildNode of buildArea) {
+        let widgetNode = buildNode.ownerDocument.getElementById(aWidgetId);
+        if (widgetNode) {
+          widgetNode.parentNode.removeChild(widgetNode);
+        }
+        for (let eventName of kSubviewEvents) {
+          let handler = "on" + eventName;
+          if (typeof widget[handler] == "function") {
+            viewNode.removeEventListener(eventName, widget[handler], false);
+          }
+        }
+      }
+    }
+
+    gPalette.delete(aWidgetId);
+
+    this.notifyListeners("onWidgetDestroyed", aWidgetId);
+  },
+
+  registerManifest: function(aBaseLocation, aData) {
+    let tokens = aData.split(/\s+/);
+    let directive = tokens.shift();
+    if (directive != "widget") {
+      return;
+    }
+
+    for (let [id, widget] of gPalette) {
+      if (widget.source == aBaseLocation.spec) {
+        return; // Already registered.
+      }
+    }
+
+    let uri = NetUtil.newURI(tokens.shift(), null, aBaseLocation);
+
+    dump("\tNew widget! " + uri.spec + "\n");
+
+    let data = "";
+    try {
+      if (uri.schemeIs("jar")) {
+        data = this.readManifestFromJar(uri);
+      } else {
+        data = this.readManifestFromFile(uri);
+      }
+    }
+    catch (e) {
+      Cu.reportError(e);
+      return;
+    }
+    data = JSON.parse(data);
+    data.source = aBaseLocation.spec;
+
+    this.createWidget(data);
+  },
+
+  // readManifestFromJar and readManifestFromFile from ChromeManifestParser.jsm.
+  readManifestFromJar: function(aURI) {
+    let data = "";
+    let entries = [];
+    let readers = [];
+
+    try {
+      // Deconstrict URI, which can be nested jar: URIs. 
+      let uri = aURI.clone();
+      while (uri instanceof Ci.nsIJARURI) {
+        entries.push(uri.JAREntry);
+        uri = uri.JARFile;
+      }
+
+      // Open the base jar.
+      let reader = Cc["@mozilla.org/libjar/zip-reader;1"]
+                     .createInstance(Ci.nsIZipReader);
+      reader.open(uri.QueryInterface(Ci.nsIFileURL).file);
+      readers.push(reader);
+
+      // Open the nested jars.
+      for (let i = entries.length - 1; i > 0; i--) {
+        let innerReader = Cc["@mozilla.org/libjar/zip-reader;1"].
+                          createInstance(Ci.nsIZipReader);
+        innerReader.openInner(reader, entries[i]);
+        readers.push(innerReader);
+        reader = innerReader;
+      }
+
+      // First entry is the actual file we want to read.
+      let zis = reader.getInputStream(entries[0]);
+      data = NetUtil.readInputStreamToString(zis, zis.available());
+    }
+    finally {
+      // Close readers in reverse order.
+      for (let i = readers.length - 1; i >= 0; i--) {
+        readers[i].close();
+        //XXXunf Don't think this is needed, but need to double check.
+        //flushJarCache(readers[i].file);
+      }
+    }
+
+    return data;
+  },
+
+  readManifestFromFile: function(aURI) {
+    let file = aURI.QueryInterface(Ci.nsIFileURL).file;
+    if (!file.exists() || !file.isFile()) {
+      return "";
+    }
+
+    let data = "";
+    let fis = Cc["@mozilla.org/network/file-input-stream;1"]
+                .createInstance(Ci.nsIFileInputStream);
+    try {
+      fis.init(file, -1, -1, false);
+      data = NetUtil.readInputStreamToString(fis, fis.available());
+    } finally {
+      fis.close();
+    }
+    return data;
+  },
+
+  getCustomizeTargetForArea: function(aArea, aWindow) {
+    let buildAreaNodes = gBuildAreas.get(aArea);
+    if (!buildAreaNodes) {
+      throw new Error("No build area nodes registered for " + aArea);
+    }
+
+    for (let node of buildAreaNodes) {
+      if (node.ownerDocument.defaultView === aWindow) {
+        return node.customizationTarget ? node.customizationTarget : node;
+      }
+    }
+
+    throw new Error("Could not find any window nodes for area " + aArea);
+  },
+
+  reset: function() {
+    Services.prefs.clearUserPref(kPrefCustomizationState);
+    LOG("State reset");
+  },
+
+  _addParentFlex: function(aElement) {
+    // If necessary, add flex to accomodate new child.
+    if (aElement.hasAttribute("flex")) {
+      let parent = aElement.parentNode;
+      let parentFlex = parent.hasAttribute("flex") ? parseInt(parent.getAttribute("flex"), 10) : 0;
+      let elementFlex = parseInt(aElement.getAttribute("flex"), 10);
+      parent.setAttribute("flex", parentFlex + elementFlex);
+    }
+  },
+
+  _removeParentFlex: function(aElement) {
+    if (aElement.parentNode.hasAttribute("flex") && aElement.hasAttribute("flex")) {
+      let parent = aElement.parentNode;
+      let parentFlex = parseInt(parent.getAttribute("flex"), 10);
+      let elementFlex = parseInt(aElement.getAttribute("flex"), 10);
+      parent.setAttribute("flex", Math.max(0, parentFlex - elementFlex));
+    }
+  }
+};
+Object.freeze(CustomizableUIInternal);
+
+this.CustomizableUI = {
+  get AREA_PANEL() "PanelUI-contents",
+  get AREA_NAVBAR() "nav-bar",
+  get AREA_MENUBAR() "toolbar-menubar",
+  get AREA_TABSTRIP() "TabsToolbar",
+  get AREA_BOOKMARKS() "PersonalToolbar",
+
+  get PROVIDER_XUL() "xul",
+  get PROVIDER_API() "api",
+  get PROVIDER_SPECIAL() "special",
+
+  get SOURCE_BUILTIN() "builtin",
+  get SOURCE_EXTERNAL() "external",
+
+  get TYPE_BUTTON() "button",
+
+  addListener: function(aListener) {
+    CustomizableUIInternal.addListener(aListener);
+  },
+  removeListener: function(aListener) {
+    CustomizableUIInternal.removeListener(aListener);
+  },
+  registerArea: function(aName, aProperties) {
+    CustomizableUIInternal.registerArea(aName, aProperties);
+  },
+  //XXXunf registerToolbarNode / registerToolbarInstance ?
+  registerToolbar: function(aToolbar) {
+    CustomizableUIInternal.registerToolbar(aToolbar);
+  },
+  registerMenuPanel: function(aPanel) {
+    CustomizableUIInternal.registerMenuPanel(aPanel);
+  },
+  addWidgetToArea: function(aWidgetId, aArea, aPosition) {
+    CustomizableUIInternal.addWidgetToArea(aWidgetId, aArea, aPosition);
+  },
+  removeWidgetFromArea: function(aWidgetId) {
+    CustomizableUIInternal.removeWidgetFromArea(aWidgetId);
+  },
+  moveWidgetWithinArea: function(aWidgetId, aPosition) {
+    CustomizableUIInternal.moveWidgetWithinArea(aWidgetId, aPosition);
+  },
+  beginBatchUpdate: function() {
+    CustomizableUIInternal.beginBatchUpdate();
+  },
+  endBatchUpdate: function(aForceSave) {
+    CustomizableUIInternal.endBatchUpdate(aForceSave);
+  },
+  createWidget: function(aProperties) {
+    return CustomizableUIInternal.wrapWidget(
+      CustomizableUIInternal.createWidget(aProperties)
+    );
+  },
+  destroyWidget: function(aWidgetId) {
+    CustomizableUIInternal.destroyWidget(aWidgetId);
+  },
+  getWidget: function(aWidgetId) {
+    return CustomizableUIInternal.wrapWidget(aWidgetId);
+  },
+  getUnusedWidgets: function(aWindowPalette) {
+    return CustomizableUIInternal.getUnusedWidgets(aWindowPalette).map(
+      CustomizableUIInternal.wrapWidget,
+      CustomizableUIInternal
+    );
+  },
+  getWidgetsInArea: function(aArea) {
+    if (!gAreas.has(aArea)) {
+      throw new Error("Unknown customization area: " + aArea);
+    }
+    if (!gPlacements.has(aArea)) {
+      throw new Error("Area not yet restored");
+    }
+
+    return gPlacements.get(aArea).map(
+      CustomizableUIInternal.wrapWidget,
+      CustomizableUIInternal
+    );
+  },
+  get areas() {
+    return [area for ([area, props] of gAreas)];
+  },
+  getCustomizeTargetForArea: function(aArea, aWindow) {
+    return CustomizableUIInternal.getCustomizeTargetForArea(aArea, aWindow);
+  },
+  reset: function() {
+    CustomizableUIInternal.reset();
+  },
+  getPlacementOfWidget: function(aWidgetId) {
+    return CustomizableUIInternal.getPlacementOfWidget(aWidgetId);
+  }
+};
+Object.freeze(this.CustomizableUI);
+
+
+/**
+ * All external consumers of widgets are really interacting with these wrappers
+ * which provide a common interface.
+ */
+
+/**
+ * WidgetGroupWrapper is the common interface for interacting with an entire
+ * widget group - AKA, all instances of a widget across a series of windows.
+ * This particular wrapper is only used for widgets created via the provider
+ * API.
+ */
+function WidgetGroupWrapper(aWidget) {
+  this.isGroup = true;
+
+  const kBareProps = ["id", "source", "type", "disabled", "name", "description"];
+  for (let prop of kBareProps) {
+    let propertyName = prop;
+    this.__defineGetter__(propertyName, function() aWidget[propertyName]);
+  }
+
+  this.__defineGetter__("provider", function() CustomizableUI.PROVIDER_API);
+
+  this.__defineSetter__("disabled", function(aValue) {
+    aValue = !!aValue;
+    aWidget.disabled = aValue;
+    for (let [,instance] of aWidget.instances) {
+      instance.disabled = aValue;
+    }
+  });
+  
+  this.forWindow = function WidgetGroupWrapper_forWindow(aWindow) {
+    let instance = aWidget.instances.get(aWindow.document);
+    if (!instance) {
+      instance = CustomizableUIInternal.buildWidget(aWindow.document,
+                                                    null,
+                                                    aWidget);
+    }
+
+    let wrapper = gWrapperCache.get(instance);
+    if (!wrapper) {
+      wrapper = new WidgetSingleWrapper(aWidget, instance);
+      gWrapperCache.set(instance, wrapper);
+    }
+    return wrapper;
+  };
+
+  Object.freeze(this);
+}
+
+/**
+ * A WidgetSingleWrapper is a wrapper around a single instance of a widget in
+ * a particular window.
+ */
+function WidgetSingleWrapper(aWidget, aNode) {
+  this.isGroup = false;
+
+  this.node = aNode;
+  this.provider = CustomizableUI.PROVIDER_API;
+
+  const kGlobalProps = ["id", "type"];
+  for (let prop of kGlobalProps) {
+    this[prop] = aWidget[prop];
+  }
+
+  const nodeProps = ["label", "description"];
+  for (let prop of nodeProps) {
+    let propertyName = prop;
+    // Look at the node for these, instead of the widget data, to ensure the
+    // wrapper always reflects this live instance.
+    this.__defineGetter__(propertyName,
+                          function() aNode.getAttribute(propertyName));
+  }
+
+  this.__defineGetter__("disabled", function() aNode.disabled);
+  this.__defineSetter__("disabled", function(aValue) {
+    aNode.disabled = !!aValue;
+  });
+
+  Object.freeze(this);
+}
+
+/**
+ * XULWidgetGroupWrapper is the common interface for interacting with an entire
+ * widget group - AKA, all instances of a widget across a series of windows.
+ * This particular wrapper is only used for widgets created via the old-school
+ * XUL method (overlays, or programmatically injecting toolbaritems, or other
+ * such things).
+ */
+//XXXunf Going to need to hook this up to some events to keep it all live.
+function XULWidgetGroupWrapper(aWidgetId) {
+  this.isGroup = true;
+
+  let nodes = [];
+
+  let placement = CustomizableUIInternal.getPlacementOfWidget(aWidgetId);
+  if (placement) {
+    let buildAreas = gBuildAreas.get(placement.area) || [];
+    for (let areaNode of buildAreas)
+      nodes.push(areaNode.ownerDocument.getElementById(aWidgetId));
+  }
+
+  this.id = aWidgetId;
+  this.type = "custom";
+  this.provider = CustomizableUI.PROVIDER_XUL;
+
+  this.forWindow = function XULWidgetGroupWrapper_forWindow(aWindow) {
+    let instance = aWindow.document.getElementById(aWidgetId);
+    if (!instance) {
+      // Toolbar palettes aren't part of the document, so elements in there
+      // won't be found via document.getElementById().
+      instance = aWindow.gNavToolbox.palette.querySelector("#" + aWidgetId);
+    }
+
+    let wrapper = gWrapperCache.get(instance);
+    if (!wrapper) {
+      wrapper = new XULWidgetSingleWrapper(aWidgetId, instance);
+      gWrapperCache.set(instance, wrapper);
+    }
+    return wrapper;
+  };
+
+  Object.freeze(this);
+}
+
+/**
+ * A XULWidgetSingleWrapper is a wrapper around a single instance of a XUL 
+ * widget in a particular window.
+ */
+function XULWidgetSingleWrapper(aWidgetId, aNode) {
+  this.isGroup = false;
+
+  this.id = aWidgetId;
+  this.type = "custom";
+  this.provider = CustomizableUI.PROVIDER_XUL;
+
+  this.node = aNode;
+
+  Object.freeze(this);
+}
+
+
+CustomizableUIInternal.initialize();
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/src/CustomizeMode.jsm
@@ -0,0 +1,759 @@
+/* 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 = ["CustomizeMode"];
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+const kPrefCustomizationDebug = "browser.uiCustomization.debug";
+const kPaletteId = "customization-palette";
+const kAboutURI = "about:customizing";
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource:///modules/CustomizableUI.jsm");
+
+let gDebug = false;
+try {
+  gDebug = Services.prefs.getBoolPref(kPrefCustomizationDebug);
+} catch (e) {}
+
+function LOG(str) {
+  if (gDebug) {
+    Services.console.logStringMessage("[CustomizeMode] " + str);
+  }
+}
+
+function ERROR(aMsg) Cu.reportError("[CustomizeMode] " + aMsg);
+
+function CustomizeMode(aWindow) {
+  this.window = aWindow;
+  this.document = aWindow.document;
+  this.browser = aWindow.gBrowser;
+};
+
+CustomizeMode.prototype = {
+  _changed: false,
+  window: null,
+  document: null,
+  // areas is used to cache the customizable areas when in customization mode.
+  areas: null,
+  // When in customizing mode, we swap out the reference to the invisible
+  // palette in gNavToolbox.palette for our visiblePalette. This way, for the
+  // customizing browser window, when widgets are removed from customizable
+  // areas and added to the palette, they're added to the visible palette.
+  // _stowedPalette is a reference to the old invisible palette so we can
+  // restore gNavToolbox.palette to its original state after exiting
+  // customization mode.
+  _stowedPalette: null,
+  _dragOverItem: null,
+  _customizing: false,
+
+  init: function() {
+    // There are two palettes - there's the palette that can be overlayed with
+    // toolbar items in browser.xul. This is invisible, and never seen by the
+    // user. Then there's the visible palette, which gets populated and displayed
+    // to the user when in customizing mode.
+    this.visiblePalette = this.document.getElementById(kPaletteId);
+
+    this.browser.tabContainer.addEventListener("TabSelect", this, false);
+    this.browser.addTabsProgressListener(this);
+  },
+
+  uninit: function() {
+    this.browser.tabContainer.removeEventListener("TabSelect", this, false);
+    this.browser.removeTabsProgressListener(this);
+  },
+
+  enter: function() {
+    if (this._customizing) {
+      return;
+    }
+
+    let window = this.window;
+    let document = this.document;
+
+    // We don't need to switch to kAboutURI, or open a new tab at
+    // kAboutURI if we're already on it.
+    if (this.browser.selectedBrowser.currentURI.spec != kAboutURI) {
+      this.window.switchToTabHavingURI(kAboutURI, true);
+    }
+
+    CustomizableUI.addListener(this);
+
+    // The menu panel is lazy, and registers itself when the popup shows. We
+    // need to force the menu panel to register itself, or else customization
+    // is really not going to work.
+    window.PanelUI.ensureRegistered();
+
+    // Add a keypress listener and click listener to the tab-view-deck so that
+    // we can quickly exit customization mode when pressing ESC or clicking on
+    // the blueprint outside the customization container.
+    let deck = document.getElementById("tab-view-deck");
+    deck.addEventListener("keypress", this, false);
+    deck.addEventListener("click", this, false);
+
+    // Same goes for the menu button - if we're customizing, a click to the
+    // menu button means a quick exit from customization mode.
+    window.PanelUI.menuButton.addEventListener("click", this, false);
+    window.PanelUI.menuButton.disabled = true;
+
+    // Let everybody in this window know that we're about to customize.
+    let evt = document.createEvent("CustomEvent");
+    evt.initCustomEvent("CustomizationStart", true, true, window);
+    window.dispatchEvent(evt);
+
+    let customizer = document.getElementById("customization-container");
+    customizer.parentNode.selectedPanel = customizer;
+
+    window.PanelUI.hide();
+    // Move the mainView in the panel to the holder so that we can see it
+    // while customizing.
+    let panelHolder = document.getElementById("customization-panelHolder");
+    panelHolder.appendChild(window.PanelUI.mainView);
+
+
+    let self = this;
+    deck.addEventListener("transitionend", function customizeTransitionEnd() {
+      deck.removeEventListener("transitionend", customizeTransitionEnd);
+
+      // Add drag-and-drop event handlers to all of the customizable areas.
+      self.areas = [];
+      for (let area of CustomizableUI.areas) {
+        let target = CustomizableUI.getCustomizeTargetForArea(area, window);
+        target.addEventListener("dragstart", self);
+        target.addEventListener("dragover", self);
+        target.addEventListener("dragexit", self);
+        target.addEventListener("drop", self);
+        for (let child of target.children) {
+          if (self.isCustomizableItem(child)) {
+            self.wrapToolbarItem(child, getPlaceForItem(child));
+          }
+        }
+        self.areas.push(target);
+      }
+
+      self.populatePalette();
+    });
+
+    this.visiblePalette.addEventListener("dragstart", this);
+    this.visiblePalette.addEventListener("dragover", this);
+    this.visiblePalette.addEventListener("dragexit", this);
+    this.visiblePalette.addEventListener("drop", this);
+
+    document.documentElement.setAttribute("customizing", true);
+    this._customizing = true;
+  },
+
+  exit: function() {
+    if (!this._customizing) {
+      return;
+    }
+
+    CustomizableUI.removeListener(this);
+
+    let deck = this.document.getElementById("tab-view-deck");
+    deck.removeEventListener("keypress", this, false);
+    deck.removeEventListener("click", this, false);
+    this.window.PanelUI.menuButton.removeEventListener("click", this, false);
+    this.window.PanelUI.menuButton.disabled = false;
+
+    this.depopulatePalette();
+
+    this.visiblePalette.removeEventListener("dragstart", this);
+    this.visiblePalette.removeEventListener("dragover", this);
+    this.visiblePalette.removeEventListener("dragexit", this);
+    this.visiblePalette.removeEventListener("drop", this);
+
+    let window = this.window;
+    let document = this.document;
+
+    let documentElement = document.documentElement;
+    documentElement.setAttribute("customize-exiting", "true");
+    let tabViewDeck = document.getElementById("tab-view-deck");
+    tabViewDeck.addEventListener("transitionend", function onTransitionEnd(evt) {
+      if (evt.propertyName != "padding-top")
+        return;
+      tabViewDeck.removeEventListener("transitionend", onTransitionEnd);
+      documentElement.removeAttribute("customize-exiting");
+    });
+    documentElement.removeAttribute("customizing");
+
+    for (let target of this.areas) {
+      for (let toolbarItem of target.children) {
+        if (this.isWrappedToolbarItem(toolbarItem)) {
+          this.unwrapToolbarItem(toolbarItem);
+        }
+      }
+      target.removeEventListener("dragstart", this);
+      target.removeEventListener("dragover", this);
+      target.removeEventListener("dragexit", this);
+      target.removeEventListener("drop", this);
+    }
+
+    if (this._changed) {
+      // XXXmconley: At first, it seems strange to also persist the old way with
+      //             currentset - but this might actually be useful for switching
+      //             to old builds. We might want to keep this around for a little
+      //             bit.
+      this.persistCurrentSets();
+    }
+
+    // And drop all area references.
+    this.areas = [];
+
+    // Let everybody in this window know that we're finished customizing.
+    let evt = document.createEvent("CustomEvent");
+    evt.initCustomEvent("CustomizationEnd", true, true, {changed: this._changed});
+    window.dispatchEvent(evt);
+
+    window.PanelUI.replaceMainView(window.PanelUI.mainView);
+
+    let browser = document.getElementById("browser");
+    browser.parentNode.selectedPanel = browser;
+
+    // We need to set this._customizing to false before removing the tab
+    // or the TabSelect event handler will think that we are exiting
+    // customization mode for a second time.
+    this._customizing = false;
+
+    if (this.browser.selectedBrowser.currentURI.spec == kAboutURI) {
+      let custBrowser = this.browser.selectedBrowser;
+      if (custBrowser.canGoBack) {
+        // If there's history to this tab, just go back.
+        custBrowser.goBack();
+      } else {
+        let customizationTab = this.browser.selectedTab;
+        if (this.browser.browsers.length == 1) {
+          this.window.BrowserOpenTab();
+        }
+        this.browser.removeTab(customizationTab);
+      }
+    }
+
+    this._changed = false;
+  },
+
+  populatePalette: function() {
+    let toolboxPalette = this.window.gNavToolbox.palette;
+
+    let unusedWidgets = CustomizableUI.getUnusedWidgets(toolboxPalette);
+    for (let widget of unusedWidgets) {
+      let paletteItem = this.makePaletteItem(widget, "palette");
+      this.visiblePalette.appendChild(paletteItem);
+    }
+
+    this._stowedPalette = this.window.gNavToolbox.palette;
+    this.window.gNavToolbox.palette = this.visiblePalette;
+  },
+
+  //XXXunf Maybe this should use -moz-element instead of wrapping the node?
+  //       Would ensure no weird interactions/event handling from original node,
+  //       and makes it possible to put this in a lazy-loaded iframe/real tab
+  //       while still getting rid of the need for overlays.
+  makePaletteItem: function(aWidget, aPlace) {
+    let widgetNode = aWidget.forWindow(this.window).node;
+    let wrapper = this.createWrapper(widgetNode, aPlace);
+    wrapper.appendChild(widgetNode);
+    return wrapper;
+  },
+
+  depopulatePalette: function() {
+    let wrapper = this.visiblePalette.firstChild;
+
+    while (wrapper) {
+      let widgetNode = wrapper.firstChild;
+
+      let provider = CustomizableUI.getWidget(widgetNode.id);
+      // If provider is PROVIDER_SPECIAL, then it just gets thrown away.
+      if (provider = CustomizableUI.PROVIDER_XUL) {
+        if (wrapper.hasAttribute("itemdisabled")) {
+          widgetNode.disabled = true;
+        }
+
+        if (wrapper.hasAttribute("itemchecked")) {
+          widgetNode.checked = true;
+        }
+
+        if (wrapper.hasAttribute("itemcommand")) {
+          let commandID = wrapper.getAttribute("itemcommand");
+          widgetNode.setAttribute("command", commandID);
+
+          // Ensure node is in sync with its command after customizing.
+          let command = this.document.getElementById(commandID);
+          if (command && command.hasAttribute("disabled")) {
+            widgetNode.setAttribute("disabled",
+                                    command.getAttribute("disabled"));
+          }
+        }
+
+        this._stowedPalette.appendChild(widgetNode);
+      } else if (provider = CustomizableUI.PROVIDER_API) {
+        //XXXunf Currently this doesn't destroy the (now unused) node. It would
+        //       be good to do so, but we need to keep strong refs to it in
+        //       CustomizableUI (can't iterate of WeakMaps), and there's the
+        //       question of what behavior wrappers should have if consumers
+        //       keep hold of them.
+        //widget.destroyInstance(widgetNode);
+      }
+
+      this.visiblePalette.removeChild(wrapper);
+      wrapper = this.visiblePalette.firstChild;
+    }
+    this.window.gNavToolbox.palette = this._stowedPalette;
+  },
+
+  isCustomizableItem: function(aNode) {
+    return aNode.localName == "toolbarbutton" ||
+           aNode.localName == "toolbaritem" ||
+           aNode.localName == "toolbarseparator" ||
+           aNode.localName == "toolbarspring" ||
+           aNode.localName == "toolbarspacer";
+  },
+
+  isWrappedToolbarItem: function(aNode) {
+    return aNode.localName == "toolbarpaletteitem";
+  },
+
+  wrapToolbarItem: function(aNode, aPlace) {
+    let wrapper = this.createWrapper(aNode, aPlace);
+    // It's possible that this toolbar node is "mid-flight" and doesn't have
+    // a parent, in which case we skip replacing it. This can happen if a
+    // toolbar item has been dragged into the palette. In that case, we tell
+    // CustomizableUI to remove the widget from its area before putting the
+    // widget in the palette - so the node will have no parent.
+    if (aNode.parentNode) {
+      aNode = aNode.parentNode.replaceChild(wrapper, aNode);
+    }
+    wrapper.appendChild(aNode);
+    return wrapper;
+  },
+
+  createWrapper: function(aNode, aPlace) {
+    let wrapper = this.document.createElement("toolbarpaletteitem");
+
+    // "place" is used by toolkit to add the toolbarpaletteitem-palette
+    // binding to a toolbarpaletteitem, which gives it a label node for when
+    // it's sitting in the palette.
+    wrapper.setAttribute("place", aPlace);
+
+    // Ensure the wrapped item doesn't look like it's in any special state, and
+    // can't be interactved with when in the customization palette.
+    if (aNode.hasAttribute("command")) {
+      wrapper.setAttribute("itemcommand", aNode.getAttribute("command"));
+      aNode.removeAttribute("command");
+    }
+
+    if (aNode.checked) {
+      wrapper.setAttribute("itemchecked", "true");
+      aNode.checked = false;
+    }
+
+    if (aNode.disabled) {
+      wrapper.setAttribute("itemdisabled", "true");
+      aNode.disabled = false;
+    }
+
+    if (aNode.hasAttribute("id")) {
+      wrapper.setAttribute("id", "wrapper-" + aNode.getAttribute("id"));
+    }
+
+    if (aNode.hasAttribute("title")) {
+      wrapper.setAttribute("title", aNode.getAttribute("title"));
+    } else if (aNode.hasAttribute("label")) {
+      wrapper.setAttribute("title", aNode.getAttribute("label"));
+    }
+
+    if (aNode.hasAttribute("flex")) {
+      wrapper.setAttribute("flex", aNode.getAttribute("flex"));
+    }
+
+    wrapper.addEventListener("mousedown", this);
+    wrapper.addEventListener("mouseup", this);
+
+    return wrapper;
+  },
+
+  unwrapToolbarItem: function(aWrapper) {
+    aWrapper.removeEventListener("mousedown", this);
+    aWrapper.removeEventListener("mouseup", this);
+
+    let toolbarItem = aWrapper.firstChild;
+
+    if (aWrapper.hasAttribute("itemdisabled")) {
+      toolbarItem.disabled = true;
+    }
+
+    if (aWrapper.hasAttribute("itemchecked")) {
+      toolbarItem.checked = true;
+    }
+
+    if (aWrapper.hasAttribute("itemcommand")) {
+      let commandID = aWrapper.getAttribute("itemcommand");
+      toolbarItem.setAttribute("command", commandID);
+
+      //XXX Bug 309953 - toolbarbuttons aren't in sync with their commands after customizing
+      let command = this.document.getElementById(commandID);
+      if (command && command.hasAttribute("disabled")) {
+        toolbarItem.setAttribute("disabled", command.getAttribute("disabled"));
+      }
+    }
+
+    if (aWrapper.parentNode) {
+      aWrapper.parentNode.replaceChild(toolbarItem, aWrapper);
+    }
+    return toolbarItem;
+  },
+
+  persistCurrentSets: function()  {
+    let document = this.document;
+    let toolbars = document.querySelectorAll("toolbar[customizable='true']");
+    for (let toolbar of toolbars) {
+      let set = toolbar.currentSet;
+      toolbar.setAttribute("currentset", set);
+      LOG("Setting currentset of " + toolbar.id + " as " + set);
+      // Persist the currentset attribute directly on hardcoded toolbars.
+      document.persist(toolbar.id, "currentset");
+    }
+  },
+
+  reset: function() {
+    CustomizableUI.reset();
+  },
+
+  onWidgetMoved: function(aWidgetId, aArea, aOldPosition, aNewPosition) {
+    this._changed = true;
+  },
+
+  onWidgetAdded: function(aWidgetId, aArea, aPosition) {
+    this._changed = true;
+  },
+
+  onWidgetRemoved: function(aWidgetId, aArea) {
+    this._changed = true;
+  },
+
+  onWidgetCreated: function(aWidgetId) {
+  },
+
+  onWidgetDestroyed: function(aWidgetId) {
+  },
+
+  handleEvent: function(aEvent) {
+    switch(aEvent.type) {
+      case "dragstart":
+        this._onDragStart(aEvent);
+        break;
+      case "dragover":
+        this._onDragOver(aEvent);
+        break;
+      case "drop":
+        this._onDragDrop(aEvent);
+        break;
+      case "dragexit":
+        this._onDragExit(aEvent);
+        break;
+      case "mousedown":
+        this._onMouseDown(aEvent);
+        break;
+      case "mouseup":
+        this._onMouseUp(aEvent);
+        break;
+      case "keypress":
+        if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
+          this.exit();
+        }
+        break;
+      case "click":
+        if (aEvent.button == 0 &&
+            (aEvent.originalTarget == this.window.PanelUI.menuButton) ||
+            (aEvent.originalTarget == this.document.getElementById("tab-view-deck"))) {
+          this.exit();
+          aEvent.preventDefault();
+        }
+        break;
+      case "TabSelect":
+        this._onTabSelect(aEvent);
+        break;
+    }
+  },
+
+  _onDragStart: function(aEvent) {
+    __dumpDragData(aEvent);
+    let item = aEvent.target;
+    while (item && item.localName != "toolbarpaletteitem") {
+      if (item.localName == "toolbar") {
+        return;
+      }
+      item = item.parentNode;
+    }
+
+    let dt = aEvent.dataTransfer;
+    let documentId = aEvent.target.ownerDocument.documentElement.id;
+    dt.setData("text/toolbarwrapper-id/" + documentId, item.firstChild.id);
+    dt.effectAllowed = "move";
+  },
+
+  _onDragOver: function(aEvent) {
+    __dumpDragData(aEvent);
+
+    let document = aEvent.target.ownerDocument;
+    let documentId = document.documentElement.id;
+    if (!aEvent.dataTransfer.types.contains("text/toolbarwrapper-id/"
+                                            + documentId.toLowerCase())) {
+      return;
+    }
+
+    let draggedItemId = aEvent.dataTransfer.getData("text/toolbarwrapper-id/" + documentId);
+    let draggedWrapper = document.getElementById("wrapper-" + draggedItemId);
+    let targetNode = aEvent.target;
+    let targetParent = targetNode.parentNode;
+    let targetArea = this._getCustomizableParent(targetNode);
+    let originArea = this._getCustomizableParent(draggedWrapper);
+
+    // Do nothing if the target or origin are not customizable.
+    if (!targetArea || !originArea) {
+      gCurrentDragOverItem = null;
+      return;
+    }
+
+    // We need to determine the place that the widget is being dropped in
+    // the target.
+    let position = Array.indexOf(targetParent.children, targetNode);
+    let dragOverItem = position == -1 ? targetParent.lastChild : targetParent.children[position];
+
+    if (this._dragOverItem && dragOverItem != this._dragOverItem) {
+      this._setDragActive(this._dragOverItem, false);
+    }
+
+    // XXXjaws Only handling the toolbar case first.
+    if (targetArea.localName == "toolbar") {
+      this._setDragActive(dragOverItem, true);
+    }
+    this._dragOverItem = dragOverItem;
+
+    aEvent.preventDefault();
+    aEvent.stopPropagation();
+  },
+
+  _onDragDrop: function(aEvent) {
+    __dumpDragData(aEvent);
+
+    this._setDragActive(this._dragOverItem, false);
+
+    let document = aEvent.target.ownerDocument;
+    let documentId = document.documentElement.id;
+    let draggedItemId = aEvent.dataTransfer.getData("text/toolbarwrapper-id/" + documentId);
+    let draggedWrapper = document.getElementById("wrapper-" + draggedItemId);
+
+    draggedWrapper.removeAttribute("mousedown");
+
+    let targetNode = aEvent.target;
+    let targetParent = targetNode.parentNode;
+    let targetArea = this._getCustomizableParent(targetNode);
+    let originArea = this._getCustomizableParent(draggedWrapper);
+
+    // Do nothing if the target area or origin area are not customizable.
+    if (!targetArea || !originArea) {
+      return;
+    }
+
+    // Do nothing if the target was dropped onto itself (ie, no change in area
+    // or position).
+    if (draggedWrapper == targetNode) {
+      return;
+    }
+
+    // Is the target area the customization palette? If so, we have two cases -
+    // either the originArea was the palette, or a customizable area.
+    if (targetArea.id == kPaletteId) {
+      if (originArea.id !== kPaletteId) {
+        let widget = this.unwrapToolbarItem(draggedWrapper);
+        CustomizableUI.removeWidgetFromArea(draggedItemId);
+        draggedWrapper = this.wrapToolbarItem(widget, "palette");
+      }
+
+      // If the targetNode is the palette itself, just append
+      if (targetNode == this.visiblePalette) {
+        this.visiblePalette.appendChild(draggedWrapper);
+      } else {
+        this.visiblePalette.insertBefore(draggedWrapper, targetNode);
+      }
+      return;
+    }
+
+    // Is the target the customization area itself? If so, we just add the
+    // widget to the end of the area.
+    if (targetNode == targetArea.customizationTarget) {
+      let widget = this.unwrapToolbarItem(draggedWrapper);
+      CustomizableUI.addWidgetToArea(draggedItemId, targetArea.id);
+      this.wrapToolbarItem(widget, getPlaceForItem(targetNode));
+      return;
+    }
+
+    // We need to determine the place that the widget is being dropped in
+    // the target.
+    let placement = CustomizableUI.getPlacementOfWidget(targetNode.firstChild.id);
+    if (!placement) {
+      ERROR("Could not get a position for " + targetNode.firstChild.id);
+      return;
+    }
+
+    let position = placement.position;
+
+    // Is the target area the same as the origin? Since we've already handled
+    // the possibility that the target is the customization palette, we know
+    // that the widget is moving within a customizable area.
+    if (targetArea == originArea) {
+      let properPlace = getPlaceForItem(targetNode);
+      // We unwrap the moving widget, as well as the widget that we're dropping
+      // on (the target) so that moveWidgetWithinArea can correctly insert the
+      // moving widget before the target widget.
+      let widget = this.unwrapToolbarItem(draggedWrapper);
+      let targetWidget = this.unwrapToolbarItem(targetNode);
+      CustomizableUI.moveWidgetWithinArea(draggedItemId, position);
+      this.wrapToolbarItem(targetWidget, properPlace);
+      this.wrapToolbarItem(widget, properPlace);
+      return;
+    }
+
+    // A little hackery - we quickly unwrap the item and use CustomizableUI's
+    // addWidgetToArea to move the widget to the right place for every window,
+    // then we re-wrap the widget. We have to unwrap the target widget too so
+    // that addWidgetToArea inserts the new widget into the right place.
+    let properPlace = getPlaceForItem(targetNode);
+    let widget = this.unwrapToolbarItem(draggedWrapper);
+    let targetWidget = this.unwrapToolbarItem(targetNode);
+    CustomizableUI.addWidgetToArea(draggedItemId, targetArea.id, position);
+    this.wrapToolbarItem(targetWidget, properPlace);
+    draggedWrapper = this.wrapToolbarItem(widget, properPlace);
+  },
+
+  _onDragExit: function(aEvent) {
+    if (this._dragOverItem) {
+      this._setDragActive(this._dragOverItem, false);
+    }
+  },
+
+  // XXXjaws Show a ghost image or blank area where the item could be added, instead of black bar
+  _setDragActive: function(aItem, aValue) {
+    let node = aItem;
+    let window = aItem.ownerDocument.defaultView;
+    let direction = window.getComputedStyle(aItem, null).direction;
+    let value = direction == "ltr"? "left" : "right";
+    if (aItem.localName == "toolbar") {
+      node = aItem.lastChild;
+      value = direction == "ltr"? "right" : "left";
+    }
+
+    if (!node) {
+      return;
+    }
+
+    if (aValue) {
+      if (!node.hasAttribute("dragover")) {
+        node.setAttribute("dragover", value);
+      }
+    } else {
+      node.removeAttribute("dragover");
+    }
+  },
+
+  _getCustomizableParent: function(aElement) {
+    let areas = CustomizableUI.areas;
+    areas.push(kPaletteId);
+    while (aElement) {
+      if (areas.indexOf(aElement.id) != -1) {
+        return aElement;
+      }
+      aElement = aElement.parentNode;
+    }
+    return null;
+  },
+
+  _onMouseDown: function(aEvent) {
+    let item = this._getWrapper(aEvent.target);
+    if (item) {
+      item.setAttribute("mousedown", "true");
+    }
+  },
+
+  _onMouseUp: function(aEvent) {
+    let item = this._getWrapper(aEvent.target);
+    if (item) {
+      item.removeAttribute("mousedown");
+    }
+  },
+
+  _getWrapper: function(aElement) {
+    while (aElement && aElement.localName != "toolbarpaletteitem") {
+      if (aElement.localName == "toolbar")
+        return null;
+      aElement = aElement.parentNode;
+    }
+    return aElement;
+  },
+
+  _onTabSelect: function(aEvent) {
+    this._toggleCustomizationModeIfNecessary();
+  },
+
+  onLocationChange: function(aBrowser, aProgress, aRequest, aLocation, aFlags) {
+    if (this.browser.selectedBrowser != aBrowser) {
+      return;
+    }
+
+    this._toggleCustomizationModeIfNecessary();
+  },
+
+  /**
+   * Looks at the currently selected browser tab, and if the location
+   * is set to kAboutURI and we're not customizing, enters customize mode.
+   * If we're not at kAboutURI and we are customizing, exits customize mode.
+   */
+  _toggleCustomizationModeIfNecessary: function() {
+    let browser = this.browser.selectedBrowser;
+    if (browser.currentURI.spec == kAboutURI &&
+        !this._customizing) {
+      this.enter();
+    } else if (browser.currentURI.spec != kAboutURI &&
+               this._customizing) {
+      this.exit();
+    }
+  }
+};
+
+function getPlaceForItem(aElement) {
+  let place;
+  let node = aElement;
+  while (node && !place) {
+    if (node.localName == "toolbar")
+      place = "toolbar";
+    else if (node.id == CustomizableUI.AREA_PANEL)
+      place = "panel";
+    else if (node.id == kPaletteId)
+      place = "palette";
+
+    node = node.parentNode;
+  }
+  return place;
+}
+
+function __dumpDragData(aEvent, caller) {
+  let str = "Dumping drag data (CustomizeMode.jsm) {\n";
+  str += "  type: " + aEvent["type"] + "\n";
+  for (let el of ["target", "currentTarget", "relatedTarget"]) {
+    if (aEvent[el]) {
+      str += "  " + el + ": " + aEvent[el] + "(localName=" + aEvent[el].localName + "; id=" + aEvent[el].id + ")\n";
+    }
+  }
+  for (let prop in aEvent.dataTransfer) {
+    if (typeof aEvent.dataTransfer[prop] != "function") {
+      str += "  dataTransfer[" + prop + "]: " + aEvent.dataTransfer[prop] + "\n";
+    }
+  }
+  str += "}";
+  LOG(str);
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/src/Makefile.in
@@ -0,0 +1,17 @@
+# 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/.
+
+DEPTH     = @DEPTH@
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+VPATH     = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+EXTRA_JS_MODULES = \
+  CustomizableUI.jsm \
+  CustomizeMode.jsm \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/src/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/.
+
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -2,16 +2,17 @@
 # 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 += [
     'about',
     'certerror',
+    'customizableui',
     'dirprovider',
     'downloads',
     'feeds',
     'places',
     'preferences',
     'privatebrowsing',
     'search',
     'sessionstore',
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1355,16 +1355,35 @@ BrowserGlue.prototype = {
     if (currentUIVersion < 13) {
       try {
         if (Services.prefs.getBoolPref("plugins.hide_infobar_for_missing_plugin"))
           Services.prefs.setBoolPref("plugins.notifyMissingFlash", false);
       }
       catch (ex) {}
     }
 
+    if (currentUIVersion < 13) {
+      // Migrate users from text or text&icons mode to icons mode.
+      let toolbarResources = [this._rdf.GetResource(BROWSER_DOCURL + "navigator-toolbox"),
+                              this._rdf.GetResource(BROWSER_DOCURL + "nav-bar"),
+                              this._rdf.GetResource(BROWSER_DOCURL + "PersonalToolbar"),
+                              this._rdf.GetResource(BROWSER_DOCURL + "addon-bar")];
+      let modeResource = this._rdf.GetResource("mode");
+      let iconsizeResource = this._rdf.GetResource("iconsize");
+      for (let toolbarResource of toolbarResources) {
+        let toolbarMode = this._getPersist(toolbarResource, modeResource);
+        if (toolbarMode != "icons") {
+          this._setPersist(toolbarResource, modeResource, "icons");
+          // If the user wasn't previously using icons mode, switch
+          // them to the default (large icon mode).
+          this._setPersist(toolbarResource, iconsizeResource, "large");
+        }
+      }
+    }
+
     if (this._dirty)
       this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
 
     delete this._rdf;
     delete this._dataSource;
 
     // Update the migration version.
     Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -10,16 +10,18 @@
 <!-- LOCALIZATION NOTE (mainWindow.titlemodifier) : DONT_TRANSLATE -->
 <!ENTITY mainWindow.titlemodifier "&brandFullName;">
 <!-- LOCALIZATION NOTE (mainWindow.titlemodifiermenuseparator): DONT_TRANSLATE -->
 <!ENTITY mainWindow.titlemodifiermenuseparator " - ">
 <!-- LOCALIZATION NOTE (mainWindow.titlePrivateBrowsingSuffix): This will be appended to the window's title
                                                                 inside the private browsing mode -->
 <!ENTITY mainWindow.titlePrivateBrowsingSuffix "(Private Browsing)">
 
+<!ENTITY appmenu.title                       "Customize and Control &brandFullName;">
+
 <!-- Tab context menu -->
 <!ENTITY  reloadTab.label                    "Reload Tab">
 <!ENTITY  reloadTab.accesskey                "R">
 <!ENTITY  reloadAllTabs.label                "Reload All Tabs">
 <!ENTITY  reloadAllTabs.accesskey            "A">
 <!ENTITY  closeOtherTabs.label               "Close Other Tabs">
 <!ENTITY  closeOtherTabs.accesskey           "o">
 
@@ -155,18 +157,16 @@ These should match what Safari and other
 
 <!ENTITY backForwardItem.title        "Back/Forward">
 <!ENTITY locationItem.title           "Location">
 <!ENTITY searchItem.title             "Search">
 <!ENTITY throbberItem.title           "Activity Indicator">
 <!ENTITY bookmarksItem.title          "Bookmarks">
 
 <!-- Toolbar items --> 
-<!ENTITY appMenuButton.label          "Menu">
-<!ENTITY appMenuButton.tooltip        "Open &brandShortName; menu">
 <!ENTITY homeButton.label             "Home">
 
 <!ENTITY tabGroupsButton.label        "Tab Groups">
 <!ENTITY tabGroupsButton.tooltip      "Group your tabs">
 
 <!ENTITY feedButton.label             "Subscribe">
 <!ENTITY feedButton.tooltip           "Subscribe to this page…">
 
@@ -315,26 +315,20 @@ These should match what Safari and other
 <!-- LOCALIZATION NOTE (historyUndoWindowMenu): see bug 394759 -->
 <!ENTITY historyUndoWindowMenu.label "Recently Closed Windows">
 <!ENTITY historyRestoreLastSession.label "Restore Previous Session">
 
 <!ENTITY historyHomeCmd.label "Home">
 <!ENTITY showAllHistoryCmd2.label "Show All History">
 <!ENTITY showAllHistoryCmd.commandkey "H">
 
-<!ENTITY appMenuEdit.label "Edit">
 <!ENTITY appMenuCustomize.label "Customize">
-<!ENTITY appMenuToolbarLayout.label "Toolbar Layout…">
-<!ENTITY appMenuSidebars.label "Sidebars">
-<!ENTITY appMenuFind.label "Find…">
-<!ENTITY appMenuUnsorted.label "Unsorted Bookmarks">
-<!ENTITY appMenuWebDeveloper.label "Web Developer">
-<!ENTITY appMenuGettingStarted.label "Getting Started">
-<!ENTITY appMenuSafeMode.label "Restart with Add-ons Disabled…">
-<!ENTITY appMenuSafeMode.accesskey "R">
+<!ENTITY appMenuBookmarks.label "Bookmarks">
+<!ENTITY appMenuHistory.label "History">
+<!ENTITY appMenuHistoryMore.label "More…">
 
 <!ENTITY openCmd.commandkey           "l">
 <!ENTITY urlbar.placeholder2          "Search or enter address">
 <!ENTITY urlbar.accesskey             "d">
 <!ENTITY urlbar.switchToTab.label     "Switch to tab:">
 
 <!-- 
   Comment duplicated from browser-sets.inc:
@@ -536,16 +530,19 @@ you can use these alternative items. Oth
 <!ENTITY copyButton.tooltip             "Copy">
 <!ENTITY pasteButton.tooltip            "Paste">
 
 <!ENTITY fullScreenButton.tooltip       "Display the window in full screen">
 
 <!ENTITY zoomOutButton.tooltip          "Zoom out">
 <!ENTITY zoomInButton.tooltip           "Zoom in">
 <!ENTITY zoomControls.label             "Zoom Controls">
+<!ENTITY zoomReset.tooltip              "Reset Zoom">
+<!-- LOCALIZATION NOTE(zoomReset.label): the &#37; is the percent symbol. -->
+<!ENTITY zoomReset.label                "100&#37;">
 
 <!ENTITY quitApplicationCmdWin.label       "Exit"> 
 <!ENTITY quitApplicationCmdWin.accesskey   "x">
 <!ENTITY goBackCmd.commandKey "[">
 <!ENTITY goForwardCmd.commandKey "]">
 <!ENTITY quitApplicationCmd.label       "Quit"> 
 <!ENTITY quitApplicationCmd.accesskey   "Q">
 <!ENTITY quitApplicationCmdMac.label    "Quit &brandShortName;">
@@ -646,16 +643,23 @@ just addresses the organization to follo
 
 <!ENTITY social.activated.description "Services from <label/> have been enabled. You can change your settings for services in the <label class='text-link'>Add-on Manager</label>.">
 <!ENTITY social.activated.undo.label "Oops, undo this!">
 <!ENTITY social.activated.undo.accesskey "U">
 <!ENTITY social.learnMore.label "Learn more…">
 <!ENTITY social.learnMore.accesskey "l">
 <!ENTITY social.closeNotificationItem.label "Not Now">
 
+
+
+<!ENTITY customizeMode.tabTitle "Customize &brandShortName;">
+<!ENTITY customizeMode.menuAndToolbars.label "Menu and toolbars">
+<!ENTITY customizeMode.menuAndToolbars.header "More Tools to Add to the Menu and Toolbar">
+<!ENTITY customizeMode.restoreDefaults "Restore Defaults">
+
 <!ENTITY social.chatBar.commandkey "c">
 <!ENTITY social.chatBar.label "Focus chats">
 <!ENTITY social.chatBar.accesskey "c">
 
 <!-- labels are set dynamically, see browser.properties -->
 <!ENTITY social.markpage.accesskey "m">
 <!ENTITY social.marklink.accesskey "M">
 
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4d0f12492fe643ade04a8ffaf333f7c729fa2f33
GIT binary patch
literal 247
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%``#fD7Ln>~ay|9<>AcIKT!^dVh
zPL~`nny9FX3QF0_hAc6;6tcysgRf4^t^C677rbS5HPZ`DB~%<wuk4)Jec#12dB&70
zX5l8mB0M@P+otl$&VQS#!NoRhkAa_i-U;LXK(-kF7yrj|Uf%a#Q@&=&9fQb=)r%4m
zJYV}6S8siM^qCG&@t?z{rA;&T{*4vkc_Z(0<&5Vdlix9>I)Mfou1K9RHs4iHP}kMe
uxHR{V$Mxmx?%StpNZgq3<I+0kqV!JNQte+wg;Rk(VeoYIb6Mw<&;$VPyJO}6
new file mode 100644
--- /dev/null
+++ b/browser/themes/linux/browser-lightweightTheme.css
@@ -0,0 +1,29 @@
+/* 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/. */
+
+%include linuxShared.inc
+%filter substitution
+
+/*
+ * LightweightThemeListener will append the current lightweight theme's header
+ * image to the background-image for each of the following rulesets.
+ */
+
+/* Lightweight theme on tabs */
+#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[selected=true]:-moz-lwtheme::before,
+#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[selected=true]:-moz-lwtheme::before {
+  background-attachment: scroll, fixed;
+  background-color: transparent;
+  background-image: @fgTabTextureLWT@;/*, lwtHeader;*/
+  background-position: 0 0, right top;
+}
+
+#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
+  background-attachment: scroll, scroll, fixed;
+  background-color: transparent;
+  background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
+                    @fgTabTextureLWT@;/*,
+                    lwtHeader;*/
+  background-position: 0 0, 0 0, right top;
+}
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -5,22 +5,22 @@
 %endif
 
 @import url("chrome://global/skin/");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
 
 %include ../shared/browser.inc
+%include linuxShared.inc
 %filter substitution
-%define toolbarHighlight rgba(255,255,255,.3)
-%define selectedTabHighlight rgba(255,255,255,.8) 1px, rgba(255,255,255,.5) 3px
+
 %define forwardTransitionLength 150ms
-%define conditionalForwardWithUrlbar       window:not([chromehidden~=toolbar]) :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"][mode=icons],                #nav-bar:not([currentset])[mode=icons])                 > #unified-back-forward-button
-%define conditionalForwardWithUrlbar_small window:not([chromehidden~=toolbar]) :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"][mode=icons][iconsize=small],#nav-bar:not([currentset])[mode=icons][iconsize=small]) > #unified-back-forward-button
+%define conditionalForwardWithUrlbar       window:not([chromehidden~=toolbar]) :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"],                #nav-bar:not([currentset]))                 > #nav-bar-customizationtarget > #unified-back-forward-button
+%define conditionalForwardWithUrlbar_small window:not([chromehidden~=toolbar]) :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"][iconsize=small],#nav-bar:not([currentset])[iconsize=small]) > #nav-bar-customizationtarget > #unified-back-forward-button
 %define conditionalForwardWithUrlbarWidth 32
 %define conditionalForwardWithUrlbarWidth_small 24
 
 #menubar-items {
   -moz-box-orient: vertical; /* for flex hack */
 }
 
 #main-menubar {
@@ -86,17 +86,17 @@ toolbarbutton.bookmark-item[open="true"]
   -moz-padding-end: 2px;
 }
 
 .bookmark-item > .toolbarbutton-icon {
   width: 16px;
   height: 16px;
 }
 
-/* Prevent [mode="icons"] from hiding the label */
+/* Force the display of the label for bookmarks */
 .bookmark-item > .toolbarbutton-text {
   display: -moz-box !important;
 }
 
 .bookmark-item > .toolbarbutton-menu-dropmarker {
   display: none;
 }
 
@@ -208,77 +208,68 @@ menuitem.bookmark-item {
   opacity: 0.7;
 }
 
 /* Stock icons for the menu bar items */
 menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
   -moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
 }
 
-#appmenu_newNavigator,
 #placesContext_open\:newwindow,
 #menu_newNavigator,
 #context-openlink,
 #context-openframe {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 80px 16px 64px);
 }
 
-#appmenu_newTab,
-#appmenu_newTab_popup,
 #placesContext_open\:newtab,
 #placesContext_openContainer\:tabs,
 #menu_newNavigatorTab,
 #context-openlinkintab,
 #context-openframeintab {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 64px 16px 48px);
 }
 
-#appmenu_openFile,
 #menu_openFile {
   list-style-image: url("moz-icon://stock/gtk-open?size=menu");
 }
 
 #menu_close {
   list-style-image: url("moz-icon://stock/gtk-close?size=menu");
 }
 
 #context-media-play {
   list-style-image: url("moz-icon://stock/gtk-media-play?size=menu");
 }
 
 #context-media-pause {
   list-style-image: url("moz-icon://stock/gtk-media-pause?size=menu");
 }
 
-#appmenu_savePage,
 #menu_savePage,
 #context-savelink,
 #context-saveimage,
 #context-savevideo,
 #context-saveaudio,
 #context-savepage,
 #context-saveframe {
   list-style-image: url("moz-icon://stock/gtk-save-as?size=menu");
 }
 
-#appmenu_printPreview,
 #menu_printPreview {
   list-style-image: url("moz-icon://stock/gtk-print-preview?size=menu");
 }
 
-#appmenu_print,
-#appmenu_print_popup,
 #menu_print,
 #context-printframe {
   list-style-image: url("moz-icon://stock/gtk-print?size=menu");
 }
 
-#appmenu-quit,
 #menu_FileQuitItem {
   list-style-image: url("moz-icon://stock/gtk-quit?size=menu");
 }
 
 #menu_undo,
 #context-undo {
   list-style-image: url("moz-icon://stock/gtk-undo?size=menu");
 }
@@ -351,27 +342,24 @@ menuitem:not([type]):not(.menuitem-toolt
   list-style-image: url("moz-icon://stock/gtk-delete?size=menu&state=disabled");
 }
 
 #menu_selectAll,
 #context-selectall {
   list-style-image: url("moz-icon://stock/gtk-select-all?size=menu");
 }
 
-#appmenu_find,
 #menu_find {
   list-style-image: url("moz-icon://stock/gtk-find?size=menu");
 }
 
 #menu_find[disabled] {
   list-style-image: url("moz-icon://stock/gtk-find?size=menu&state=disabled");
 }
 
-#appmenu_customize,
-#appmenu_preferences,
 #menu_preferences {
   list-style-image: url("moz-icon://stock/gtk-preferences?size=menu");
 }
 
 #menu_stop,
 #context-stop {
   list-style-image: url("moz-icon://stock/gtk-stop?size=menu");
 }
@@ -444,25 +432,21 @@ menuitem:not([type]):not(.menuitem-toolt
 #context-forward[disabled]:-moz-locale-dir(rtl) {
   list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=menu&state=disabled");
 }
 
 #historyMenuHome {
   list-style-image: url("moz-icon://stock/gtk-home?size=menu");
 }
 
-#appmenu_history,
-#appmenu_showAllHistory,
 #menu_showAllHistory {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 32px 16px 16px);
 }
 
-#appmenu_bookmarks,
-#appmenu_showAllBookmarks,
 #bookmarksShowAll {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 48px 16px 32px);
 }
 
 #subscribeToPageMenuitem:not([disabled]),
 #subscribeToPageMenupopup,
 #BMB_subscribeToPageMenuitem:not([disabled]),
@@ -478,55 +462,47 @@ menuitem:not([type]):not(.menuitem-toolt
 #BMB_bookmarkThisPage {
   list-style-image: url("chrome://browser/skin/places/starPage.png");
 }
 
 #BMB_unsortedBookmarks {
   list-style-image: url("chrome://browser/skin/places/unsortedBookmarks.png");
 }
 
-#appmenu_downloads,
 #menu_openDownloads {
   list-style-image: url("chrome://browser/skin/Toolbar-small.png");
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
-#appmenu_addons,
 #menu_openAddons {
   list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
 }
 
 #menu_pageInfo,
 #context-viewinfo,
 #context-viewframeinfo {
   list-style-image: url("moz-icon://stock/gtk-info?size=menu");
 }
 
-#appmenu_privateBrowsing,
-#appmenu_newPrivateWindow,
 #privateBrowsingItem {
   list-style-image: url("chrome://browser/skin/Privacy-16.png");
 }
 
 #placesContext_show\:info {
   list-style-image: url("moz-icon://stock/gtk-properties?size=menu");
 }
 
-#appmenu_sanitizeHistory,
 #sanitizeItem {
   list-style-image: url("moz-icon://stock/gtk-clear?size=menu");
 }
 
-#appmenu_help,
-#appmenu_openHelp,
 #menu_openHelp {
   list-style-image: url("moz-icon://stock/gtk-help?size=menu");
 }
 
-#appmenu_about,
 #aboutName {
   list-style-image: url("moz-icon://stock/gtk-about?size=menu");
 }
 
 #javascriptConsole {
   list-style-image: url("chrome://global/skin/console/console.png");
 }
 
@@ -536,21 +512,16 @@ menuitem:not([type]):not(.menuitem-toolt
   min-width: 0;
   list-style-image: url("chrome://browser/skin/Toolbar.png");
 }
 
 .toolbarbutton-1 > .toolbarbutton-icon {
   -moz-margin-end: 0;
 }
 
-toolbar[mode="full"] .toolbarbutton-1:not([type="menu-button"]),
-toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
-  min-width: 57px;
-}
-
 .toolbarbutton-1:not([type="menu-button"]),
 .toolbarbutton-1 > .toolbarbutton-menubutton-button {
   padding: 5px;
 }
 
 .toolbarbutton-1[checked="true"] {
   padding: 5px !important;
 }
@@ -1606,135 +1577,57 @@ richlistitem[type~="action"][actiontype=
 
 #navigator-throbber,
 #wrapper-navigator-throbber > #navigator-throbber {
   list-style-image: url("chrome://global/skin/icons/notloading_16.png");
 }
 
 /* Tabstrip */
 
+%include ../shared/tabs.inc.css
+
 #TabsToolbar {
   min-height: 0;
   padding: 0;
 }
 
 #TabsToolbar[tabsontop=true]:not(:-moz-lwtheme) {
   -moz-appearance: menubar;
   color: -moz-menubartext;
+}
+
+#TabsToolbar[tabsontop=true] {
   box-shadow: 0 -1px 0 rgba(0,0,0,.1) inset;
 }
 
 #TabsToolbar[tabsontop=true]:not(:-moz-lwtheme):-moz-system-metric(menubar-drag) {
   -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
 }
 
+#TabsToolbar[tabsontop=true]:not(:-moz-lwtheme) > #tabbrowser-tabs > .tabbrowser-tab:not([selected]) {
+  color: -moz-menubartext;
+}
+
 #TabsToolbar[tabsontop=false] {
   background-image: linear-gradient(to top, rgba(0,0,0,.3) 1px, rgba(0,0,0,.05) 1px, transparent 50%);
 }
 
-.tabbrowser-tab,
-.tabs-newtab-button {
-  position: static;
-  -moz-appearance: none;
-  background: linear-gradient(hsla(0,0%,100%,.2), hsla(0,0%,45%,.2) 2px, hsla(0,0%,32%,.2) 80%);
-  background-origin: border-box;
-  background-position: 1px 2px;
-  background-size: 100% calc(100% - 2px);
-  background-repeat: no-repeat;
-  color: inherit;
-  margin: 0;
-  padding: 0;
-  border-width: 4px 5px 3px 6px;
-  border-style: solid;
-  border-image: url(tabbrowser/tab.png) 4 5 3 6 fill repeat stretch;
-  border-radius: 10px 8px 0 0;
-  min-height: 25px; /* reserve space for the sometimes hidden close button */
+.tab-background-middle[selected=true]:-moz-lwtheme {
+  background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
+                    @fgTabTexture@;
 }
 
-.tabbrowser-tab:hover,
-.tabs-newtab-button:hover {
-  background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.2) 4px, hsla(0,0%,75%,.2) 80%);
-}
-
-.tabbrowser-tab[selected="true"] {
-  background-image: linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%),
-                    linear-gradient(-moz-dialog, -moz-dialog);
-  color: -moz-dialogtext;
-}
-
-#main-window[tabsontop=false]:not([disablechrome]) .tabbrowser-tab[selected=true]:not(:-moz-lwtheme) {
-  background-image: linear-gradient(to top, rgba(0,0,0,.3) 1px, transparent 1px),
-                    linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%),
-                    linear-gradient(-moz-dialog, -moz-dialog);
-}
-
-.tabbrowser-tab[selected="true"]:-moz-lwtheme {
-  background-image: linear-gradient(@selectedTabHighlight@, @toolbarHighlight@ 32%);
+.tabbrowser-tab:-moz-lwtheme {
   color: inherit;
 }
 
-.tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]),
-.tabs-newtab-button:-moz-lwtheme-brighttext {
-  background-image: linear-gradient(hsla(0,0%,60%,.6), hsla(0,0%,40%,.6) 4px, hsla(0,0%,30%,.6) 80%);
-}
-
-.tabbrowser-tab:-moz-lwtheme-brighttext:not([selected="true"]):hover,
-.tabs-newtab-button:-moz-lwtheme-brighttext:hover {
-  background-image: linear-gradient(hsla(0,0%,80%,.6), hsla(0,0%,60%,.6) 4px, hsla(0,0%,45%,.6) 80%);
-}
-
-.tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]),
-.tabs-newtab-button:-moz-lwtheme-darktext {
-  background-image: linear-gradient(hsla(0,0%,100%,.5), hsla(0,0%,60%,.5) 4px, hsla(0,0%,45%,.5) 80%);
-}
-
-.tabbrowser-tab:-moz-lwtheme-darktext:not([selected="true"]):hover,
-.tabs-newtab-button:-moz-lwtheme-darktext:hover {
-  background-image: linear-gradient(hsla(0,0%,100%,.5), hsla(0,0%,80%,.5) 4px, hsla(0,0%,60%,.5) 80%);
-}
-
-.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) {
-  background-image: radial-gradient(circle farthest-corner at 50% 3px, rgba(233,242,252,1) 3%, rgba(172,206,255,.75) 40%, rgba(87,151,201,.5) 80%, rgba(87,151,201,0));
-}
-.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]):hover {
-  background-image: linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.6) 2px, hsla(0,0%,75%,.2) 80%),
-                    radial-gradient(circle farthest-corner at 50% 3px, rgba(233,242,252,1) 3%, rgba(172,206,255,.75) 40%, rgba(87,151,201,.5) 80%, rgba(87,151,201,0));
-}
-
-#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab > .tab-stack > .tab-content[pinned] {
-  min-height: 18px; /* corresponds to the max. height of non-textual tab contents, i.e. the tab close button */
-}
-
-.tabbrowser-tab:focus > .tab-stack {
+.tabbrowser-tab:focus > .tab-stack > .tab-content > .tab-label {
   outline: 1px dotted;
 }
 
-.tab-throbber,
-.tab-icon-image {
-  width: 16px;
-  height: 16px;
-  -moz-margin-end: 3px;
-  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
-}
-
-.tab-throbber {
-  list-style-image: url("chrome://browser/skin/tabbrowser/connecting.png");
-}
-
-.tab-throbber[progress] {
-  list-style-image: url("chrome://browser/skin/tabbrowser/loading.png");
-}
-
-.tab-throbber[pinned],
-.tab-icon-image[pinned],
-.tabs-newtab-button > .toolbarbutton-icon {
-  -moz-margin-start: 2px;
-  -moz-margin-end: 2px;
-}
-
 #context_reloadTab {
   list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
 }
 
 #context_closeOtherTabs {
   list-style-image: url("moz-icon://stock/gtk-clear?size=menu");
 }
 
@@ -1759,21 +1652,20 @@ richlistitem[type~="action"][actiontype=
 /* In-tab close button */
 .tab-close-button > .toolbarbutton-icon {
   /* XXX Buttons have padding in widget/ that we don't want here but can't override with good CSS, so we must
      use evil CSS to give the impression of smaller content */
   margin: -4px;
 }
 
 .tab-close-button {
-  padding: 0;
   list-style-image: url("moz-icon://stock/gtk-close?size=menu");
-  margin-top: -1px;
+  margin-top: 0;
   margin-bottom: -1px;
-  -moz-margin-end: -1px;
+  -moz-margin-end: -4px;
 }
 
 /* Tabstrip new tab button */
 .tabs-newtab-button,
 #TabsToolbar > #new-tab-button ,
 #TabsToolbar > #wrapper-new-tab-button > #new-tab-button {
   list-style-image: url("moz-icon://stock/gtk-add?size=menu");
   -moz-image-region: auto;
@@ -1884,20 +1776,16 @@ toolbarbutton.chevron > .toolbarbutton-t
 toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
   display: none;
 }
 
 toolbarbutton.chevron > .toolbarbutton-icon {
   margin: 0;
 }
 
-toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon {
-  display: -moz-box; /* display chevron icon in text mode */
-}
-
 /* Ctrl-Tab */
 
 .ctrlTab-preview {
   -moz-appearance: toolbarbutton;
 }
 
 .tabPreview-canvas {
   box-shadow: 0 0 5px ThreeDShadow;
@@ -1925,54 +1813,16 @@ toolbar[mode="text"] toolbarbutton.chevr
 
 #ctrlTab-showAll {
   -moz-appearance: button;
   color: ButtonText;
   padding: 0 3px;
   margin-top: 10px;
 }
 
-/* Application button menu */
-
-.splitmenu-menuitem {
-  -moz-margin-end: 1px;
-}
-
-#appmenu-toolbar-button:not(:hover):not([open]):not(:-moz-lwtheme) {
-  color: inherit;
-}
-
-#appmenu-toolbar-button > .toolbarbutton-text,
-#appmenu-toolbar-button > .toolbarbutton-menu-dropmarker {
-  margin-top: -2px !important;
-  margin-bottom: -2px !important;
-}
-#appmenuSecondaryPane {
-  -moz-border-start: 1px solid ThreeDShadow;
-}
-#appmenuSecondaryPane-spacer {
-  min-height: 1em;
-}
-#appmenu-cut,
-#appmenu-editmenu-cut {
-  list-style-image: url("moz-icon://stock/gtk-cut?size=menu");
-}
-#appmenu-copy,
-#appmenu-editmenu-copy {
-  list-style-image: url("moz-icon://stock/gtk-copy?size=menu");
-}
-#appmenu-paste,
-#appmenu-editmenu-paste {
-  list-style-image: url("moz-icon://stock/gtk-paste?size=menu");
-}
-#wrapper-appmenu-toolbar-button,
-.appmenu-edit-button[disabled="true"] {
-  opacity: .3;
-}
-
 /* Add-on bar */
 
 #addon-bar {
   box-shadow: 0 1px 0 rgba(0,0,0,.15) inset;
   padding: 0;
   min-height: 20px;
 }
 
@@ -2272,16 +2122,37 @@ toolbar[iconsize="small"] .toolbarbutton
   background-image: radial-gradient(circle farthest-corner at center 3px, rgb(233,242,252) 3%, rgba(172,206,255,0.75) 40%, rgba(87,151,201,0.5) 80%, rgba(87,151,201,0));
 }
 
 chatbox {
   border-top-left-radius: 2.5px;
   border-top-right-radius: 2.5px;
 }
 
+/* Customization mode */
+
+%include ../shared/customizableui/customizeMode.inc.css
+
+#main-window[customizing] #tab-view-deck {
+  background-image: url("chrome://browser/skin/customizableui/customizeMode-gridTexture.png"),
+                    url("chrome://browser/skin/customizableui/background-noise-toolbar.png"),
+                    linear-gradient(to bottom, #bcbcbc, #b5b5b5);
+  background-attachment: fixed;
+}
+
+#main-window[customizing] #tab-view-deck {
+  padding: 2em;
+}
+
+#main-window[customizing] #tab-view-deck > #browser-panel {
+  box-shadow: 0 0 3px #333;
+}
+
+/* End customization mode */
+
 .click-to-play-plugins-notification-content {
   margin: -10px;
 }
 
 .click-to-play-plugins-notification-icon-box {
   -moz-border-end: 1px solid hsla(0,0%,100%,.2);
   padding-top: 16px;
   -moz-padding-start: 16px;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d09ba9dafb5ede66e92ce577ecaa6f9575dba104
GIT binary patch
literal 15601
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
LNkvXXu0mjfSmbEw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a7c2775cfc799da31a505b249f5a59b89c148a58
GIT binary patch
literal 118
zc%17D@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3ww^AIAr-gYUfIaWpuppLFlU13
zo%)jzH=|it_dY6Z)V5Pum31fM;KsnRdyNMlls~YU+j}r!!}-)?gCEKjOuj1pzc){H
R6$2W?;OXk;vd$@?2>=UhDL4QC
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e17cb4db08e310e6c3a9e14c5bd722772dfb639
GIT binary patch
literal 1426
zc$@)}1#S9?P)<h;3K|Lk000e1NJLTq00H0t000aK1^@s6x+QMd000G9Nkl<ZcwX(B
zO>g8j42Jp2&TP87-2_FZ*z`~YX#f8&$|0v-TD03O+GIW~_Au6rWZI@|*6s|(0=Oef
z<V%hN>?7I<zJ2)NCprvAU4sc?4Z&YAsqGrtL{MTBO{tKpXU?nV*0rS?|0gxWT$4Rk
zkDq6Nu6OXn`raBhV?2-0_U3vZGP6O?P^%%gJ+DtHfU3z^dAVgB<XdX;8F{>6-g3=8
z#sk;;h`5Ij-#^|G5f#TWiW4lD8x^whqh#Wuxx}uaD}y=tQ2h$Y0e5uiL<09ifHnU#
zGmA_)={O5VPW94tmGYFkWHq({k?Ep`n}Bd<40otN!Hnl8UBM564!pS@pN%O<Pbd*d
zft6k>^cwWr;FGJWH56^iUiAxVNY_!3*S`zWWypI|h0Q&Pl6nxug~ff)Ask{N|0o70
zU(|K)2nWE{pR_|*^#s(KAbeauu4+)$qNVGiBDWB;q!32LB8CMt0-;$2NC!C5Dr8Jq
z1n^7HWB}e-LBmBZQJlg|HyfQ;*|f_$6Q7u`0JN72W(f^gVd*D*=mEoRHi*J^>g!ri
z;i|JAgJM&N?JI?U7{GJL8LF1L(fB~kx%vaa7d>1*64%FIhtv<EQRqGv@<+Iapt!C8
z?Oj;gg<Ju)KKKM3xE<mB!{h3Ph?rwYlqm?f4SFoyxz~$`xgRcR4Fb|bpb=^+WDz|e
zEX9BJY=IIF1r8e;>45NpOrtOn+bOOlycd`ERQIZ$uvfZ^H#A~4=gR!;x)F-pLj)#j
z{GqLcF0BXrNTwAfP|{NS4!EW{0S)%@tk4BY+4c71+56KLXxE{Q)7;ZG=p1n?wSfkJ
zW55QN?V%HYBiaC|4~X#byU%482xa%e>2!4?m+OmFB%?u#Q%BcLn~+a|WG<{ra)U72
zb4VGC7*-+-S`)#=jfP|~sz7(fEL;W*9i--4!N5;L!DcBas|vtIb+;05x&lO~LT_a|
ztnB){5(st=B(mG%Dx}MHM+6Cf9mwPf=+-4fb#5XVq<Ud@lYrF=EyQ}Sr#V2lzyDk&
z0KApJk)RCru4j*3FB8QAn;u7UC%EO(O}JjwR|DEi=ILm_{o+o~dDA648hkuumslEP
z7rXo>d_P#&&w^XXXdN(mjQ}RQ$$%0gmUf=D4QxV>M}7f5#}9;I@K545U3>B!@LS>+
zT|&kuGBq?I{9=p1i%wwUZ`Xi35k9Qft_G+Z4v24Bh{Rzhip$kwE%!iU*Q@g`{9^^A
ztljR$S~2syl4Q0^bk(*p<X`N(EeAGR!#iMGem~du1YwfL&33?Vh&Ea*l>4OBpu$vT
z^lKC=onCV~YYozQd(NG5HT>{btl{FhSo;HClHVJ~-QABhfTMf;NkAvR6ZL*v2g_^*
zK{!Nc_C7sCD7lq7ZKQQl-(G{gW1XpnTUy37+nZei!2kKa+~?MS(P?1^pY%=8_D_DC
zHy=oVadFP&#>qTisRfW-YhQXh+~323b6OqJrzlSIUupo;dhLcn@1b$+y&nV%J5=tY
zxYpdc`>r+jr+GRvd0?3<@63?5YAv>O&vro1U$YJri}~!lUkAckf=Ywd5cr$@TnaY-
z+t{B;&`BYw`AaLy!{jCRJ==5K*FUAIPn0+Idm22vr%|J-!pxj=JqK{);lylur$0ZC
zucZcQcXVFk&okjBuCfN%8QRS`H|zcRRfCOg5@Nd9bCzWuR9+M?3OLSV2wmW1+0Vv!
z<?!${MpDt7hVFE+qpD~bi-nHkBFzrTF~Auf^P-B9Z9LQRC-LJ9be+S|G8VHP0ME#t
gX&H-M9>A9IFDL!=ycbq6DF6Tf07*qoM6N<$g5jpFQvd(}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dc4caee812878f246c87d71093768eb36c5656fc
GIT binary patch
literal 1649
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
new file mode 100644
--- /dev/null
+++ b/browser/themes/linux/customizableui/panelUIOverlay.css
@@ -0,0 +1,41 @@
+/* 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/. */
+
+%filter substitution
+%define menuPanelWidth 23em
+
+%include ../../shared/customizableui/panelUIOverlay.inc.css
+
+#PanelUI-cut-btn {
+  list-style-image: url("moz-icon://stock/gtk-cut?size=toolbar");
+}
+#PanelUI-cut-btn[disabled="true"] {
+  list-style-image: url("moz-icon://stock/gtk-cut?size=toolbar&state=disabled");
+}
+
+#PanelUI-copy-btn {
+  list-style-image: url("moz-icon://stock/gtk-copy?size=toolbar");
+}
+#PanelUI-copy-btn[disabled="true"] {
+  list-style-image: url("moz-icon://stock/gtk-copy?size=toolbar&state=disabled");
+}
+
+#PanelUI-paste-btn {
+  list-style-image: url("moz-icon://stock/gtk-paste?size=toolbar");
+}
+#PanelUI-paste-btn[disabled="true"] {
+  list-style-image: url("moz-icon://stock/gtk-paste?size=toolbar&state=disabled");
+}
+
+#PanelUI-zoomOut-btn {
+  list-style-image: url("moz-icon://stock/gtk-zoom-out?size=toolbar");
+  padding-left: 12px;
+  padding-right: 12px;
+}
+
+#PanelUI-zoomIn-btn {
+  list-style-image: url("moz-icon://stock/gtk-zoom-in?size=toolbar");
+  padding-left: 12px;
+  padding-right: 12px;
+}
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -13,18 +13,24 @@ browser.jar:
   skin/classic/browser/aboutCertError_sectionCollapsed.png
   skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png
   skin/classic/browser/aboutCertError_sectionExpanded.png
   skin/classic/browser/aboutSocialError.css
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/aboutSyncTabs.css
 #endif
   skin/classic/browser/actionicon-tab.png
+  skin/classic/browser/appmenu.png
 * skin/classic/browser/browser.css
+* skin/classic/browser/browser-lightweightTheme.css
   skin/classic/browser/click-to-play-warning-stripes.png
+  skin/classic/browser/customizableui/background-noise-toolbar.png  (customizableui/background-noise-toolbar.png)
+  skin/classic/browser/customizableui/customizeMode-gridTexture.png  (customizableui/customizeMode-gridTexture.png)
+  skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png  (customizableui/customizeMode-separatorHorizontal.png)
+  skin/classic/browser/customizableui/customizeMode-separatorVertical.png  (customizableui/customizeMode-separatorVertical.png)
 * skin/classic/browser/engineManager.css
   skin/classic/browser/Geolocation-16.png
   skin/classic/browser/Geolocation-64.png
   skin/classic/browser/Go-arrow.png
   skin/classic/browser/identity.png
   skin/classic/browser/identity-icons-generic.png
   skin/classic/browser/identity-icons-https.png
   skin/classic/browser/identity-icons-https-ev.png
@@ -52,16 +58,17 @@ browser.jar:
   skin/classic/browser/setDesktopBackground.css
   skin/classic/browser/slowStartup-16.png
   skin/classic/browser/Toolbar.png
   skin/classic/browser/Toolbar-small.png
   skin/classic/browser/urlbar-arrow.png
   skin/classic/browser/webRTC-shareDevice-16.png
   skin/classic/browser/webRTC-shareDevice-64.png
   skin/classic/browser/webRTC-sharingDevice-16.png
+* skin/classic/browser/customizableui/panelUIOverlay.css (customizableui/panelUIOverlay.css)
   skin/classic/browser/downloads/buttons.png          (downloads/buttons.png)
   skin/classic/browser/downloads/download-glow.png    (downloads/download-glow.png)
   skin/classic/browser/downloads/download-glow-small.png (downloads/download-glow-small.png)
   skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
   skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
   skin/classic/browser/downloads/download-summary.png (downloads/download-summary.png)
   skin/classic/browser/downloads/downloads.css        (downloads/downloads.css)
   skin/classic/browser/downloads/allDownloadsViewOverlay.css   (downloads/allDownloadsViewOverlay.css)
@@ -108,18 +115,25 @@ browser.jar:
   skin/classic/browser/social/services-16.png         (social/services-16.png)
   skin/classic/browser/social/services-64.png         (social/services-64.png)
   skin/classic/browser/social/share-button.png        (social/share-button.png)
   skin/classic/browser/social/share-button-active.png (social/share-button-active.png)
   skin/classic/browser/social/chat-close.png          (social/chat-close.png)
   skin/classic/browser/tabbrowser/connecting.png      (tabbrowser/connecting.png)
   skin/classic/browser/tabbrowser/loading.png         (tabbrowser/loading.png)
   skin/classic/browser/tabbrowser/tab.png             (tabbrowser/tab.png)
-  skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png)
-  skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
+  skin/classic/browser/tabbrowser/tab-active-middle.png     (tabbrowser/tab-active-middle.png)
+  skin/classic/browser/tabbrowser/tab-background-end.png    (tabbrowser/tab-background-end.png)
+  skin/classic/browser/tabbrowser/tab-background-middle.png (tabbrowser/tab-background-middle.png)
+  skin/classic/browser/tabbrowser/tab-background-start.png  (tabbrowser/tab-background-start.png)
+  skin/classic/browser/tabbrowser/tab-overflow-border.png   (tabbrowser/tab-overflow-border.png)
+  skin/classic/browser/tabbrowser/tab-stroke-end.png        (tabbrowser/tab-stroke-end.png)
+  skin/classic/browser/tabbrowser/tab-stroke-start.png      (tabbrowser/tab-stroke-start.png)
+  skin/classic/browser/tabbrowser/tabDragIndicator.png      (tabbrowser/tabDragIndicator.png)
+  skin/classic/browser/tabbrowser/tab-separator.png         (tabbrowser/tab-separator.png)
   skin/classic/browser/tabview/edit-light.png         (tabview/edit-light.png)
   skin/classic/browser/tabview/search.png             (tabview/search.png)
   skin/classic/browser/tabview/stack-expander.png     (tabview/stack-expander.png)
   skin/classic/browser/tabview/tabview.png            (tabview/tabview.png)
   skin/classic/browser/tabview/tabview.css            (tabview/tabview.css)
 * skin/classic/browser/devtools/common.css            (devtools/common.css)
   skin/classic/browser/devtools/dark-theme.css        (devtools/dark-theme.css)
   skin/classic/browser/devtools/light-theme.css       (devtools/light-theme.css)
new file mode 100644
--- /dev/null
+++ b/browser/themes/linux/linuxShared.inc
@@ -0,0 +1,10 @@
+/* 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/. */
+
+%filter substitution
+
+%define toolbarHighlight rgba(255,255,255,.3)
+%define fgTabTexture linear-gradient(transparent 0px, transparent 1px, hsla(0,0%,100%,0.35) 1px, hsla(0,0%,100%,0.35) 2px, hsla(0,0%,100%,0.65) 2px, hsla(0,0%,100%,0.65) 3px, @toolbarHighlight@)
+%define fgTabTextureLWT @fgTabTexture@
+%define fgTabBackgroundMiddle @fgTabTexture@, linear-gradient(transparent 0px, transparent 2px, -moz-dialog 2px, -moz-dialog)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6c903ae15688e88e50e9ce817afdc0cbab17ea24
GIT binary patch
literal 96
zc%17D@N?(olHy`uVBq!ia0vp^j6f{U!3HGNPA*RZQtF;Ajv*Dd&K}>$$-uzDd~iL>
u_6>e-W!~-gWm&$#(jvz>jNhZM_7GE+SNM9@YkC<#EexKnelF{r5}E*7of}&K
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..78a4f1f1cbb8d9395750d1e2cef78ae9e82838b9
GIT binary patch
literal 721
zc$@*z0xtcDP)<h;3K|Lk000e1NJLTq0015U0018d1^@s6@N9ht0007*Nkl<Zc-pns
z+e?#i9LMoTx4DCdG`CrsJGi+y+M3!<Z93;{t5!Ol;*t@RL_!1+6?oxAH{Apg1YPtW
zL_r6lf-nk-4&+4?SW=NmRQ3-Tj2-%X;dx*eq3-uQUA%smdq2PL@8P$NlW7bZo(hzp
z06En1YIvNKXz_s;+~5EMG=K^eAQK*-R4Q>&q2=(e)!$Q}zkJO;e)4Q=cJ9KSMy)-7
zP#5Sy1#%%yBncM^g+WL_5{8S#;>6n8pWO2ouQQqKbd;Y$Gt@~L=MWnBhd8A2`TU`q
zx9+7IT5UnZOhR0$aC99p82PsHJ?n6XBM7!j6{m3j2BMI}J22VO*0q~IcZJwEg(I8L
z2Z@)j7BYx=Kn-%S;qWF!AT@LHTmnIh*pX8>RD}peKB{ao(|Ol}TueAng&@SIXHF*(
zG>SQE3j3-Qy8m$gAb;Db#DsTM$%hLjxkcxQ@mH&iHQd7>JT`fh#%&PB%@X!9@L#@i
z?Er!<P_m4h!X5_QkLI7!jsvXcOv?@io*zF~qlgWH24pN@7bCyb>EDN73n*B^4n{k(
zx#KAWtt>AXEp|q(i<hp_j=Nc2Fj_hob-r16JAhc6<(z4;FtUQz<_gj+rmc3|w3tM&
zpE@&_;;&Dou<LTU%x#3iMiI;(mp+B-8ck^g8!NvwHWN08)R{YSg2vqoYGK!8qwqG7
zjLXX_A$_}h6fs-H$ZOYo09y1CFkQcKXGq;_8Ar$g>dHR@yc&TJ)=EGJ*4uX<#PL&@
z;yus+YEV`_gb=52t3<S5dG~&?e`4y`Fg|<)0?-LYXsS4Wj>0VxYXj%vho!!=v*-5@
z?j28idSjXG7Vi*(Zm1W+&HsrGI=}@UaDo}ptrY$Xsi^vbGE;I800000NkvXXu0mjf
Dz`;ej
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c0b65dad63471961c4aa942a69f4733372c2c7cf
GIT binary patch
literal 161
zc%17D@N?(olHy`uVBq!ia0vp^Y(Ol}0V0ox?vVykk|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*D5XoIPC}Lp07OCqA3>DCq!GL_>t|>Lc&<{Wp03`ThO9VHl^I
z+p+&U-YCRAlK)!rN4lnr;c!>U;(wP8J~!dl-c;kaG=zyk^n_B^;swh4fW|R+y85}S
Ib4q9e0C=@I!T<mO
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..300dc1d757171af84e84267853aba9c450388b8f
GIT binary patch
literal 705
zc$@*j0zUnTP)<h;3K|Lk000e1NJLTq0015U0018d1^@s6@N9ht0007rNkl<Zc-pns
z-Ahwp90%~VIp^kPTh3XVdvSVnv~|?nW}D7!wq<KN-NYp$D2ap!A}a90i*C9JA_%(Z
zKZt@}hzi0;D0(3;qQH`hOd_>^z+mj9ukgrOLT%?cr;E?U9?tW8&+qqp7@I_<GKy^*
zAtkCn4hpCN)doqSP!LT?pbX?BNDW3{zzHmLix>!`LK0|zc8$KpGd**0|C6WBMn8Y~
znqFP|Ie|S##15?nEilRSWZ?OW*U9zuUzvP9KbFhoh9C+N2#FKSg__m%cJHm*_Y>J{
z_Amlt5QhG(#0+g>oId}z<?m@6JPbhy{EZl)axmx`+xKCH<2W=*4)6OHp}|$41lP+~
z^GO^SfnM;JBSwp@Q>V^H$UObvtAx;MYZY}CKUzFOLVGGDbhf6+sWVY>bG_iHl#t*W
zU>`i1jgu<6`JfG!fqHub6T}xplpMB~5B|Yin~kI6$D-u2bn->pW(7E|T)ln>hq!^|
zOUQgZk7wsLD((OmU$pa8LFmWIS^(=V*v%JBupD%@HuoUb+~A-=d$DZk%!wG*_5eeJ
z_F{Ehx_oVrynPD|+WCgx%)jl&dMh;3plP$-?(oL3#)1v3G$h4hv7FLs6~LZ8I};-<
zGt;Upl&e-#tuZG)E`IW1vjt4F%7=2*DxoWL^kkgO)+j`|Kxs*f?S>}j$kNhs4|(gI
zLU2JG>6RbmN??>)YwE_$y90RM3<jaN&_BZzBv1{V_{o~ObMIjo8*I=3dZ9}H@5rDI
zOwbA*7#^EAKJ@PWLLVNsl1=qu*bJ@(=PoNd;OYt{LkCicbJG_NE__(*#Y1h-2s$xs
n2JgTJ3kh+71DZ)&wg1C!qPhBl8*`*i00000NkvXXu0mjfgAqxS
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..63f77f1b760b2e66e2fab7e739979b7cdede2116
GIT binary patch
literal 192
zc%17D@N?(olHy`uVBq!ia0vp^%s?#1!3HE>CM@{{q$EpRBT9nv(@M${i&7aJQ}UBi
z6+Ckj(^G>|6H_V+Po~-c6(xDPIEGZ*O8WEvzdbXLfuRE9vh(lf8+&zsHf+wAz@sd%
zxhX@Uo%a}HqL@H$XdAB@^C6iNr*2G~T9^>pb}-TXSwYfM1Lv;>$)*jHEvhXFqq^=|
nO8iSata-RghnX+10qCqHCR~QDO&0Ay+Za4u{an^LB{Ts5X9_^D
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b1b7cc0145523cc8141b939a10b34fe8dda1a445
GIT binary patch
literal 439
zc%17D@N?(olHy`uVBq!ia0vp^azHH4!3-piZ|XG#QjEnx?oJHr&dIz4a#+$GeH|GX
zHuiJ>Nn{1`djotzTp6Gsl!3vXK}(B4-kw2RPgq!8NX1N0$(UbGmsiS^N5z0!Nsmj;
zh*L(NQ`(F}!H`{EpIy$3Pu7T6!GuT7fLq3hThS1x0IbG@Q_+}H!H8GhkVn>-N70B!
z!IWDbsKA&@!H7%VluO<isuHMI!I(!LXo3m1f)Tg8@t4V#F+jKImjw9*GcYo<uyJtn
z^6?7_i;77~%g8GzDywVh>KPfEnweYL*xEU|x_fwe`}p|>1&2j0*z<Wd$WNXwjv*3~
ztp~fA8Vwj&FYMknMXn<&#a7q!*#G)@`Y){5>n*HjSsfGGYCq-d=`b#rd%Kiplw_)Q
zJh0;uSY)2CME5|79)od6!Y1_<ri_c%CwyX;_&G7*8Bfp315;#YR4_gjo$-!mnZyAP
z`KC;h882j;E-FhHN-`?FSkBV2V@>efcOu(5F6Wm0i*D|G!@uD>N3pQthb5o@_H^}g
JS?83{1OVkFad-d#
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..08941c8a783419fd8c0e743c3cafbfaaf6b43ea5
GIT binary patch
literal 433
zc%17D@N?(olHy`uVBq!ia0vp^azHH4!3-piZ|XG#QjEnx?oJHr&dIz4a#+$GeH|GX
zHuiJ>Nn{1`+XH+;Tp6Gsl!3vXK}(B4MTJ3JPgq!8P|28IPM258luO=}OU{T>MxRsK
zj9p%zPu7S}#*kORgh$?(N6vs-#t0}2QlMzesbIt_Z^$cW!Xs<UqhQJ{Z_F)k#4TsY
zEoZ{5Xw0Qx1TsqA7^)s<f`T!Ryb%vjy_|7Uf3_{q6}lxse!&ck%q(o|+`RmP!V;3w
zG78En>Ka<QM#g65mR2@)4vx+)uI?UQ-adZ*fx)5N*6(HjHTHYDIEF|_&OMmT<m4d1
zdf~U>Ck{p5%9J3@#Q(3enT@}<7jFoz*mrln@tP1zz3WEZA~~COT5`!O`KeOy+L}M_
z7RQ}SC);QHNOnA8O!IMUv1bg-HgM)k<92X~H&`y$v+lqiA%S~p3PsGzbRAZhG6Zf_
zxFXd2!sL!iKhyFXJa%iYD6Tvk#JNWA^`C1y+im|vJG0lfDG8c^g4Wa3&t;ucLK6UQ
CX>CRT
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..aab0a02c84d63603ec1fc3a385a08c5cf5360fd2
GIT binary patch
literal 15667
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
Z%Ktt2F}8~Q0|)>B002ovPDHLkV1jXE7}o#*
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4d0f12492fe643ade04a8ffaf333f7c729fa2f33
GIT binary patch
literal 247
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%``#fD7Ln>~ay|9<>AcIKT!^dVh
zPL~`nny9FX3QF0_hAc6;6tcysgRf4^t^C677rbS5HPZ`DB~%<wuk4)Jec#12dB&70
zX5l8mB0M@P+otl$&VQS#!NoRhkAa_i-U;LXK(-kF7yrj|Uf%a#Q@&=&9fQb=)r%4m
zJYV}6S8siM^qCG&@t?z{rA;&T{*4vkc_Z(0<&5Vdlix9>I)Mfou1K9RHs4iHP}kMe
uxHR{V$Mxmx?%StpNZgq3<I+0kqV!JNQte+wg;Rk(VeoYIb6Mw<&;$VPyJO}6
new file mode 100644
--- /dev/null
+++ b/browser/themes/osx/browser-lightweightTheme.css
@@ -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/. */
+
+%include shared.inc
+
+/*
+ * LightweightThemeListener will append the current lightweight theme's header
+ * image to the background-image for each of the following rulesets.
+ */
+
+/* Lightweight theme on tabs */
+#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[selected=true]:-moz-lwtheme::before,
+#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[selected=true]:-moz-lwtheme::before {
+  background-attachment: scroll, fixed;
+  background-color: transparent;
+  background-image: @fgTabTextureLWT@;/*, lwtHeader;*/
+  background-position: 0 0, right top;
+}
+
+#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
+  background-attachment: scroll, scroll, fixed;
+  background-color: transparent;
+  background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle-lwtheme.png),
+                    @fgTabTextureLWT@;/*,
+                    lwtHeader;*/
+  background-position: 0 0, 0 0, right top;
+}
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -2,54 +2,68 @@
  * 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/. */
 
 @import url("chrome://global/skin/");
 
 %include shared.inc
 %filter substitution
 %define forwardTransitionLength 150ms
-%define conditionalForwardWithUrlbar window:not([chromehidden~=toolbar]) #navigator-toolbox[iconsize=large][mode=icons] > :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"],#nav-bar:not([currentset])) > #unified-back-forward-button
+%define conditionalForwardWithUrlbar window:not([chromehidden~=toolbar]) #navigator-toolbox[iconsize=large] > :-moz-any(#nav-bar[currentset*="unified-back-forward-button,urlbar-container"],#nav-bar:not([currentset])) > #nav-bar-customizationtarget > #unified-back-forward-button
 %define conditionalForwardWithUrlbarWidth 27
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 @namespace html url("http://www.w3.org/1999/xhtml");
 
 #urlbar:-moz-lwtheme:not([focused="true"]),
 .searchbar-textbox:-moz-lwtheme:not([focused="true"]) {
   opacity: .9;
 }
 
+#navigator-toolbox::after {
+  -moz-box-ordinal-group: 101; /* tabs toolbar is 100 */
+  background-image: linear-gradient(to top, hsla(0,0%,0%,.15), hsla(0,0%,0%,.15) 1px, hsla(0,0%,100%,.15) 1px, hsla(0,0%,100%,.15) 2px, transparent 3px);
+  content: "";
+  display: -moz-box;
+  height: 2px;
+  margin-top: -2px;
+}
+#navigator-toolbox[tabsontop=false]::after,
+#main-window[disablechrome] #navigator-toolbox::after {
+  visibility: collapse;
+}
+
 #navigator-toolbox toolbarbutton:-moz-lwtheme {
   color: inherit;
   text-shadow: inherit;
 }
 
-#PersonalToolbar:-moz-lwtheme,
-#nav-bar:-moz-lwtheme,
 #main-window[privatebrowsingmode=temporary] #nav-bar[tabsontop=false] {
   -moz-appearance: none !important;
-  background: none !important;
-  /* Switching to a lightweight theme shouldn't move the content area,
-     so avoid changing border widths here. */
-  border-color: transparent !important;
 }
 
 #main-window {
   -moz-appearance: none;
   background-color: #eeeeee;
 }
 
-#titlebar-buttonbox-container,
-#main-window:not([drawintitlebar=true]) > #titlebar {
+#titlebar-buttonbox > .titlebar-button {
   display: none;
 }
 
 #titlebar {
-  height: 22px;
+  padding-top: 9px;
+}
+
+#main-window[chromehidden~="toolbar"] > #titlebar {
+  padding-top: 22px;
+}
+
+#main-window:not(:-moz-lwtheme):not([privatebrowsingmode=temporary]) > #titlebar {
+  -moz-appearance: -moz-window-titlebar;
 }
 
 #main-window[chromehidden~="toolbar"][chromehidden~="location"][chromehidden~="directories"] {
   border-top: 1px solid rgba(0,0,0,0.65);
 }
 
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
   -moz-box-align: center;
@@ -57,59 +71,46 @@
 }
 
 /* Because of -moz-box-align: center above, separators will be invisible unless
    we set their min-height. See bug 583510 for more information. */
 toolbarseparator {
   min-height: 22px;
 }
 
-/* We need more height when toolbar buttons show both icon and text. */
-toolbar[mode="full"] toolbarseparator {
-  min-height: 36px;
+toolbox[tabsontop=true] > toolbar:not(#TabsToolbar):not(#nav-bar):not(:-moz-lwtheme) {
+  -moz-appearance: none;
+  background: url(chrome://browser/skin/Toolbar-background-noise.png) hsl(0,0%,83%);
 }
 
 #nav-bar {
   padding-bottom: 4px !important;
 }
 
-#PersonalToolbar {
-  -moz-appearance: none;
-  margin-top: -2px; /* overlay the bottom border of the toolbar above us */
-  padding-top: 1px !important;
-  background-color: -moz-mac-chrome-active;
-  border-bottom: 1px solid rgba(0, 0, 0, 0.57);
-}
-
 #nav-bar[tabsontop=true],
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + toolbar,
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar {
   -moz-appearance: none;
-  margin-top: 0; /* don't overlay the bottom border of the tabs toolbar */
   padding-top: 4px !important;
-  border-bottom: 1px solid rgba(0, 0, 0, 0.57);
-  background-color: -moz-mac-chrome-active;
-  background-image: linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0)) !important; /* override lwtheme style */
+  background: url(chrome://browser/skin/Toolbar-background-noise.png),
+              linear-gradient(hsl(0,0%,93%), hsl(0,0%,83%));
+  background-clip: border-box;
   background-origin: border-box !important;
 }
 
-#PersonalToolbar:-moz-lwtheme,
-#nav-bar[tabsontop=true]:-moz-lwtheme,
-#nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + toolbar:-moz-lwtheme,
-#nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar:-moz-lwtheme {
-  background-color: transparent;
-  border-bottom-color: transparent;
+#navigator-toolbox[tabsontop=true] > toolbar:not(#TabsToolbar):-moz-lwtheme {
+  background-color: @toolbarColorLWT@;
+  background-image: url(chrome://browser/skin/Toolbar-background-noise.png);
 }
 
 #PersonalToolbar:not(:-moz-lwtheme):-moz-window-inactive,
 #nav-bar[tabsontop=true]:not(:-moz-lwtheme):-moz-window-inactive,
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + toolbar:not(:-moz-lwtheme):-moz-window-inactive,
 #nav-bar[tabsontop=true][collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme):-moz-window-inactive {
   background-color: -moz-mac-chrome-inactive;
-  border-bottom-color: rgba(0, 0, 0, 0.32);
 }
 
 /* ----- BOOKMARK TOOLBAR ----- */
 
 #personal-bookmarks {
   min-height: 17px; /* 16px button height + 1px margin-bottom */
 }
 
@@ -118,20 +119,16 @@ toolbarbutton.chevron {
   margin: 1px 0 0;
   padding: 0;
 }
 
 toolbarbutton.chevron > .toolbarbutton-text {
   display: none;
 }
 
-toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon {
-  display: -moz-box; /* display chevron icon in text mode */
-}
-
 toolbarbutton.chevron:-moz-locale-dir(rtl) > .toolbarbutton-icon {
   transform: scaleX(-1);
 }
 
 @media (min-resolution: 2dppx) {
   toolbarbutton.chevron {
     list-style-image: url("chrome://global/skin/icons/chevron@2x.png");
   }
@@ -167,17 +164,17 @@ toolbarbutton.bookmark-item {
   }
 
   .bookmark-item > .toolbarbutton-menu-dropmarker > .dropmarker-icon {
     width: 7px;
   }
 }
 
 .bookmark-item > .toolbarbutton-text {
-  display: -moz-box !important; /* prevent [mode="icons"] from hiding the label */
+  display: -moz-box !important; /* Force the display of the label for bookmarks */
   margin: 0 !important;
 }
 
 toolbarbutton.bookmark-item:hover,
 toolbarbutton.bookmark-item[open="true"] {
   background-color: rgba(0, 0, 0, .205);
 }
 
@@ -423,40 +420,22 @@ toolbarbutton.bookmark-item > menupopup 
   }
 
   :-moz-any(@primaryToolbarButtons@):not(#tabview-button) > .toolbarbutton-icon,
   :-moz-any(@primaryToolbarButtons@):not(#tabview-button) > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
     width: 20px;
   }
 }
 
-toolbar:not([mode="icons"]) .toolbarbutton-1:not([type="menu-button"]),
-toolbar:not([mode="icons"]) .toolbarbutton-1 > .toolbarbutton-menubutton-button,
-toolbar:not([mode="icons"]) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
-toolbar:not([mode="icons"]) #restore-button {
-  -moz-appearance: none;
-  padding: 0;
-  height: auto;
-  border: none;
-  box-shadow: none;
-  background: none;
-}
-
 .toolbarbutton-1:not([type="menu-button"]),
 .toolbarbutton-1 > .toolbarbutton-menubutton-button,
 #restore-button {
   min-width: 28px;
 }
 
-toolbar:not([mode="icons"]) .toolbarbutton-1:not([type="menu-button"]),
-toolbar:not([mode="icons"]) .toolbarbutton-1 > .toolbarbutton-menubutton-button,
-toolbar:not([mode="icons"]) #restore-button {
-  min-width: 0;
-}
-
 .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon,
 .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
   margin: 2px;
 }
 
 .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon,
 .toolbarbutton-1[disabled="true"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
 .toolbarbutton-1 > .toolbarbutton-menubutton-button[disabled="true"] > .toolbarbutton-icon,
@@ -509,167 +488,158 @@ toolbar:not([mode="icons"]) #restore-but
   -moz-margin-end: 1px;
 }
 
 .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
   padding: 2px 4px 0;
   -moz-border-start: none !important;
 }
 
-toolbar:not([mode="icons"]) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
-  width: auto;
-  padding-top: 0;
-}
-
 .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(rtl),
 .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(ltr) {
   border-top-left-radius: 0;
   border-bottom-left-radius: 0;
 }
 
 .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(ltr),
 .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(rtl) {
   border-top-right-radius: 0;
   border-bottom-right-radius: 0;
 }
 
-toolbar:not([mode="icons"]) .toolbarbutton-1:not([open="true"]) > .toolbarbutton-menubutton-dropmarker {
-  opacity: .7;
-}
-
 .toolbarbutton-1 > .toolbarbutton-text,
 .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-text {
   margin: 2px 0 0;
 }
 
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):active:hover:-moz-lwtheme,
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"])[open="true"]:-moz-lwtheme,
-toolbar[mode="icons"] .toolbarbutton-1:not([disabled="true"]) > .toolbarbutton-menubutton-button:active:hover:-moz-lwtheme,
-toolbar[mode="icons"] .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker:-moz-lwtheme,
-toolbar[mode="icons"] #restore-button:not([disabled="true"]):active:hover:-moz-lwtheme {
+.toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):active:hover:-moz-lwtheme,
+.toolbarbutton-1:not([type="menu-button"])[open="true"]:-moz-lwtheme,
+.toolbarbutton-1:not([disabled="true"]) > .toolbarbutton-menubutton-button:active:hover:-moz-lwtheme,
+.toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker:-moz-lwtheme,
+#restore-button:not([disabled="true"]):active:hover:-moz-lwtheme {
   text-shadow: @loweredShadow@;
   background-color: rgba(0,0,0,0.2);
   box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
 }
 
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:-moz-lwtheme {
+.toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:-moz-lwtheme {
   background-color: rgba(0,0,0,0.4);
   box-shadow: inset 0 2px 5px rgba(0,0,0,0.7), 0 1px rgba(255,255,255,0.2);
 }
 
-toolbar[mode="icons"] .toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:not([disabled="true"]):active:hover:-moz-lwtheme {
+.toolbarbutton-1:not([type="menu-button"]):not(#fullscreen-button)[checked="true"]:not([disabled="true"]):active:hover:-moz-lwtheme {
   background-color: rgba(0, 0, 0, 0.6);
   box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.8), 0 1px rgba(255, 255, 255, 0.2);
 }
 
-toolbar[mode="icons"] .toolbarbutton-1 > menupopup {
+.toolbarbutton-1 > menupopup {
   margin-top: 1px;
 }
 
 #navigator-toolbox > toolbar {
   /* force iconsize="small" on these toolbars */
   counter-reset: smallicons;
 }
 
 /* unified back/forward button */
 
 #unified-back-forward-button {
   -moz-box-align: center;
 }
 
 #back-button,
 #forward-button:-moz-locale-dir(rtl),
-toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl):-moz-lwtheme {
+#back-button:-moz-locale-dir(rtl):-moz-lwtheme {
   -moz-image-region: rect(0, 40px, 20px, 20px);
 }
 
 @media (min-resolution: 2dppx) {
   #back-button,
   #forward-button:-moz-locale-dir(rtl),
-  toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl):-moz-lwtheme {
+  #back-button:-moz-locale-dir(rtl):-moz-lwtheme {
     -moz-image-region: rect(0, 80px, 40px, 40px);
   }
 }
 
 #forward-button,
 #back-button:-moz-locale-dir(rtl),
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-locale-dir(rtl),
-toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme {
+#navigator-toolbox[iconsize="large"] > #nav-bar #forward-button:-moz-locale-dir(rtl),
+#forward-button:-moz-locale-dir(rtl):-moz-lwtheme {
   -moz-image-region: rect(0, 60px, 20px, 40px);
 }
 
 @media (min-resolution: 2dppx) {
   #forward-button,
   #back-button:-moz-locale-dir(rtl),
-  #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-locale-dir(rtl),
-  toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme {
+  #navigator-toolbox[iconsize="large"] > #nav-bar #forward-button:-moz-locale-dir(rtl),
+  #forward-button:-moz-locale-dir(rtl):-moz-lwtheme {
     -moz-image-region: rect(0, 120px, 40px, 80px);
   }
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-locale-dir(rtl),
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-locale-dir(rtl),
-toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl):-moz-lwtheme,
-toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme {
+#navigator-toolbox[iconsize="large"] > #nav-bar #back-button:-moz-locale-dir(rtl),
+#navigator-toolbox[iconsize="large"] > #nav-bar #forward-button:-moz-locale-dir(rtl),
+#back-button:-moz-locale-dir(rtl):-moz-lwtheme,
+#forward-button:-moz-locale-dir(rtl):-moz-lwtheme {
   transform: scaleX(-1);
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button {
+#navigator-toolbox[iconsize="large"] > #nav-bar #back-button {
   -moz-appearance: none;
   -moz-margin-end: -7px;
   position: relative;
   z-index: 1;
   -moz-image-region: rect(0, 20px, 20px, 0);
   width: 30px;
   height: 30px;
   padding: 4px 5px 4px 3px;
   border-radius: 10000px;
 }
 
 @media (min-resolution: 2dppx) {
-  #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button {
+  #navigator-toolbox[iconsize="large"] > #nav-bar #back-button {
     -moz-image-region: rect(0, 40px, 40px, 0);
   }
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not(:-moz-lwtheme) {
+#navigator-toolbox[iconsize="large"] > #nav-bar #back-button:not(:-moz-lwtheme) {
   height: 31px;
   padding: 4px 5px 5px 3px;
   margin-bottom: -1px;
   background: url(chrome://browser/skin/keyhole-circle.png) 0 0 no-repeat;
   border-radius: 0;
 }
 
 @media (min-resolution: 2dppx) {
-  #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not(:-moz-lwtheme) {
+  #navigator-toolbox[iconsize="large"] > #nav-bar #back-button:not(:-moz-lwtheme) {
     background-image: url(chrome://browser/skin/keyhole-circle@2x.png);
     background-size: 90px;
   }
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-window-inactive:not(:-moz-lwtheme) {
+#navigator-toolbox[iconsize="large"] > #nav-bar #back-button:-moz-window-inactive:not(:-moz-lwtheme) {
   background-position: -60px 0;
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):active:hover:not(:-moz-lwtheme),
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button[open="true"]:not(:-moz-lwtheme) {
+#navigator-toolbox[iconsize="large"] > #nav-bar #back-button:not([disabled="true"]):active:hover:not(:-moz-lwtheme),
+#navigator-toolbox[iconsize="large"] > #nav-bar #back-button[open="true"]:not(:-moz-lwtheme) {
   background-position: -30px 0;
 }
 
-toolbar[mode="icons"] #forward-button {
+#forward-button {
   -moz-margin-start: 0;
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button > .toolbarbutton-icon {
+#navigator-toolbox[iconsize="large"] > #nav-bar #forward-button > .toolbarbutton-icon {
   /* shift the icon away from the back button */
   margin-left: 3px;
   margin-right: -1px;
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button {
+#navigator-toolbox[iconsize="large"] > #nav-bar #forward-button {
   clip-path: url(chrome://browser/content/browser.xul#osx-keyhole-forward-clip-path);
 }
 
 @conditionalForwardWithUrlbar@ > #forward-button:not(:-moz-lwtheme) {
   -moz-appearance: none;
   -moz-padding-start: 2px;
   background: linear-gradient(hsl(0,0%,99%), hsl(0,0%,67%)) padding-box;
   border: 1px solid;
@@ -728,35 +698,35 @@ toolbar[mode="icons"] #forward-button {
   }
 
   @conditionalForwardWithUrlbar@ > #forward-button:-moz-window-inactive:not(:-moz-lwtheme) {
     background-image: none;
     border-color: hsla(0,0%,0%,.2);
   }
 }
 
-#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar #forward-button {
+#navigator-toolbox[iconsize="small"] > #nav-bar #forward-button {
   width: 27px;
 }
 
-#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar #forward-button:-moz-lwtheme {
+#navigator-toolbox[iconsize="small"] > #nav-bar #forward-button:-moz-lwtheme {
   padding-left: 2px;
 }
 
-toolbar[mode="icons"] #forward-button:-moz-lwtheme {
+#forward-button:-moz-lwtheme {
   border-top-left-radius: 0;
   border-bottom-left-radius: 0;
 }
 
-#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar #back-button {
+#navigator-toolbox[iconsize="small"] > #nav-bar #back-button {
   -moz-margin-end: 0;
   width: 26px;
 }
 
-#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar #back-button:-moz-lwtheme {
+#navigator-toolbox[iconsize="small"] > #nav-bar #back-button:-moz-lwtheme {
   padding-right: 2px;
   border-right-width: 0;
   border-top-right-radius: 0;
   border-bottom-right-radius: 0;
 }
 
 .unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr),
 .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
@@ -1064,21 +1034,21 @@ toolbar[mode="icons"] #forward-button:-m
     -moz-image-region: rect(0, 800px, 40px, 760px);
   }
 
   #zoom-in-button {
     -moz-image-region: rect(0, 840px, 40px, 800px);
   }
 }
 
-toolbar[mode="icons"] #zoom-out-button {
+#zoom-out-button {
   -moz-margin-end: 0;
 }
 
-toolbar[mode="icons"] #zoom-in-button {
+#zoom-in-button {
   -moz-border-start: none;
   -moz-margin-start: 0;
 }
 
 #zoom-out-button:-moz-locale-dir(ltr),
 #zoom-in-button:-moz-locale-dir(rtl) {
   border-top-right-radius: 0;
   border-bottom-right-radius: 0;
@@ -2180,29 +2150,22 @@ toolbarbutton.chevron > .toolbarbutton-m
 }
 
 /* ::::: tabbrowser ::::: */
 
 .tabbrowser-tabbox {
   margin: 0;
 }
 
-.tab-throbber,
-.tab-icon-image {
-  width: 16px;
-  height: 16px;
-  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
-}
-
-.tab-throbber {
-  list-style-image: url("chrome://browser/skin/tabbrowser/connecting.png");
-}
-
-.tab-throbber[progress] {
-  list-style-image: url("chrome://browser/skin/tabbrowser/loading.png");
+%include ../shared/tabs.inc.css
+
+.tab-label {
+  margin-top: 3px;
+  margin-bottom: 0;
+  text-align: center;
 }
 
 @media (min-resolution: 2dppx) {
   .tab-icon-image {
     list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png");
     image-rendering: -moz-crisp-edges;
   }
 
@@ -2211,337 +2174,122 @@ toolbarbutton.chevron > .toolbarbutton-m
   }
 
   .tab-throbber[progress] {
     list-style-image: url("chrome://browser/skin/tabbrowser/loading@2x.png");
   }
 }
 
 .tabbrowser-tab:not(:hover) > .tab-stack > .tab-content > .tab-icon-image:not([selected="true"]) {
-  opacity: .8;
+  opacity: .9;
+}
+
+.tab-label:not([selected="true"]) {
+  opacity: .7;
 }
 
 .tabbrowser-tab:not([pinned]):not([fadein]) {
   transition: min-width 200ms ease-out /* copied from browser/base/content/browser.css */,
-              max-width 250ms ease-out /* copied from browser/base/content/browser.css */,
-              opacity 50ms ease-out 100ms /* hide the tab for the last 100ms of the max-width transition */;
-}
-
-.tab-stack {
-  /* ensure stable tab height with and without toolbarbuttons on the tab bar */
-  height: 26px;
+              max-width 230ms ease-out /* copied from browser/base/content/browser.css */,
+              opacity 50ms ease-out 80ms /* hide the tab for the last 100ms of the max-width transition */;
 }
 
 .tabbrowser-tab,
 .tabs-newtab-button {
-  -moz-appearance: none;
   font: message-box;
   font-weight: bold;
   text-shadow: @loweredShadow@;
-  margin: 0;
-  padding: 0;
   border: none;
-  text-align: center;
-  -moz-box-align: stretch;
-}
-
-%define TABSONTOP_TAB #tabbrowser-tabs[tabsontop="true"] > .tabbrowser-tab
-%define TABSONBOTTOM_TAB #tabbrowser-tabs[tabsontop="false"] > .tabbrowser-tab
-%define TABSONTOP_TAB_STACK #tabbrowser-tabs[tabsontop="true"] > .tabbrowser-tab > .tab-stack
-%define TABSONBOTTOM_TAB_STACK #tabbrowser-tabs[tabsontop="false"] > .tabbrowser-tab > .tab-stack
+}
+
+.tabbrowser-tab {
+  color: #333;
+}
+
 %define TABSONTOP_NEWTAB_BUTTON #tabbrowser-tabs[tabsontop="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button
 %define TABSONBOTTOM_NEWTAB_BUTTON #tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button
 
-@TABSONTOP_TAB_STACK@ > .tab-background {
-  margin-top: 3px;
-}
-
-@TABSONBOTTOM_TAB_STACK@ > .tab-background {
-  margin-bottom: 3px;
-}
-
-@TABSONTOP_TAB_STACK@ > .tab-background:not([selected="true"]):not(:-moz-lwtheme) {
-  margin-bottom: 2px;
-}
-
-@TABSONBOTTOM_TAB_STACK@ > .tab-background:not([selected="true"]) {
-  margin-top: 2px;
-}
-
-.tab-background,
-.tab-content,
-.tabs-newtab-button > .toolbarbutton-icon {
-  -moz-margin-start: -5px;
-  -moz-margin-end: -4px;
-  pointer-events: none;
-}
-
-.tab-close-button {
-  pointer-events: auto;
-}
-
 .tabbrowser-tabs[closebuttons="hidden"] > * > * > * > .tab-close-button:not([pinned]) {
   display: -moz-box;
   visibility: hidden;
 }
 
-.tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox {
-  -moz-padding-start: 5px;
-  -moz-padding-end: 4px;
-}
-
-.tab-content,
 .tabs-newtab-button > .toolbarbutton-icon {
   -moz-box-align: center;
   border: solid transparent;
   border-width: 0 11px;
 }
 
-.tab-background-start,
-.tab-background-end {
-  width: 12px;
-  height: 21px;
-}
-
-.tab-background-middle {
-  -moz-box-flex: 1;
-}
-
-@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-start:-moz-locale-dir(ltr),
-@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-end:-moz-locale-dir(rtl) {
-  clip-path: url(chrome://browser/content/browser.xul#osx-tab-ontop-left-curve-clip-path);
-}
-
-@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-end:-moz-locale-dir(ltr),
-@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-start:-moz-locale-dir(rtl) {
-  clip-path: url(chrome://browser/content/browser.xul#osx-tab-ontop-right-curve-clip-path);
-}
-
-@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-start:-moz-locale-dir(ltr),
-@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-end:-moz-locale-dir(rtl) {
-  clip-path: url(chrome://browser/content/browser.xul#osx-tab-onbottom-left-curve-clip-path);
-}
-
-@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-end:-moz-locale-dir(ltr),
-@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-start:-moz-locale-dir(rtl) {
-  clip-path: url(chrome://browser/content/browser.xul#osx-tab-onbottom-right-curve-clip-path);
-}
-
-.tab-background-start[selected="true"]:not(:-moz-lwtheme),
-.tab-background-middle[selected="true"]:not(:-moz-lwtheme),
-.tab-background-end[selected="true"]:not(:-moz-lwtheme) {
-  background-color: -moz-mac-chrome-active;
-}
-
-.tab-background-start[selected="true"]:not(:-moz-lwtheme):-moz-window-inactive,
-.tab-background-middle[selected="true"]:not(:-moz-lwtheme):-moz-window-inactive,
-.tab-background-end[selected="true"]:not(:-moz-lwtheme):-moz-window-inactive {
-  background-color: -moz-mac-chrome-inactive;
-}
-
-.tab-background-start[pinned][titlechanged]:not([selected="true"]),
-.tab-background-end[pinned][titlechanged]:not([selected="true"]) {
-  background-image: linear-gradient(rgba(148,205,253,.2), rgba(148,205,253,.2)) !important;
-}
-
-@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-middle[pinned][titlechanged]:not([selected="true"]) {
-  background-image: radial-gradient(circle farthest-corner at 50% 99%, rgba(254,254,255,1) 3%, rgba(210,235,255,.9) 12%, rgba(148,205,253,.6) 30%, rgba(148,205,253,.2) 70%);
-}
-
-@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-middle[pinned][titlechanged]:not([selected="true"]) {
-  background-image: radial-gradient(circle farthest-corner at 50% 2px, rgba(254,254,255,1) 3%, rgba(210,235,255,.9) 12%, rgba(148,205,253,.6) 30%, rgba(148,205,253,.2) 70%);
-}
-
-.tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start:-moz-lwtheme-brighttext:not([selected="true"]),
-.tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle:-moz-lwtheme-brighttext:not([selected="true"]),
-.tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end:-moz-lwtheme-brighttext:not([selected="true"]) {
-  background-image: linear-gradient(hsla(0,0%,40%,.6), hsla(0,0%,30%,.6) 50%);
-}
-
-.tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start:-moz-lwtheme-darktext:not([selected="true"]),
-.tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle:-moz-lwtheme-darktext:not([selected="true"]),
-.tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end:-moz-lwtheme-darktext:not([selected="true"]) {
-  background-image: linear-gradient(hsla(0,0%,60%,.5), hsla(0,0%,45%,.5) 50%);
-}
-
-@TABSONTOP_TAB_STACK@ > .tab-content,
-@TABSONTOP_NEWTAB_BUTTON@ > .toolbarbutton-icon {
-  border-image: url(chrome://browser/skin/tabbrowser/tab-top-normal-active.png) 0 11 fill repeat stretch;
-}
-
-@TABSONTOP_TAB@:hover > .tab-stack > .tab-content:not([selected="true"]),
-@TABSONTOP_NEWTAB_BUTTON@:hover > .toolbarbutton-icon {
-  border-image: url(chrome://browser/skin/tabbrowser/tab-top-hover-active.png) 0 11 fill repeat stretch;
-}
-
-@TABSONTOP_TAB_STACK@ > .tab-content[selected="true"] {
-  border-image: url(chrome://browser/skin/tabbrowser/tab-top-selected-active.png) 0 11 fill repeat stretch;
-}
-
-@TABSONBOTTOM_TAB_STACK@ > .tab-content,
-@TABSONBOTTOM_NEWTAB_BUTTON@ > .toolbarbutton-icon {
-  border-image: url(chrome://browser/skin/tabbrowser/tab-bottom-normal-active.png) 0 11 fill repeat stretch;
-}
-
-@media (min-resolution: 2dppx) {
-  @TABSONTOP_TAB_STACK@ > .tab-content,
-  @TABSONTOP_NEWTAB_BUTTON@ > .toolbarbutton-icon {
-    border-image: url(chrome://browser/skin/tabbrowser/tab-top-normal-active@2x.png) 0 22 fill repeat stretch;
-  }
-
-  @TABSONTOP_TAB@:hover > .tab-stack > .tab-content:not([selected="true"]),
-  @TABSONTOP_NEWTAB_BUTTON@:hover > .toolbarbutton-icon {
-    border-image: url(chrome://browser/skin/tabbrowser/tab-top-hover-active@2x.png) 0 22 fill repeat stretch;
-  }
-
-  @TABSONTOP_TAB_STACK@ > .tab-content[selected="true"] {
-    border-image: url(chrome://browser/skin/tabbrowser/tab-top-selected-active@2x.png) 0 22 fill repeat stretch;
-  }
-}
-
-@TABSONBOTTOM_TAB@:hover > .tab-stack > .tab-content:not([selected="true"]),
-@TABSONBOTTOM_NEWTAB_BUTTON@:hover > .toolbarbutton-icon {
-  border-image: url(chrome://browser/skin/tabbrowser/tab-bottom-hover-active.png) 0 11 fill repeat stretch;
-}
-
-@TABSONBOTTOM_TAB_STACK@ > .tab-content[selected="true"] {
-  border-image: url(chrome://browser/skin/tabbrowser/tab-bottom-selected-active.png) 0 11 fill repeat stretch;
-}
-
-/* preloading hack */
-#TabsToolbar::after {
-  content: '';
-  display: block;
-  background-image:
-    url(chrome://browser/skin/tabbrowser/tab-top-normal-active.png),
-    url(chrome://browser/skin/tabbrowser/tab-top-hover-active.png),
-    url(chrome://browser/skin/tabbrowser/tab-top-selected-active.png),
-    url(chrome://browser/skin/tabbrowser/tab-bottom-normal-active.png),
-    url(chrome://browser/skin/tabbrowser/tab-bottom-hover-active.png),
-    url(chrome://browser/skin/tabbrowser/tab-bottom-selected-active.png),
-    url(chrome://browser/skin/tabbrowser/tabbar-top-bg-active.png),
-    url(chrome://browser/skin/tabbrowser/tabbar-top-bg-inactive.png),
-    url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-active.png),
-    url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-inactive.png);
-}
-
-@media (min-resolution: 2dppx) {
-  #TabsToolbar::after {
-    content: '';
-    display: block;
-    background-image:
-      url(chrome://browser/skin/tabbrowser/tab-top-normal-active@2x.png),
-      url(chrome://browser/skin/tabbrowser/tab-top-hover-active@2x.png),
-      url(chrome://browser/skin/tabbrowser/tab-top-selected-active@2x.png),
-      url(chrome://browser/skin/tabbrowser/tab-bottom-normal-active.png),
-      url(chrome://browser/skin/tabbrowser/tab-bottom-hover-active.png),
-      url(chrome://browser/skin/tabbrowser/tab-bottom-selected-active.png),
-      url(chrome://browser/skin/tabbrowser/tabbar-top-bg-active.png),
-      url(chrome://browser/skin/tabbrowser/tabbar-top-bg-inactive.png),
-      url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-active.png),
-      url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-inactive.png);
-  }
-}
-
-.tabbrowser-tab:focus > .tab-stack {
+.tabbrowser-tab:focus > .tab-stack > .tab-content > .tab-label {
   box-shadow: @focusRingShadow@;
 }
 
-.tabbrowser-tab:not([selected="true"]):not(:hover):not(:-moz-lwtheme) {
-  color: #222;
-}
-
-.tabbrowser-tab[selected="true"] {
-  color: #000;
-  z-index: 1;
-  position: relative;
-}
-
 .tabbrowser-tab:-moz-lwtheme {
   color: inherit;
   text-shadow: inherit;
 }
 
-#main-window:not([privatebrowsingmode=temporary]) #navigator-toolbox[tabsontop="true"]:not(:-moz-lwtheme)::before {
+#main-window:not([privatebrowsingmode=temporary]):not([customizing]):not([customize-exiting]) #navigator-toolbox[tabsontop="true"]:not(:-moz-lwtheme)::before {
   /* We want the titlebar to be unified, but we still want to be able
    * to give #TabsToolbar a background. So we can't set -moz-appearance:
    * toolbar on #TabsToolbar itself. Instead, we set it on a box of the
    * right size which is put underneath #TabsToolbar.
    */
   content: '';
   display: block;
   -moz-appearance: toolbar;
-  height: 25px;
-  margin-bottom: -25px;
+  height: calc(@tabHeight@ + 1px);
+  margin-bottom: calc(-1px - @tabHeight@);
 }
 
 #TabsToolbar {
+  position: relative;
   -moz-appearance: none;
-  height: 26px;
   background-repeat: repeat-x;
 }
 
 #TabsToolbar[tabsontop="false"] {
   margin-top: -2px;
   padding-top: 2px;
 }
 
-/* For tabs-on-top, only fill the bottom 2px with the chrome background
- * color, so that the borders in tabbar-top-bg-*.png can mix with it.
- * In the top 24px the unified toolbar (from the ::before above) will show.
+/*
+ * Draw the bottom border of the tabstrip:
  */
-#TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme) {
-  padding-bottom: 2px;
-  background: url(chrome://browser/skin/tabbrowser/tabbar-top-bg-active.png),
-              linear-gradient(to top, -moz-mac-chrome-active 2px, transparent 2px);
-}
-
-#TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme):-moz-window-inactive {
-  background: url(chrome://browser/skin/tabbrowser/tabbar-top-bg-inactive.png),
-              linear-gradient(to top, -moz-mac-chrome-inactive 2px, transparent 2px);
+#TabsToolbar::after {
+  content: '';
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  z-index: 0;
+  border-bottom: 1px solid hsla(0,0%,0%,.22);
 }
 
 /* In tabs-on-bottom mode, fill the whole toolbar with the chrome
  * background color.
  */
 #TabsToolbar[tabsontop="false"]:not(:-moz-lwtheme) {
-  background: url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-active.png) -moz-mac-chrome-active;
+  background: -moz-mac-chrome-active;
 }
 
 #TabsToolbar[tabsontop="false"]:not(:-moz-lwtheme):-moz-window-inactive {
-  background: url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-inactive.png) -moz-mac-chrome-inactive;
+  background: -moz-mac-chrome-inactive;
 }
 
 #tabbrowser-tabs {
   -moz-box-align: stretch;
-  height: 26px;
-}
-
-#tabbrowser-tabs[tabsontop="true"] > .tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox:not(:-moz-lwtheme) {
-  margin-bottom: -2px;
-}
-
-#tabbrowser-tabs[tabsontop="false"] > .tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox {
-  margin-top: -2px;
 }
 
 @TABSONTOP_NEWTAB_BUTTON@ > .toolbarbutton-icon {
-  padding: 4px 0 2px;
-}
-
-@TABSONTOP_TAB_STACK@ > .tab-content {
-  padding-top: 2px;
+  padding: 6px 0 4px;
 }
 
 @TABSONBOTTOM_NEWTAB_BUTTON@ > .toolbarbutton-icon {
-  padding: 2px 0 4px;
-}
-
-@TABSONBOTTOM_TAB_STACK@ > .tab-content {
-  padding-bottom: 2px;
+  padding: 4px 0 6px;
 }
 
 /**
  * Tab Drag and Drop
  */
 
 .tab-drop-indicator {
   list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png);
@@ -2562,18 +2310,16 @@ toolbarbutton.chevron > .toolbarbutton-m
 .tab-close-button > .toolbarbutton-icon {
   -moz-margin-end: 0px !important;
 }
 
 .tab-close-button {
   list-style-image: url("chrome://global/skin/icons/close.png");
   -moz-appearance: none;
   border: none !important;
-  padding: 0;
-  margin: 0;
   background: none;
   cursor: default;
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
 .tab-close-button:hover {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
@@ -3881,16 +3627,59 @@ toolbar[mode="icons"] > *|* > .toolbarbu
   background-image: radial-gradient(circle farthest-corner at center 2px, rgb(254,254,255) 3%, rgba(210,235,255,0.9) 12%, rgba(148,205,253,0.6) 30%, rgba(148,205,253,0.2) 70%);
 }
 
 chatbox {
   border-top-left-radius: @toolbarbuttonCornerRadius@;
   border-top-right-radius: @toolbarbuttonCornerRadius@;
 }
 
+/* Customization mode */
+
+%include ../shared/customizableui/customizeMode.inc.css
+
+#main-window[customizing] #titlebar {
+  padding-top: 0;
+}
+
+#main-window[customizing] #tab-view-deck {
+  padding: 28px 2em 2em;
+}
+
+#main-window[customizing] #tab-view-deck,
+#main-window[customize-exiting] #tab-view-deck {
+  background-image: url("chrome://browser/skin/customizableui/customizeMode-gridTexture.png"),
+                    url("chrome://browser/skin/customizableui/background-noise-toolbar.png"),
+                    linear-gradient(to bottom, rgb(233,233,233), rgb(178,178,178) 21px);
+  background-attachment: fixed;
+}
+
+#main-window[customizing] #navigator-toolbox > toolbar:not(#TabsToolbar),
+#main-window[customizing] #customization-container {
+  border: 3px solid hsla(0,0%,0%,.1);
+  border-top-width: 0;
+  background-clip: padding-box;
+  background-origin: padding-box;
+  -moz-border-right-colors: hsla(0,0%,0%,.05) hsla(0,0%,0%,.1) hsla(0,0%,0%,.2);
+  -moz-border-bottom-colors: hsla(0,0%,0%,.05) hsla(0,0%,0%,.1) hsla(0,0%,0%,.2);
+  -moz-border-left-colors: hsla(0,0%,0%,.05) hsla(0,0%,0%,.1) hsla(0,0%,0%,.2);
+}
+
+#main-window[customizing] #navigator-toolbox > toolbar:not(#TabsToolbar) {
+  border-bottom-width: 0;
+}
+
+#main-window[customizing] #TabsToolbar {
+  background-clip: padding-box;
+  border-right: 3px solid transparent;
+  border-left: 3px solid transparent;
+}
+
+/* End customization mode */
+
 panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow[side="top"],
 panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow[side="bottom"] {
   list-style-image: url("chrome://global/skin/arrow/panelarrow-light-vertical.png");
 }
 @media (min-resolution: 2dppx) {
   panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow[side="top"],
   panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow[side="bottom"] {
     list-style-image: url("chrome://global/skin/arrow/panelarrow-light-vertical@2x.png");
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d09ba9dafb5ede66e92ce577ecaa6f9575dba104
GIT binary patch
literal 15601
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
LNkvXXu0mjfSmbEw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a7c2775cfc799da31a505b249f5a59b89c148a58
GIT binary patch
literal 118
zc%17D@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3ww^AIAr-gYUfIaWpuppLFlU13
zo%)jzH=|it_dY6Z)V5Pum31fM;KsnRdyNMlls~YU+j}r!!}-)?gCEKjOuj1pzc){H
R6$2W?;OXk;vd$@?2>=UhDL4QC
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5e17cb4db08e310e6c3a9e14c5bd722772dfb639
GIT binary patch
literal 1426
zc$@)}1#S9?P)<h;3K|Lk000e1NJLTq00H0t000aK1^@s6x+QMd000G9Nkl<ZcwX(B
zO>g8j42Jp2&TP87-2_FZ*z`~YX#f8&$|0v-TD03O+GIW~_Au6rWZI@|*6s|(0=Oef
z<V%hN>?7I<zJ2)NCprvAU4sc?4Z&YAsqGrtL{MTBO{tKpXU?nV*0rS?|0gxWT$4Rk
zkDq6Nu6OXn`raBhV?2-0_U3vZGP6O?P^%%gJ+DtHfU3z^dAVgB<XdX;8F{>6-g3=8
z#sk;;h`5Ij-#^|G5f#TWiW4lD8x^whqh#Wuxx}uaD}y=tQ2h$Y0e5uiL<09ifHnU#
zGmA_)={O5VPW94tmGYFkWHq({k?Ep`n}Bd<40otN!Hnl8UBM564!pS@pN%O<Pbd*d
zft6k>^cwWr;FGJWH56^iUiAxVNY_!3*S`zWWypI|h0Q&Pl6nxug~ff)Ask{N|0o70
zU(|K)2nWE{pR_|*^#s(KAbeauu4+)$qNVGiBDWB;q!32LB8CMt0-;$2NC!C5Dr8Jq
z1n^7HWB}e-LBmBZQJlg|HyfQ;*|f_$6Q7u`0JN72W(f^gVd*D*=mEoRHi*J^>g!ri
z;i|JAgJM&N?JI?U7{GJL8LF1L(fB~kx%vaa7d>1*64%FIhtv<EQRqGv@<+Iapt!C8
z?Oj;gg<Ju)KKKM3xE<mB!{h3Ph?rwYlqm?f4SFoyxz~$`xgRcR4Fb|bpb=^+WDz|e
zEX9BJY=IIF1r8e;>45NpOrtOn+bOOlycd`ERQIZ$uvfZ^H#A~4=gR!;x)F-pLj)#j
z{GqLcF0BXrNTwAfP|{NS4!EW{0S)%@tk4BY+4c71+56KLXxE{Q)7;ZG=p1n?wSfkJ
zW55QN?V%HYBiaC|4~X#byU%482xa%e>2!4?m+OmFB%?u#Q%BcLn~+a|WG<{ra)U72
zb4VGC7*-+-S`)#=jfP|~sz7(fEL;W*9i--4!N5;L!DcBas|vtIb+;05x&lO~LT_a|
ztnB){5(st=B(mG%Dx}MHM+6Cf9mwPf=+-4fb#5XVq<Ud@lYrF=EyQ}Sr#V2lzyDk&
z0KApJk)RCru4j*3FB8QAn;u7UC%EO(O}JjwR|DEi=ILm_{o+o~dDA648hkuumslEP
z7rXo>d_P#&&w^XXXdN(mjQ}RQ$$%0gmUf=D4QxV>M}7f5#}9;I@K545U3>B!@LS>+
zT|&kuGBq?I{9=p1i%wwUZ`Xi35k9Qft_G+Z4v24Bh{Rzhip$kwE%!iU*Q@g`{9^^A
ztljR$S~2syl4Q0^bk(*p<X`N(EeAGR!#iMGem~du1YwfL&33?Vh&Ea*l>4OBpu$vT
z^lKC=onCV~YYozQd(NG5HT>{btl{FhSo;HClHVJ~-QABhfTMf;NkAvR6ZL*v2g_^*
zK{!Nc_C7sCD7lq7ZKQQl-(G{gW1XpnTUy37+nZei!2kKa+~?MS(P?1^pY%=8_D_DC
zHy=oVadFP&#>qTisRfW-YhQXh+~323b6OqJrzlSIUupo;dhLcn@1b$+y&nV%J5=tY
zxYpdc`>r+jr+GRvd0?3<@63?5YAv>O&vro1U$YJri}~!lUkAckf=Ywd5cr$@TnaY-
z+t{B;&`BYw`AaLy!{jCRJ==5K*FUAIPn0+Idm22vr%|J-!pxj=JqK{);lylur$0ZC
zucZcQcXVFk&okjBuCfN%8QRS`H|zcRRfCOg5@Nd9bCzWuR9+M?3OLSV2wmW1+0Vv!
z<?!${MpDt7hVFE+qpD~bi-nHkBFzrTF~Auf^P-B9Z9LQRC-LJ9be+S|G8VHP0ME#t
gX&H-M9>A9IFDL!=ycbq6DF6Tf07*qoM6N<$g5jpFQvd(}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dc4caee812878f246c87d71093768eb36c5656fc
GIT binary patch
literal 1649
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
new file mode 100644
--- /dev/null
+++ b/browser/themes/osx/customizableui/panelUIOverlay.css
@@ -0,0 +1,57 @@
+/* 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/. */
+
+%filter substitution
+%define menuPanelWidth 26em
+
+%include ../../shared/customizableui/panelUIOverlay.inc.css
+
+.PanelUI-pageControls toolbarbutton {
+  list-style-image: url("chrome://browser/skin/Toolbar.png");
+}
+
+.PanelUI-pageControls toolbarbutton:not(:first-child) {
+  -moz-margin-start: 0;
+}
+.PanelUI-pageControls toolbarbutton:not(:last-child) {
+  -moz-margin-end: 0;
+}
+.PanelUI-pageControls toolbarbutton:not(:first-child):not(:last-child) {
+  margin-left: 0;
+  margin-right: 0;
+}
+
+#PanelUI-cut-btn {
+  -moz-image-region: rect(0, 260px, 20px, 240px);
+}
+#PanelUI-copy-btn {
+  -moz-image-region: rect(0, 280px, 20px, 260px);
+}
+#PanelUI-paste-btn {
+  -moz-image-region: rect(0, 300px, 20px, 280px);
+}
+
+#PanelUI-zoomOut-btn {
+  -moz-image-region: rect(0, 400px, 20px, 380px);
+  padding-left: 12px;
+  padding-right: 12px;
+}
+#PanelUI-zoomIn-btn {
+  -moz-image-region: rect(0, 420px, 20px, 400px);
+  padding-left: 12px;
+  padding-right: 12px;
+}
+
+.PanelUI-editControls #PanelUI-copy-btn,
+.PanelUI-zoomControls #PanelUI-zoomReset-btn {
+  border-left: none;
+  border-right: none;
+  border-radius: 0;
+}
+
+#PanelUI-zoomIn-btn .toolbarbutton-text,
+#PanelUI-zoomOut-btn .toolbarbutton-text,
+#PanelUI-zoomReset-btn .toolbarbutton-icon {
+  display: none;
+}
\ No newline at end of file
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -13,18 +13,24 @@ browser.jar:
   skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png
   skin/classic/browser/aboutCertError_sectionExpanded.png
   skin/classic/browser/aboutSocialError.css
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/aboutSyncTabs.css
 #endif
   skin/classic/browser/actionicon-tab.png
   skin/classic/browser/actionicon-tab@2x.png
+  skin/classic/browser/appmenu.png
 * skin/classic/browser/browser.css                          (browser.css)
+* skin/classic/browser/browser-lightweightTheme.css
   skin/classic/browser/click-to-play-warning-stripes.png
+  skin/classic/browser/customizableui/background-noise-toolbar.png  (customizableui/background-noise-toolbar.png)
+  skin/classic/browser/customizableui/customizeMode-gridTexture.png  (customizableui/customizeMode-gridTexture.png)
+  skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png  (customizableui/customizeMode-separatorHorizontal.png)
+  skin/classic/browser/customizableui/customizeMode-separatorVertical.png  (customizableui/customizeMode-separatorVertical.png)
 * skin/classic/browser/engineManager.css                    (engineManager.css)
   skin/classic/browser/Geolocation-16.png
   skin/classic/browser/Geolocation-16@2x.png
   skin/classic/browser/Geolocation-64.png
   skin/classic/browser/Geolocation-64@2x.png
   skin/classic/browser/home.png
   skin/classic/browser/identity.png
   skin/classic/browser/identity@2x.png
@@ -89,16 +95,17 @@ browser.jar:
   skin/classic/browser/urlbar-popup-blocked.png
   skin/classic/browser/urlbar-popup-blocked@2x.png
   skin/classic/browser/webRTC-shareDevice-16.png
   skin/classic/browser/webRTC-shareDevice-16@2x.png
   skin/classic/browser/webRTC-shareDevice-64.png
   skin/classic/browser/webRTC-shareDevice-64@2x.png
   skin/classic/browser/webRTC-sharingDevice-16.png
   skin/classic/browser/webRTC-sharingDevice-16@2x.png
+* skin/classic/browser/customizableui/panelUIOverlay.css    (customizableui/panelUIOverlay.css)
   skin/classic/browser/downloads/buttons.png                (downloads/buttons.png)
   skin/classic/browser/downloads/buttons@2x.png             (downloads/buttons@2x.png)
   skin/classic/browser/downloads/download-glow.png          (downloads/download-glow.png)
   skin/classic/browser/downloads/download-glow@2x.png       (downloads/download-glow@2x.png)
   skin/classic/browser/downloads/download-notification-finish.png  (downloads/download-notification-finish.png)
   skin/classic/browser/downloads/download-notification-finish@2x.png  (downloads/download-notification-finish@2x.png)
   skin/classic/browser/downloads/download-notification-start.png  (downloads/download-notification-start.png)
   skin/classic/browser/downloads/download-notification-start@2x.png  (downloads/download-notification-start@2x.png)
@@ -177,36 +184,35 @@ browser.jar:
   skin/classic/browser/social/chat-close.png                             (social/chat-close.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png             (tabbrowser/alltabs-box-bkgnd-icon.png)
   skin/classic/browser/tabbrowser/newtab.png                             (tabbrowser/newtab.png)
   skin/classic/browser/tabbrowser/newtab@2x.png                          (tabbrowser/newtab@2x.png)
   skin/classic/browser/tabbrowser/connecting.png                         (tabbrowser/connecting.png)
   skin/classic/browser/tabbrowser/connecting@2x.png                      (tabbrowser/connecting@2x.png)
   skin/classic/browser/tabbrowser/loading.png                            (tabbrowser/loading.png)
   skin/classic/browser/tabbrowser/loading@2x.png                         (tabbrowser/loading@2x.png)
+  skin/classic/browser/tabbrowser/tab-active-middle.png                  (tabbrowser/tab-active-middle.png)
+  skin/classic/browser/tabbrowser/tab-active-middle-lwtheme.png          (tabbrowser/tab-active-middle-lwtheme.png)
   skin/classic/browser/tabbrowser/tab-arrow-left.png                     (tabbrowser/tab-arrow-left.png)
   skin/classic/browser/tabbrowser/tab-arrow-left@2x.png                  (tabbrowser/tab-arrow-left@2x.png)
   skin/classic/browser/tabbrowser/tab-arrow-right.png                    (tabbrowser/tab-arrow-right.png)
   skin/classic/browser/tabbrowser/tab-arrow-right@2x.png                 (tabbrowser/tab-arrow-right@2x.png)
+  skin/classic/browser/tabbrowser/tab-background-end.png                 (tabbrowser/tab-background-end.png)
+  skin/classic/browser/tabbrowser/tab-background-middle.png              (tabbrowser/tab-background-middle.png)
+  skin/classic/browser/tabbrowser/tab-background-start.png               (tabbrowser/tab-background-start.png)
+  skin/classic/browser/tabbrowser/tab-stroke-end.png                     (tabbrowser/tab-stroke-end.png)
+  skin/classic/browser/tabbrowser/tab-stroke-start.png                   (tabbrowser/tab-stroke-start.png)
   skin/classic/browser/tabbrowser/tabbar-bottom-bg-active.png            (tabbrowser/tabbar-bottom-bg-active.png)
   skin/classic/browser/tabbrowser/tabbar-bottom-bg-inactive.png          (tabbrowser/tabbar-bottom-bg-inactive.png)
-  skin/classic/browser/tabbrowser/tab-bottom-normal-active.png           (tabbrowser/tab-bottom-normal-active.png)
-  skin/classic/browser/tabbrowser/tab-bottom-hover-active.png            (tabbrowser/tab-bottom-hover-active.png)
-  skin/classic/browser/tabbrowser/tab-bottom-selected-active.png         (tabbrowser/tab-bottom-selected-active.png)
   skin/classic/browser/tabbrowser/tabbar-top-bg-active.png               (tabbrowser/tabbar-top-bg-active.png)
   skin/classic/browser/tabbrowser/tabbar-top-bg-inactive.png             (tabbrowser/tabbar-top-bg-inactive.png)
-  skin/classic/browser/tabbrowser/tab-top-normal-active.png              (tabbrowser/tab-top-normal-active.png)
-  skin/classic/browser/tabbrowser/tab-top-normal-active@2x.png           (tabbrowser/tab-top-normal-active@2x.png)
-  skin/classic/browser/tabbrowser/tab-top-hover-active.png               (tabbrowser/tab-top-hover-active.png)
-  skin/classic/browser/tabbrowser/tab-top-hover-active@2x.png            (tabbrowser/tab-top-hover-active@2x.png)
-  skin/classic/browser/tabbrowser/tab-top-selected-active.png            (tabbrowser/tab-top-selected-active.png)
-  skin/classic/browser/tabbrowser/tab-top-selected-active@2x.png         (tabbrowser/tab-top-selected-active@2x.png)
   skin/classic/browser/tabbrowser/tab-overflow-border.png                (tabbrowser/tab-overflow-border.png)
   skin/classic/browser/tabbrowser/tabDragIndicator.png                   (tabbrowser/tabDragIndicator.png)
   skin/classic/browser/tabbrowser/tabDragIndicator@2x.png                (tabbrowser/tabDragIndicator.png)
+  skin/classic/browser/tabbrowser/tab-separator.png                      (tabbrowser/tab-separator.png)
   skin/classic/browser/tabview/close.png                    (tabview/close.png)
   skin/classic/browser/tabview/edit-light.png               (tabview/edit-light.png)
   skin/classic/browser/tabview/search.png                   (tabview/search.png)
   skin/classic/browser/tabview/stack-expander.png           (tabview/stack-expander.png)
   skin/classic/browser/tabview/tabview.png                  (tabview/tabview.png)
   skin/classic/browser/tabview/tabview.css                  (tabview/tabview.css)
 * skin/classic/browser/devtools/common.css                  (devtools/common.css)
   skin/classic/browser/devtools/dark-theme.css              (devtools/dark-theme.css)
@@ -317,16 +323,17 @@ browser.jar:
   skin/classic/browser/syncCommon.css
   skin/classic/browser/syncQuota.css
   skin/classic/browser/syncProgress.css
 #endif
   skin/classic/browser/lion/keyhole-circle.png              (keyhole-circle-lion.png)
   skin/classic/browser/keyhole-circle@2x.png                (keyhole-circle-lion@2x.png)
   skin/classic/browser/lion/Toolbar.png                     (Toolbar-lion.png)
   skin/classic/browser/Toolbar@2x.png                       (Toolbar-lion@2x.png)
+  skin/classic/browser/Toolbar-background-noise.png         (Toolbar-background-noise.png)
   skin/classic/browser/lion/toolbarbutton-dropmarker.png    (toolbarbutton-dropmarker-lion.png)
   skin/classic/browser/toolbarbutton-dropmarker@2x.png      (toolbarbutton-dropmarker-lion@2x.png)
   skin/classic/browser/lion/tabbrowser/alltabs-box-bkgnd-icon.png      (tabbrowser/alltabs-box-bkgnd-icon-lion.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon@2x.png        (tabbrowser/alltabs-box-bkgnd-icon-lion@2x.png)
   skin/classic/browser/lion/tabview/tabview.png                        (tabview/tabview-lion.png)
   skin/classic/browser/lion/places/toolbar.png              (places/toolbar-lion.png)
   skin/classic/browser/webapps-16.png
   skin/classic/browser/webapps-16@2x.png
--- a/browser/themes/osx/shared.inc
+++ b/browser/themes/osx/shared.inc
@@ -1,6 +1,10 @@
 %include ../../../toolkit/themes/osx/global/shared.inc
 %include ../shared/browser.inc
 
+%define fgTabTexture linear-gradient(hsla(0,0%,100%,0.6), hsla(0,0%,100%,0.6) 0px, hsl(0,0%,99%) 1px, hsl(0,0%,92%))
+%define toolbarColorLWT rgba(253,253,253,0.45)
+%define fgTabTextureLWT linear-gradient(transparent, transparent 2px, rgba(254,254,254,0.72) 2px, @toolbarColorLWT@)
+%define fgTabBackgroundMiddle linear-gradient(transparent, transparent)
 %define hudButton -moz-appearance: none; color: #434343; border-radius: 4px; border: 1px solid #b5b5b5; background: linear-gradient(#fff, #f2f2f2); box-shadow: inset 0 1px rgba(255,255,255,.8), inset 0 0 1px rgba(255,255, 255,.25), 0 1px rgba(255,255,255,.3); background-clip: padding-box; background-origin: padding-box; padding: 2px 6px;
 %define hudButtonPressed box-shadow: inset 0 1px 4px -3px #000, 0 1px rgba(255,255,255,.3);
 %define hudButtonFocused box-shadow: 0 0 1px -moz-mac-focusring inset, 0 0 4px 1px -moz-mac-focusring, 0 0 2px 1px -moz-mac-focusring;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ec7c84e3476db7204115f8a9bc03cf2436b0405f
GIT binary patch
literal 148
zc%17D@N?(olHy`uVBq!ia0vp^Y(Ol}0V0ox?vVxwBze2LF#HF>1$&oI28wVNctjR6
zFmMZlFeAgPITAoY_7YEDSN6NC93m{*d+wX60fiJjT^vI+&L^iNB_$;vV3LrOkf_<{
lwddc5&`F6RJxz%$3?4g~-8{VaECDKJ@O1TaS?83{1ORhhCHDXT
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7872d03678032661cced28b941f1fbd353019707
GIT binary patch
literal 227
zc%17D@N?(olHy`uVBq!ia0vp^Y(Ol}0V0ox?vVykk|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*D5XT0LDHLo_B{4UFbHpulmt?oHP2_wSbbd7QFpXP5AN%<Q$1
z>A=KA-|NyGvfrL+FmyZFu&Hytfld(H<m%q2>~)57d$ex1x5Y(lxNvmsT-hCM7B4@`
z&trKhRmN8+o0RRTa;5LQ^^MzX1-(}t`uO)gDLI!gb!)}W)lzHtj{Oq5eqrA#Q8l3+
Z>4mxm7tMYeO#nKG!PC{xWt~$(699F7SXlr7
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9374cbda64b64563200cb6b8488ef3495781375b
GIT binary patch
literal 677
zc$@*H0$TlvP)<h;3K|Lk000e1NJLTq0015U0018d1^@s6@N9ht0007PNkl<Zc-p<!
z&1xD^7{+lE$2!_72`SR1P%6?&KWHh9X*9+d<40mlQng7M0<EQ8xEF;8-h(@@z>Qlk
zz*Rueg=;ri1XOe(Sp-26)8~aVAfW{3%(TMqU5N1K9Ovka1}`Hcf*y1rz$`OEZf<Tg
zYNFRC_yF(VB`m@t5J3l8m{mJYBiZlwf1aP8f3H+3hq+uXU^bf_2-(2`A_!`)UUPkY
zy$ex@!!h3cadma|yH=|m9~~We5qbr4@Bp-G#c4$TVh;{SqtUN&xg1+qSXf5vIg1NY
zd^{d&cu{!g9ufG~?RFDOOG~SWy<qX#e;t<MF^b#mc8Wg*ozggk!&8bjo6Qq;^&3G@
z8s44~#ShZybWrh@v+$M-;ZCP>VltVW2tEWsNjM}^G?hw)5PZhHY8DR4w0(AVcEG-C
zQAs!;Q*byOex0A6cOz&5fj8{u5J@JJwB3u+(c%ejatIZR#V_plT+g%JG<+QVjYcDe
z*hdgS%M;$<;JduMq!qis$Q$-@+IBb`n+QGz9Zz_jQy`no?jUI8InOjaoP4EHX`lBz
z(^%uQ-fFcdyu$N6({OX5_?E}x2_k5b`&UV0RRM24pQly7mV2ydxD;^rdc8eS6nzMq
z<*b^9Q=yI1)6)oIZ@~cCY2upO+uId|T!X=2-)gl=HwgO4IKgK$chUH)g0*V38poFV
z*||1MJ`6B35-Gf_6pMT7^?KZ5vCzujfC&tszxzZ&DC|(lGI%a7E@GKXW={}=00QsX
z_CJ}pLDZ@pmN+5QZnxuwLLr(+BzAGu!#10ZF1|VG8u<TVcHaL0pr1FohJ36x00000
LNkvXXu0mjfU3W3*
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..060a3afa4abd9a732e2da16ecb57d0b4df0c851d
GIT binary patch
literal 153
zc%17D@N?(olHy`uVBq!ia0vp^Y(Ol}0V0ox?vVykk|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*D5XtUX;ELp07OCnh93NIJk2(GVfL`pEtL^}ZXt{`~*{Uowo-
z&F$F#9d8b39(35$w@}3~Y(mekIb0{%wHX)|>dUV;d=$P4Xbgj=tDnm{r-UW|Vtq7`
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5b0c62ca637166ead5fbdac5e054e69dab18e7f9
GIT binary patch
literal 657
zc$@)|0&e|@P)<h;3K|Lk000e1NJLTq0015U0018d1^@s6@N9ht00075Nkl<Zc-p<z
zO=}uK9LI4R*SbxsL@d&#P!wsUjkJ_%8ckwt;zJ%ankF^`T1$KIE(R2Q58iwQUcCAO
zJOvDT@a)AyKt&JYK?G6LpYRtGA>ht#Dts=>?0k1-9aJ_P4kd-pBeFm^P=FG6SR9i)
zN-;Ubcz6cO@CMBA5k5b}Dme=3z@%2It;uB4ozLe_tJUhyR;%?J_e7+O%Hc6A!P`(M
z<h;7NI_q}3e=+XYU@$m?V+g>ZY&06Nx*g>x`dX{iuI6&NV87r0gWxIn;9!;%;RTB7
zEf&jqqtOUs;vW>)zmF7A1-vwwOp|DE5`D-p2a8}Xm&@mvFaUe=kYtNvv6u&wozSGa
z^ANk*rz(}oR<GC3DY`Q+v8#O*jYhq+#a<!Agn2MuUS6Ki_IZR5v&|}vMzhiD^}f?&
zZXsC0lOwboiA20~bX-EQZnF|hnM~%0-r2TLEMYnD@TpWP1##U4TSBph7s1}?bdG4E
zZ$hzz74Y0@wQl3uE;w1Ro?k;Ek=Vy|H+*Hme15apte>{o!GiVuu2m`(KRx{>3znZi
zox|bq;Q9_tvcZDo7`;oSQhxf9tg{ljS~bt}Tg_(EM^A2NHE&c7Phce;j~~!kw22|R
zxw)A|!8=hU=nV#gr`>M*F~$ySV$6gnHVrChr3P%Vt57H$WBew35o;Q~8&gtH1@Cn_
zou^nVj-yVxaaAk|BRKuz_5$?qf#W#$#l?m1`uaME!4A5~Dh1iCcerFU8dq>e_rl@u
rVLF`-)M~ZyD!pK13d|Aa|9AKw@hUgEwE0yI00000NkvXXu0mjfafUN!
deleted file mode 100644
index a5fdaba4bb0f223984253e0839b70b9f81f0e7f2..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 1a0dceea376d576199d3c6d4bcf8ac974104c4c3..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644