mobile/android/base/sync/setup/SyncAccounts.java

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 package org.mozilla.gecko.sync.setup;
     7 import java.io.File;
     8 import java.io.UnsupportedEncodingException;
     9 import java.security.NoSuchAlgorithmException;
    11 import org.mozilla.gecko.background.common.GlobalConstants;
    12 import org.mozilla.gecko.background.common.log.Logger;
    13 import org.mozilla.gecko.db.BrowserContract;
    14 import org.mozilla.gecko.sync.CredentialException;
    15 import org.mozilla.gecko.sync.ExtendedJSONObject;
    16 import org.mozilla.gecko.sync.SyncConfiguration;
    17 import org.mozilla.gecko.sync.SyncConstants;
    18 import org.mozilla.gecko.sync.ThreadPool;
    19 import org.mozilla.gecko.sync.Utils;
    20 import org.mozilla.gecko.sync.config.AccountPickler;
    21 import org.mozilla.gecko.sync.repositories.android.RepoUtils;
    23 import android.accounts.Account;
    24 import android.accounts.AccountManager;
    25 import android.content.ActivityNotFoundException;
    26 import android.content.ContentResolver;
    27 import android.content.Context;
    28 import android.content.Intent;
    29 import android.content.SharedPreferences;
    30 import android.content.pm.PackageManager.NameNotFoundException;
    31 import android.os.Bundle;
    32 import android.provider.Settings;
    33 import android.util.Log;
    35 /**
    36  * This class contains utilities that are of use to Fennec
    37  * and Sync setup activities.
    38  * <p>
    39  * Do not break these APIs without correcting upstream code!
    40  */
    41 public class SyncAccounts {
    42   private static final String LOG_TAG = "SyncAccounts";
    44   private static final String MOTO_BLUR_SETTINGS_ACTIVITY = "com.motorola.blur.settings.AccountsAndServicesPreferenceActivity";
    45   private static final String MOTO_BLUR_PACKAGE           = "com.motorola.blur.setup";
    47   /**
    48    * Return Sync accounts.
    49    *
    50    * @param c
    51    *          Android context.
    52    * @return Sync accounts.
    53    */
    54   public static Account[] syncAccounts(final Context c) {
    55     return AccountManager.get(c).getAccountsByType(SyncConstants.ACCOUNTTYPE_SYNC);
    56   }
    58   /**
    59    * Returns true if a Sync account is set up, or we have a pickled Sync account
    60    * on disk that should be un-pickled (Bug 769745). If we have a pickled Sync
    61    * account, try to un-pickle it and create the corresponding Sync account.
    62    * <p>
    63    * Do not call this method from the main thread.
    64    */
    65   public static boolean syncAccountsExist(Context c) {
    66     final boolean accountsExist = AccountManager.get(c).getAccountsByType(SyncConstants.ACCOUNTTYPE_SYNC).length > 0;
    67     if (accountsExist) {
    68       return true;
    69     }
    71     final File file = c.getFileStreamPath(Constants.ACCOUNT_PICKLE_FILENAME);
    72     if (!file.exists()) {
    73       return false;
    74     }
    76     // There is a small race window here: if the user creates a new Sync account
    77     // between our checks, this could erroneously report that no Sync accounts
    78     // exist.
    79     final Account account = AccountPickler.unpickle(c, Constants.ACCOUNT_PICKLE_FILENAME);
    80     return (account != null);
    81   }
    83   /**
    84    * This class encapsulates the parameters needed to create a new Firefox Sync
    85    * account.
    86    */
    87   public static class SyncAccountParameters {
    88     public final Context context;
    89     public final AccountManager accountManager;
    92     public final String username;   // services.sync.account
    93     public final String syncKey;    // in password manager: "chrome://weave (Mozilla Services Encryption Passphrase)"
    94     public final String password;   // in password manager: "chrome://weave (Mozilla Services Password)"
    95     public final String serverURL;  // services.sync.serverURL
    96     public final String clusterURL; // services.sync.clusterURL
    97     public final String clientName; // services.sync.client.name
    98     public final String clientGuid; // services.sync.client.GUID
   100     /**
   101      * Encapsulate the parameters needed to create a new Firefox Sync account.
   102      *
   103      * @param context
   104      *          the current <code>Context</code>; cannot be null.
   105      * @param accountManager
   106      *          an <code>AccountManager</code> instance to use; if null, get it
   107      *          from <code>context</code>.
   108      * @param username
   109      *          the desired username; cannot be null.
   110      * @param syncKey
   111      *          the desired sync key; cannot be null.
   112      * @param password
   113      *          the desired password; cannot be null.
   114      * @param serverURL
   115      *          the server URL to use; if null, use the default.
   116      * @param clusterURL
   117      *          the cluster URL to use; if null, a fresh cluster URL will be
   118      *          retrieved from the server during the next sync.
   119      * @param clientName
   120      *          the client name; if null, a fresh client record will be uploaded
   121      *          to the server during the next sync.
   122      * @param clientGuid
   123      *          the client GUID; if null, a fresh client record will be uploaded
   124      *          to the server during the next sync.
   125      */
   126     public SyncAccountParameters(Context context, AccountManager accountManager,
   127         String username, String syncKey, String password,
   128         String serverURL, String clusterURL,
   129         String clientName, String clientGuid) {
   130       if (context == null) {
   131         throw new IllegalArgumentException("Null context passed to SyncAccountParameters constructor.");
   132       }
   133       if (username == null) {
   134         throw new IllegalArgumentException("Null username passed to SyncAccountParameters constructor.");
   135       }
   136       if (syncKey == null) {
   137         throw new IllegalArgumentException("Null syncKey passed to SyncAccountParameters constructor.");
   138       }
   139       if (password == null) {
   140         throw new IllegalArgumentException("Null password passed to SyncAccountParameters constructor.");
   141       }
   142       this.context = context;
   143       this.accountManager = accountManager;
   144       this.username = username;
   145       this.syncKey = syncKey;
   146       this.password = password;
   147       this.serverURL = serverURL;
   148       this.clusterURL = clusterURL;
   149       this.clientName = clientName;
   150       this.clientGuid = clientGuid;
   151     }
   153     public SyncAccountParameters(Context context, AccountManager accountManager,
   154         String username, String syncKey, String password, String serverURL) {
   155       this(context, accountManager, username, syncKey, password, serverURL, null, null, null);
   156     }
   158     public SyncAccountParameters(final Context context, final AccountManager accountManager, final ExtendedJSONObject o) {
   159       this(context, accountManager,
   160           o.getString(Constants.JSON_KEY_ACCOUNT),
   161           o.getString(Constants.JSON_KEY_SYNCKEY),
   162           o.getString(Constants.JSON_KEY_PASSWORD),
   163           o.getString(Constants.JSON_KEY_SERVER),
   164           o.getString(Constants.JSON_KEY_CLUSTER),
   165           o.getString(Constants.JSON_KEY_CLIENT_NAME),
   166           o.getString(Constants.JSON_KEY_CLIENT_GUID));
   167     }
   169     public ExtendedJSONObject asJSON() {
   170       final ExtendedJSONObject o = new ExtendedJSONObject();
   171       o.put(Constants.JSON_KEY_ACCOUNT, username);
   172       o.put(Constants.JSON_KEY_PASSWORD, password);
   173       o.put(Constants.JSON_KEY_SERVER, serverURL);
   174       o.put(Constants.JSON_KEY_SYNCKEY, syncKey);
   175       o.put(Constants.JSON_KEY_CLUSTER, clusterURL);
   176       o.put(Constants.JSON_KEY_CLIENT_NAME, clientName);
   177       o.put(Constants.JSON_KEY_CLIENT_GUID, clientGuid);
   178       return o;
   179     }
   180   }
   182   /**
   183    * Create a sync account, clearing any existing preferences, and set it to
   184    * sync automatically.
   185    * <p>
   186    * Do not call this method from the main thread.
   187    *
   188    * @param syncAccount
   189    *          parameters of the account to be created.
   190    * @return created <code>Account</code>, or null if an error occurred and the
   191    *         account could not be added.
   192    */
   193   public static Account createSyncAccount(SyncAccountParameters syncAccount) {
   194     return createSyncAccount(syncAccount, true, true);
   195   }
   197   /**
   198    * Create a sync account, clearing any existing preferences.
   199    * <p>
   200    * Do not call this method from the main thread.
   201    * <p>
   202    * Intended for testing; use
   203    * <code>createSyncAccount(SyncAccountParameters)</code> instead.
   204    *
   205    * @param syncAccount
   206    *          parameters of the account to be created.
   207    * @param syncAutomatically
   208    *          whether to start syncing this Account automatically (
   209    *          <code>false</code> for test accounts).
   210    * @return created Android <code>Account</code>, or null if an error occurred
   211    *         and the account could not be added.
   212    */
   213   public static Account createSyncAccount(SyncAccountParameters syncAccount,
   214       boolean syncAutomatically) {
   215     return createSyncAccount(syncAccount, syncAutomatically, true);
   216   }
   218   public static Account createSyncAccountPreservingExistingPreferences(SyncAccountParameters syncAccount,
   219       boolean syncAutomatically) {
   220     return createSyncAccount(syncAccount, syncAutomatically, false);
   221   }
   223   /**
   224    * Create a sync account.
   225    * <p>
   226    * Do not call this method from the main thread.
   227    * <p>
   228    * Intended for testing; use
   229    * <code>createSyncAccount(SyncAccountParameters)</code> instead.
   230    *
   231    * @param syncAccount
   232    *          parameters of the account to be created.
   233    * @param syncAutomatically
   234    *          whether to start syncing this Account automatically (
   235    *          <code>false</code> for test accounts).
   236    * @param clearPreferences
   237    *          <code>true</code> to clear existing preferences before creating.
   238    * @return created Android <code>Account</code>, or null if an error occurred
   239    *         and the account could not be added.
   240    */
   241   protected static Account createSyncAccount(SyncAccountParameters syncAccount,
   242       boolean syncAutomatically, boolean clearPreferences) {
   243     final Context context = syncAccount.context;
   244     final AccountManager accountManager = (syncAccount.accountManager == null) ?
   245           AccountManager.get(syncAccount.context) : syncAccount.accountManager;
   246     final String username  = syncAccount.username;
   247     final String syncKey   = syncAccount.syncKey;
   248     final String password  = syncAccount.password;
   249     final String serverURL = (syncAccount.serverURL == null) ?
   250         SyncConstants.DEFAULT_AUTH_SERVER : syncAccount.serverURL;
   252     Logger.debug(LOG_TAG, "Using account manager " + accountManager);
   253     if (!RepoUtils.stringsEqual(syncAccount.serverURL, SyncConstants.DEFAULT_AUTH_SERVER)) {
   254       Logger.info(LOG_TAG, "Setting explicit server URL: " + serverURL);
   255     }
   257     final Account account = new Account(username, SyncConstants.ACCOUNTTYPE_SYNC);
   258     final Bundle userbundle = new Bundle();
   260     // Add sync key and server URL.
   261     userbundle.putString(Constants.OPTION_SYNCKEY, syncKey);
   262     userbundle.putString(Constants.OPTION_SERVER, serverURL);
   263     Logger.debug(LOG_TAG, "Adding account for " + SyncConstants.ACCOUNTTYPE_SYNC);
   264     boolean result = false;
   265     try {
   266       result = accountManager.addAccountExplicitly(account, password, userbundle);
   267     } catch (SecurityException e) {
   268       // We use Log rather than Logger here to avoid possibly hiding these errors.
   269       final String message = e.getMessage();
   270       if (message != null && (message.indexOf("is different than the authenticator's uid") > 0)) {
   271         Log.wtf(SyncConstants.GLOBAL_LOG_TAG,
   272                 "Unable to create account. " +
   273                 "If you have more than one version of " +
   274                 "Firefox/Beta/Aurora/Nightly/Fennec installed, that's why.",
   275                 e);
   276       } else {
   277         Log.e(SyncConstants.GLOBAL_LOG_TAG, "Unable to create account.", e);
   278       }
   279     }
   281     if (!result) {
   282       Logger.error(LOG_TAG, "Failed to add account " + account + "!");
   283       return null;
   284     }
   285     Logger.debug(LOG_TAG, "Account " + account + " added successfully.");
   287     setSyncAutomatically(account, syncAutomatically);
   288     setIsSyncable(account, syncAutomatically);
   289     Logger.debug(LOG_TAG, "Set account to sync automatically? " + syncAutomatically + ".");
   291     try {
   292       final String product = GlobalConstants.BROWSER_INTENT_PACKAGE;
   293       final String profile = Constants.DEFAULT_PROFILE;
   294       final long version = SyncConfiguration.CURRENT_PREFS_VERSION;
   296       final SharedPreferences.Editor editor = Utils.getSharedPreferences(context, product, username, serverURL, profile, version).edit();
   297       if (clearPreferences) {
   298         final String prefsPath = Utils.getPrefsPath(product, username, serverURL, profile, version);
   299         Logger.info(LOG_TAG, "Clearing preferences path " + prefsPath + " for this account.");
   300         editor.clear();
   301       }
   303       if (syncAccount.clusterURL != null) {
   304         editor.putString(SyncConfiguration.PREF_CLUSTER_URL, syncAccount.clusterURL);
   305       }
   307       if (syncAccount.clientName != null && syncAccount.clientGuid != null) {
   308         Logger.debug(LOG_TAG, "Setting client name to " + syncAccount.clientName + " and client GUID to " + syncAccount.clientGuid + ".");
   309         editor.putString(SyncConfiguration.PREF_CLIENT_NAME, syncAccount.clientName);
   310         editor.putString(SyncConfiguration.PREF_ACCOUNT_GUID, syncAccount.clientGuid);
   311       } else {
   312         Logger.debug(LOG_TAG, "Client name and guid not both non-null, so not setting client data.");
   313       }
   315       editor.commit();
   316     } catch (Exception e) {
   317       Logger.error(LOG_TAG, "Could not clear prefs path!", e);
   318     }
   319     return account;
   320   }
   322   public static void setIsSyncable(Account account, boolean isSyncable) {
   323     String authority = BrowserContract.AUTHORITY;
   324     ContentResolver.setIsSyncable(account, authority, isSyncable ? 1 : 0);
   325   }
   327   public static void setSyncAutomatically(Account account, boolean syncAutomatically) {
   328     if (syncAutomatically) {
   329       ContentResolver.setMasterSyncAutomatically(true);
   330     }
   332     String authority = BrowserContract.AUTHORITY;
   333     Logger.debug(LOG_TAG, "Setting authority " + authority + " to " +
   334                           (syncAutomatically ? "" : "not ") + "sync automatically.");
   335     ContentResolver.setSyncAutomatically(account, authority, syncAutomatically);
   336   }
   338   public static void backgroundSetSyncAutomatically(final Account account, final boolean syncAutomatically) {
   339     ThreadPool.run(new Runnable() {
   340       @Override
   341       public void run() {
   342         setSyncAutomatically(account, syncAutomatically);
   343       }
   344     });
   345   }
   346   /**
   347    * Bug 721760: try to start a vendor-specific Accounts & Sync activity on Moto
   348    * Blur devices.
   349    * <p>
   350    * Bug 773562: actually start and catch <code>ActivityNotFoundException</code>,
   351    * rather than just returning the <code>Intent</code> only, because some
   352    * Moto devices fail to start the activity.
   353    *
   354    * @param context
   355    *          current Android context.
   356    * @param vendorPackage
   357    *          vendor specific package name.
   358    * @param vendorClass
   359    *          vendor specific class name.
   360    * @return null on failure, otherwise the <code>Intent</code> started.
   361    */
   362   protected static Intent openVendorSyncSettings(Context context, final String vendorPackage, final String vendorClass) {
   363     try {
   364       final int contextFlags = Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY;
   365       Context foreignContext = context.createPackageContext(vendorPackage, contextFlags);
   366       Class<?> klass = foreignContext.getClassLoader().loadClass(vendorClass);
   368       final Intent intent = new Intent(foreignContext, klass);
   369       context.startActivity(intent);
   370       Logger.info(LOG_TAG, "Vendor package " + vendorPackage + " and class " +
   371           vendorClass + " found, and activity launched.");
   372       return intent;
   373     } catch (NameNotFoundException e) {
   374       Logger.debug(LOG_TAG, "Vendor package " + vendorPackage + " not found. Skipping.");
   375     } catch (ClassNotFoundException e) {
   376       Logger.debug(LOG_TAG, "Vendor package " + vendorPackage + " found but class " +
   377           vendorClass + " not found. Skipping.", e);
   378     } catch (ActivityNotFoundException e) {
   379       // Bug 773562 - android.content.ActivityNotFoundException on Motorola devices.
   380       Logger.warn(LOG_TAG, "Vendor package " + vendorPackage + " and class " +
   381           vendorClass + " found, but activity not launched. Skipping.", e);
   382     } catch (Exception e) {
   383       // Just in case.
   384       Logger.warn(LOG_TAG, "Caught exception launching activity from vendor package " + vendorPackage +
   385           " and class " + vendorClass + ". Ignoring.", e);
   386     }
   387     return null;
   388   }
   390   /**
   391    * Start Sync settings activity.
   392    *
   393    * @param context
   394    *          current Android context.
   395    * @return the <code>Intent</code> started.
   396    */
   397   public static Intent openSyncSettings(Context context) {
   398     // Bug 721760 - opening Sync settings takes user to Battery & Data Manager
   399     // on a variety of Motorola devices. This work around tries to load the
   400     // correct Intent by hand. Oh, Android.
   401     Intent intent = openVendorSyncSettings(context, MOTO_BLUR_PACKAGE, MOTO_BLUR_SETTINGS_ACTIVITY);
   402     if (intent != null) {
   403       return intent;
   404     }
   406     // Open default Sync settings activity.
   407     intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
   408     // Bug 774233: do not start activity as a new task (second run fails on some HTC devices).
   409     context.startActivity(intent); // We should always find this Activity.
   410     return intent;
   411   }
   413   /**
   414    * Synchronously extract Sync account parameters from Android account version
   415    * 0, using plain auth token type.
   416    * <p>
   417    * Safe to call from main thread.
   418    *
   419    * @param context
   420    *          Android context.
   421    * @param accountManager
   422    *          Android account manager.
   423    * @param account
   424    *          Android Account.
   425    * @return Sync account parameters, always non-null; fields username,
   426    *         password, serverURL, and syncKey always non-null.
   427    */
   428   public static SyncAccountParameters blockingFromAndroidAccountV0(final Context context, final AccountManager accountManager, final Account account)
   429       throws CredentialException {
   430     String username;
   431     try {
   432       username = Utils.usernameFromAccount(account.name);
   433     } catch (NoSuchAlgorithmException e) {
   434       throw new CredentialException.MissingCredentialException("username");
   435     } catch (UnsupportedEncodingException e) {
   436       throw new CredentialException.MissingCredentialException("username");
   437     }
   439     /*
   440      * If we are accessing an Account that we don't own, Android will throw an
   441      * unchecked <code>SecurityException</code> saying
   442      * "W FxSync(XXXX) java.lang.SecurityException: caller uid XXXXX is different than the authenticator's uid".
   443      * We catch that error and throw accordingly.
   444      */
   445     String password;
   446     String syncKey;
   447     String serverURL;
   448     try {
   449       password = accountManager.getPassword(account);
   450       syncKey = accountManager.getUserData(account, Constants.OPTION_SYNCKEY);
   451       serverURL = accountManager.getUserData(account, Constants.OPTION_SERVER);
   452     } catch (SecurityException e) {
   453       Logger.warn(LOG_TAG, "Got security exception fetching Sync account parameters; throwing.");
   454       throw new CredentialException.MissingAllCredentialsException(e);
   455     }
   457     if (password  == null &&
   458         username  == null &&
   459         syncKey   == null &&
   460         serverURL == null) {
   461       throw new CredentialException.MissingAllCredentialsException();
   462     }
   464     if (password == null) {
   465       throw new CredentialException.MissingCredentialException("password");
   466     }
   468     if (syncKey == null) {
   469       throw new CredentialException.MissingCredentialException("syncKey");
   470     }
   472     if (serverURL == null) {
   473       throw new CredentialException.MissingCredentialException("serverURL");
   474     }
   476     try {
   477       // SyncAccountParameters constructor throws on null inputs. This shouldn't
   478       // happen, but let's be safe.
   479       return new SyncAccountParameters(context, accountManager, username, syncKey, password, serverURL);
   480     } catch (Exception e) {
   481       Logger.warn(LOG_TAG, "Got exception fetching Sync account parameters; throwing.");
   482       throw new CredentialException.MissingAllCredentialsException(e);
   483     }
   484   }
   486   /**
   487    * Bug 790931: create an intent announcing that a Sync account will be
   488    * deleted.
   489    * <p>
   490    * This intent <b>must</b> be broadcast with secure permissions, because it
   491    * contains sensitive user information including the Sync account password and
   492    * Sync key.
   493    * <p>
   494    * Version 1 of the created intent includes extras with keys
   495    * <code>Constants.JSON_KEY_VERSION</code>,
   496    * <code>Constants.JSON_KEY_TIMESTAMP</code>, and
   497    * <code>Constants.JSON_KEY_ACCOUNT</code> (which is the Android Account name,
   498    * not the encoded Sync Account name).
   499    * <p>
   500    * If possible, it contains the key <code>Constants.JSON_KEY_PAYLOAD</code>
   501    * with value the Sync account parameters as JSON, <b>except the Sync key has
   502    * been replaced with the empty string</b>. (We replace, rather than remove,
   503    * the Sync key because SyncAccountParameters expects a non-null Sync key.)
   504    *
   505    * @see SyncAccountParameters#asJSON
   506    *
   507    * @param context
   508    *          Android context.
   509    * @param accountManager
   510    *          Android account manager.
   511    * @param account
   512    *          Android account being removed.
   513    * @return <code>Intent</code> to broadcast.
   514    */
   515   public static Intent makeSyncAccountDeletedIntent(final Context context, final AccountManager accountManager, final Account account) {
   516     final Intent intent = new Intent(SyncConstants.SYNC_ACCOUNT_DELETED_ACTION);
   518     intent.putExtra(Constants.JSON_KEY_VERSION, Long.valueOf(SyncConstants.SYNC_ACCOUNT_DELETED_INTENT_VERSION));
   519     intent.putExtra(Constants.JSON_KEY_TIMESTAMP, Long.valueOf(System.currentTimeMillis()));
   520     intent.putExtra(Constants.JSON_KEY_ACCOUNT, account.name);
   522     SyncAccountParameters accountParameters = null;
   523     try {
   524       accountParameters = SyncAccounts.blockingFromAndroidAccountV0(context, accountManager, account);
   525     } catch (Exception e) {
   526       Logger.warn(LOG_TAG, "Caught exception fetching account parameters.", e);
   527     }
   529     if (accountParameters != null) {
   530       ExtendedJSONObject json = accountParameters.asJSON();
   531       json.put(Constants.JSON_KEY_SYNCKEY, ""); // Reduce attack surface area by removing Sync key.
   532       intent.putExtra(Constants.JSON_KEY_PAYLOAD, json.toJSONString());
   533     }
   535     return intent;
   536   }
   538   /**
   539    * Synchronously fetch SharedPreferences of a profile associated with a Sync
   540    * account.
   541    * <p>
   542    * Safe to call from main thread.
   543    *
   544    * @param context
   545    *          Android context.
   546    * @param accountManager
   547    *          Android account manager.
   548    * @param account
   549    *          Android Account.
   550    * @param product
   551    *          package.
   552    * @param profile
   553    *          of account.
   554    * @param version
   555    *          number.
   556    * @return SharedPreferences associated with Sync account.
   557    * @throws CredentialException
   558    * @throws NoSuchAlgorithmException
   559    * @throws UnsupportedEncodingException
   560    */
   561   public static SharedPreferences blockingPrefsFromAndroidAccountV0(final Context context, final AccountManager accountManager, final Account account,
   562       final String product, final String profile, final long version)
   563           throws CredentialException, NoSuchAlgorithmException, UnsupportedEncodingException {
   564     SyncAccountParameters params = SyncAccounts.blockingFromAndroidAccountV0(context, accountManager, account);
   565     String prefsPath = Utils.getPrefsPath(product, params.username, params.serverURL, profile, version);
   567     return context.getSharedPreferences(prefsPath, Utils.SHARED_PREFERENCES_MODE);
   568   }
   570   /**
   571    * Synchronously fetch SharedPreferences of a profile associated with the
   572    * default Firefox profile of a Sync Account.
   573    * <p>
   574    * Uses the default package, default profile, and current version.
   575    * <p>
   576    * Safe to call from main thread.
   577    *
   578    * @param context
   579    *          Android context.
   580    * @param accountManager
   581    *          Android account manager.
   582    * @param account
   583    *          Android Account.
   584    * @return SharedPreferences associated with Sync account.
   585    * @throws CredentialException
   586    * @throws NoSuchAlgorithmException
   587    * @throws UnsupportedEncodingException
   588    */
   589   public static SharedPreferences blockingPrefsFromDefaultProfileV0(final Context context, final AccountManager accountManager, final Account account)
   590       throws CredentialException, NoSuchAlgorithmException, UnsupportedEncodingException {
   591     final String product = GlobalConstants.BROWSER_INTENT_PACKAGE;
   592     final String profile = Constants.DEFAULT_PROFILE;
   593     final long version = SyncConfiguration.CURRENT_PREFS_VERSION;
   595     return blockingPrefsFromAndroidAccountV0(context, accountManager, account, product, profile, version);
   596   }
   597 }

mercurial