Bug 985212 - check if the username looks like an email address to determine what sync to use. r=rnewman

This commit is contained in:
Mark Hammond 2014-03-23 14:20:38 +11:00
parent 6b1d7eec4c
commit 6a5ecb9cbc
34 changed files with 79 additions and 45 deletions

View File

@ -173,16 +173,15 @@ function uninstallFakePAC() {
Cm.nsIComponentRegistrar.unregisterFactory(CID, PACSystemSettings); Cm.nsIComponentRegistrar.unregisterFactory(CID, PACSystemSettings);
} }
// We want to ensure the legacy provider is used for most of these tests, // Many tests do service.startOver() and don't expect the provider type to
// including after a service.startOver. The tests that know how to deal with // change (whereas by default, a startOver will do exactly that so FxA is
// subsequently used). The tests that know how to deal with
// the Firefox Accounts identity hack things to ensure that still works. // the Firefox Accounts identity hack things to ensure that still works.
function setDefaultIdentityConfig() { function ensureStartOverKeepsIdentity() {
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
Services.prefs.setBoolPref("services.sync.fxaccounts.enabled", false);
Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", true); Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", true);
do_register_cleanup(function() { do_register_cleanup(function() {
Services.prefs.clearUserPref("services.sync.fxaccounts.enabled");
Services.prefs.clearUserPref("services.sync-testing.startOverKeepIdentity"); Services.prefs.clearUserPref("services.sync-testing.startOverKeepIdentity");
}); });
} }
setDefaultIdentityConfig(); ensureStartOverKeepsIdentity();

View File

@ -98,23 +98,14 @@ WeaveService.prototype = {
* @return bool * @return bool
*/ */
get fxAccountsEnabled() { get fxAccountsEnabled() {
// work out what identity manager to use. This is stored in a preference;
// if the preference exists, we trust it.
let fxAccountsEnabled;
try { try {
fxAccountsEnabled = Services.prefs.getBoolPref("services.sync.fxaccounts.enabled"); // Old sync guarantees '@' will never appear in the username while FxA
// uses the FxA email address - so '@' is the flag we use.
let username = Services.prefs.getCharPref(SYNC_PREFS_BRANCH + "username");
return !username || username.contains('@');
} catch (_) { } catch (_) {
// That pref doesn't exist - so let's assume this is a first-run. return true; // No username == only allow FxA to be configured.
// If sync already appears configured, we assume it's for the legacy
// provider.
let prefs = Services.prefs.getBranch(SYNC_PREFS_BRANCH);
fxAccountsEnabled = !prefs.prefHasUserValue("username");
Services.prefs.setBoolPref("services.sync.fxaccounts.enabled", fxAccountsEnabled);
} }
// Currently we don't support toggling this pref after initialization -
// except when sync is reset - but this 1 exception is enough that we can't
// cache the value.
return fxAccountsEnabled;
}, },
/** /**

View File

@ -7,6 +7,7 @@
this.EXPORTED_SYMBOLS = [ this.EXPORTED_SYMBOLS = [
"btoa", // It comes from a module import. "btoa", // It comes from a module import.
"encryptPayload", "encryptPayload",
"ensureLegacyIdentityManager",
"setBasicCredentials", "setBasicCredentials",
"makeIdentityConfig", "makeIdentityConfig",
"configureFxAccountIdentity", "configureFxAccountIdentity",
@ -49,6 +50,17 @@ this.waitForZeroTimer = function waitForZeroTimer(callback) {
CommonUtils.namedTimer(wait, 150, {}, "timer"); CommonUtils.namedTimer(wait, 150, {}, "timer");
} }
/**
* Ensure Sync is configured with the "legacy" identity provider.
*/
this.ensureLegacyIdentityManager = function() {
let ns = {};
Cu.import("resource://services-sync/service.js", ns);
Status.__authManager = ns.Service.identity = new IdentityManager();
ns.Service._clusterManager = ns.Service.identity.createClusterManager(ns.Service);
}
this.setBasicCredentials = this.setBasicCredentials =
function setBasicCredentials(username, password, syncKey) { function setBasicCredentials(username, password, syncKey) {
let ns = {}; let ns = {};
@ -170,7 +182,7 @@ this.SyncTestingInfrastructure = function (server, username, password, syncKey)
let ns = {}; let ns = {};
Cu.import("resource://services-sync/service.js", ns); Cu.import("resource://services-sync/service.js", ns);
let auth = ns.Service.identity; ensureLegacyIdentityManager();
let config = makeIdentityConfig(); let config = makeIdentityConfig();
// XXX - hacks for the sync identity provider. // XXX - hacks for the sync identity provider.
if (username) if (username)
@ -233,7 +245,7 @@ this.add_identity_test = function(test, testFunction) {
test.add_task(function() { test.add_task(function() {
note("sync"); note("sync");
let oldIdentity = Status._authManager; let oldIdentity = Status._authManager;
Status.__authManager = ns.Service.identity = new IdentityManager(); ensureLegacyIdentityManager();
yield testFunction(); yield testFunction();
Status.__authManager = ns.Service.identity = oldIdentity; Status.__authManager = ns.Service.identity = oldIdentity;
}); });

View File

@ -910,7 +910,6 @@ Sync11Service.prototype = {
this.identity.finalize().then( this.identity.finalize().then(
() => { () => {
this.identity.username = ""; this.identity.username = "";
Services.prefs.clearUserPref("services.sync.fxaccounts.enabled");
this.status.__authManager = null; this.status.__authManager = null;
this.identity = Status._authManager; this.identity = Status._authManager;
this._clusterManager = this.identity.createClusterManager(this); this._clusterManager = this.identity.createClusterManager(this);

View File

@ -7,6 +7,7 @@ Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/record.js"); Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/utils.js");
function prepareBookmarkItem(collection, id) { function prepareBookmarkItem(collection, id) {
let b = new Bookmark(collection, id); let b = new Bookmark(collection, id);
@ -15,6 +16,7 @@ function prepareBookmarkItem(collection, id) {
} }
function run_test() { function run_test() {
ensureLegacyIdentityManager();
Service.identity.username = "john@example.com"; Service.identity.username = "john@example.com";
Service.identity.syncKey = "abcdeabcdeabcdeabcdeabcdea"; Service.identity.syncKey = "abcdeabcdeabcdeabcdeabcdea";
generateNewKeys(Service.collectionKeys); generateNewKeys(Service.collectionKeys);

View File

@ -81,6 +81,7 @@ add_test(function test_bad_hmac() {
} }
try { try {
ensureLegacyIdentityManager();
let passphrase = "abcdeabcdeabcdeabcdeabcdea"; let passphrase = "abcdeabcdeabcdeabcdeabcdea";
Service.serverURL = server.baseURI; Service.serverURL = server.baseURI;
Service.login("foo", "ilovejane", passphrase); Service.login("foo", "ilovejane", passphrase);

View File

@ -5,10 +5,12 @@ Cu.import("resource://services-sync/keys.js");
Cu.import("resource://services-sync/record.js"); Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/utils.js");
function run_test() { function run_test() {
_("Set up test fixtures."); _("Set up test fixtures.");
ensureLegacyIdentityManager();
Service.identity.username = "john@example.com"; Service.identity.username = "john@example.com";
Service.clusterURL = "http://fakebase/"; Service.clusterURL = "http://fakebase/";
let baseUri = "http://fakebase/1.1/foo/storage/"; let baseUri = "http://fakebase/1.1/foo/storage/";

View File

@ -204,6 +204,8 @@ function run_test() {
let logger = Log.repository.rootLogger; let logger = Log.repository.rootLogger;
Log.repository.rootLogger.addAppender(new Log.DumpAppender()); Log.repository.rootLogger.addAppender(new Log.DumpAppender());
ensureLegacyIdentityManager();
run_next_test(); run_next_test();
} }

View File

@ -55,6 +55,8 @@ function run_test() {
Log.repository.getLogger("Sync.SyncScheduler").level = Log.Level.Trace; Log.repository.getLogger("Sync.SyncScheduler").level = Log.Level.Trace;
Log.repository.getLogger("Sync.ErrorHandler").level = Log.Level.Trace; Log.repository.getLogger("Sync.ErrorHandler").level = Log.Level.Trace;
ensureLegacyIdentityManager();
run_next_test(); run_next_test();
} }

View File

@ -15,10 +15,10 @@ add_task(function* test_startover() {
let oldValue = Services.prefs.getBoolPref("services.sync-testing.startOverKeepIdentity", true); let oldValue = Services.prefs.getBoolPref("services.sync-testing.startOverKeepIdentity", true);
Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", false); Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", false);
ensureLegacyIdentityManager();
yield configureIdentity({username: "johndoe"}); yield configureIdentity({username: "johndoe"});
// The pref that forces FxA identities should not be set.
do_check_false(Services.prefs.getBoolPref("services.sync.fxaccounts.enabled")); // The boolean flag on the xpcom service should reflect a legacy provider.
// And the boolean flag on the xpcom service should reflect this.
let xps = Cc["@mozilla.org/weave/service;1"] let xps = Cc["@mozilla.org/weave/service;1"]
.getService(Components.interfaces.nsISupports) .getService(Components.interfaces.nsISupports)
.wrappedJSObject; .wrappedJSObject;
@ -43,9 +43,7 @@ add_task(function* test_startover() {
Service.startOver(); Service.startOver();
yield deferred.promise; // wait for the observer to fire. yield deferred.promise; // wait for the observer to fire.
// should have reset the pref that indicates if FxA is enabled. // the xpcom service should indicate FxA is enabled.
do_check_true(Services.prefs.getBoolPref("services.sync.fxaccounts.enabled"));
// the xpcom service should agree FxA is enabled.
do_check_true(xps.fxAccountsEnabled); do_check_true(xps.fxAccountsEnabled);
// should have swapped identities. // should have swapped identities.
do_check_true(Service.identity instanceof BrowserIDManager); do_check_true(Service.identity instanceof BrowserIDManager);
@ -57,6 +55,5 @@ add_task(function* test_startover() {
do_check_neq(oldClusterManager, Service._clusterManager); do_check_neq(oldClusterManager, Service._clusterManager);
// reset the world. // reset the world.
Services.prefs.setBoolPref("services.sync.fxaccounts.enabled", false);
Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", oldValue); Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", oldValue);
}); });

View File

@ -14,15 +14,6 @@ Cu.import("resource://testing-common/services/healthreport/utils.jsm", this);
function run_test() { function run_test() {
initTestLogging(); initTestLogging();
// A head JS file always sets the
// services.sync.fxaccounts.enabled pref. This prevents us from testing
// pristine profile conditions and likely indicates there isn't test
// coverage of the Sync service's fxAccountsEnabled property. Check
// that pre-condition and hack around it.
let branch = new Preferences("services.sync.");
Assert.ok(branch.isSet("fxaccounts.enabled"), "Check precondition");
branch.reset("fxaccounts.enabled");
run_next_test(); run_next_test();
} }

View File

@ -21,6 +21,7 @@ function shared_setup() {
hmacErrorCount = 0; hmacErrorCount = 0;
// Do not instantiate SyncTestingInfrastructure; we need real crypto. // Do not instantiate SyncTestingInfrastructure; we need real crypto.
ensureLegacyIdentityManager();
setBasicCredentials("foo", "foo", "aabcdeabcdeabcdeabcdeabcde"); setBasicCredentials("foo", "foo", "aabcdeabcdeabcdeabcdeabcde");
// Make sure RotaryEngine is the only one we sync. // Make sure RotaryEngine is the only one we sync.

View File

@ -186,6 +186,7 @@ function run_test() {
// Simulate Sync setup with credentials in place. We want to make // Simulate Sync setup with credentials in place. We want to make
// sure the J-PAKE requests don't include those data. // sure the J-PAKE requests don't include those data.
ensureLegacyIdentityManager();
setBasicCredentials("johndoe", "ilovejane"); setBasicCredentials("johndoe", "ilovejane");
initTestLogging("Trace"); initTestLogging("Trace");

View File

@ -8,6 +8,7 @@ Cu.import("resource://services-sync/record.js");
Cu.import("resource://services-sync/resource.js"); Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/utils.js");
let cryptoWrap; let cryptoWrap;
@ -30,6 +31,7 @@ function run_test() {
let server; let server;
do_test_pending(); do_test_pending();
ensureLegacyIdentityManager();
Service.identity.username = "john@example.com"; Service.identity.username = "john@example.com";
Service.identity.syncKey = "a-abcde-abcde-abcde-abcde-abcde"; Service.identity.syncKey = "a-abcde-abcde-abcde-abcde-abcde";
let keyBundle = Service.identity.syncKeyBundle; let keyBundle = Service.identity.syncKeyBundle;

View File

@ -6,6 +6,7 @@ Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/resource.js"); Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/utils.js");
function test_toJSON() { function test_toJSON() {
@ -78,6 +79,7 @@ function test_fetch() {
function run_test() { function run_test() {
initTestLogging("Trace"); initTestLogging("Trace");
ensureLegacyIdentityManager();
test_toJSON(); test_toJSON();
test_fetch(); test_fetch();

View File

@ -31,6 +31,7 @@ function run_test() {
"/1.1/johndoe/storage/meta/global": uaHandler(meta_global.handler()), "/1.1/johndoe/storage/meta/global": uaHandler(meta_global.handler()),
}); });
ensureLegacyIdentityManager();
setBasicCredentials("johndoe", "ilovejane"); setBasicCredentials("johndoe", "ilovejane");
Service.serverURL = server.baseURI + "/"; Service.serverURL = server.baseURI + "/";
Service.clusterURL = server.baseURI + "/"; Service.clusterURL = server.baseURI + "/";

View File

@ -8,6 +8,7 @@ Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/utils.js"); Cu.import("resource://testing-common/services/sync/utils.js");
function run_test() { function run_test() {
ensureLegacyIdentityManager();
setBasicCredentials("johndoe", "ilovejane", Utils.generatePassphrase()); setBasicCredentials("johndoe", "ilovejane", Utils.generatePassphrase());
Service.serverURL = "http://weave.server/"; Service.serverURL = "http://weave.server/";

View File

@ -5,10 +5,12 @@ Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/fakeservices.js"); Cu.import("resource://testing-common/services/sync/fakeservices.js");
Cu.import("resource://testing-common/services/sync/utils.js");
function test_urls() { function test_urls() {
_("URL related Service properties correspond to preference settings."); _("URL related Service properties correspond to preference settings.");
try { try {
ensureLegacyIdentityManager();
do_check_true(!!Service.serverURL); // actual value may change do_check_true(!!Service.serverURL); // actual value may change
do_check_eq(Service.clusterURL, ""); do_check_eq(Service.clusterURL, "");
do_check_eq(Service.userBaseURL, undefined); do_check_eq(Service.userBaseURL, undefined);

View File

@ -13,6 +13,8 @@ function run_test() {
Log.repository.getLogger("Sync.Resource").level = Log.Level.Trace; Log.repository.getLogger("Sync.Resource").level = Log.Level.Trace;
Log.repository.getLogger("Sync.Service").level = Log.Level.Trace; Log.repository.getLogger("Sync.Service").level = Log.Level.Trace;
ensureLegacyIdentityManager();
run_next_test(); run_next_test();
} }

View File

@ -7,6 +7,7 @@ Cu.import("resource://testing-common/services/sync/utils.js");
function run_test() { function run_test() {
do_test_pending(); do_test_pending();
ensureLegacyIdentityManager();
let server = httpd_setup({ let server = httpd_setup({
"/user/1.0/johndoe": httpd_handler(200, "OK", "1"), "/user/1.0/johndoe": httpd_handler(200, "OK", "1"),
"/user/1.0/janedoe": httpd_handler(200, "OK", "0"), "/user/1.0/janedoe": httpd_handler(200, "OK", "0"),

View File

@ -18,11 +18,12 @@ function do_check_throws(func) {
add_test(function test_findCluster() { add_test(function test_findCluster() {
_("Test Service._findCluster()"); _("Test Service._findCluster()");
let server; let server;
ensureLegacyIdentityManager();
try { try {
_("_findCluster() throws on network errors (e.g. connection refused)."); _("_findCluster() throws on network errors (e.g. connection refused).");
do_check_throws(function() { do_check_throws(function() {
Service.serverURL = "http://dummy:9000/"; Service.serverURL = "http://dummy:9000/";
Service.identify.account = "johndoe"; Service.identity.account = "johndoe";
Service._clusterManager._findCluster(); Service._clusterManager._findCluster();
}); });

View File

@ -43,6 +43,8 @@ add_test(function v4_upgrade() {
"/1.1/johndoe/storage/prefs": new ServerCollection().handler() "/1.1/johndoe/storage/prefs": new ServerCollection().handler()
}); });
ensureLegacyIdentityManager();
try { try {
_("Set up some tabs."); _("Set up some tabs.");

View File

@ -16,6 +16,7 @@ function run_test() {
Log.repository.getLogger("Sync.StorageRequest").level = Log.Level.Trace; Log.repository.getLogger("Sync.StorageRequest").level = Log.Level.Trace;
initTestLogging(); initTestLogging();
ensureLegacyIdentityManager();
setBasicCredentials("johndoe", "ilovejane"); setBasicCredentials("johndoe", "ilovejane");
run_next_test(); run_next_test();

View File

@ -72,6 +72,7 @@ add_test(function test_login_logout() {
try { try {
_("Force the initial state."); _("Force the initial state.");
ensureLegacyIdentityManager();
Service.status.service = STATUS_OK; Service.status.service = STATUS_OK;
do_check_eq(Service.status.service, STATUS_OK); do_check_eq(Service.status.service, STATUS_OK);

View File

@ -58,6 +58,8 @@ function run_test() {
let upd = collectionsHelper.with_updated_collection; let upd = collectionsHelper.with_updated_collection;
let collections = collectionsHelper.collections; let collections = collectionsHelper.collections;
ensureLegacyIdentityManager();
do_test_pending(); do_test_pending();
let server = httpd_setup({ let server = httpd_setup({
"/1.1/johndoe/info/collections": login_handling(collectionsHelper.handler), "/1.1/johndoe/info/collections": login_handling(collectionsHelper.handler),

View File

@ -9,6 +9,7 @@ Cu.import("resource://testing-common/services/sync/utils.js");
function run_test() { function run_test() {
try { try {
// Ensure we have a blank slate to start. // Ensure we have a blank slate to start.
ensureLegacyIdentityManager();
Services.logins.removeAllLogins(); Services.logins.removeAllLogins();
setBasicCredentials("johndoe", "ilovejane", "abbbbbcccccdddddeeeeefffff"); setBasicCredentials("johndoe", "ilovejane", "abbbbbcccccdddddeeeeefffff");

View File

@ -65,6 +65,7 @@ function run_test() {
try { try {
_("Log in."); _("Log in.");
ensureLegacyIdentityManager();
Service.serverURL = server.baseURI; Service.serverURL = server.baseURI;
_("Checking Status.sync with no credentials."); _("Checking Status.sync with no credentials.");

View File

@ -30,6 +30,7 @@ function run_test() {
let logger = Log.repository.rootLogger; let logger = Log.repository.rootLogger;
Log.repository.rootLogger.addAppender(new Log.DumpAppender()); Log.repository.rootLogger.addAppender(new Log.DumpAppender());
ensureLegacyIdentityManager();
// This test expects a clean slate -- no saved passphrase. // This test expects a clean slate -- no saved passphrase.
Services.logins.removeAllLogins(); Services.logins.removeAllLogins();
let johnHelper = track_collections_helper(); let johnHelper = track_collections_helper();

View File

@ -82,6 +82,7 @@ add_test(function test_credentials_preserved() {
_("Ensure that credentials are preserved if client is wiped."); _("Ensure that credentials are preserved if client is wiped.");
// Required for wipeClient(). // Required for wipeClient().
ensureLegacyIdentityManager();
Service.identity.account = "testaccount"; Service.identity.account = "testaccount";
Service.identity.basicPassword = "testpassword"; Service.identity.basicPassword = "testpassword";
Service.clusterURL = "http://dummy:9000/"; Service.clusterURL = "http://dummy:9000/";

View File

@ -4,9 +4,11 @@
Cu.import("resource://services-sync/constants.js"); Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/status.js"); Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/utils.js");
function run_test() { function run_test() {
initTestLogging("Trace"); initTestLogging("Trace");
ensureLegacyIdentityManager();
try { try {
_("Ensure fresh config."); _("Ensure fresh config.");

View File

@ -85,6 +85,13 @@ function run_test() {
Log.repository.getLogger("Sync.Service").level = Log.Level.Trace; Log.repository.getLogger("Sync.Service").level = Log.Level.Trace;
Log.repository.getLogger("Sync.scheduler").level = Log.Level.Trace; Log.repository.getLogger("Sync.scheduler").level = Log.Level.Trace;
// The scheduler checks Weave.fxaEnabled to determine whether to use
// FxA defaults or legacy defaults. As .fxaEnabled checks the username, we
// set a username here then reset the default to ensure they are used.
ensureLegacyIdentityManager();
setBasicCredentials("johndoe");
scheduler.setDefaults();
run_next_test(); run_next_test();
} }

View File

@ -12,6 +12,8 @@ function run_test() {
Log.repository.getLogger("Sync.RESTRequest").level = Log.Level.Trace; Log.repository.getLogger("Sync.RESTRequest").level = Log.Level.Trace;
initTestLogging(); initTestLogging();
ensureLegacyIdentityManager();
run_next_test(); run_next_test();
} }

View File

@ -4,11 +4,13 @@
Cu.import("resource://services-sync/constants.js"); Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/utils.js");
// Test upgrade of a dashed old-style sync key. // Test upgrade of a dashed old-style sync key.
function run_test() { function run_test() {
const PBKDF2_KEY_BYTES = 16; const PBKDF2_KEY_BYTES = 16;
initTestLogging("Trace"); initTestLogging("Trace");
ensureLegacyIdentityManager();
let passphrase = "abcde-abcde-abcde-abcde"; let passphrase = "abcde-abcde-abcde-abcde";
do_check_false(Utils.isPassphrase(passphrase)); do_check_false(Utils.isPassphrase(passphrase));

View File

@ -95,11 +95,10 @@ let TPS = {
* Check if the Firefox Accounts feature is enabled * Check if the Firefox Accounts feature is enabled
*/ */
get fxaccounts_enabled() { get fxaccounts_enabled() {
try { let service = Cc["@mozilla.org/weave/service;1"]
return Services.prefs.getBoolPref("services.sync.fxaccounts.enabled"); .getService(Components.interfaces.nsISupports)
} catch (e) { .wrappedJSObject;
return false; return service.fxAccountsEnabled;
}
}, },
DumpError: function (msg) { DumpError: function (msg) {