Bug 771826: implement Social toolbar button UI, including notification icons, notification panel, and "profile" panel. Styling only for Windows/Mac for the moment, r=gavin
authorShane Caraveo <mixedpuppy@gmail.com>
Sun, 15 Jul 2012 16:12:13 -0700
changeset 104213 934ef44ce5af34ceef2674b51df86d17a6c4c9fa
parent 104212 075af07e9952cff2c1f6adae85a2ed8b688a7164
child 104214 6fdf9985acfe6f939da584b2559464ab22264fe7
push idunknown
push userunknown
push dateunknown
reviewersgavin
bugs771826
milestone16.0a1
Bug 771826: implement Social toolbar button UI, including notification icons, notification panel, and "profile" panel. Styling only for Windows/Mac for the moment, r=gavin
browser/app/profile/firefox.js
browser/base/content/browser-social.js
browser/base/content/browser.xul
browser/base/content/test/Makefile.in
browser/base/content/test/browser_social_toolbar.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/modules/Social.jsm
browser/themes/pinstripe/browser.css
browser/themes/pinstripe/jar.mn
browser/themes/pinstripe/social/panelarrow-down.png
browser/themes/pinstripe/social/panelarrow-horiz.png
browser/themes/pinstripe/social/panelarrow-up.png
browser/themes/pinstripe/social/social.png
browser/themes/winstripe/browser.css
browser/themes/winstripe/jar.mn
browser/themes/winstripe/social/social.png
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1179,9 +1179,9 @@ pref("pdfjs.previousHandler.preferredAct
 pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
 
 // The maximum amount of decoded image data we'll willingly keep around (we
 // might keep around more than this, but we'll try to get down to this value).
 // (This is intentionally on the high side; see bug 746055.)
 pref("image.mem.max_decoded_image_kb", 256000);
 
 // Example social provider
-pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\"}");
+pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\",\"iconURL\":\"https://motown-dev.mozillalabs.com/images/motown-icon.png\"}");
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -1,57 +1,77 @@
 // 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/.
 
 let SocialUI = {
   // Called on delayed startup to initialize UI
   init: function SocialUI_init() {
     Services.obs.addObserver(this, "social:pref-changed", false);
+    Services.obs.addObserver(this, "social:ambient-notification-changed", false);
+    Services.obs.addObserver(this, "social:profile-changed", false);
+
     Social.init(this._providerReady.bind(this));
   },
 
   // Called on window unload
   uninit: function SocialUI_uninit() {
     Services.obs.removeObserver(this, "social:pref-changed");
+    Services.obs.removeObserver(this, "social:ambient-notification-changed");
+    Services.obs.removeObserver(this, "social:profile-changed");
+  },
+
+  showProfile: function SocialUI_showProfile() {
+    if (Social.provider)
+      openUILink(Social.provider.profile.profileURL);
   },
 
-  // Called when the social.enabled pref is changed
-  observe: function SocialUI_observe(aSubject, aTopic, aData) {
-    SocialShareButton.updateButtonEnabledState();
+  observe: function SocialUI_observe(subject, topic, data) {
+    switch (topic) {
+      case "social:pref-changed":
+        SocialShareButton.updateButtonHiddenState();
+        SocialToolbar.updateButtonHiddenState();
+        break;
+      case "social:ambient-notification-changed":
+        SocialToolbar.updateButton();
+        break;
+      case "social:profile-changed":
+        SocialToolbar.updateProfile();
+        break;
+    }
   },
 
   // Called once Social.jsm's provider has been set
   _providerReady: function SocialUI_providerReady() {
+    SocialToolbar.init();
     SocialShareButton.init();
   }
 }
 
 let SocialShareButton = {
   init: function SSB_init() {
     this.sharePopup.hidden = false;
-    this.updateButtonEnabledState();
+    this.updateButtonHiddenState();
   },
 
   get shareButton() {
     return document.getElementById("share-button");
   },
   get sharePopup() {
     return document.getElementById("editSharePopup");
   },
 
   dismissSharePopup: function SSB_dismissSharePopup() {
     this.sharePopup.hidePopup();
   },
 
-  updateButtonEnabledState: function SSB_updateButtonEnabledState() {
+  updateButtonHiddenState: function SSB_updateButtonHiddenState() {
     let shareButton = this.shareButton;
     if (shareButton)
-      shareButton.hidden = !Social.provider || !Social.provider.enabled ||
-                           !Social.provider.port;
+      shareButton.hidden = !Social.uiVisible;
   },
 
   onClick: function SSB_onClick(aEvent) {
     if (aEvent.button != 0)
       return;
 
     // Don't bubble to the textbox, to avoid unwanted selection of the address.
     aEvent.stopPropagation();
@@ -101,8 +121,124 @@ let SocialShareButton = {
       shareButton.setAttribute("shared", "true");
       shareButton.setAttribute("tooltiptext", gNavigatorBundle.getString("social.shareButton.sharedtooltip"));
     } else {
       shareButton.removeAttribute("shared");
       shareButton.setAttribute("tooltiptext", gNavigatorBundle.getString("social.shareButton.tooltip"));
     }
   }
 };
+
+var SocialToolbar = {
+  // Called once, after window load, when the Social.provider object is initialized
+  init: function SocialToolbar_init() {
+    document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
+    
+    // handle button state
+    document.getElementById("social-statusarea-popup").addEventListener("popupshowing", function(e) {
+      document.getElementById("social-toolbar-button").setAttribute("open", "true");
+    }, false);
+    document.getElementById("social-statusarea-popup").addEventListener("popuphiding", function(e) {
+      document.getElementById("social-toolbar-button").removeAttribute("open");
+    }, false);
+
+    this.updateButton();
+    this.updateProfile();
+  },
+
+  updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
+    let toolbarbutton = document.getElementById("social-toolbar-button");
+    toolbarbutton.hidden = !Social.uiVisible;
+  },
+
+  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
+    let profile = Social.provider.profile || {};
+    let userPortrait = profile.portrait || "chrome://browser/skin/social/social.png";
+    document.getElementById("social-statusarea-user-portrait").setAttribute("src", userPortrait);
+
+    let notLoggedInLabel = document.getElementById("social-statusarea-notloggedin");
+    let userNameBtn = document.getElementById("social-statusarea-username");
+    if (profile.userName) {
+      notLoggedInLabel.hidden = true;
+      userNameBtn.hidden = false;
+      userNameBtn.label = profile.userName;
+    } else {
+      notLoggedInLabel.hidden = false;
+      userNameBtn.hidden = true;
+    }
+  },
+
+  updateButton: function SocialToolbar_updateButton() {
+    this.updateButtonHiddenState();
+
+    let provider = Social.provider;
+    // if there are no ambient icons, we collapse them in the following loop
+    let iconNames = Object.keys(provider.ambientNotificationIcons);
+    let iconBox = document.getElementById("social-status-iconbox");
+    for (var i = 0; i < iconBox.childNodes.length; i++) {
+      let iconContainer = iconBox.childNodes[i];
+      if (i > iconNames.length - 1) {
+        iconContainer.collapsed = true;
+        continue;
+      }
+
+      iconContainer.collapsed = false;
+      let icon = provider.ambientNotificationIcons[iconNames[i]];
+      let iconImage = iconContainer.firstChild;
+      let iconCounter = iconImage.nextSibling;
+
+      iconImage.setAttribute("contentPanel", icon.contentPanel);
+      iconImage.setAttribute("src", icon.iconURL);
+
+      if (iconCounter.firstChild)
+        iconCounter.removeChild(iconCounter.firstChild);
+
+      if (icon.counter) {
+        iconCounter.appendChild(document.createTextNode(icon.counter));
+        iconCounter.collapsed = false;
+      } else {
+        iconCounter.collapsed = true;
+      }
+    }
+  },
+
+  showAmbientPopup: function SocialToolbar_showAmbientPopup(iconContainer) {
+    let iconImage = iconContainer.firstChild;
+    let panel = document.getElementById("social-notification-panel");
+    let notifBrowser = document.getElementById("social-notification-browser");
+
+    panel.hidden = false;
+
+    function sizePanelToContent() {
+      // XXX Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
+      // XXX need to handle dynamic sizing
+      let doc = notifBrowser.contentDocument;
+      // XXX "notif" is an implementation detail that we should get rid of
+      // eventually
+      let body = doc.getElementById("notif") || doc.body.firstChild;
+      if (!body)
+        return;
+      let h = body.scrollHeight > 0 ? body.scrollHeight : 300;
+      notifBrowser.style.width = body.scrollWidth + "px";
+      notifBrowser.style.height = h + "px";
+    }
+
+    notifBrowser.addEventListener("DOMContentLoaded", function onload() {
+      notifBrowser.removeEventListener("DOMContentLoaded", onload);
+      sizePanelToContent();
+    });
+
+    panel.addEventListener("popuphiding", function onpopuphiding() {
+      panel.removeEventListener("popuphiding", onpopuphiding);
+      // unload the panel
+      document.getElementById("social-toolbar-button").removeAttribute("open");
+      notifBrowser.setAttribute("src", "about:blank");
+    });
+
+    notifBrowser.service = Social.provider;
+    notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
+    document.getElementById("social-toolbar-button").setAttribute("open", "true");
+    panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
+  }
+}
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -216,16 +216,20 @@
                 class="editSharePopupBottomButton"
                 label="&social.sharePopup.undo.label;"
                 accesskey="&social.sharePopup.undo.accesskey;"
                 command="Social:UnsharePage"/>
 #endif
       </hbox>
     </panel>
 
+    <panel id="social-notification-panel" type="arrow" hidden="true" noautofocus="true">
+      <browser id="social-notification-browser" type="content" flex="1"/>
+    </panel>
+
     <menupopup id="inspector-node-popup">
       <menuitem id="inspectorHTMLCopyInner"
                 label="&inspectorHTMLCopyInner.label;"
                 accesskey="&inspectorHTMLCopyInner.accesskey;"
                 command="Inspector:CopyInner"/>
       <menuitem id="inspectorHTMLCopyOuter"
                 label="&inspectorHTMLCopyOuter.label;"
                 accesskey="&inspectorHTMLCopyOuter.accesskey;"
@@ -599,16 +603,55 @@
                      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;"/>
 
+      <toolbaritem id="social-toolbar-button"
+                   class="toolbarbutton-1 chromeclass-toolbar-additional"
+                   removable="false"
+                   title="&socialToolbar.title;"
+                   hidden="true">
+        <hbox id="social-toolbar-button-box" class="social-statusarea-container">
+          <button id="social-provider-image" type="menu">
+            <menupopup id="social-statusarea-popup">
+              <hbox id="social-statusarea-user" pack="left" align="center">
+                <image id="social-statusarea-user-portrait"/>
+                <vbox>
+                  <label id="social-statusarea-notloggedin"
+                         value="&social.notLoggedIn.label;"/>
+                  <button id="social-statusarea-username"
+                          oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();"/>
+                </vbox>
+              </hbox>
+            </menupopup>
+          </button>
+          <hbox id="social-status-iconbox" flex="1">
+            <box class="social-notification-icon-container" collapsed="true"
+                     onclick="SocialToolbar.showAmbientPopup(this);">
+              <image class="social-notification-icon-image"/>
+              <box class="social-notification-icon-counter" collapsed="true"/>
+            </box>
+            <box class="social-notification-icon-container" collapsed="true"
+                     onclick="SocialToolbar.showAmbientPopup(this);">
+              <image class="social-notification-icon-image"/>
+              <box class="social-notification-icon-counter" collapsed="true"/>
+            </box>
+            <box class="social-notification-icon-container" collapsed="true"
+                     onclick="SocialToolbar.showAmbientPopup(this);">
+              <image class="social-notification-icon-image"/>
+              <box class="social-notification-icon-counter" collapsed="true"/>
+            </box>
+          </hbox>
+        </hbox>
+      </toolbaritem>
+
       <toolbaritem id="bookmarks-menu-button-container"
                    class="chromeclass-toolbar-additional"
                    removable="true"
                    title="&bookmarksMenuButton.label;">
         <toolbarbutton id="bookmarks-menu-button"
                        type="menu"
                        class="toolbarbutton-1"
                        label="&bookmarksMenuButton.label;"
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -251,16 +251,17 @@ endif
                  authenticate.sjs \
                  browser_minimize.js \
                  browser_aboutSyncProgress.js \
                  browser_middleMouse_inherit.js \
                  redirect_bug623155.sjs \
                  browser_tabDrop.js \
                  browser_lastAccessedTab.js \
                  browser_bug734076.js \
+                 browser_social_toolbar.js \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_social_toolbar.js
@@ -0,0 +1,140 @@
+/* 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/. */
+
+let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
+let gProvider;
+
+function test() {
+  waitForExplicitFinish();
+
+  Services.prefs.setBoolPref("social.enabled", true);
+  registerCleanupFunction(function () {
+    Services.prefs.clearUserPref("social.enabled");
+  });
+
+  let oldProvider;
+  function saveOldProviderAndStartTestWith(provider) {
+    oldProvider = Social.provider;
+    registerCleanupFunction(function () {
+      Social.provider = oldProvider;
+    });
+    Social.provider = gProvider = provider;
+    runTests(tests, undefined, undefined, function () {
+      SocialService.removeProvider(provider.origin, finish);
+    });
+  }
+
+  let manifest = { // normal provider
+    name: "provider 1",
+    origin: "https://example1.com",
+    workerURL: "https://example1.com/worker.js",
+    iconURL: "chrome://branding/content/icon48.png"
+  };
+  SocialService.addProvider(manifest, function(provider) {
+    // If the UI is already active, run the test immediately, otherwise wait
+    // for initialization.
+    if (Social.provider) {
+      saveOldProviderAndStartTestWith(provider);
+    } else {
+      Services.obs.addObserver(function obs() {
+        Services.obs.removeObserver(obs, "test-social-ui-ready");
+        saveOldProviderAndStartTestWith(provider);
+      }, "test-social-ui-ready", false);
+    }
+  });
+}
+
+var tests = {
+  testProfileSet: function(next) {
+    let profile = {
+      portrait: "chrome://branding/content/icon48.png",
+      userName: "trickster",
+      displayName: "Kuma Lisa",
+      profileURL: "http://en.wikipedia.org/wiki/Kuma_Lisa"
+    }
+    gProvider.updateUserProfile(profile);
+    // check dom values
+    let portrait = document.getElementById("social-statusarea-user-portrait").getAttribute("src");
+    is(portrait, profile.portrait, "portrait is set");
+    let userButton = document.getElementById("social-statusarea-username");
+    ok(!userButton.hidden, "username is visible");
+    is(userButton.label, profile.userName, "username is set");
+    next();
+  },
+  testAmbientNotifications: function(next) {
+    let ambience = {
+      name: "testIcon",
+      iconURL: "chrome://branding/content/icon48.png",
+      contentPanel: "about:blank",
+      counter: 42
+    };
+    gProvider.setAmbientNotification(ambience);
+
+    let statusIcons = document.getElementById("social-status-iconbox");
+    ok(!statusIcons.firstChild.collapsed, "status icon is visible");
+    ok(!statusIcons.firstChild.lastChild.collapsed, "status value is visible");
+    is(statusIcons.firstChild.lastChild.textContent, "42", "status value is correct");
+
+    ambience.counter = 0;
+    gProvider.setAmbientNotification(ambience);
+    ok(statusIcons.firstChild.lastChild.collapsed, "status value is not visible");
+    is(statusIcons.firstChild.lastChild.textContent, "", "status value is correct");
+    next();
+  },
+  testProfileUnset: function(next) {
+    gProvider.updateUserProfile({});
+    // check dom values
+    let portrait = document.getElementById("social-statusarea-user-portrait").getAttribute("src");
+    is(portrait, "chrome://browser/skin/social/social.png", "portrait is generic");
+    let userButton = document.getElementById("social-statusarea-username");
+    ok(userButton.hidden, "username is not visible");
+    let ambience = document.getElementById("social-status-iconbox").firstChild;
+    while (ambience) {
+      ok(ambience.collapsed, "ambient icon is collapsed");
+      ambience = ambience.nextSibling;
+    }
+    
+    next();
+  }
+}
+
+function runTests(tests, cbPreTest, cbPostTest, cbFinish) {
+  let testIter = Iterator(tests);
+
+  if (cbPreTest === undefined) {
+    cbPreTest = function(cb) {cb()};
+  }
+  if (cbPostTest === undefined) {
+    cbPostTest = function(cb) {cb()};
+  }
+
+  function runNextTest() {
+    let name, func;
+    try {
+      [name, func] = testIter.next();
+    } catch (err if err instanceof StopIteration) {
+      // out of items:
+      (cbFinish || finish)();
+      return;
+    }
+    // We run on a timeout as the frameworker also makes use of timeouts, so
+    // this helps keep the debug messages sane.
+    executeSoon(function() {
+      function cleanupAndRunNextTest() {
+        info("sub-test " + name + " complete");
+        cbPostTest(runNextTest);
+      }
+      cbPreTest(function() {
+        info("sub-test " + name + " starting");
+        try {
+          func.call(tests, cleanupAndRunNextTest);
+        } catch (ex) {
+          ok(false, "sub-test " + name + " failed: " + ex.toString() +"\n"+ex.stack);
+          cleanupAndRunNextTest();
+        }
+      })
+    });
+  }
+  runNextTest();
+}
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -648,12 +648,15 @@ just addresses the organization to follo
 located in front of the breadcrumbs display in the inspector toolbar. The button
 doesn't display any label, but exposes a label to screen-readers with "aria-label".
 -->
 <!ENTITY markupButton.arialabel          "Markup">
 <!-- LOCALIZATION NOTE (markupButton.accesskey): The key bound to the Markup panel's
 toolbar button -->
 <!ENTITY markupButton.accesskey          "M">
 
+<!ENTITY socialToolbar.title        "Social Toolbar Button">
+<!ENTITY social.notLoggedIn.label   "Not logged in">
+
 <!ENTITY social.sharePopup.undo.label     "Unshare">
 <!ENTITY social.sharePopup.undo.accesskey "U">
 <!ENTITY social.sharePopup.ok.label       "OK">
 <!ENTITY social.sharePopup.ok.accesskey   "O">
--- a/browser/modules/Social.jsm
+++ b/browser/modules/Social.jsm
@@ -33,16 +33,20 @@ let Social = {
       Services.obs.notifyObservers(null, "test-social-ui-ready", "");
     }.bind(this));
   },
 
   get enabled() {
     return SocialService.enabled;
   },
 
+  get uiVisible() {
+    return this.provider && this.provider.enabled && this.provider.port;
+  },
+
   sendWorkerMessage: function Social_sendWorkerMessage(message) {
     // Responses aren't handled yet because there is no actions to perform
     // based on the response from the provider at this point.
     if (this.provider && this.provider.port)
       this.provider.port.postMessage(message);
   },
 
   // Sharing functionality
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -3338,8 +3338,128 @@ stack[anonid=browserStack][responsivemod
 
 #developer-toolbar-webconsole[error-count]:before {
   color: #FDF3DE;
   min-width: 16px;
   text-shadow: none;
   background-image: -moz-linear-gradient(top, #B4211B, #8A1915);
   border-radius: 1px;
 }
+
+/* === social toolbar button === */
+
+/* button icon for the service */
+#social-provider-image {
+  -moz-appearance: none;
+  margin: 0;
+  padding: 2px;
+  min-width: 0;
+  max-height: 20px;
+  list-style-image: url("chrome://browser/skin/social/social.png");
+}
+
+/* hbox that surrounds an image and its counter */
+.social-notification-icon-container {
+  cursor: pointer;
+  padding: 0px;
+  margin: 0px;
+  position: relative;
+}
+
+/* notification counter box */
+.social-notification-icon-counter {
+  background-color: rgb(240,61,37);
+  border: 1px solid rgb(216,55,34);
+  box-shadow: 0px 1px 0px rgba(0,39,121,0.77);
+  padding-right: 1px;
+  padding-left: 1px;
+  color: white;
+  font-size: 9px;
+  font-weight: bold;
+  position: absolute;
+  right: -3px;
+  top: -4px;
+  z-index: 1;
+  text-align: center;
+}
+
+/* notification image */
+.social-notification-icon-image {
+  padding: 2px;
+  margin: 0px;
+  min-width: 20px;
+  max-width: 32px;
+  max-height: 20px;
+  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
+}
+
+/* === end of social toolbar button === */
+
+/* === social toolbar provider menu  === */
+
+#social-statusarea-user {
+  background-color: white;
+  color: black;
+  cursor: default;
+  font-family: "lucida grande",tahoma,verdana,arial,sans-serif;
+  font-size: 12px;
+}
+
+#social-statusarea-user-portrait {
+  width: 32px;
+  height: 32px;
+  margin: 10px;
+  list-style-image: url("chrome://browser/skin/social/social.png");
+}
+
+#social-statusarea-username {
+  -moz-appearance: none;
+  color: -moz-nativehyperlinktext;
+  cursor: pointer;
+  min-width: 0;
+  margin: 0 6px;
+}
+
+#social-statusarea-username:hover {
+  text-decoration: underline;
+}
+
+/* === end of social toolbar provider menu === */
+
+/* === start of social toolbar panels === */
+
+#social-notification-panel {
+  min-height: 100px;
+  min-width: 240px;
+  max-height: 600px;
+  max-width: 400px;
+}
+
+#social-notification-panel .panel-arrowcontent {
+  margin: -4px 0 0 0;
+  padding: 0;
+  border-radius: 0px;
+}
+
+#social-notification-panel .panel-arrow[side="top"] {
+  list-style-image: url("chrome://browser/skin/social/panelarrow-up.png");
+  margin-top: -4px;
+  margin-bottom: 3px;
+  height: 21px;
+}
+
+#social-notification-panel .panel-arrow[side="bottom"] {
+  list-style-image: url("chrome://browser/skin/social/panelarrow-down.png");
+  margin-top: -5px;
+}
+
+#social-notification-panel .panel-arrow[side="left"] {
+  list-style-image: url("chrome://browser/skin/social/panelarrow-horiz.png");
+  margin-right: -1px;
+  -moz-transform: scaleX(-1);
+}
+
+#social-notification-panel .panel-arrow[side="right"] {
+  list-style-image: url("chrome://browser/skin/social/panelarrow-horiz.png");
+  margin-left: -1px;
+}
+
+/* === end of social toolbar panels === */
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -108,16 +108,20 @@ browser.jar:
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/preferences/Options-sync.png         (preferences/Options-sync.png)
 #endif
   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/social.png                    (social/social.png)
+  skin/classic/browser/social/panelarrow-down.png           (social/panelarrow-down.png)
+  skin/classic/browser/social/panelarrow-horiz.png          (social/panelarrow-horiz.png)
+  skin/classic/browser/social/panelarrow-up.png             (social/panelarrow-up.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/connecting.png                         (tabbrowser/connecting.png)
   skin/classic/browser/tabbrowser/loading.png                            (tabbrowser/loading.png)
   skin/classic/browser/tabbrowser/tab-arrow-left.png                     (tabbrowser/tab-arrow-left.png)
   skin/classic/browser/tabbrowser/tab-arrow-right.png                    (tabbrowser/tab-arrow-right.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)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0224ebdf153bec5d7125f88bb9494d6d36dfbeae
GIT binary patch
literal 2186
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ed59312c14252fe9c7f37e902285d652cbb09359
GIT binary patch
literal 2188
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..451b83b3b9bfde3ffba768feba91566bea92210d
GIT binary patch
literal 2157
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
AwEzGB
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..14916fb074c79b18c732f41661110027983c5d03
GIT binary patch
literal 1654
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4(FKV3x~tb`J1#c2)=|%1_J8No8QD
zU~CP!pM5z%<ln8-xf>pKTcrzf+GR}4O9?J<p0h1GeAn5iS7zH4J!UV<jhS^!<!#*t
z_M6@LR!7S}vfKS+=egOOUp<NUm`LJ}H62Pm-;_4bn{DE&9?ZP+`|kTc-&v|Ze-gLg
zXJOQ35q*A<&|v?ghyEOSB69x|W1Nh$_MZ&j?lv(mHFpR8%bP0SZ~n|DcPyvmUH<*m
z|B|oHn#v>iK}KQU6w@P04<i?3##|{8esHbx{ai!SLuY-8BbKvp%BNf8CpSLq=~bSV
zW@73vi}MisQ70?!9S#;VG9P^Ay>YHl<cYf4%1L_NHmhBO^q;1<ZsPg&LB6>8Q~ZV%
zQ(n$q`&^(mcb25z#hR{r@|Lv)J<k}f9<+~_*z34sZb5|E<He?RPG?ot399XV{;ni*
z#@p0c(<3#7RAp55B!#Rq&dGen&D=Tb+2yxi0w!&kZ?fOSIP&x3w*gaGUK<|$`pw(z
z%dWlGZ%>@e{@B!Rx#qQchktv&e=X{IS~=;%>n(D<SHDD0vI@I>`^nj5%7>4X2ih}x
zI5qXjq-Z>t=){vaEBVN(A3kD|N?uDYWtN0gZnC&$tucApTN(F?lkt2z;>5m2Z`$$g
z!S8u@Rj>E$5p6xXeesRJw_6)u?%E_gOS--^ap~f`hvqw<&X&$y&CL<`uj}bXkGRxR
z{!M|`OU<552%i3@l>5BVly|CSLJ>T>)_jQjp_Rks-zt7+`u-~?&fQxpc)Fob$8Pn!
z;Iqfxs9y59^g3n7{;sc1$0UAEFm#TZyHCY;PM77UTLIkaY~@X_pFN7vzs^2y_nFv-
zzjku0)hkl&J0$+qwMOy7KI46M@!Rt|5|`iJcRA(tV#BD{yDv}NwP<72l>Xc5-)#F<
z2}^F;xNl=!7>D+jMafxSn@ju|m{oKArhjIg{9dqyyQX8EZfF1Mr0@y;+FbcFdE%z?
zc&_)jskgzp|1I;j;A^qZGUJOaKWi1dl>U48wVrt>Tb$&9i^Y243ye#jaBirH(|Ij=
zTi#~g_J)bpx0Bb}<|gjywhLQ*yF@Qqj&V2t>Z|k5uey5o`ICC?ip77}Rw{E{JG3y~
z2$*3w3p^r=85p>QL70(Y)*J~21}3@8kcg59UmvUF{9L`nl>DSry^7od1`x2RumUo3
zQ%e#RDspr3imfVamB1>jfNYSkzLEl1NlCV?QiN}Sf^&XRs)C80iJpOy9hZWFf=y9M
znpKdC8&o@xXRDM^Qc_^0uU}qXu2*iXmtT~wZ)j<0sc&GUZ)BtkRH0j3nOBlnp_^B%
z3^4>|j!SBBa#3bMNoIbY0*IfOlwVq6tE2=~0|5|=Qj+2J6qFX_fNe=h)=$kz%}vcK
zDb_dCGt`G04l+L_*{ZlSDJwO(#16$cu*FV^>H5fu^)Xf3=%cxiT$cj_6Yli9VrYB-
zV@AIsu>k0715{@NRa-e1r6!i-7lq{K=h!)dlq-1VCZ?wbr6#6S+UTRJ!0TR!C@{Y4
zxPUrgac{>JuxDWiFgaZDba4!^5ZpS+k*nE2!1eg0&o^3yHs09FE&eET(-v_d@p%gu
zU164NUFp0s<xxlLrACKOm6e_+Dmpm!U#ZM54iq^P6FOCW<Ghk)oAZXJjgFc7GMC2Y
zt32YpWYStWZ)SthN|%EszCzk*{{<zIk6d2zL8Ue7wYBFP$C*dEnpkztS~S^e{EjN{
z7TV&!+%mPVq2=i^{&j^tUYhN-`oH(JyWidvm(ZlqWx&H!_*uP%kGUjvyVni#xElGs
zss@SOGY-79lfE;1v${^ePIjxGr*<;6TgUBVI3k(zKwqXI1(e=BUHx3vIVCg!0Cn%A
AApigX
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -3265,8 +3265,139 @@ stack[anonid=browserStack][responsivemod
 
 #developer-toolbar-webconsole[error-count]:before {
   color: #FDF3DE;
   min-width: 16px;
   text-shadow: none;
   background-image: -moz-linear-gradient(top, #B4211B, #8A1915);
   border-radius: 1px;
 }
+
+
+/* === social toolbar button === */
+
+.social-statusarea-container {
+  -moz-appearance: toolbarbutton;
+  margin: 0 2px;
+  padding: 3px;
+}
+
+.social-statusarea-container {
+  -moz-appearance: none;
+  margin: 2px; /* make sure we have the correct platform spacing*/
+  padding: 1px;
+}
+
+/* aero look for hover */
+#social-toolbar-button[open="true"] > .social-statusarea-container,
+.social-statusarea-container:hover {
+  background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
+  border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
+  box-shadow: 0 1px hsla(0,0%,100%,.85) inset,
+              0 1px hsla(210,54%,20%,.1),
+              0 0 2px hsla(210,54%,20%,.4);
+}
+
+/* favicon for the service */
+#social-provider-image {
+  width: 20px;
+  height: 20px;
+  max-height: 20px;
+  max-width: 20px;
+  padding: 2px;
+  list-style-image: url("chrome://browser/skin/social/social.png");
+}
+
+/* hbox that hold notification icons */
+#social-status-iconbox {
+  margin: 0px;
+  padding: 0px;
+}
+
+/* hbox that surrounds an image and its counter */
+.social-notification-icon-container {
+  cursor: pointer;
+  padding: 0px;
+  margin: 0px;
+  position: relative;
+}
+
+/* notification counter box */
+.social-notification-icon-counter {
+  background-color: rgb(240,61,37);
+  border: 1px solid rgb(216,55,34);
+  box-shadow: 0px 1px 0px rgba(0,39,121,0.77);
+  padding-right: 1px;
+  padding-left: 1px;
+  color: white;
+  font-size: 9px;
+  font-weight: bold;
+  position: absolute;
+  right: -3px;
+  top: -4px;
+  z-index: 1;
+  text-align: center;
+}
+
+/* notification image */
+.social-notification-icon-image {
+  padding: 2px;
+  margin: 0px;
+  min-width: 20px;
+  max-width: 32px;
+  max-height: 20px;
+  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
+}
+
+/* === end of social toolbar button === */
+
+/* === social toolbar provider menu  === */
+
+/* popups that hang off our toolbaritem */
+#social-statusarea-popup {
+  margin-top:0px;
+  margin-left: -12px;
+  margin-right: -12px;
+}
+
+#social-statusarea-user {
+  border-bottom:1px solid rgb(221,221,221);
+  background-color:-moz-Dialog;
+  color:black;
+  cursor:default;
+  position:relative;
+  font-family: "lucida grande",tahoma,verdana,arial,sans-serif;
+  font-size:12px;
+}
+
+#social-statusarea-user-portrait {
+  width:32px;
+  height:32px;
+  border-radius:2px;
+  margin:10px;
+  list-style-image: url("chrome://browser/skin/social/social.png");
+}
+
+#social-statusarea-username {
+  -moz-appearance: none;
+  background: transparent;
+  border: none;
+  color: -moz-nativehyperlinktext;
+  cursor: pointer;
+  min-width: 0;
+  margin: 0 6px;
+}
+#social-statusarea-username:hover {
+  text-decoration: underline;
+}
+
+/* === end of social toolbar provider menu === */
+
+/* === end of social toolbar panels === */
+
+#social-notification-panel {
+  min-height: 100px;
+  min-width: 100px;
+  max-height: 600px;
+  max-width: 400px;
+}
+
+/* === end of social toolbar panels === */
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -101,16 +101,17 @@ browser.jar:
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/preferences/Options-sync.png            (preferences/Options-sync.png)
 #endif
         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/social.png                       (social/social.png)
         skin/classic/browser/tabbrowser/alltabs.png                  (tabbrowser/alltabs.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-arrow-left.png           (tabbrowser/tab-arrow-left.png)
         skin/classic/browser/tabbrowser/tab-arrow-left-inverted.png  (tabbrowser/tab-arrow-left-inverted.png)
@@ -302,16 +303,17 @@ browser.jar:
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/preferences/Options-sync.png       (preferences/Options-sync.png)
 #endif
         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/social.png                  (social/social.png)
         skin/classic/aero/browser/tabbrowser/alltabs.png             (tabbrowser/alltabs.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-arrow-left.png      (tabbrowser/tab-arrow-left.png)
         skin/classic/aero/browser/tabbrowser/tab-arrow-left-inverted.png (tabbrowser/tab-arrow-left-inverted.png)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..14916fb074c79b18c732f41661110027983c5d03
GIT binary patch
literal 1654
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4(FKV3x~tb`J1#c2)=|%1_J8No8QD
zU~CP!pM5z%<ln8-xf>pKTcrzf+GR}4O9?J<p0h1GeAn5iS7zH4J!UV<jhS^!<!#*t
z_M6@LR!7S}vfKS+=egOOUp<NUm`LJ}H62Pm-;_4bn{DE&9?ZP+`|kTc-&v|Ze-gLg
zXJOQ35q*A<&|v?ghyEOSB69x|W1Nh$_MZ&j?lv(mHFpR8%bP0SZ~n|DcPyvmUH<*m
z|B|oHn#v>iK}KQU6w@P04<i?3##|{8esHbx{ai!SLuY-8BbKvp%BNf8CpSLq=~bSV
zW@73vi}MisQ70?!9S#;VG9P^Ay>YHl<cYf4%1L_NHmhBO^q;1<ZsPg&LB6>8Q~ZV%
zQ(n$q`&^(mcb25z#hR{r@|Lv)J<k}f9<+~_*z34sZb5|E<He?RPG?ot399XV{;ni*
z#@p0c(<3#7RAp55B!#Rq&dGen&D=Tb+2yxi0w!&kZ?fOSIP&x3w*gaGUK<|$`pw(z
z%dWlGZ%>@e{@B!Rx#qQchktv&e=X{IS~=;%>n(D<SHDD0vI@I>`^nj5%7>4X2ih}x
zI5qXjq-Z>t=){vaEBVN(A3kD|N?uDYWtN0gZnC&$tucApTN(F?lkt2z;>5m2Z`$$g
z!S8u@Rj>E$5p6xXeesRJw_6)u?%E_gOS--^ap~f`hvqw<&X&$y&CL<`uj}bXkGRxR
z{!M|`OU<552%i3@l>5BVly|CSLJ>T>)_jQjp_Rks-zt7+`u-~?&fQxpc)Fob$8Pn!
z;Iqfxs9y59^g3n7{;sc1$0UAEFm#TZyHCY;PM77UTLIkaY~@X_pFN7vzs^2y_nFv-
zzjku0)hkl&J0$+qwMOy7KI46M@!Rt|5|`iJcRA(tV#BD{yDv}NwP<72l>Xc5-)#F<
z2}^F;xNl=!7>D+jMafxSn@ju|m{oKArhjIg{9dqyyQX8EZfF1Mr0@y;+FbcFdE%z?
zc&_)jskgzp|1I;j;A^qZGUJOaKWi1dl>U48wVrt>Tb$&9i^Y243ye#jaBirH(|Ij=
zTi#~g_J)bpx0Bb}<|gjywhLQ*yF@Qqj&V2t>Z|k5uey5o`ICC?ip77}Rw{E{JG3y~
z2$*3w3p^r=85p>QL70(Y)*J~21}3@8kcg59UmvUF{9L`nl>DSry^7od1`x2RumUo3
zQ%e#RDspr3imfVamB1>jfNYSkzLEl1NlCV?QiN}Sf^&XRs)C80iJpOy9hZWFf=y9M
znpKdC8&o@xXRDM^Qc_^0uU}qXu2*iXmtT~wZ)j<0sc&GUZ)BtkRH0j3nOBlnp_^B%
z3^4>|j!SBBa#3bMNoIbY0*IfOlwVq6tE2=~0|5|=Qj+2J6qFX_fNe=h)=$kz%}vcK
zDb_dCGt`G04l+L_*{ZlSDJwO(#16$cu*FV^>H5fu^)Xf3=%cxiT$cj_6Yli9VrYB-
zV@AIsu>k0715{@NRa-e1r6!i-7lq{K=h!)dlq-1VCZ?wbr6#6S+UTRJ!0TR!C@{Y4
zxPUrgac{>JuxDWiFgaZDba4!^5ZpS+k*nE2!1eg0&o^3yHs09FE&eET(-v_d@p%gu
zU164NUFp0s<xxlLrACKOm6e_+Dmpm!U#ZM54iq^P6FOCW<Ghk)oAZXJjgFc7GMC2Y
zt32YpWYStWZ)SthN|%EszCzk*{{<zIk6d2zL8Ue7wYBFP$C*dEnpkztS~S^e{EjN{
z7TV&!+%mPVq2=i^{&j^tUYhN-`oH(JyWidvm(ZlqWx&H!_*uP%kGUjvyVni#xElGs
zss@SOGY-79lfE;1v${^ePIjxGr*<;6TgUBVI3k(zKwqXI1(e=BUHx3vIVCg!0Cn%A
AApigX