bug 935640 part 1 Australis, update social sidebar with new ux, r=markh
authorShane Caraveo <scaraveo@mozilla.com>
Mon, 16 Dec 2013 21:37:30 -0800
changeset 160760 d3ef31b50bf953a2567c2b278c695283d2fe85d9
parent 160759 07f6abdf6cd71cc2e9b1b59330d6c94b84618784
child 160761 45d47db0c321cbc1d916c524531ec97c9ff8c1a7
push id4002
push usermixedpuppy@gmail.com
push dateTue, 17 Dec 2013 05:39:19 +0000
treeherderfx-team@e53121069b64 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarkh
bugs935640
milestone29.0a1
bug 935640 part 1 Australis, update social sidebar with new ux, r=markh
browser/base/content/browser-menubar.inc
browser/base/content/browser-sets.inc
browser/base/content/browser-social.js
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/test/social/head.js
browser/components/customizableui/src/CustomizableUI.jsm
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/linux/jar.mn
browser/themes/osx/browser.css
browser/themes/osx/jar.mn
browser/themes/shared/social/chat.inc.css
browser/themes/shared/social/gear_clicked.png
browser/themes/shared/social/gear_default.png
browser/themes/windows/browser-aero.css
browser/themes/windows/jar.mn
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -197,20 +197,19 @@
                   <menupopup id="viewSidebarMenu">
                     <menuitem id="menu_bookmarksSidebar"
                               key="viewBookmarksSidebarKb"
                               observes="viewBookmarksSidebar"/>
                     <menuitem id="menu_historySidebar"
                               key="key_gotoHistory"
                               observes="viewHistorySidebar"
                               label="&historyButton.label;"/>
-                    <menuitem id="menu_socialSidebar"
-                              type="checkbox"
-                              autocheck="false"
-                              command="Social:ToggleSidebar"/>
+                    <!-- Service providers with sidebars are inserted between these two menuseperators -->
+                    <menuseparator hidden="true"/>
+                    <menuseparator class="social-provider-menu" hidden="true"/>
                   </menupopup>
                 </menu>
                 <menuseparator/>
                 <menu id="viewFullZoomMenu" label="&fullZoom.label;"
                       accesskey="&fullZoom.accesskey;"
                       onpopupshowing="FullZoom.updateMenu();">
                   <menupopup>
                     <menuitem id="menu_zoomEnlarge"
@@ -442,59 +441,16 @@
                         accesskey="&downloads.accesskey;"
                         key="key_openDownloads"
                         command="Tools:Downloads"/>
               <menuitem id="menu_openAddons"
                         label="&addons.label;"
                         accesskey="&addons.accesskey;"
                         key="key_openAddons"
                         command="Tools:Addons"/>
-              <menu id="menu_socialAmbientMenu"
-                    observes="socialActiveBroadcaster">
-                <menupopup id="menu_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
-                  <menuseparator id="socialAmbientMenuSeparator"
-                                 hidden="true"/>
-                  <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 id="menu_focusChatBar"
-                            label="&social.chatBar.label;"
-                            accesskey="&social.chatBar.accesskey;"
-                            key="focusChatBar"
-                            command="Social:FocusChat"
-                            class="show-only-for-keyboard"/>
-                  <menuitem class="social-toggle-menuitem" command="Social:Toggle"/>
-                  <menuseparator class="social-statusarea-separator"/>
-                  <menuseparator class="social-provider-menu" hidden="true"/>
-                  <menuitem class="social-addons-menuitem" command="Social:Addons"
-                            label="&social.addons.label;"/>
-                </menupopup>
-              </menu>
 #ifdef MOZ_SERVICES_SYNC
               <!-- only one of sync-setup or sync-menu will be showing at once -->
               <menuitem id="sync-setup"
                         label="&syncSetup.label;"
                         accesskey="&syncSetup.accesskey;"
                         observes="sync-setup-state"
                         oncommand="gSyncUI.openSetup()"/>
               <menuitem id="sync-syncnowitem"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -164,17 +164,16 @@
     <broadcaster id="multipleFeedsMenuState" hidden="true"/>
     <broadcaster id="tabviewGroupsNumber" groups="1"/>
 #ifdef MOZ_SERVICES_SYNC
     <broadcaster id="sync-setup-state"/>
     <broadcaster id="sync-syncnow-state"/>
 #endif
     <broadcaster id="workOfflineMenuitemState"/>
     <broadcaster id="socialSidebarBroadcaster" hidden="true"/>
-    <broadcaster id="socialActiveBroadcaster" hidden="true"/>
 
     <!-- DevTools broadcasters -->
     <broadcaster id="devtoolsMenuBroadcaster_DevToolbox"
                  label="&devToolboxMenuItem.label;"
                  type="checkbox" autocheck="false"
                  command="Tools:DevToolbox"
                  key="key_devToolboxMenuItem"/>
     <broadcaster id="devtoolsMenuBroadcaster_DevToolbar"
@@ -209,20 +208,16 @@
                  label="&errorConsoleCmd.label;"
                  command="Tools:ErrorConsole"/>
     <broadcaster id="devtoolsMenuBroadcaster_GetMoreTools"
                  label="&getMoreDevtoolsCmd.label;"
                  oncommand="openUILinkIn('https://addons.mozilla.org/firefox/collections/mozilla/webdeveloper/', 'tab');"/>
     <broadcaster id="devtoolsMenuBroadcaster_connect"
                  label="&devtoolsConnect.label;"
                  command="Tools:DevToolsConnect"/>
-
-    <!-- SocialAPI broadcasters -->
-    <broadcaster id="socialBroadcaster_userDetails"
-                 notLoggedInLabel="&social.notLoggedIn.label;"/>
   </broadcasterset>
 
   <keyset id="mainKeyset">
     <key id="key_newNavigator"
          key="&newNavigatorCmd.key;"
          command="cmd_newNavigator"
          modifiers="accel"/>
     <key id="key_newNavigatorTab" key="&tabCmd.commandkey;" modifiers="accel" command="cmd_newNavigatorTab"/>
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -3,18 +3,16 @@
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 // the "exported" symbols
 let SocialUI,
     SocialChatBar,
     SocialFlyout,
     SocialMarks,
     SocialShare,
-    SocialMenu,
-    SocialToolbar,
     SocialSidebar,
     SocialStatus;
 
 (function() {
 
 // The minimum sizes for the auto-resize panel code.
 const PANEL_MIN_HEIGHT = 100;
 const PANEL_MIN_WIDTH = 330;
@@ -65,16 +63,21 @@ SocialUI = {
     Services.obs.addObserver(this, "social:provider-disabled", false);
 
     Services.prefs.addObserver("social.sidebar.open", this, false);
     Services.prefs.addObserver("social.toast-notifications.enabled", this, false);
 
     gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler.bind(this), true, true);
     document.getElementById("PanelUI-popup").addEventListener("popupshown", SocialMarks.updatePanelButtons, true);
 
+    // menupopups that list social providers. we only populate them when shown,
+    // and if it has not been done already.
+    document.getElementById("viewSidebarMenu").addEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true);
+    document.getElementById("social-statusarea-popup").addEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true);
+
     if (!Social.initialized) {
       Social.init();
     } else if (Social.providers.length > 0) {
       // Social was initialized during startup in a previous window. If we have
       // providers enabled initialize the UI for this window.
       this.observe(null, "social:providers-changed", null);
       this.observe(null, "social:provider-set", Social.provider ? Social.provider.origin : null);
     }
@@ -90,16 +93,18 @@ SocialUI = {
     Services.obs.removeObserver(this, "social:provider-reload");
     Services.obs.removeObserver(this, "social:provider-enabled");
     Services.obs.removeObserver(this, "social:provider-disabled");
 
     Services.prefs.removeObserver("social.sidebar.open", this);
     Services.prefs.removeObserver("social.toast-notifications.enabled", this);
 
     document.getElementById("PanelUI-popup").removeEventListener("popupshown", SocialMarks.updatePanelButtons, true);
+    document.getElementById("viewSidebarMenu").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true);
+    document.getElementById("social-statusarea-popup").removeEventListener("popupshowing", SocialSidebar.populateSidebarMenu, true);
   },
 
   _matchesCurrentProvider: function (origin) {
     return Social.provider && Social.provider.origin == origin;
   },
 
   observe: function SocialUI_observe(subject, topic, data) {
     // Exceptions here sometimes don't get reported properly, report them
@@ -124,98 +129,69 @@ SocialUI = {
           // has not changed, it will be loaded in provider-set below. Other
           // panels will be unloaded or handle reload.
           SocialSidebar.unloadSidebar();
           // fall through to social:provider-set
         case "social:provider-set":
           // Social.provider has changed (possibly to null), update any state
           // which depends on it.
           this._updateActiveUI();
-          this._updateMenuItems();
 
           SocialFlyout.unload();
           SocialChatBar.update();
           SocialShare.update();
           SocialSidebar.update();
-          SocialToolbar.update();
           SocialStatus.populateToolbarPalette();
           SocialMarks.populateToolbarPalette();
-          SocialMenu.populate();
           break;
         case "social:providers-changed":
           // the list of providers changed - this may impact the "active" UI.
           this._updateActiveUI();
           // and the multi-provider menu
-          SocialToolbar.populateProviderMenus();
+          SocialSidebar.clearProviderMenus();
           SocialShare.populateProviderMenu();
           SocialStatus.populateToolbarPalette();
           SocialMarks.populateToolbarPalette();
           break;
 
         // Provider-specific notifications
         case "social:ambient-notification-changed":
           SocialStatus.updateButton(data);
-          if (this._matchesCurrentProvider(data)) {
-            SocialToolbar.updateButton();
-            SocialMenu.populate();
-          }
           break;
         case "social:profile-changed":
           // make sure anything that happens here only affects the provider for
           // which the profile is changing, and that anything we call actually
           // needs to change based on profile data.
           SocialStatus.updateButton(data);
-          if (this._matchesCurrentProvider(data)) {
-            SocialToolbar.updateProvider();
-          }
-          // Refresh the provider menus, as the icons may have changed.
-          SocialToolbar.populateProviderMenus();
           break;
         case "social:frameworker-error":
           if (this.enabled && Social.provider.origin == data) {
             SocialSidebar.setSidebarErrorMessage();
           }
           break;
 
         case "nsPref:changed":
           if (data == "social.sidebar.open") {
             SocialSidebar.update();
           } else if (data == "social.toast-notifications.enabled") {
-            SocialToolbar.updateButton();
+            SocialSidebar.updateToggleNotifications();
           }
           break;
       }
     } catch (e) {
       Components.utils.reportError(e + "\n" + e.stack);
       throw e;
     }
   },
 
-  nonBrowserWindowInit: function SocialUI_nonBrowserInit() {
-    // Disable the social menu item in non-browser windows
-    document.getElementById("menu_socialAmbientMenu").hidden = true;
-  },
-
-  // Miscellaneous helpers
-  showProfile: function SocialUI_showProfile() {
-    if (Social.provider.haveLoggedInUser())
-      openUILinkIn(Social.provider.profile.profileURL, "tab");
-    else {
-      // XXX Bug 789585 will implement an API for provider-specified login pages.
-      openUILinkIn(Social.provider.origin, "tab");
-    }
-  },
-
   _updateActiveUI: function SocialUI_updateActiveUI() {
     // The "active" UI isn't dependent on there being a provider, just on
     // social being "active" (but also chromeless/PB)
     let enabled = Social.providers.length > 0 && !this._chromeless &&
                   !PrivateBrowsingUtils.isWindowPrivate(window);
-    let broadcaster = document.getElementById("socialActiveBroadcaster");
-    broadcaster.hidden = !enabled;
 
     let toggleCommand = document.getElementById("Social:Toggle");
     toggleCommand.setAttribute("hidden", enabled ? "false" : "true");
 
     if (enabled) {
       // enabled == true means we at least have a defaultProvider
       let provider = Social.provider || Social.defaultProvider;
       // We only need to update the command itself - all our menu items use it.
@@ -233,25 +209,16 @@ SocialUI = {
       let accesskey = gNavigatorBundle.getString(Social.provider
                                                  ? "social.turnOff.accesskey"
                                                  : "social.turnOn.accesskey");
       toggleCommand.setAttribute("label", label);
       toggleCommand.setAttribute("accesskey", accesskey);
     }
   },
 
-  _updateMenuItems: function () {
-    let provider = Social.provider || Social.defaultProvider;
-    if (!provider)
-      return;
-    // The View->Sidebar and Menubar->Tools menu.
-    for (let id of ["menu_socialSidebar", "menu_socialAmbientMenu"])
-      document.getElementById(id).setAttribute("label", provider.name);
-  },
-
   // This handles "ActivateSocialFeature" events fired against content documents
   // in this window.
   _activationEventHandler: function SocialUI_activationHandler(e) {
     let targetDoc;
     let node;
     if (e.target instanceof HTMLDocument) {
       // version 0 support
       targetDoc = e.target;
@@ -328,19 +295,20 @@ SocialUI = {
 
       let notificationPanel = SocialUI.activationPanel;
       // Set the origin being activated and the previously active one, to allow undo
       notificationPanel.setAttribute("origin", provider.origin);
       notificationPanel.setAttribute("oldorigin", oldOrigin);
 
       // Show the panel
       notificationPanel.hidden = false;
-      setTimeout(function () {
-        notificationPanel.openPopup(SocialToolbar.button, "bottomcenter topright");
-      }, 0);
+      // XXX addressed in patch part 2
+      //setTimeout(function () {
+      //  notificationPanel.openPopup(SocialToolbar.button, "bottomcenter topright");
+      //}, 0);
     });
   },
 
   undoActivation: function SocialUI_undoActivation() {
     let origin = this.activationPanel.getAttribute("origin");
     let oldOrigin = this.activationPanel.getAttribute("oldorigin");
     Social.deactivateFromOrigin(origin, oldOrigin);
     this.activationPanel.hidePopup();
@@ -799,408 +767,22 @@ SocialShare = {
 
     let navBar = document.getElementById("nav-bar");
     let anchor = document.getAnonymousElementByAttribute(this.shareButton, "class", "toolbarbutton-icon");
     this.panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
     Social.setErrorListener(iframe, this.setErrorMessage.bind(this));
   }
 };
 
-SocialMenu = {
-  populate: function SocialMenu_populate() {
-    let submenu = document.getElementById("menu_social-statusarea-popup");
-    let ambientMenuItems = submenu.getElementsByClassName("ambient-menuitem");
-    while (ambientMenuItems.length)
-      submenu.removeChild(ambientMenuItems.item(0));
-
-    let separator = document.getElementById("socialAmbientMenuSeparator");
-    separator.hidden = true;
-    let provider = SocialUI.enabled ? Social.provider : null;
-    if (!provider)
-      return;
-
-    let iconNames = Object.keys(provider.ambientNotificationIcons);
-    for (let name of iconNames) {
-      let icon = provider.ambientNotificationIcons[name];
-      if (!icon.label || !icon.menuURL)
-        continue;
-      separator.hidden = false;
-      let menuitem = document.createElement("menuitem");
-      menuitem.setAttribute("label", icon.label);
-      menuitem.classList.add("ambient-menuitem");
-      menuitem.addEventListener("command", function() {
-        openUILinkIn(icon.menuURL, "tab");
-      }, false);
-      submenu.insertBefore(menuitem, separator);
-    }
-  }
-};
-
-// XXX Need to audit that this is being initialized correctly
-SocialToolbar = {
-  // Called once, after window load, when the Social.provider object is
-  // initialized.
-  get _dynamicResizer() {
-    delete this._dynamicResizer;
-    this._dynamicResizer = new DynamicResizeWatcher();
-    return this._dynamicResizer;
-  },
-
-  update: function() {
-    this._updateButtonHiddenState();
-    this.updateProvider();
-    this.populateProviderMenus();
-  },
-
-  // Called when the Social.provider changes
-  updateProvider: function () {
-    let provider = Social.provider;
-    // If the provider uses the new SocialStatus button, then they do
-    // not get to customize the old toolbar button.  Since the status
-    // button depends on multiple workers, if not enabled we will
-    // ignore this limitation.  That allows a provider to migrate to
-    // the new functionality once we enable multiple workers.
-    if (provider && (!provider.statusURL || !Social.allowMultipleWorkers)) {
-      this.button.setAttribute("label", provider.name);
-      this.button.setAttribute("tooltiptext", provider.name);
-      this.button.style.listStyleImage = "url(" + provider.iconURL + ")";
-    } else {
-      this.button.setAttribute("label", gNavigatorBundle.getString("service.toolbarbutton.label"));
-      this.button.setAttribute("tooltiptext", gNavigatorBundle.getString("service.toolbarbutton.tooltiptext"));
-      this.button.style.removeProperty("list-style-image");
-    }
-    if (provider)
-      this.updateProfile();
-    this.updateButton();
-  },
-
-  get button() {
-    return document.getElementById("social-provider-button");
-  },
-
-  // Note: this doesn't actually handle hiding the toolbar button,
-  // socialActiveBroadcaster is responsible for that.
-  _updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
-    let socialEnabled = SocialUI.enabled;
-    for (let className of ["social-statusarea-separator", "social-statusarea-user"]) {
-      for (let element of document.getElementsByClassName(className))
-        element.hidden = !socialEnabled;
-    }
-    let toggleNotificationsCommand = document.getElementById("Social:ToggleNotifications");
-    toggleNotificationsCommand.setAttribute("hidden", !socialEnabled);
-
-    // we need to remove buttons and frames if !socialEnabled or the provider
-    // has changed (frame origin does not match current provider). We only
-    // remove frames that are "attached" to buttons in this toolbar button since
-    // other buttons may also be using grouped frames.
-    let tbi = document.getElementById("social-provider-button");
-    if (tbi) {
-      // buttons after social-provider-button are ambient icons
-      let next = tbi.nextSibling;
-      let currentOrigin = Social.provider ? Social.provider.origin : null;
-
-      while (next) {
-        let button = next;
-        next = next.nextSibling;
-        // get the frame for this button
-        let frameId = button.getAttribute("notificationFrameId");
-        let frame = document.getElementById(frameId);
-        if (!socialEnabled || frame.getAttribute("origin") != currentOrigin) {
-          SharedFrame.forgetGroup(frame.id);
-          frame.parentNode.removeChild(frame);
-          button.parentNode.removeChild(button);
-        }
-      }
-    }
-  },
-
-  updateProfile: function SocialToolbar_updateProfile() {
-    // Profile may not have been initialized yet, since it depends on a worker
-    // response. In that case we'll be called again when it's available, via
-    // social:profile-changed
-    if (!Social.provider)
-      return;
-    let profile = Social.provider.profile || {};
-    let userPortrait = profile.portrait;
-
-    let userDetailsBroadcaster = document.getElementById("socialBroadcaster_userDetails");
-    let loggedInStatusValue = profile.userName ||
-                              userDetailsBroadcaster.getAttribute("notLoggedInLabel");
-
-    // "image" and "label" are used by Mac's native menus that do not render the menuitem's children
-    // elements. "src" and "value" are used by the image/label children on the other platforms.
-    if (userPortrait) {
-      userDetailsBroadcaster.setAttribute("src", userPortrait);
-      userDetailsBroadcaster.setAttribute("image", userPortrait);
-    } else {
-      userDetailsBroadcaster.removeAttribute("src");
-      userDetailsBroadcaster.removeAttribute("image");
-    }
-
-    userDetailsBroadcaster.setAttribute("value", loggedInStatusValue);
-    userDetailsBroadcaster.setAttribute("label", loggedInStatusValue);
-  },
-
-  updateButton: function SocialToolbar_updateButton() {
-    this._updateButtonHiddenState();
-    let panel = document.getElementById("social-notification-panel");
-    panel.hidden = !SocialUI.enabled;
-
-    let command = document.getElementById("Social:ToggleNotifications");
-    command.setAttribute("checked", Services.prefs.getBoolPref("social.toast-notifications.enabled"));
-
-    const CACHE_PREF_NAME = "social.cached.ambientNotificationIcons";
-    // provider.profile == undefined means no response yet from the provider
-    // to tell us whether the user is logged in or not.
-    if (!SocialUI.enabled ||
-        (!Social.provider.haveLoggedInUser() && Social.provider.profile !== undefined)) {
-      // Either no enabled provider, or there is a provider and it has
-      // responded with a profile and the user isn't loggedin.  The icons
-      // etc have already been removed by updateButtonHiddenState, so we want
-      // to nuke any cached icons we have and get out of here!
-      Services.prefs.clearUserPref(CACHE_PREF_NAME);
-      return;
-    }
-
-    // If the provider uses the new SocialStatus button, then they do not get
-    // to use the ambient icons in the old toolbar button.  Since the status
-    // button depends on multiple workers, if not enabled we will ignore this
-    // limitation.  That allows a provider to migrate to the new functionality
-    // once we enable multiple workers.
-    if (Social.provider.statusURL && Social.allowMultipleWorkers)
-      return;
-
-    let icons = Social.provider.ambientNotificationIcons;
-    let iconNames = Object.keys(icons);
-
-    if (Social.provider.profile === undefined) {
-      // provider has not told us about the login state yet - see if we have
-      // a cached version for this provider.
-      let cached;
-      try {
-        cached = JSON.parse(Services.prefs.getComplexValue(CACHE_PREF_NAME,
-                                                           Ci.nsISupportsString).data);
-      } catch (ex) {}
-      if (cached && cached.provider == Social.provider.origin && cached.data) {
-        icons = cached.data;
-        iconNames = Object.keys(icons);
-        // delete the counter data as it is almost certainly stale.
-        for each(let name in iconNames) {
-          icons[name].counter = '';
-        }
-      }
-    } else {
-      // We have a logged in user - save the current set of icons back to the
-      // "cache" so we can use them next startup.
-      let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
-      str.data = JSON.stringify({provider: Social.provider.origin, data: icons});
-      Services.prefs.setComplexValue(CACHE_PREF_NAME,
-                                     Ci.nsISupportsString,
-                                     str);
-    }
-
-    let toolbarButtons = document.createDocumentFragment();
-
-    let createdFrames = [];
-
-    for each(let name in iconNames) {
-      let icon = icons[name];
-
-      let notificationFrameId = "social-status-" + icon.name;
-      let notificationFrame = document.getElementById(notificationFrameId);
-
-      if (!notificationFrame) {
-        notificationFrame = SharedFrame.createFrame(
-          notificationFrameId, /* frame name */
-          panel, /* parent */
-          {
-            "type": "content",
-            "mozbrowser": "true",
-            "class": "social-panel-frame",
-            "id": notificationFrameId,
-            "tooltip": "aHTMLTooltip",
-
-            // work around bug 793057 - by making the panel roughly the final size
-            // we are more likely to have the anchor in the correct position.
-            "style": "width: " + PANEL_MIN_WIDTH + "px;",
-
-            "origin": Social.provider.origin,
-            "src": icon.contentPanel
-          }
-        );
-
-        createdFrames.push(notificationFrame);
-      } else {
-        notificationFrame.setAttribute("origin", Social.provider.origin);
-        SharedFrame.updateURL(notificationFrameId, icon.contentPanel);
-      }
-
-      let toolbarButtonId = "social-notification-icon-" + icon.name;
-      let toolbarButton = document.getElementById(toolbarButtonId);
-      if (!toolbarButton) {
-        toolbarButton = document.createElement("toolbarbutton");
-        toolbarButton.setAttribute("type", "badged");
-        toolbarButton.setAttribute("class", "toolbarbutton-1 chromeclass-toolbar-additional");
-        toolbarButton.setAttribute("id", toolbarButtonId);
-        toolbarButton.setAttribute("notificationFrameId", notificationFrameId);
-        toolbarButton.addEventListener("mousedown", function (event) {
-          if (event.button == 0 && panel.state == "closed")
-            SocialToolbar.showAmbientPopup(toolbarButton);
-        });
-
-        toolbarButtons.appendChild(toolbarButton);
-      }
-
-      toolbarButton.style.listStyleImage = "url(" + icon.iconURL + ")";
-      toolbarButton.setAttribute("label", icon.label);
-      toolbarButton.setAttribute("tooltiptext", icon.label);
-
-      let badge = icon.counter || "";
-      toolbarButton.setAttribute("badge", badge);
-      let ariaLabel = icon.label;
-      // if there is a badge value, we must use a localizable string to insert it.
-      if (badge)
-        ariaLabel = gNavigatorBundle.getFormattedString("social.aria.toolbarButtonBadgeText",
-                                                        [ariaLabel, badge]);
-      toolbarButton.setAttribute("aria-label", ariaLabel);
-    }
-    let socialToolbarItem = document.getElementById("social-toolbar-item");
-    socialToolbarItem.appendChild(toolbarButtons);
-
-    for (let frame of createdFrames) {
-      if (frame.socialErrorListener)
-        frame.socialErrorListener.remove();
-      if (frame.docShell) {
-        frame.docShell.isActive = false;
-        Social.setErrorListener(frame, this.setPanelErrorMessage.bind(this));
-      }
-    }
-  },
-
-  showAmbientPopup: function SocialToolbar_showAmbientPopup(aToolbarButton) {
-    // Hide any other social panels that may be open.
-    SocialFlyout.panel.hidePopup();
-
-    let panel = document.getElementById("social-notification-panel");
-    let notificationFrameId = aToolbarButton.getAttribute("notificationFrameId");
-    let notificationFrame = document.getElementById(notificationFrameId);
-
-    let wasAlive = SharedFrame.isGroupAlive(notificationFrameId);
-    SharedFrame.setOwner(notificationFrameId, notificationFrame);
-
-    // Clear dimensions on all browsers so the panel size will
-    // only use the selected browser.
-    let frameIter = panel.firstElementChild;
-    while (frameIter) {
-      frameIter.collapsed = (frameIter != notificationFrame);
-      frameIter = frameIter.nextElementSibling;
-    }
-
-    function dispatchPanelEvent(name) {
-      let evt = notificationFrame.contentDocument.createEvent("CustomEvent");
-      evt.initCustomEvent(name, true, true, {});
-      notificationFrame.contentDocument.documentElement.dispatchEvent(evt);
-    }
-
-    let dynamicResizer = this._dynamicResizer;
-    panel.addEventListener("popuphidden", function onpopuphiding() {
-      panel.removeEventListener("popuphidden", onpopuphiding);
-      aToolbarButton.removeAttribute("open");
-      aToolbarButton.parentNode.removeAttribute("open");
-      dynamicResizer.stop();
-      notificationFrame.docShell.isActive = false;
-      dispatchPanelEvent("socialFrameHide");
-    });
-
-    panel.addEventListener("popupshown", function onpopupshown() {
-      panel.removeEventListener("popupshown", onpopupshown);
-      // The "open" attribute is needed on both the button and the containing
-      // toolbaritem since the buttons on OS X have moz-appearance:none, while
-      // their container gets moz-appearance:toolbarbutton due to the way that
-      // toolbar buttons get combined on OS X.
-      aToolbarButton.setAttribute("open", "true");
-      aToolbarButton.parentNode.setAttribute("open", "true");
-      notificationFrame.docShell.isActive = true;
-      notificationFrame.docShell.isAppTab = true;
-      if (notificationFrame.contentDocument.readyState == "complete" && wasAlive) {
-        dynamicResizer.start(panel, notificationFrame);
-        dispatchPanelEvent("socialFrameShow");
-      } else {
-        // first time load, wait for load and dispatch after load
-        notificationFrame.addEventListener("load", function panelBrowserOnload(e) {
-          notificationFrame.removeEventListener("load", panelBrowserOnload, true);
-          dynamicResizer.start(panel, notificationFrame);
-          setTimeout(function() {
-            dispatchPanelEvent("socialFrameShow");
-          }, 0);
-        }, true);
-      }
-    });
-
-    let navBar = document.getElementById("nav-bar");
-    let anchor = document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-badge-container");
-    // Bug 849216 - open the popup in a setTimeout so we avoid the auto-rollup
-    // handling from preventing it being opened in some cases.
-    setTimeout(function() {
-      panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
-    }, 0);
-  },
-
-  setPanelErrorMessage: function SocialToolbar_setPanelErrorMessage(aNotificationFrame) {
-    if (!aNotificationFrame)
-      return;
-
-    let src = aNotificationFrame.getAttribute("src");
-    aNotificationFrame.removeAttribute("src");
-    aNotificationFrame.webNavigation.loadURI("about:socialerror?mode=tryAgainOnly&url=" +
-                                             encodeURIComponent(src), null, null, null, null);
-    let panel = aNotificationFrame.parentNode;
-    sizeSocialPanelToContent(panel, aNotificationFrame);
-  },
-
-  populateProviderMenus: function SocialToolbar_renderProviderMenus() {
-    let providerMenuSeps = document.getElementsByClassName("social-provider-menu");
-    for (let providerMenuSep of providerMenuSeps)
-      this._populateProviderMenu(providerMenuSep);
-  },
-
-  _populateProviderMenu: function SocialToolbar_renderProviderMenu(providerMenuSep) {
-    let menu = providerMenuSep.parentNode;
-    // selectable providers are inserted before the provider-menu seperator,
-    // remove any menuitems in that area
-    while (providerMenuSep.previousSibling.nodeName == "menuitem") {
-      menu.removeChild(providerMenuSep.previousSibling);
-    }
-    // only show a selection if enabled and there is more than one
-    let providers = [p for (p of Social.providers) if (p.workerURL || p.sidebarURL)];
-    if (providers.length < 2) {
-      providerMenuSep.hidden = true;
-      return;
-    }
-    for (let provider of providers) {
-      let menuitem = document.createElement("menuitem");
-      menuitem.className = "menuitem-iconic social-provider-menuitem";
-      menuitem.setAttribute("image", provider.iconURL);
-      menuitem.setAttribute("label", provider.name);
-      menuitem.setAttribute("origin", provider.origin);
-      if (provider == Social.provider) {
-        menuitem.setAttribute("checked", "true");
-      } else {
-        menuitem.setAttribute("oncommand", "Social.setProviderByOrigin(this.getAttribute('origin'));");
-      }
-      menu.insertBefore(menuitem, providerMenuSep);
-    }
-    providerMenuSep.hidden = false;
-  }
-}
-
 SocialSidebar = {
   // Whether the sidebar can be shown for this window.
   get canShow() {
-    return SocialUI.enabled && Social.provider.sidebarURL;
+    if (PrivateBrowsingUtils.isWindowPrivate(window))
+      return false;
+    return [p for (p of Social.providers) if (p.enabled && p.sidebarURL)].length > 0;
   },
 
   // Whether the user has toggled the sidebar on (for windows where it can appear)
   get opened() {
     return Services.prefs.getBoolPref("social.sidebar.open") && !document.mozFullScreen;
   },
 
   setSidebarVisibilityState: function(aEnabled) {
@@ -1210,17 +792,25 @@ SocialSidebar = {
     if (aEnabled == sbrowser.docShellIsActive)
       return;
     sbrowser.docShellIsActive = aEnabled;
     let evt = sbrowser.contentDocument.createEvent("CustomEvent");
     evt.initCustomEvent(aEnabled ? "socialFrameShow" : "socialFrameHide", true, true, {});
     sbrowser.contentDocument.documentElement.dispatchEvent(evt);
   },
 
+  updateToggleNotifications: function() {
+    let command = document.getElementById("Social:ToggleNotifications");
+    command.setAttribute("checked", Services.prefs.getBoolPref("social.toast-notifications.enabled"));
+    command.setAttribute("hidden", !SocialUI.enabled);
+  },
+
   update: function SocialSidebar_update() {
+    this.updateToggleNotifications();
+    this._updateHeader();
     clearTimeout(this._unloadTimeoutId);
     // Hide the toggle menu item if the sidebar cannot appear
     let command = document.getElementById("Social:ToggleSidebar");
     command.setAttribute("hidden", this.canShow ? "false" : "true");
 
     // Hide the sidebar if it cannot appear, or has been toggled off.
     // Also set the command "checked" state accordingly.
     let hideSidebar = !this.canShow || !this.opened;
@@ -1248,35 +838,41 @@ SocialSidebar = {
       sbrowser.setAttribute("origin", Social.provider.origin);
       if (Social.provider.errorState == "frameworker-error") {
         SocialSidebar.setSidebarErrorMessage();
         return;
       }
 
       // Make sure the right sidebar URL is loaded
       if (sbrowser.getAttribute("src") != Social.provider.sidebarURL) {
+        // we check readyState right after setting src, we need a new content
+        // viewer to ensure we are checking against the correct document.
+        sbrowser.docShell.createAboutBlankContentViewer(null);
         Social.setErrorListener(sbrowser, this.setSidebarErrorMessage.bind(this));
         // setting isAppTab causes clicks on untargeted links to open new tabs
         sbrowser.docShell.isAppTab = true;
         sbrowser.setAttribute("src", Social.provider.sidebarURL);
         PopupNotifications.locationChange(sbrowser);
       }
 
       // if the document has not loaded, delay until it is
       if (sbrowser.contentDocument.readyState != "complete") {
+        document.getElementById("social-sidebar-button").setAttribute("loading", "true");
         sbrowser.addEventListener("load", SocialSidebar._loadListener, true);
       } else {
         this.setSidebarVisibilityState(true);
       }
     }
+    this._updateCheckedMenuItems(this.opened && this.provider ? this.provider.origin : null);
   },
 
   _loadListener: function SocialSidebar_loadListener() {
     let sbrowser = document.getElementById("social-sidebar-browser");
     sbrowser.removeEventListener("load", SocialSidebar._loadListener, true);
+    document.getElementById("social-sidebar-button").removeAttribute("loading");
     SocialSidebar.setSidebarVisibilityState(true);
   },
 
   unloadSidebar: function SocialSidebar_unloadSidebar() {
     let sbrowser = document.getElementById("social-sidebar-browser");
     if (!sbrowser.hasAttribute("origin"))
       return;
 
@@ -1296,16 +892,118 @@ SocialSidebar = {
     let sbrowser = document.getElementById("social-sidebar-browser");
     // a frameworker error "trumps" a sidebar error.
     if (Social.provider.errorState == "frameworker-error") {
       sbrowser.setAttribute("src", "about:socialerror?mode=workerFailure");
     } else {
       let url = encodeURIComponent(Social.provider.sidebarURL);
       sbrowser.loadURI("about:socialerror?mode=tryAgain&url=" + url, null, null);
     }
+  },
+
+  // provider will move to a sidebar specific member in bug 894806
+  get provider() {
+    return Social.provider;
+  },
+
+  setProvider: function(origin) {
+    Social.setProviderByOrigin(origin);
+    this._updateHeader();
+    this._updateCheckedMenuItems(origin);
+  },
+
+  _updateHeader: function() {
+    let provider = this.provider;
+    let image, title;
+    if (provider) {
+      image = "url(" + (provider.icon32URL || provider.iconURL) + ")";
+      title = provider.name;
+    }
+    document.getElementById("social-sidebar-favico").style.listStyleImage = image;
+    document.getElementById("social-sidebar-title").value = title;
+  },
+
+  _updateCheckedMenuItems: function(origin) {
+    // update selected menuitems
+    let menuitems = document.getElementsByClassName("social-provider-menuitem");
+    for (let mi of menuitems) {
+      if (origin && mi.getAttribute("origin") == origin) {
+        mi.setAttribute("checked", "true");
+        mi.setAttribute("oncommand", "SocialSidebar.hide();");
+      } else if (mi.getAttribute("checked")) {
+        mi.removeAttribute("checked");
+        mi.setAttribute("oncommand", "SocialSidebar.show(this.getAttribute('origin'));");
+      }
+    }
+  },
+
+  show: function(origin) {
+    // always show the sidebar, and set the provider
+    this.setProvider(origin);
+    Services.prefs.setBoolPref("social.sidebar.open", true);
+  },
+
+  hide: function() {
+    Services.prefs.setBoolPref("social.sidebar.open", false);
+    this._updateCheckedMenuItems();
+  },
+
+  populateSidebarMenu: function(event) {
+    // Providers are removed from the view->sidebar menu when there is a change
+    // in providers, so we only have to populate onshowing if there are no
+    // provider menus. We populate this menu so long as there are enabled
+    // providers with sidebars.
+    let popup = event.target;
+    let providerMenuSeps = popup.getElementsByClassName("social-provider-menu");
+    if (providerMenuSeps[0].previousSibling.nodeName == "menuseparator")
+      SocialSidebar._populateProviderMenu(providerMenuSeps[0]);
+  },
+
+  clearProviderMenus: function() {
+    // called when there is a change in the provider list we clear all menus,
+    // they will be repopulated when the menu is shown
+    let providerMenuSeps = document.getElementsByClassName("social-provider-menu");
+    for (let providerMenuSep of providerMenuSeps) {
+      while (providerMenuSep.previousSibling.nodeName == "menuitem") {
+        let menu = providerMenuSep.parentNode;
+        menu.removeChild(providerMenuSep.previousSibling);
+      }
+    }
+  },
+
+  _populateProviderMenu: function(providerMenuSep) {
+    let menu = providerMenuSep.parentNode;
+    // selectable providers are inserted before the provider-menu seperator,
+    // remove any menuitems in that area
+    while (providerMenuSep.previousSibling.nodeName == "menuitem") {
+      menu.removeChild(providerMenuSep.previousSibling);
+    }
+    // only show a selection in the sidebar header menu if there is more than one
+    let providers = [p for (p of Social.providers) if (p.sidebarURL)];
+    if (providers.length < 2 && menu.id != "viewSidebarMenu") {
+      providerMenuSep.hidden = true;
+      return;
+    }
+    let topSep = providerMenuSep.previousSibling;
+    for (let provider of providers) {
+      let menuitem = document.createElement("menuitem");
+      menuitem.className = "menuitem-iconic social-provider-menuitem";
+      menuitem.setAttribute("image", provider.iconURL);
+      menuitem.setAttribute("label", provider.name);
+      menuitem.setAttribute("origin", provider.origin);
+      if (this.opened && provider == this.provider) {
+        menuitem.setAttribute("checked", "true");
+        menuitem.setAttribute("oncommand", "SocialSidebar.hide();");
+      } else {
+        menuitem.setAttribute("oncommand", "SocialSidebar.show(this.getAttribute('origin'));");
+      }
+      menu.insertBefore(menuitem, providerMenuSep);
+    }
+    topSep.hidden = topSep.nextSibling == providerMenuSep;
+    providerMenuSep.hidden = !providerMenuSep.nextSibling;
   }
 }
 
 // this helper class is used by removable/customizable buttons to handle
 // widget creation/destruction
 
 // When a provider is installed we show all their UI so the user will see the
 // functionality of what they installed. The user can later customize the UI,
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1347,18 +1347,16 @@ var gBrowserInit = {
                             .getService(Ci.nsIMacDockSupport);
           dockSupport.dockMenu = nativeMenu;
         }
         catch (e) {
         }
       }
     }
 
-    SocialUI.nonBrowserWindowInit();
-
     if (PrivateBrowsingUtils.permanentPrivateBrowsing) {
       document.getElementById("macDockMenuNewWindow").hidden = true;
     }
 
     this._delayedStartupTimeoutId = setTimeout(this.nonBrowserWindowDelayedStartup.bind(this), 0);
   },
 
   nonBrowserWindowDelayedStartup: function() {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -823,68 +823,16 @@
         <toolbarbutton id="social-share-button"
                        class="toolbarbutton-1 chromeclass-toolbar-additional"
                        hidden="true"
                        overflows="false"
                        label="&sharePageCmd.label;"
                        tooltiptext="&sharePageCmd.label;"
                        cui-areatype="toolbar"
                        command="Social:SharePage"/>
-
-        <toolbaritem id="social-toolbar-item"
-                     class="chromeclass-toolbar-additional toolbaritem-with-separator"
-                     removable="false"
-                     title="&socialToolbar.title;"
-                     hidden="true"
-                     overflows="false"
-                     cui-areatype="toolbar"
-                     observes="socialActiveBroadcaster">
-        <toolbarbutton id="social-notification-icon" class="default-notification-icon toolbarbutton-1 notification-anchor-icon"
-                   oncommand="PopupNotifications._reshowNotifications(this,
-                                document.getElementById('social-sidebar-browser'));"/>
-          <toolbarbutton id="social-provider-button"
-                         class="toolbarbutton-1"
-                         type="menu">
-            <menupopup id="social-statusarea-popup">
-              <menuitem class="social-statusarea-user menuitem-iconic" pack="start" align="center"
-                        observes="socialBroadcaster_userDetails"
-                        oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();">
-                <image class="social-statusarea-user-portrait"
-                       observes="socialBroadcaster_userDetails"/>
-                <vbox>
-                  <label class="social-statusarea-loggedInStatus"
-                         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>
-        </toolbaritem>
       </hbox>
 
       <toolbarbutton id="nav-bar-overflow-button"
                      class="toolbarbutton-1 chromeclass-toolbar-additional overflow-button"
                      skipintoolbarset="true"
                      tooltiptext="&navbarOverflow.label;"/>
 
       <toolbaritem id="PanelUI-button"
@@ -1045,16 +993,47 @@
       </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">
+
+        <sidebarheader id="social-sidebar-header" class="sidebar-header" align="center">
+          <image id="social-sidebar-favico"/>
+          <label id="social-sidebar-title" class="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
+          <button id="social-sidebar-button"
+                         type="menu">
+            <menupopup id="social-statusarea-popup" position="after_end">
+              <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>
+          </button>
+        </sidebarheader>
+
         <browser id="social-sidebar-browser"
                  type="content"
                  context="contentAreaContextMenu"
                  disableglobalhistory="true"
                  tooltip="aHTMLTooltip"
                popupnotificationanchor="social-notification-icon"
                  flex="1"
                  style="min-width: 14em; width: 18em; max-width: 36em;"/>
--- a/browser/base/content/test/social/head.js
+++ b/browser/base/content/test/social/head.js
@@ -247,19 +247,16 @@ function checkSocialUI(win) {
     if (!enabled || (Social.defaultProvider.statusURL && Social.allowMultipleWorkers)) {
       _ok(!win.SocialToolbar.button.style.listStyleImage, "toolbar button is default icon");
     } else {
       _is(win.SocialToolbar.button.style.listStyleImage, 'url("' + Social.defaultProvider.iconURL + '")', "toolbar button has provider icon");
     }
   }
   // the menus should always have the provider name
   if (provider) {
-    for (let id of ["menu_socialSidebar", "menu_socialAmbientMenu"])
-      _is(document.getElementById(id).getAttribute("label"), Social.provider.name, "element has the provider name");
-
     let contextMenus = [
       {
         type: "link",
         id: "context-marklinkMenu",
         label: "social.marklinkMenu.label"
       },
       {
         type: "page",
@@ -294,18 +291,16 @@ function checkSocialUI(win) {
 
   // and for good measure, check all the social commands.
   isbool(!doc.getElementById("Social:Toggle").hidden, active, "Social:Toggle visible?");
   isbool(!doc.getElementById("Social:ToggleSidebar").hidden, enabled, "Social:ToggleSidebar visible?");
   isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Social:ToggleNotifications visible?");
   isbool(!doc.getElementById("Social:FocusChat").hidden, enabled, "Social:FocusChat visible?");
   isbool(doc.getElementById("Social:FocusChat").getAttribute("disabled"), enabled ? "false" : "true", "Social:FocusChat disabled?");
 
-  // broadcasters.
-  isbool(!doc.getElementById("socialActiveBroadcaster").hidden, active, "socialActiveBroadcaster hidden?");
   // and report on overall success of failure of the various checks here.
   is(numGoodTests, numTests, "The Social UI tests succeeded.")
 }
 
 function waitForNotification(topic, cb) {
   function observer(subject, topic, data) {
     Services.obs.removeObserver(observer, topic);
     cb();
--- a/browser/components/customizableui/src/CustomizableUI.jsm
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -179,17 +179,16 @@ let CustomizableUIInternal = {
       defaultPlacements: [
         "urlbar-container",
         "search-container",
         "webrtc-status-button",
         "bookmarks-menu-button",
         "downloads-button",
         "home-button",
         "social-share-button",
-        "social-toolbar-item",
       ]
     });
 #ifndef XP_MACOSX
     this.registerArea(CustomizableUI.AREA_MENUBAR, {
       legacy: true,
       type: CustomizableUI.TYPE_TOOLBAR,
       defaultPlacements: [
         "menubar-items",
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -640,17 +640,16 @@ just addresses the organization to follo
 
 <!ENTITY syncSetup.label              "Set Up &syncBrand.shortName.label;…">
 <!ENTITY syncSetup.accesskey          "Y">
 <!ENTITY syncSyncNowItem.label        "Sync Now">
 <!ENTITY syncSyncNowItem.accesskey    "S">
 <!ENTITY syncToolbarButton.label      "Sync">
 
 <!ENTITY socialToolbar.title        "Social Toolbar Button">
-<!ENTITY social.notLoggedIn.label   "Not logged in">
 
 <!ENTITY social.ok.label       "OK">
 <!ENTITY social.ok.accesskey   "O">
 
 <!ENTITY social.toggleSidebar.label "Show sidebar">
 <!ENTITY social.toggleSidebar.accesskey "s">
 
 <!ENTITY social.addons.label "Manage Services…">
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -118,16 +118,18 @@ browser.jar:
 * skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
   skin/classic/browser/preferences/applications.css   (preferences/applications.css)
   skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
   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-icons.png          (social/chat-icons.png)
+  skin/classic/browser/social/gear_default.png        (../shared/social/gear_default.png)
+  skin/classic/browser/social/gear_clicked.png        (../shared/social/gear_clicked.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-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)
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -2397,21 +2397,23 @@ sidebarheader {
 
 #appcontent ~ .sidebar-splitter {
   -moz-border-start: 1px solid #ccc;
   -moz-border-end: none;
   -moz-margin-start: 0;
   -moz-margin-end: -3px;
 }
 
+.sidebar-title,
 #sidebar-title {
   color: #535f6d;
   font-weight: bold;
 }
 
+.sidebar-throbber[loading="true"],
 #sidebar-throbber[loading="true"] {
   list-style-image: url("chrome://global/skin/icons/loading_16.png");
 }
 
 sidebarheader > .tabs-closebutton > .toolbarbutton-text {
   display: none;
 }
 
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -191,16 +191,18 @@ browser.jar:
   skin/classic/browser/preferences/applications.css         (preferences/applications.css)
   skin/classic/browser/preferences/aboutPermissions.css     (preferences/aboutPermissions.css)
   skin/classic/browser/social/services-16.png               (social/services-16.png)
   skin/classic/browser/social/services-16@2x.png            (social/services-16@2x.png)
   skin/classic/browser/social/services-64.png               (social/services-64.png)
   skin/classic/browser/social/services-64@2x.png            (social/services-64@2x.png)
   skin/classic/browser/social/chat-icons.png                             (social/chat-icons.png)
   skin/classic/browser/social/chat-icons@2x.png                          (social/chat-icons@2x.png)
+  skin/classic/browser/social/gear_default.png                           (../shared/social/gear_default.png)
+  skin/classic/browser/social/gear_clicked.png                           (../shared/social/gear_clicked.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png             (tabbrowser/alltabs-box-bkgnd-icon.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted.png    (tabbrowser/alltabs-box-bkgnd-icon-inverted.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png (tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.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/newtab-inverted.png                    (tabbrowser/newtab-inverted.png)
   skin/classic/browser/tabbrowser/newtab-inverted@2x.png                 (tabbrowser/newtab-inverted@2x.png)
   skin/classic/browser/tabbrowser/connecting.png                         (tabbrowser/connecting.png)
--- a/browser/themes/shared/social/chat.inc.css
+++ b/browser/themes/shared/social/chat.inc.css
@@ -1,14 +1,44 @@
 %if 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/. */
 %endif
 
+#social-sidebar-header {
+  padding: 3px;
+}
+
+#social-sidebar-button {
+  -moz-appearance: none;
+  list-style-image: url(chrome://browser/skin/social/gear_default.png);
+  min-width: 16px;
+  padding: 0;
+  margin: 2px;
+}
+#social-sidebar-button:hover,
+#social-sidebar-button:hover:active {
+  list-style-image: url(chrome://browser/skin/social/gear_clicked.png);
+}
+#social-sidebar-button > .toolbarbutton-menu-dropmarker {
+  display: none;
+}
+
+#social-sidebar-button[loading="true"] {
+  list-style-image: url("chrome://global/skin/icons/loading_16.png");
+}
+
+#social-sidebar-favico {
+  max-height: 16px;
+  max-width: 16px;
+  padding: 0;
+  margin: 2px;
+}
+
 .chat-status-icon {
   max-height: 16px;
   max-width: 16px;
   padding: 0;
 }
 
 .chat-toolbarbutton {
   -moz-appearance: none;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7c93aa767e4b9542ab143f6bf7062514761f7304
GIT binary patch
literal 1262
zc%17D@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa$r9IylHmNblJdl&R0hYC{G?O`
z&)mfH)S%SFl*+=BsWuD@%*vS|5hW46K32*3xq68pHF_1f1q>iyV_#8_n4FzjqL7rD
zo|$K>^nUk#C56lsTcvPQUjyF)=hTc$kE){7;3~h6<f`ms%M>MhI|Z8xE1&_nsU?XD
z6}dTi#a0!zN?>!XfNYSkzLEl1NlCV?62wsvz5xo(`9-M;rh2Bj$p(fd3g(u2hNgxl
z7KS<sMh1q)`Ub}OhQ_*vMpg!vR)(euP@n{~ttchUD#*nRY8Q}atCUevQedU8UtV6W
zS8lAAUzDzIXlZGwZ(yWvWTXpJp<7&;SCUwvn^&w1Gr=XbIJqdZpd>RtPXWYFOv*1U
zu~kxnc_Fs|ZfssLG?;(^reBd*pl_&WppT@`*B8Ii++4Wo;*y}$H2kWILn;eW^@CE2
z^Gl18ff1Lc4ANX+<y@4SSdw29lAoUg3&ntp{F40QjQj!xXJ-Ws-^Aq1JP=<KtijjU
z$}_LHBrz{J)zigR2`HkMnVDkcWZ`0AZsh7{V(jE<Xy|HeVeD$+YG&Z%WMXP+VP@n4
z)9aF-T$-DjR|3<Ug3#-PQ!gkjKy;@TWtOF;xE1B+DuDfLm5JLe7P#F4(VK$XEtWX-
z>H{64j~3G~Az<<WG2!VJ$bqN))I4BvF9N3PNq-NRFfcGCdb&7<RNShW<gMY7D02M0
z?ECOF$NEGf{Vy)jIP0`=!_3Hq9aECl>qJ(rQCH!P-fUEvqocEI3hT`kn%t>NTQ+@=
zy8hnhfAsv-HD7oC|2?<*oNfR6&&>)S4oy9oB6PxL&C{Zti*kxRY*RMwZQVEZ-g{GC
z;{-l#7Slzq6RLR37cQ1Rd80YTfpgyj=2;Ks<kaS|+0XU+zL+<lL0RI%zjfs^8iXa9
z_DtQy9s6O`B%9P-O<@`BQa2{=l{}VgWA^YIXH{dIm-nK%8<eZ(Hm%uoyQu%mw4`D!
z_Sr8MUEcon2hX%8J^9V^%+}pn)%7L)?T@PeW$l|6DrZc5D;V_W=d2vDDXo#Un?2<Z
zOkx!?ox|Q?eR$`Uea>dqx4A+?<jzT`JPDW(Y^pL>!Me{ggL${-?~B|9O)`g;|I&Q9
z>#1h#m0TM!$s<!rB#%dJiLT}SeECOx<LV8px3?+&kc(uro~M5Oqk97*gGP5&g2Kzc
QlAsdE)78&qol`;+0DFeR0ssI2
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2a9c8e19895a44c153fb6cc953d7373778befd3a
GIT binary patch
literal 1271
zc%17D@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa$r9IylHmNblJdl&R0hYC{G?O`
z&)mfH)S%SFl*+=BsWuD@%*vS|5hW46K32*3xq68pHF_1f1q>iyV_#8_n4FzjqL7rD
zo|$K>^nUk#C56lsTcvPQUjyF)=hTc$kE){7;3~h6<f`ms%M>MhI|Z8xE1&_nsU?XD
z6}dTi#a0!zN?>!XfNYSkzLEl1NlCV?62wsvz5xo(`9-M;rh2Bj$p(fd3g(u2hNgxl
z7KS<sMh1q)`Ub}OhQ_*vMpg!vR)(euP@n{~ttchUD#*nRY8Q}atCUevQedU8UtV6W
zS8lAAUzDzIXlZGwZ(yWvWTXpJp<7&;SCUwvn^&w1Gr=XbIJqdZpd>RtPXWYFOv*1U
zu~kxnc_Fs|ZfssLG?;(^reBd*pl_&WppT@`*B8Ii++4Wo;*y}$H2kWILn;eW^@CE2
z^Gl18ff1Lc4ANX+<y@4SSdw29lAoUg3&ntp{F40QjQj!xXJ-Ws-^Aq1JP=<KtijjU
z$}_LHBrz{J)zigR2`HkMnVDkcV&-aT=4fPYV(jc}Xy|HeVeD$+YG&Z%WMXP+VP@n4
z)9aF-T$-DjR|3<Ug3xP$Q!gkjKy;@TWtOF;xE1B+DuDfLm5IeIP8Kc}=0>j0CdN*#
z*xdrrn}XXdW;orV4|I$^T1>-)fXN5Mgr{2|2cGg%^MJ{{2$-(V^{zX}z`&U0>Eakt
zajRz1d2N?Kk>mGgKm0lOZiM2~<JVf$o=(*f;jU-sx}ovymF~;lKM@g}Cl6gKI+UaH
zWmb?_#7a%>)WdA453g6)rCY6ExBSkpGv)7gKHu~Cahx@evv$<Y9JAgthi5&nblrMZ
zaqEWGx4NI!Zm3%?IfJz@LScnmEc->_9i1|7BaX#AVe<OGDu03DdCF^Z;~V?l^Dih3
zXh<$tyZ^PUnj-(<36q1qFJz9}s^V=N>nOa%NmORVUO_dXKRJiz3Vva#oifewcB21V
zQz@0Hcc)b^*{*1|{FQ=mtjVuwa`PQ0%_%g?czG-&a_Yu^OJt+}*SjBE^4LQ91y{)G
zwZ<GxdtUG2Pno>H_r=A{Y3Fu5j9M0T<)Mw!DT#AS-`&2VRzCYm*Qvvj?OUuwuAFS_
z5mdQu$f~QL|I*+egWE*qA6M$Ue%&eJNj;NeBPe}j%PXP2OU2XoEfBPu^-I4%v@9Xq
mjOD)aX@%>bQ>^}R7%(^<%Dc*2xb`WiDDrgmb6Mw<&;$TplE}~i
--- a/browser/themes/windows/browser-aero.css
+++ b/browser/themes/windows/browser-aero.css
@@ -47,24 +47,26 @@
     border-color: hsla(210,54%,20%,.35) hsla(210,54%,20%,.37) hsla(210,54%,20%,.4);
   }
 
   #urlbar:not(:-moz-lwtheme)[focused],
   .searchbar-textbox:not(:-moz-lwtheme)[focused] {
     border-color: hsla(206,100%,60%,.65) hsla(206,100%,55%,.65) hsla(206,100%,50%,.65);
   }
 
+  .sidebar-header,
   #sidebar-header {
     -moz-appearance: none;
     color: black;
     background-color: #EEF3FA;
     border-bottom: none;
     text-shadow: none;
   }
 
+  .sidebar-title,
   #sidebar-title {
     font-weight: bold;
   }
 
   .sidebar-splitter {
     border: 0;
     -moz-border-end: 1px solid #A9B7C9;
     min-width: 0;
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -137,16 +137,18 @@ browser.jar:
         skin/classic/browser/preferences/saveFile.png                (preferences/saveFile.png)
 *       skin/classic/browser/preferences/preferences.css             (preferences/preferences.css)
 *       skin/classic/browser/preferences/in-content/preferences.css  (preferences/in-content/preferences.css)
         skin/classic/browser/preferences/applications.css            (preferences/applications.css)
         skin/classic/browser/preferences/aboutPermissions.css        (preferences/aboutPermissions.css)
         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/chat-icons.png                   (social/chat-icons.png)
+        skin/classic/browser/social/gear_default.png                 (../shared/social/gear_default.png)
+        skin/classic/browser/social/gear_clicked.png                 (../shared/social/gear_clicked.png)
         skin/classic/browser/tabbrowser/newtab.png                   (tabbrowser/newtab.png)
         skin/classic/browser/tabbrowser/newtab-inverted.png          (tabbrowser/newtab-inverted.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-active-middle.png        (tabbrowser/tab-active-middle.png)
         skin/classic/browser/tabbrowser/tab-arrow-left.png           (tabbrowser/tab-arrow-left.png)
         skin/classic/browser/tabbrowser/tab-arrow-left-inverted.png  (tabbrowser/tab-arrow-left-inverted.png)
@@ -444,16 +446,18 @@ browser.jar:
         skin/classic/aero/browser/preferences/saveFile.png           (preferences/saveFile-aero.png)
 *       skin/classic/aero/browser/preferences/preferences.css        (preferences/preferences.css)
 *       skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
         skin/classic/aero/browser/preferences/applications.css       (preferences/applications.css)
         skin/classic/aero/browser/preferences/aboutPermissions.css   (preferences/aboutPermissions.css)
         skin/classic/aero/browser/social/services-16.png             (social/services-16.png)
         skin/classic/aero/browser/social/services-64.png             (social/services-64.png)
         skin/classic/aero/browser/social/chat-icons.png              (social/chat-icons.png)
+        skin/classic/aero/browser/social/gear_default.png            (../shared/social/gear_default.png)
+        skin/classic/aero/browser/social/gear_clicked.png            (../shared/social/gear_clicked.png)
         skin/classic/aero/browser/tabbrowser/newtab.png              (tabbrowser/newtab.png)
         skin/classic/aero/browser/tabbrowser/newtab-inverted.png     (tabbrowser/newtab-inverted.png)
         skin/classic/aero/browser/tabbrowser/connecting.png          (tabbrowser/connecting.png)
         skin/classic/aero/browser/tabbrowser/loading.png             (tabbrowser/loading.png)
         skin/classic/aero/browser/tabbrowser/tab.png                 (tabbrowser/tab.png)
         skin/classic/aero/browser/tabbrowser/tab-active-middle.png   (tabbrowser/tab-active-middle.png)
         skin/classic/aero/browser/tabbrowser/tab-arrow-left.png      (tabbrowser/tab-arrow-left.png)
         skin/classic/aero/browser/tabbrowser/tab-arrow-left-inverted.png (tabbrowser/tab-arrow-left-inverted.png)