Bug 755126 add social services management to about:addons, r=felipe
authorShane Caraveo <scaraveo@mozilla.com>
Tue, 26 Feb 2013 14:50:24 -0800
changeset 134494 d84192e9779f2aa96cb12095fa6498aa11adafc8
parent 134493 1907943cdee2633136320a8f6ee527099605978a
child 134495 2a33d38e3a1add83322d0b29dd2a0b148c5232e7
push id336
push userakeybl@mozilla.com
push dateMon, 17 Jun 2013 22:53:19 +0000
treeherdermozilla-release@574a39cdf657 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfelipe
bugs755126
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 755126 add social services management to about:addons, r=felipe
browser/app/profile/firefox.js
browser/base/content/browser-menubar.inc
browser/base/content/browser-sets.inc
browser/base/content/browser-social.js
browser/base/content/browser.xul
browser/base/content/test/social/Makefile.in
browser/base/content/test/social/blocklist.xml
browser/base/content/test/social/blocklistEmpty.xml
browser/base/content/test/social/browser_addons.js
browser/base/content/test/social/browser_blocklist.js
browser/base/content/test/social/browser_social_toolbar.js
browser/base/content/test/social/head.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/locales/en-US/chrome/browser/browser.properties
toolkit/components/social/SocialService.jsm
toolkit/components/social/test/xpcshell/blocklist.xml
toolkit/components/social/test/xpcshell/head.js
toolkit/components/social/test/xpcshell/test_SocialService.js
toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
toolkit/mozapps/extensions/content/selectAddons.js
toolkit/mozapps/extensions/nsBlocklistService.js
toolkit/themes/linux/mozapps/extensions/extensions.css
toolkit/themes/osx/mozapps/extensions/extensions.css
toolkit/themes/windows/mozapps/extensions/extensions.css
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1195,15 +1195,15 @@ 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);
 
 // Default social providers
-pref("social.manifest.facebook", "{\"origin\":\"https://www.facebook.com\",\"name\":\"Facebook Messenger\",\"workerURL\":\"https://www.facebook.com/desktop/fbdesktop2/socialfox/fbworker.js.php\",\"iconURL\":\"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAX0lEQVQ4jWP4%2F%2F8%2FAyUYTFhHzjgDxP9JxGeQDSBVMxgTbUBCxer%2Fr999%2BQ8DJBuArJksA9A10s8AXIBoA0B%2BR%2FY%2FjD%2BEwoBoA1yT5v3PbdmCE8MAshhID%2FUMoDgzUYIBj0Cgi7ar4coAAAAASUVORK5CYII%3D\",\"sidebarURL\":\"https://www.facebook.com/desktop/fbdesktop2/?socialfox=true\",\"icon32URL\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAADbklEQVRYCc1Xv08UQRj99tctexAuCEFjRE0kGBEtLDSGqIWNxkYKbTAxNlY2JhaGWltNtNFeKgsKKxITK43/gCYW+IsoRhA4D47bH7fn9+bcvdm5JR7sefolC3Ozu9978+bNN7PayUv3HN3umdY0Y6IWBtSJ0HSTarXqTOiuTep6Lj+tdxAcA8RAgSmwdd2aCDs0clldYALb/FvgYVhjmfliVA2XpjEgWo0Attn42Z6WH1RFor5ehwo9XQIUZMoVn4qlCoVMSo62EvD8Kh0b3U2Xz43R2PBO6mUCGDlAf65V6MadZzT/rUimoccc2kYA4BfPHqJb105RzjJigKhRq9kEJUBIjgYVuXeL7SAI6eD+Abp5dTwVHOmEHxT50d8WBYJqSOdPj5BjW8gZR8UNqFR2xagx/65XFYaMH+BGWwiYpi4UkBPPLxTp9v1Z+lHc4DWvCQXWmIy6EjITgKowVd5Jjv7N3Hd6y5esigoOwpkJIAmMpZpLJGdiaaC4F0UmAj6bD84GCEwmB/qxMmRilmnwb/mpjAocHh4UEoNAt5NLZB7oy9OJo0PxqkAtePdhiSqunyC1LQUwWMPQaOr6GRre258Ajn4cP7KHcEXhsxpXbj+lT19X2TMNGTLVAcjcalS8gDwsQ2UOMhH4k8FkcrEn5E5ub2sKohxLK2VR77Hl9RUcsrgeRIEiVOT6z+tDbIeLy+vk+kGTCbXxycet6xhl//3f6bJEkdHYhA+mLtDIvoH4ieev5+juoxdk5+pjhALYEdXIpEB5w+NlSKSzqVQ/+H7IO6BLtl3fngGMiqhGJgIwlM6qpyUGFjySdk8m0Zg0ubeD7X9OIDEFajltRQgUJaUKx69tdgaQa0FMADuahZPMFtcEwNPm2hA7ZI5sK4aoE2NvYI+o8hkCIe7CwTv68zS0q9Dk5vpbm/8FXxitSzmMFHpsGj0wyLUheTwD2Y9fVgh1Ae0EPUgD9241ZEnld+v5kgnVZ/8fE0brVh5BK+1oCqKKF72Dk7HwBsssB/pklU1dfChy3S659H5+uelgIb+8WRv1/uGTV9Sdb5wJFlfW6fPCalMhwhSU1j2xKwKbP838GcOwJja4TqO0bjdmXxYTy1EYjFdCWoCEYZhseH/GDL3yJPHnuW6YmT7P1SlIA4768Hke4vOcsX8BE346lLHhDUQAAAAASUVORK5CYII=\", \"icon64URL\":\"data:image/png;base64,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\"}");
+pref("social.manifest.facebook", "{\"origin\":\"https://www.facebook.com\",\"name\":\"Facebook Messenger\",\"workerURL\":\"https://www.facebook.com/desktop/fbdesktop2/socialfox/fbworker.js.php\",\"iconURL\":\"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAX0lEQVQ4jWP4%2F%2F8%2FAyUYTFhHzjgDxP9JxGeQDSBVMxgTbUBCxer%2Fr999%2BQ8DJBuArJksA9A10s8AXIBoA0B%2BR%2FY%2FjD%2BEwoBoA1yT5v3PbdmCE8MAshhID%2FUMoDgzUYIBj0Cgi7ar4coAAAAASUVORK5CYII%3D\",\"sidebarURL\":\"https://www.facebook.com/desktop/fbdesktop2/?socialfox=true\",\"icon32URL\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAADbklEQVRYCc1Xv08UQRj99tctexAuCEFjRE0kGBEtLDSGqIWNxkYKbTAxNlY2JhaGWltNtNFeKgsKKxITK43/gCYW+IsoRhA4D47bH7fn9+bcvdm5JR7sefolC3Ozu9978+bNN7PayUv3HN3umdY0Y6IWBtSJ0HSTarXqTOiuTep6Lj+tdxAcA8RAgSmwdd2aCDs0clldYALb/FvgYVhjmfliVA2XpjEgWo0Attn42Z6WH1RFor5ehwo9XQIUZMoVn4qlCoVMSo62EvD8Kh0b3U2Xz43R2PBO6mUCGDlAf65V6MadZzT/rUimoccc2kYA4BfPHqJb105RzjJigKhRq9kEJUBIjgYVuXeL7SAI6eD+Abp5dTwVHOmEHxT50d8WBYJqSOdPj5BjW8gZR8UNqFR2xagx/65XFYaMH+BGWwiYpi4UkBPPLxTp9v1Z+lHc4DWvCQXWmIy6EjITgKowVd5Jjv7N3Hd6y5esigoOwpkJIAmMpZpLJGdiaaC4F0UmAj6bD84GCEwmB/qxMmRilmnwb/mpjAocHh4UEoNAt5NLZB7oy9OJo0PxqkAtePdhiSqunyC1LQUwWMPQaOr6GRre258Ajn4cP7KHcEXhsxpXbj+lT19X2TMNGTLVAcjcalS8gDwsQ2UOMhH4k8FkcrEn5E5ub2sKohxLK2VR77Hl9RUcsrgeRIEiVOT6z+tDbIeLy+vk+kGTCbXxycet6xhl//3f6bJEkdHYhA+mLtDIvoH4ieev5+juoxdk5+pjhALYEdXIpEB5w+NlSKSzqVQ/+H7IO6BLtl3fngGMiqhGJgIwlM6qpyUGFjySdk8m0Zg0ubeD7X9OIDEFajltRQgUJaUKx69tdgaQa0FMADuahZPMFtcEwNPm2hA7ZI5sK4aoE2NvYI+o8hkCIe7CwTv68zS0q9Dk5vpbm/8FXxitSzmMFHpsGj0wyLUheTwD2Y9fVgh1Ae0EPUgD9241ZEnld+v5kgnVZ/8fE0brVh5BK+1oCqKKF72Dk7HwBsssB/pklU1dfChy3S659H5+uelgIb+8WRv1/uGTV9Sdb5wJFlfW6fPCalMhwhSU1j2xKwKbP838GcOwJja4TqO0bjdmXxYTy1EYjFdCWoCEYZhseH/GDL3yJPHnuW6YmT7P1SlIA4768Hke4vOcsX8BE346lLHhDUQAAAAASUVORK5CYII=\", \"icon64URL\":\"data:image/png;base64,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\", \"description\":\"Keep up with friends wherever you go on the web.\",\"author\":\"Facebook\",\"homepageURL\":\"https://www.facebook.com/about/messenger-for-firefox\"}");
 
 pref("social.sidebar.open", true);
 pref("social.sidebar.unload_timeout_ms", 10000);
 pref("social.toast-notifications.enabled", true);
 
 pref("dom.identity.enabled", false);
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -540,17 +540,18 @@
                             label="&social.chatBar.label;"
                             accesskey="&social.chatBar.accesskey;"
                             key="focusChatBar"
                             command="Social:FocusChat"
                             class="show-only-for-keyboard"/>
                   <menuseparator class="social-statusarea-separator"/>
                   <menuseparator class="social-provider-menu" hidden="true"/>
                   <menuitem class="social-toggle-menuitem" command="Social:Toggle"/>
-                  <menuitem class="social-remove-menuitem" command="Social:Remove"/>
+                  <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"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -109,17 +109,17 @@
     <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
     <command id="Browser:ToggleAddonBar" oncommand="toggleAddonBar();"/>
     <command id="Social:SharePage" oncommand="SocialShareButton.sharePage();" disabled="true"/>
     <command id="Social:UnsharePage" oncommand="SocialShareButton.unsharePage();"/>
     <command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();"/>
     <command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();"/>
     <command id="Social:FocusChat" oncommand="SocialChatBar.focus();" hidden="true" disabled="true"/>
     <command id="Social:Toggle" oncommand="Social.toggle();" hidden="true"/>
-    <command id="Social:Remove" oncommand="SocialUI.disableWithConfirmation();"/>
+    <command id="Social:Addons" oncommand="BrowserOpenAddonsMgr('addons://list/service');"/>
   </commandset>
 
   <commandset id="placesCommands">
     <command id="Browser:ShowAllBookmarks"
              oncommand="PlacesCommandHook.showPlacesOrganizer('AllBookmarks');"/>
     <command id="Browser:ShowAllHistory"
              oncommand="PlacesCommandHook.showPlacesOrganizer('History');"/>
   </commandset>
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -737,30 +737,23 @@ var SocialMenu = {
   }
 };
 
 // XXX Need to audit that this is being initialized correctly
 var SocialToolbar = {
   // Called once, after window load, when the Social.provider object is
   // initialized.
   init: function SocialToolbar_init() {
-    let accesskey = gNavigatorBundle.getString("social.removeProvider.accesskey");
-    let removeCommand = document.getElementById("Social:Remove");
-    removeCommand.setAttribute("accesskey", accesskey);
     this._dynamicResizer = new DynamicResizeWatcher();
   },
 
   // Called when the Social.provider changes
   updateProvider: function () {
     let provider = Social.provider || Social.defaultProvider;
     if (provider) {
-      let label = gNavigatorBundle.getFormattedString("social.removeProvider.label",
-                                                      [provider.name]);
-      let removeCommand = document.getElementById("Social:Remove");
-      removeCommand.setAttribute("label", label);
       this.button.setAttribute("label", provider.name);
       this.button.setAttribute("tooltiptext", provider.name);
       this.button.style.listStyleImage = "url(" + provider.iconURL + ")";
 
       this.updateProfile();
     }
     this.updateButton();
     this.populateProviderMenus();
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -710,17 +710,18 @@
                       type="checkbox"
                       autocheck="false"
                       command="Social:ToggleNotifications"
                       label="&social.toggleNotifications.label;"
                       accesskey="&social.toggleNotifications.accesskey;"/>
             <menuseparator class="social-statusarea-separator"/>
             <menuseparator class="social-provider-menu" hidden="true"/>
             <menuitem class="social-toggle-menuitem" command="Social:Toggle"/>
-            <menuitem class="social-remove-menuitem" command="Social:Remove"/>
+            <menuitem class="social-addons-menuitem" command="Social:Addons"
+                      label="&social.addons.label;"/>
           </menupopup>
         </toolbarbutton>
       </toolbaritem>
 
       <toolbaritem id="bookmarks-menu-button-container"
                    class="chromeclass-toolbar-additional"
                    removable="true"
                    title="&bookmarksMenuButton.label;">
--- a/browser/base/content/test/social/Makefile.in
+++ b/browser/base/content/test/social/Makefile.in
@@ -7,16 +7,20 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 _BROWSER_FILES = \
                  head.js \
+		 blocklist.xml \
+		 blocklistEmpty.xml \
+		 browser_blocklist.js \
+		 browser_addons.js \
                  browser_social_perwindowPB.js \
                  browser_social_toolbar.js \
                  browser_social_shareButton.js \
                  browser_social_sidebar.js \
                  browser_social_flyout.js \
                  browser_social_mozSocial_API.js \
                  browser_social_isVisible.js \
                  browser_social_chatwindow.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/blocklist.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
+  <emItems>
+    <emItem  blockID="s1" id="bad.com@services.mozilla.org"></emItem>
+  </emItems>
+</blocklist>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/blocklistEmpty.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
+  <emItems>
+    <emItem  blockID="s2" id="nothing@services.mozilla.org"></emItem>
+  </emItems>
+</blocklist>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/browser_addons.js
@@ -0,0 +1,133 @@
+
+
+let AddonManager = Cu.import("resource://gre/modules/AddonManager.jsm", {}).AddonManager;
+let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
+
+const ADDON_TYPE_SERVICE     = "service";
+const ID_SUFFIX              = "@services.mozilla.org";
+const STRING_TYPE_NAME       = "type.%ID%.name";
+
+let manifest = { // normal provider
+  name: "provider 1",
+  origin: "https://example.com",
+  sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+  workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
+  iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
+};
+
+function test() {
+  waitForExplicitFinish();
+
+  Services.prefs.setCharPref("social.manifest.good", JSON.stringify(manifest));
+  runSocialTests(tests, undefined, undefined, function () {
+    Services.prefs.clearUserPref("social.manifest.good");
+    finish();
+  });
+}
+
+var tests = {
+  testInstalledProviders: function(next) {
+    // tests that our builtin manfests are actually available to the addon
+    // manager.  We may have interference from the real builtin providers, so
+    // we will expect our test provider above to be in the list
+    AddonManager.getAddonsByTypes([ADDON_TYPE_SERVICE], function(addons) {
+      for (let addon of addons) {
+        if (addon.manifest.origin == manifest.origin) {
+          ok(true, "test addon is installed");
+          next();
+          return;
+        }
+      }
+      // failure state
+      ok(false, "test addon is not installed");
+      next();
+    });
+  },
+  testAddonEnableToggle: function(next) {
+    // take the first addon in the list, and toggle its enabled state via the
+    // addon interface to see that we get events. restore the enabled state at
+    // the end.
+
+    let expectEvent;
+    let listener = {
+      onEnabled: function(addon) {
+        is(expectEvent, "onEnabled", "provider onEnabled");
+        ok(!addon.userDisabled, "provider enabled");
+        executeSoon(function() {
+          // restore previous state
+          expectEvent = "onDisabling";
+          addon.userDisabled = !addon.userDisabled;
+        });
+      },
+      onEnabling: function(addon) {
+        is(expectEvent, "onEnabling", "provider onEnabling");
+        expectEvent = "onEnabled";
+      },
+      onDisabled: function(addon) {
+        is(expectEvent, "onDisabled", "provider onDisabled");
+        ok(addon.userDisabled, "provider disabled");
+        executeSoon(function() {
+          // restore previous state
+          AddonManager.removeAddonListener(listener);
+          addon.userDisabled = !addon.userDisabled;
+          next();
+        });
+      },
+      onDisabling: function(addon) {
+        is(expectEvent, "onDisabling", "provider onDisabling");
+        expectEvent = "onDisabled";
+      }
+    };
+    AddonManager.addAddonListener(listener);
+
+    AddonManager.getAddonsByTypes([ADDON_TYPE_SERVICE], function(addons) {
+      for (let addon of addons) {
+        expectEvent = addon.userDisabled ? "onEnabling" : "onDisabling";
+        addon.userDisabled = !addon.userDisabled;
+        // only test with one addon
+        return;
+      }
+      ok(false, "no addons toggled");
+      next();
+    });
+  },
+  testProviderEnableToggle: function(next) {
+    // enable and disabel a provider from the SocialService interface, check
+    // that the addon manager is updated
+
+    let expectEvent;
+
+    let listener = {
+      onEnabled: function(addon) {
+        is(expectEvent, "onEnabled", "provider onEnabled");
+        is(addon.manifest.origin, manifest.origin, "provider enabled");
+        ok(!addon.userDisabled, "provider !userDisabled");
+      },
+      onEnabling: function(addon) {
+        is(expectEvent, "onEnabling", "provider onEnabling");
+        is(addon.manifest.origin, manifest.origin, "provider about to be enabled");
+        expectEvent = "onEnabled";
+      },
+      onDisabled: function(addon) {
+        is(expectEvent, "onDisabled", "provider onDisabled");
+        is(addon.manifest.origin, manifest.origin, "provider disabled");
+        ok(addon.userDisabled, "provider userDisabled");
+      },
+      onDisabling: function(addon) {
+        is(expectEvent, "onDisabling", "provider onDisabling");
+        is(addon.manifest.origin, manifest.origin, "provider about to be disabled");
+        expectEvent = "onDisabled";
+      }
+    };
+    AddonManager.addAddonListener(listener);
+
+    expectEvent = "onEnabling";
+    SocialService.addBuiltinProvider(manifest.origin, function(provider) {
+      expectEvent = "onDisabling";
+      SocialService.removeProvider(provider.origin, function() {
+        AddonManager.removeAddonListener(listener);
+        next();
+      });
+    });
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/browser_blocklist.js
@@ -0,0 +1,124 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// a place for miscellaneous social tests
+
+let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
+
+const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
+let blocklistURL = "http://test:80/browser/browser/base/content/test/social/blocklist.xml";
+let blocklistEmpty = "http://test:80/browser/browser/base/content/test/social/blocklistEmpty.xml";
+
+let manifest = { // normal provider
+  name: "provider 1",
+  origin: "https://example.com",
+  sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+  workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
+  iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
+};
+let manifest_bad = { // normal provider
+  name: "provider 1",
+  origin: "https://bad.com",
+  sidebarURL: "https://bad.com/browser/browser/base/content/test/social/social_sidebar.html",
+  workerURL: "https://bad.com/browser/browser/base/content/test/social/social_worker.js",
+  iconURL: "https://bad.com/browser/browser/base/content/test/moz.png"
+};
+
+function test() {
+  waitForExplicitFinish();
+
+  runSocialTests(tests, undefined, undefined, function () {
+    resetBlocklist(); //restore to original pref
+    finish();
+  });
+}
+
+var tests = {
+  testSimpleBlocklist: function(next) {
+    // this really just tests adding and clearing our blocklist for later tests
+    var blocklist = Components.classes["@mozilla.org/extensions/blocklist;1"]
+                        .getService(Components.interfaces.nsIBlocklistService);
+    setAndUpdateBlocklist(blocklistURL, function() {
+      ok(blocklist.isAddonBlocklisted("bad.com@services.mozilla.org", "0", "0", "0"), "blocking 'blocked'");
+      ok(!blocklist.isAddonBlocklisted("good.cpm@services.mozilla.org", "0", "0", "0"), "not blocking 'good'");
+      setAndUpdateBlocklist(blocklistEmpty, function() {
+        ok(!blocklist.isAddonBlocklisted("bad.com@services.mozilla.org", "0", "0", "0"), "blocklist cleared");
+        next();
+      });
+    });
+  },
+  testAddingNonBlockedProvider: function(next) {
+    function finish(isgood) {
+      ok(isgood, "adding non-blocked provider ok");
+      Services.prefs.clearUserPref("social.manifest.good");
+      setAndUpdateBlocklist(blocklistEmpty, next);
+    }
+    Services.prefs.setCharPref("social.manifest.good", JSON.stringify(manifest));
+    setAndUpdateBlocklist(blocklistURL, function() {
+      try {
+        SocialService.addProvider(manifest, function(provider) {
+          if (provider) {
+            SocialService.removeProvider(provider.origin, function() {
+              ok(true, "added and removed provider");
+              finish(true);
+            });
+          } else {
+            finish(false);
+          }
+        });
+      } catch(e) {
+        dump(e+" - "+e.stack+"\n");
+        finish(false);
+      }
+    });
+  },
+  testAddingBlockedProvider: function(next) {
+    function finish(good) {
+      ok(good, "Unable to add blocklisted provider");
+      Services.prefs.clearUserPref("social.manifest.blocked");
+      setAndUpdateBlocklist(blocklistEmpty, next);
+    }
+    Services.prefs.setCharPref("social.manifest.blocked", JSON.stringify(manifest_bad));
+    setAndUpdateBlocklist(blocklistURL, function() {
+      try {
+        SocialService.addProvider(manifest_bad, function(provider) {
+          if (provider) {
+            SocialService.removeProvider(provider.origin, function() {
+              finish(false);
+            });
+          } else {
+            finish(true);
+          }
+        });
+      } catch(e) {
+        finish(true);
+      }
+    });
+  },
+  testBlockingExistingProvider: function(next) {
+
+    addWindowListener(URI_EXTENSION_BLOCKLIST_DIALOG,  function(win) {
+      win.close();
+      ok(true, "window closed");
+    });
+
+    function finish(good) {
+      ok(good, "blocklisted provider removed");
+      Services.prefs.clearUserPref("social.manifest.blocked");
+      setAndUpdateBlocklist(blocklistEmpty, next);
+    }
+    Services.prefs.setCharPref("social.manifest.blocked", JSON.stringify(manifest_bad));
+    SocialService.addProvider(manifest_bad, function(provider) {
+      if (provider) {
+        setAndUpdateBlocklist(blocklistURL, function() {
+          SocialService.getProvider(provider.origin, function(p) {
+            finish(p==null);
+          })
+        });
+      } else {
+        finish(false);
+      }
+    });
+  }
+}
--- a/browser/base/content/test/social/browser_social_toolbar.js
+++ b/browser/base/content/test/social/browser_social_toolbar.js
@@ -152,18 +152,16 @@ var tests = {
   },
   testMenuitemsExist: function(next) {
     let toggleSidebarMenuitems = document.getElementsByClassName("social-toggle-sidebar-menuitem");
     is(toggleSidebarMenuitems.length, 2, "Toggle Sidebar menuitems exist");
     let toggleDesktopNotificationsMenuitems = document.getElementsByClassName("social-toggle-notifications-menuitem");
     is(toggleDesktopNotificationsMenuitems.length, 2, "Toggle notifications menuitems exist");
     let toggleSocialMenuitems = document.getElementsByClassName("social-toggle-menuitem");
     is(toggleSocialMenuitems.length, 2, "Toggle Social menuitems exist");
-    let removeSocialMenuitems = document.getElementsByClassName("social-remove-menuitem");
-    is(removeSocialMenuitems.length, 2, "Remove Social menuitems exist");
     next();
   },
   testToggleNotifications: function(next) {
     let enabled = Services.prefs.getBoolPref("social.toast-notifications.enabled");
     let cmd = document.getElementById("Social:ToggleNotifications");
     is(cmd.getAttribute("checked"), enabled ? "true" : "false");
     enabled = !enabled;
     Services.prefs.setBoolPref("social.toast-notifications.enabled", enabled);
--- a/browser/base/content/test/social/head.js
+++ b/browser/base/content/test/social/head.js
@@ -182,18 +182,62 @@ function checkSocialUI(win) {
   isbool(win.SocialChatBar.isAvailable, enabled && Social.haveLoggedInUser(), "chatbar available?");
   isbool(!win.SocialChatBar.chatbar.hidden, enabled && Social.haveLoggedInUser(), "chatbar visible?");
   isbool(!win.SocialShareButton.shareButton.hidden, enabled && provider.recommendInfo, "share button visible?");
   isbool(!doc.getElementById("social-toolbar-item").hidden, enabled, "toolbar items visible?");
   if (enabled)
     is(win.SocialToolbar.button.style.listStyleImage, 'url("' + provider.iconURL + '")', "toolbar button has provider icon");
 
   // and for good measure, check all the social commands.
-  // Social:Remove - never disabled directly but parent nodes are
   isbool(!doc.getElementById("Social:Toggle").hidden, enabled, "Social:Toggle visible?");
   isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Social:ToggleNotifications visible?");
   isbool(!doc.getElementById("Social:FocusChat").hidden, enabled && Social.haveLoggedInUser(), "Social:FocusChat visible?");
   isbool(doc.getElementById("Social:FocusChat").getAttribute("disabled"), enabled ? "false" : "true", "Social:FocusChat disabled?");
   is(doc.getElementById("Social:SharePage").getAttribute("disabled"), enabled && provider.recommendInfo ? "false" : "true", "Social:SharePage visible?");
 
   // broadcasters.
   isbool(!doc.getElementById("socialActiveBroadcaster").hidden, enabled, "socialActiveBroadcaster hidden?");
 }
+
+// blocklist testing
+function updateBlocklist(aCallback) {
+  var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"]
+                          .getService(Ci.nsITimerCallback);
+  var observer = function() {
+    Services.obs.removeObserver(observer, "blocklist-updated");
+    if (aCallback)
+      executeSoon(aCallback);
+  };
+  Services.obs.addObserver(observer, "blocklist-updated", false);
+  blocklistNotifier.notify(null);
+}
+
+var _originalTestBlocklistURL = null;
+function setAndUpdateBlocklist(aURL, aCallback) {
+  if (!_originalTestBlocklistURL)
+    _originalTestBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url");
+  Services.prefs.setCharPref("extensions.blocklist.url", aURL);
+  updateBlocklist(aCallback);
+}
+
+function resetBlocklist() {
+  Services.prefs.setCharPref("extensions.blocklist.url", _originalTestBlocklistURL);
+}
+
+function addWindowListener(aURL, aCallback) {
+  Services.wm.addListener({
+    onOpenWindow: function(aXULWindow) {
+      info("window opened, waiting for focus");
+      Services.wm.removeListener(this);
+
+      var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                                .getInterface(Ci.nsIDOMWindow);
+      waitForFocus(function() {
+        is(domwindow.document.location.href, aURL, "window opened and focused");
+        executeSoon(function() {
+          aCallback(domwindow);
+        });
+      }, domwindow);
+    },
+    onCloseWindow: function(aXULWindow) { },
+    onWindowTitleChange: function(aXULWindow, aNewTitle) { }
+  });
+}
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -607,16 +607,18 @@ just addresses the organization to follo
 <!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…">
+
 <!ENTITY social.toggleNotifications.label "Show desktop notifications">
 <!ENTITY social.toggleNotifications.accesskey "n">
 
 <!ENTITY social.activated.undobutton.label "Undo">
 <!ENTITY social.activated.undobutton.accesskey "U">
 
 <!ENTITY social.chatBar.commandkey "c">
 <!ENTITY social.chatBar.label "Focus chats">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -369,25 +369,16 @@ webapps.install.success = Application In
 # LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
 fullscreen.entered=%S is now fullscreen.
 # LOCALIZATION NOTE (fullscreen.rememberDecision): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
 fullscreen.rememberDecision=Remember decision for %S
 
 # LOCALIZATION NOTE (social.activated.description): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
 social.activated.description=You've turned on %1$S for %2$S.
 
-# LOCALIZATION NOTE (social.removeProvider.label): %S is the name of the social provider
-social.removeProvider.label=Remove %S
-social.removeProvider.accesskey=R
-# LOCALIZATION NOTE (social.remove.confirmationLabel): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
-social.remove.confirmationLabel=Are you sure you want to remove %1$S for %2$S?
-# LOCALIZATION NOTE (social.remove.confirmationOK): %S is the name of the social provider
-social.remove.confirmationOK=Remove %S
-
-
 # LOCALIZATION NOTE (social.turnOff.label): %S is the name of the social provider
 social.turnOff.label=Turn off %S
 social.turnOff.accesskey=T
 # LOCALIZATION NOTE (social.turnOn.label): %S is the name of the social provider
 social.turnOn.label=Turn on %S
 social.turnOn.accesskey=T
 
 # LOCALIZATION NOTE (social.error.message): %1$S is brandShortName (e.g. Firefox), %2$S is the name of the social provider
--- a/toolkit/components/social/SocialService.jsm
+++ b/toolkit/components/social/SocialService.jsm
@@ -3,16 +3,22 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 this.EXPORTED_SYMBOLS = ["SocialService"];
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/AddonManager.jsm");
+
+const URI_EXTENSION_STRINGS  = "chrome://mozapps/locale/extensions/extensions.properties";
+const ADDON_TYPE_SERVICE     = "service";
+const ID_SUFFIX              = "@services.mozilla.org";
+const STRING_TYPE_NAME       = "type.%ID%.name";
 
 XPCOMUtils.defineLazyModuleGetter(this, "getFrameWorkerHandle", "resource://gre/modules/FrameWorker.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WorkerAPI", "resource://gre/modules/WorkerAPI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MozSocialAPI", "resource://gre/modules/MozSocialAPI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm");
 
 /**
  * The SocialService is the public API to social providers - it tracks which
@@ -35,16 +41,24 @@ let SocialServiceInternal = {
         var manifest = JSON.parse(MANIFEST_PREFS.getCharPref(pref));
         if (manifest && typeof(manifest) == "object" && manifest.origin)
           yield manifest;
       } catch (err) {
         Cu.reportError("SocialService: failed to load manifest: " + pref +
                        ", exception: " + err);
       }
     }
+  },
+  getManifestByOrigin: function(origin) {
+    for (let manifest of SocialServiceInternal.manifests) {
+      if (origin == manifest.origin) {
+        return manifest;
+      }
+    }
+    return null;
   }
 };
 
 let ActiveProviders = {
   get _providers() {
     delete this._providers;
     this._providers = {};
     try {
@@ -170,21 +184,25 @@ this.SocialService = {
   // provider exists, or the activated provider on success.
   addBuiltinProvider: function addBuiltinProvider(origin, onDone) {
     if (SocialServiceInternal.providers[origin]) {
       schedule(function() {
         onDone(SocialServiceInternal.providers[origin]);
       });
       return;
     }
-    for (let manifest of SocialServiceInternal.manifests) {
-      if (manifest.origin == origin) {
-        this.addProvider(manifest, onDone);
-        return;
-      }
+    let manifest = SocialServiceInternal.getManifestByOrigin(origin);
+    if (manifest) {
+      let addon = new AddonWrapper(manifest);
+      AddonManagerPrivate.callAddonListeners("onEnabling", addon, false);
+      addon.pendingOperations |= AddonManager.PENDING_ENABLE;
+      this.addProvider(manifest, onDone);
+      addon.pendingOperations -= AddonManager.PENDING_ENABLE;
+      AddonManagerPrivate.callAddonListeners("onEnabled", addon);
+      return;
     }
     schedule(function() {
       onDone(null);
     });
   },
 
   // Adds a provider given a manifest, and returns the added provider.
   addProvider: function addProvider(manifest, onDone) {
@@ -202,25 +220,39 @@ this.SocialService = {
         onDone(provider);
     }.bind(this));
   },
 
   // Removes a provider with the given origin, and notifies when the removal is
   // complete.
   removeProvider: function removeProvider(origin, onDone) {
     if (!(origin in SocialServiceInternal.providers))
-      throw new Error("SocialService.removeProvider: no provider with this origin exists!");
+      throw new Error("SocialService.removeProvider: no provider with origin " + origin + " exists!");
 
     let provider = SocialServiceInternal.providers[origin];
+    let manifest = SocialServiceInternal.getManifestByOrigin(origin);
+    let addon = manifest && new AddonWrapper(manifest);
+    if (addon) {
+      AddonManagerPrivate.callAddonListeners("onDisabling", addon, false);
+      addon.pendingOperations |= AddonManager.PENDING_DISABLE;
+    }
     provider.enabled = false;
 
     ActiveProviders.delete(provider.origin);
 
     delete SocialServiceInternal.providers[origin];
 
+    if (addon) {
+      // we have to do this now so the addon manager ui will update an uninstall
+      // correctly.
+      addon.pendingOperations -= AddonManager.PENDING_DISABLE;
+      AddonManagerPrivate.callAddonListeners("onDisabled", addon);
+      AddonManagerPrivate.notifyAddonChanged(addon.id, ADDON_TYPE_SERVICE, false);
+    }
+
     schedule(function () {
       this._notifyProviderListeners("provider-removed",
                                     SocialServiceInternal.providerArray);
       if (onDone)
         onDone();
     }.bind(this));
   },
 
@@ -274,16 +306,23 @@ this.SocialService = {
  * @param {jsobj} object representing the manifest file describing this provider
  */
 function SocialProvider(input) {
   if (!input.name)
     throw new Error("SocialProvider must be passed a name");
   if (!input.origin)
     throw new Error("SocialProvider must be passed an origin");
 
+  let id = getAddonIDFromOrigin(input.origin);
+  let bs = Cc["@mozilla.org/extensions/blocklist;1"].
+           getService(Ci.nsIBlocklistService);
+  if (bs.getAddonBlocklistState(id, input.version || "0") == Ci.nsIBlocklistService.STATE_BLOCKED)
+    throw new Error("SocialProvider: provider with origin [" +
+                    input.origin + "] is blocklisted");
+
   this.name = input.name;
   this.iconURL = input.iconURL;
   this.icon32URL = input.icon32URL;
   this.icon64URL = input.icon64URL;
   this.workerURL = input.workerURL;
   this.sidebarURL = input.sidebarURL;
   this.origin = input.origin;
   let originUri = Services.io.newURI(input.origin, null, null);
@@ -526,8 +565,238 @@ SocialProvider.prototype = {
       let fullURL = this.principal.URI.resolve(url);
       return Services.io.newURI(fullURL, null, null);
     } catch (ex) {
       Cu.reportError("mozSocial: failed to resolve window URL: " + url + "; " + ex);
       return null;
     }
   }
 }
+
+function getAddonIDFromOrigin(origin) {
+  let originUri = Services.io.newURI(origin, null, null);
+  return originUri.host + ID_SUFFIX;
+}
+
+var SocialAddonProvider = {
+  startup: function() {},
+
+  shutdown: function() {},
+
+  updateAddonAppDisabledStates: function() {
+    let bs = Cc["@mozilla.org/extensions/blocklist;1"].
+             getService(Ci.nsIBlocklistService);
+    // we wont bother with "enabling" services that are released from blocklist
+    for (let manifest of SocialServiceInternal.manifests) {
+      try {
+        if (ActiveProviders.has(manifest.origin)) {
+          let id = getAddonIDFromOrigin(manifest.origin);
+          if (bs.getAddonBlocklistState(id, manifest.version || "0") != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
+            SocialService.removeProvider(manifest.origin);
+          }
+        }
+      } catch(e) {
+        Cu.reportError(e);
+      }
+    }
+  },
+
+  getAddonByID: function(aId, aCallback) {
+    for (let manifest of SocialServiceInternal.manifests) {
+      if (aId == getAddonIDFromOrigin(manifest.origin)) {
+        aCallback(new AddonWrapper(manifest));
+        return;
+      }
+    }
+    aCallback(null);
+  },
+
+  getAddonsByTypes: function(aTypes, aCallback) {
+    if (aTypes && aTypes.indexOf(ADDON_TYPE_SERVICE) == -1) {
+      aCallback([]);
+      return;
+    }
+    aCallback([new AddonWrapper(a) for each (a in SocialServiceInternal.manifests)]);
+  }
+}
+
+
+function AddonWrapper(aManifest) {
+  this.manifest = aManifest;
+  this.id = getAddonIDFromOrigin(this.manifest.origin);
+  this._pending = AddonManager.PENDING_NONE;
+}
+AddonWrapper.prototype = {
+  get type() {
+    return ADDON_TYPE_SERVICE;
+  },
+
+  get appDisabled() {
+    return this.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED;
+  },
+
+  set softDisabled(val) {
+    this.userDisabled = val;
+  },
+
+  get softDisabled() {
+    return this.userDisabled;
+  },
+
+  get isCompatible() {
+    return true;
+  },
+
+  get isPlatformCompatible() {
+    return true;
+  },
+
+  get scope() {
+    return AddonManager.SCOPE_PROFILE;
+  },
+
+  get foreignInstall() {
+    return false;
+  },
+
+  isCompatibleWith: function(appVersion, platformVersion) {
+    return true;
+  },
+
+  get providesUpdatesSecurely() {
+    return true;
+  },
+
+  get blocklistState() {
+    let bs = Cc["@mozilla.org/extensions/blocklist;1"].
+             getService(Ci.nsIBlocklistService);
+    return bs.getAddonBlocklistState(this.id, this.version || "0");
+  },
+
+  get blocklistURL() {
+    let bs = Cc["@mozilla.org/extensions/blocklist;1"].
+             getService(Ci.nsIBlocklistService);
+    return bs.getAddonBlocklistURL(this.id, this.version || "0");
+  },
+
+  get screenshots() {
+    return [];
+  },
+
+  get pendingOperations() {
+    return this._pending || AddonManager.PENDING_NONE;
+  },
+  set pendingOperations(val) {
+    this._pending = val;
+  },
+
+  get operationsRequiringRestart() {
+    return AddonManager.OP_NEEDS_RESTART_NONE;
+  },
+
+  get size() {
+    return null;
+  },
+
+  get permissions() {
+    let permissions = 0;
+    // XXX we will not have install until BUG 786133 lands
+    if (!this.appDisabled) {
+      if (this.userDisabled) {
+        permissions |= AddonManager.PERM_CAN_ENABLE;
+      } else {
+        permissions |= AddonManager.PERM_CAN_DISABLE;
+      }
+    }
+    return permissions;
+  },
+
+  findUpdates: function(listener, reason, appVersion, platformVersion) {
+    if ("onNoCompatibilityUpdateAvailable" in listener)
+      listener.onNoCompatibilityUpdateAvailable(this);
+    if ("onNoUpdateAvailable" in listener)
+      listener.onNoUpdateAvailable(this);
+    if ("onUpdateFinished" in listener)
+      listener.onUpdateFinished(this);
+  },
+
+  get isActive() {
+    return ActiveProviders.has(this.manifest.origin);
+  },
+
+  get name() {
+    return this.manifest.name;
+  },
+  get version() {
+    return this.manifest.version ? this.manifest.version : "";
+  },
+
+  get iconURL() {
+    return this.manifest.icon32URL ? this.manifest.icon32URL : this.manifest.iconURL;
+  },
+  get icon64URL() {
+    return this.manifest.icon64URL;
+  },
+  get icons() {
+    let icons = {
+      16: this.manifest.iconURL
+    };
+    if (this.manifest.icon32URL)
+      icons[32] = this.manifest.icon32URL;
+    if (this.manifest.icon64URL)
+      icons[64] = this.manifest.icon64URL;
+    return icons;
+  },
+
+  get description() {
+    return this.manifest.description;
+  },
+  get homepageURL() {
+    return this.manifest.homepageURL;
+  },
+  get defaultLocale() {
+    return this.manifest.defaultLocale;
+  },
+  get selectedLocale() {
+    return this.manifest.selectedLocale;
+  },
+
+  get installDate() {
+    return this.manifest.installDate ? new Date(this.manifest.installDate) : null;
+  },
+  get updateDate() {
+    return this.manifest.updateDate ? new Date(this.manifest.updateDate) : null;
+  },
+
+  get creator() {
+    return new AddonManagerPrivate.AddonAuthor(this.manifest.author);
+  },
+
+  get userDisabled() {
+    return this.appDisabled || !ActiveProviders.has(this.manifest.origin);
+  },
+
+  set userDisabled(val) {
+    if (val == this.userDisabled)
+      return val;
+    if (val) {
+      SocialService.removeProvider(this.manifest.origin);
+    } else if (!this.appDisabled) {
+      SocialService.addBuiltinProvider(this.manifest.origin);
+    }
+    return val;
+  },
+
+  uninstall: function() {
+    // XXX we will not uninstall until BUG 786133 lands
+  },
+
+  cancelUninstall: function() {
+    // XXX we will not uninstall until BUG 786133 lands
+  }
+};
+
+
+AddonManagerPrivate.registerProvider(SocialAddonProvider, [
+  new AddonManagerPrivate.AddonType(ADDON_TYPE_SERVICE, URI_EXTENSION_STRINGS,
+                                    STRING_TYPE_NAME,
+                                    AddonManager.VIEW_TYPE_LIST, 10000)
+]);
new file mode 100644
--- /dev/null
+++ b/toolkit/components/social/test/xpcshell/blocklist.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
+  <emItems>
+    <emItem  blockID="s1" id="bad.com@services.mozilla.org"></emItem>
+  </emItems>
+</blocklist>
--- a/toolkit/components/social/test/xpcshell/head.js
+++ b/toolkit/components/social/test/xpcshell/head.js
@@ -1,16 +1,66 @@
 /* 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/. */
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
+const gProfD = do_get_profile();
+
+const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1";
+const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}");
+
+function createAppInfo(id, name, version, platformVersion) {
+  gAppInfo = {
+    // nsIXULAppInfo
+    vendor: "Mozilla",
+    name: name,
+    ID: id,
+    version: version,
+    appBuildID: "2007010101",
+    platformVersion: platformVersion ? platformVersion : "1.0",
+    platformBuildID: "2007010101",
+
+    // nsIXULRuntime
+    inSafeMode: false,
+    logConsoleErrors: true,
+    OS: "XPCShell",
+    XPCOMABI: "noarch-spidermonkey",
+    invalidateCachesOnRestart: function invalidateCachesOnRestart() {
+      // Do nothing
+    },
+
+    // nsICrashReporter
+    annotations: {},
+
+    annotateCrashReport: function(key, data) {
+      this.annotations[key] = data;
+    },
+
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIXULAppInfo,
+                                           Ci.nsIXULRuntime,
+                                           Ci.nsICrashReporter,
+                                           Ci.nsISupports])
+  };
+
+  var XULAppInfoFactory = {
+    createInstance: function (outer, iid) {
+      if (outer != null)
+        throw Components.results.NS_ERROR_NO_AGGREGATION;
+      return gAppInfo.QueryInterface(iid);
+    }
+  };
+  var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
+  registrar.registerFactory(XULAPPINFO_CID, "XULAppInfo",
+                            XULAPPINFO_CONTRACTID, XULAppInfoFactory);
+}
 
 function AsyncRunner() {
   do_test_pending();
   do_register_cleanup((function () this.destroy()).bind(this));
 
   this._callbacks = {
     done: do_test_finished,
     error: function (err) {
--- a/toolkit/components/social/test/xpcshell/test_SocialService.js
+++ b/toolkit/components/social/test/xpcshell/test_SocialService.js
@@ -1,15 +1,24 @@
 /* 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/. */
 
 Cu.import("resource://gre/modules/Services.jsm");
 
 function run_test() {
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
+  // prepare a blocklist file for the blocklist service
+  var blocklistFile = gProfD.clone();
+  blocklistFile.append("blocklist.xml");
+  if (blocklistFile.exists())
+    blocklistFile.remove(false);
+  var source = do_get_file("blocklist.xml");
+  source.copyTo(gProfD, "blocklist.xml");
+
   // NOTE: none of the manifests here can have a workerURL set, or we attempt
   // to create a FrameWorker and that fails under xpcshell...
   let manifests = [
     { // normal provider
       name: "provider 1",
       origin: "https://example1.com",
     },
     { // provider without workerURL
--- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
@@ -121,8 +121,9 @@ cmd.purchaseAddon.accesskey=u
 #LOCALIZATION NOTE (eulaHeader) %S is name of the add-on asking the user to agree to the EULA
 eulaHeader=%S requires that you accept the following End User License Agreement before installation can proceed:
 
 type.extension.name=Extensions
 type.theme.name=Appearance
 type.locale.name=Languages
 type.plugin.name=Plugins
 type.dictionary.name=Dictionaries
+type.service.name=Services
--- a/toolkit/mozapps/extensions/content/selectAddons.js
+++ b/toolkit/mozapps/extensions/content/selectAddons.js
@@ -69,17 +69,17 @@ var gChecking = {
     let self = this;
     AddonManager.getAllAddons(function gChecking_getAllAddons(aAddons) {
       if (aAddons.length == 0) {
         window.close();
         return;
       }
 
       aAddons = aAddons.filter(function gChecking_filterAddons(aAddon) {
-        if (aAddon.type == "plugin")
+        if (aAddon.type == "plugin" || aAddon.type == "service")
           return false;
 
         if (aAddon.type == "theme") {
           // Don't show application shipped themes
           if (aAddon.scope == AddonManager.SCOPE_APPLICATION)
             return false;
           // Don't show already disabled themes
           if (aAddon.userDisabled)
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -886,17 +886,17 @@ Blocklist.prototype = {
       }
     }
   },
 
   _blocklistUpdated: function Blocklist_blocklistUpdated(oldAddonEntries, oldPluginEntries) {
     var addonList = [];
 
     var self = this;
-    const types = ["extension", "theme", "locale", "dictionary"]
+    const types = ["extension", "theme", "locale", "dictionary", "service"]
     AddonManager.getAddonsByTypes(types, function blocklistUpdated_getAddonsByTypes(addons) {
 
       for (let addon of addons) {
         let oldState = Ci.nsIBlocklistService.STATE_NOTBLOCKED;
         if (oldAddonEntries)
           oldState = self._getAddonBlocklistState(addon.id, addon.version,
                                                   oldAddonEntries);
         let state = self.getAddonBlocklistState(addon.id, addon.version);
--- a/toolkit/themes/linux/mozapps/extensions/extensions.css
+++ b/toolkit/themes/linux/mozapps/extensions/extensions.css
@@ -209,16 +209,19 @@
   list-style-image: url("chrome://mozapps/skin/extensions/category-languages.png");
 }
 #category-searchengine > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-searchengines.png");
 }
 #category-extension > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-extensions.png");
 }
+#category-service > .category-icon {
+  list-style-image: url("chrome://mozapps/skin/extensions/category-extensions.png");
+}
 #category-theme > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-themes.png");
 }
 #category-plugin > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-plugins.png");
 }
 #category-dictionary > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-dictionaries.png");
@@ -902,9 +905,8 @@ setting[type="radio"] > radiogroup {
 
 .button-link:active {
   color: -moz-activehyperlinktext;
 }
 
 .header-button .toolbarbutton-text {
   display: none;
 }
-
--- a/toolkit/themes/osx/mozapps/extensions/extensions.css
+++ b/toolkit/themes/osx/mozapps/extensions/extensions.css
@@ -242,16 +242,19 @@
   list-style-image: url("chrome://mozapps/skin/extensions/category-languages.png");
 }
 #category-searchengine > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-searchengines.png");
 }
 #category-extension > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-extensions.png");
 }
+#category-service > .category-icon {
+  list-style-image: url("chrome://mozapps/skin/extensions/category-extensions.png");
+}
 #category-theme > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-themes.png");
 }
 #category-plugin > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-plugins.png");
 }
 #category-dictionary > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-dictionaries.png");
@@ -1142,9 +1145,8 @@ button.button-link:not([disabled="true"]
 }
 
 .header-button:not([disabled="true"]):active:hover,
 .header-button[open="true"] {
   border-color: rgba(45,54,71,0.7);
   box-shadow: inset 0 0 4px rgb(45,54,71), 0 1px rgba(255,255,255,0.25);
   background-image: -moz-linear-gradient(rgba(45,54,71,0.6), rgba(45,54,71,0));
 }
-
--- a/toolkit/themes/windows/mozapps/extensions/extensions.css
+++ b/toolkit/themes/windows/mozapps/extensions/extensions.css
@@ -254,16 +254,19 @@
   list-style-image: url("chrome://mozapps/skin/extensions/category-languages.png");
 }
 #category-searchengine > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-searchengines.png");
 }
 #category-extension > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-extensions.png");
 }
+#category-service > .category-icon {
+  list-style-image: url("chrome://mozapps/skin/extensions/category-extensions.png");
+}
 #category-theme > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-themes.png");
 }
 #category-plugin > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-plugins.png");
 }
 #category-dictionary > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-dictionaries.png");