bug 914926 fix workers on startup when social disabled, r=markh
authorShane Caraveo <scaraveo@mozilla.com>
Sat, 14 Sep 2013 10:16:47 -0700
changeset 160098 bc8d1b9545c5516d4a11ef6953f25a5a4af7201f
parent 160097 1d12266ddc4ca4ee0da3444b1689d281cfc1f402
child 160099 2260a05fdb3588b6fcf082b99a288cc628175811
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarkh
bugs914926
milestone26.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 914926 fix workers on startup when social disabled, r=markh
browser/base/content/test/social/browser_social_multiworker.js
browser/modules/Social.jsm
browser/modules/test/moz.build
browser/modules/test/unit/moz.build
browser/modules/test/unit/social/Makefile.in
browser/modules/test/unit/social/blocklist.xml
browser/modules/test/unit/social/head.js
browser/modules/test/unit/social/moz.build
browser/modules/test/unit/social/test_social.js
browser/modules/test/unit/social/test_socialDisabledStartup.js
browser/modules/test/unit/social/xpcshell.ini
--- a/browser/base/content/test/social/browser_social_multiworker.js
+++ b/browser/base/content/test/social/browser_social_multiworker.js
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   waitForExplicitFinish();
 
   Services.prefs.setBoolPref("social.allowMultipleWorkers", true);
   runSocialTestWithProvider(gProviders, function (finishcb) {
+    Social.enabled = true;
     runSocialTests(tests, undefined, undefined, function() {
       Services.prefs.clearUserPref("social.allowMultipleWorkers");
       finishcb();
     });
   });
 }
 
 let gProviders = [
--- a/browser/modules/Social.jsm
+++ b/browser/modules/Social.jsm
@@ -29,19 +29,18 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "nsIScriptableUnescapeHTML");
 
 // Add a pref observer for the enabled state
 function prefObserver(subject, topic, data) {
   let enable = Services.prefs.getBoolPref("social.enabled");
   if (enable && !Social.provider) {
     // this will result in setting Social.provider
     SocialService.getOrderedProviderList(function(providers) {
+      Social.enabled = true;
       Social._updateProviderCache(providers);
-      Social.enabled = true;
-      Services.obs.notifyObservers(null, "social:providers-changed", null);
     });
   } else if (!enable && Social.provider) {
     Social.provider = null;
   }
 }
 
 Services.prefs.addObserver("social.enabled", prefObserver, false);
 Services.obs.addObserver(function xpcomShutdown() {
@@ -163,58 +162,64 @@ this.Social = {
     }
     this.initialized = true;
     // if SocialService.hasEnabledProviders, retreive the providers so the
     // front-end can generate UI
     if (SocialService.hasEnabledProviders) {
       // Retrieve the current set of providers, and set the current provider.
       SocialService.getOrderedProviderList(function (providers) {
         Social._updateProviderCache(providers);
-        Social._updateWorkerState(true);
+        Social._updateWorkerState(SocialService.enabled);
       });
     }
 
     // Register an observer for changes to the provider list
     SocialService.registerProviderListener(function providerListener(topic, origin, providers) {
       // An engine change caused by adding/removing a provider should notify.
       // any providers we receive are enabled in the AddonsManager
       if (topic == "provider-installed" || topic == "provider-uninstalled") {
         // installed/uninstalled do not send the providers param
         Services.obs.notifyObservers(null, "social:" + topic, origin);
         return;
       }
-      if (topic == "provider-enabled" || topic == "provider-disabled") {
+      if (topic == "provider-enabled") {
         Social._updateProviderCache(providers);
-        Social._updateWorkerState(true);
-        Services.obs.notifyObservers(null, "social:providers-changed", null);
+        Social._updateWorkerState(Social.enabled);
+        Services.obs.notifyObservers(null, "social:" + topic, origin);
+        return;
+      }
+      if (topic == "provider-disabled") {
+        // a provider was removed from the list of providers, that does not
+        // affect worker state for other providers
+        Social._updateProviderCache(providers);
         Services.obs.notifyObservers(null, "social:" + topic, origin);
         return;
       }
       if (topic == "provider-update") {
         // a provider has self-updated its manifest, we need to update our cache
         // and reload the provider.
         Social._updateProviderCache(providers);
         let provider = Social._getProviderFromOrigin(origin);
         provider.reload();
-        Services.obs.notifyObservers(null, "social:providers-changed", null);
       }
     });
   },
 
   _updateWorkerState: function(enable) {
     // ensure that our providers are all disabled, and enabled if we allow
     // multiple workers
     if (enable && !Social.allowMultipleWorkers)
       return;
     [p.enabled = enable for (p of Social.providers) if (p.enabled != enable)];
   },
 
   // Called to update our cache of providers and set the current provider
   _updateProviderCache: function (providers) {
     this.providers = providers;
+    Services.obs.notifyObservers(null, "social:providers-changed", null);
 
     // If social is currently disabled there's nothing else to do other than
     // to notify about the lack of a provider.
     if (!SocialService.enabled) {
       Services.obs.notifyObservers(null, "social:provider-set", null);
       return;
     }
     // Otherwise set the provider.
--- a/browser/modules/test/moz.build
+++ b/browser/modules/test/moz.build
@@ -1,7 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-DIRS += ['chrome']
+DIRS += ['chrome', 'unit']
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/unit/moz.build
@@ -0,0 +1,9 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DIRS += ['social']
+
+XPCSHELL_TESTS_MANIFESTS += ['social/xpcshell.ini']
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/unit/social/Makefile.in
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+XPCSHELL_RESOURCES = \
+  xpcshell.ini \
+  head.js \
+  blocklist.xml \
+  test_social.js \
+  test_socialDisabledStartup.js \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/unit/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/modules/test/unit/social/head.js
@@ -0,0 +1,146 @@
+/* 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");
+
+var Social, SocialService;
+
+let manifests = [
+  {
+    name: "provider 1",
+    origin: "https://example1.com",
+    sidebarURL: "https://example1.com/sidebar/",
+  },
+  {
+    name: "provider 2",
+    origin: "https://example2.com",
+    sidebarURL: "https://example1.com/sidebar/",
+  }
+];
+
+const MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
+
+// SocialProvider class relies on blocklisting being enabled.  To enable
+// blocklisting, we have to setup an app and initialize the blocklist (see
+// initApp below).
+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 initApp() {
+  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");
+}
+
+function setManifestPref(manifest) {
+  let string = Cc["@mozilla.org/supports-string;1"].
+               createInstance(Ci.nsISupportsString);
+  string.data = JSON.stringify(manifest);
+  Services.prefs.setComplexValue("social.manifest." + manifest.origin, Ci.nsISupportsString, string);
+}
+
+function do_wait_observer(topic, cb) {
+  function observer(subject, topic, data) {
+    Services.obs.removeObserver(observer, topic);
+    cb();
+  }
+  Services.obs.addObserver(observer, topic, false);
+}
+
+function do_initialize_social(enabledOnStartup, cb) {
+  initApp();
+
+  manifests.forEach(function (manifest) {
+    setManifestPref(manifest);
+  });
+  // Set both providers active and flag the first one as "current"
+  let activeVal = Cc["@mozilla.org/supports-string;1"].
+             createInstance(Ci.nsISupportsString);
+  let active = {};
+  for (let m of manifests)
+    active[m.origin] = 1;
+  activeVal.data = JSON.stringify(active);
+  Services.prefs.setComplexValue("social.activeProviders",
+                                 Ci.nsISupportsString, activeVal);
+  Services.prefs.setCharPref("social.provider.current", manifests[0].origin);
+  Services.prefs.setBoolPref("social.enabled", enabledOnStartup);
+
+  do_register_cleanup(function() {
+    manifests.forEach(function (manifest) {
+      Services.prefs.clearUserPref("social.manifest." + manifest.origin);
+    });
+    Services.prefs.clearUserPref("social.enabled");
+    Services.prefs.clearUserPref("social.provider.current");
+    Services.prefs.clearUserPref("social.activeProviders");
+  });
+
+  // expecting 2 providers installed
+  do_wait_observer("social:providers-changed", function() {
+    do_check_eq(Social.providers.length, 2, "2 providers installed");
+    cb();
+  });
+
+  // import and initialize everything
+  SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
+  do_check_eq(SocialService.enabled, enabledOnStartup, "service is doing its thing");
+  do_check_true(SocialService.hasEnabledProviders, "Service has enabled providers");
+  Social = Cu.import("resource:///modules/Social.jsm", {}).Social;
+  do_check_false(Social.initialized, "Social is not initialized");
+  Social.init();
+  do_check_true(Social.initialized, "Social is initialized");
+}
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/unit/social/moz.build
@@ -0,0 +1,6 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/unit/social/test_social.js
@@ -0,0 +1,34 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function run_test() {
+  // we are testing worker startup specifically
+  Services.prefs.setBoolPref("social.allowMultipleWorkers", true);
+  do_register_cleanup(function() {
+    Services.prefs.clearUserPref("social.allowMultipleWorkers");
+  });
+  do_test_pending();
+  add_test(testStartupEnabled);
+  add_test(testDisableAfterStartup);
+  do_initialize_social(true, run_next_test);
+}
+
+function testStartupEnabled() {
+  // wait on startup before continuing
+  do_check_eq(Social.providers.length, 2, "two social providers enabled");
+  do_check_true(Social.providers[0].enabled, "provider is enabled");
+  do_check_true(Social.providers[1].enabled, "provider is enabled");
+  run_next_test();
+}
+
+function testDisableAfterStartup() {
+  do_wait_observer("social:provider-set", function() {
+    do_check_eq(Social.enabled, false, "Social is disabled");
+    do_check_false(Social.providers[0].enabled, "provider is enabled");
+    do_check_false(Social.providers[1].enabled, "provider is enabled");
+    do_test_finished();
+    run_next_test();
+  });
+  Social.enabled = false;
+}
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/unit/social/test_socialDisabledStartup.js
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function run_test() {
+  // we are testing worker startup specifically
+  Services.prefs.setBoolPref("social.allowMultipleWorkers", true);
+  do_register_cleanup(function() {
+    Services.prefs.clearUserPref("social.allowMultipleWorkers");
+  });
+  do_test_pending();
+  add_test(testStartupDisabled);
+  add_test(testEnableAfterStartup);
+  do_initialize_social(false, run_next_test);
+}
+
+function testStartupDisabled() {
+  // wait on startup before continuing
+  do_check_eq(Social.providers.length, 2, "two social providers available");
+  do_check_false(Social.providers[0].enabled, "provider is enabled");
+  do_check_false(Social.providers[1].enabled, "provider is enabled");
+  run_next_test();
+}
+
+function testEnableAfterStartup() {
+  do_wait_observer("social:provider-set", function() {
+    do_check_true(Social.enabled, "Social is enabled");
+    do_check_eq(Social.providers.length, 2, "two social providers available");
+    do_check_true(Social.providers[0].enabled, "provider is enabled");
+    do_check_true(Social.providers[1].enabled, "provider is enabled");
+    do_test_finished();
+    run_next_test();
+  });
+  Social.enabled = true;
+}
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/unit/social/xpcshell.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+head = head.js
+tail =
+firefox-appdir = browser
+
+[test_social.js]
+
+[test_socialDisabledStartup.js]