1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/sync/receivers/SyncAccountDeletedService.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,148 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +package org.mozilla.gecko.sync.receivers; 1.9 + 1.10 +import org.mozilla.gecko.sync.ExtendedJSONObject; 1.11 +import org.mozilla.gecko.background.common.GlobalConstants; 1.12 +import org.mozilla.gecko.background.common.log.Logger; 1.13 +import org.mozilla.gecko.sync.Sync11Configuration; 1.14 +import org.mozilla.gecko.sync.SyncConstants; 1.15 +import org.mozilla.gecko.sync.SyncConfiguration; 1.16 +import org.mozilla.gecko.sync.Utils; 1.17 +import org.mozilla.gecko.sync.config.AccountPickler; 1.18 +import org.mozilla.gecko.sync.config.ClientRecordTerminator; 1.19 +import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider; 1.20 +import org.mozilla.gecko.sync.setup.Constants; 1.21 +import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters; 1.22 + 1.23 +import android.accounts.AccountManager; 1.24 +import android.app.IntentService; 1.25 +import android.content.Context; 1.26 +import android.content.Intent; 1.27 +import android.content.SharedPreferences; 1.28 + 1.29 +public class SyncAccountDeletedService extends IntentService { 1.30 + public static final String LOG_TAG = "SyncAccountDeletedService"; 1.31 + 1.32 + public SyncAccountDeletedService() { 1.33 + super(LOG_TAG); 1.34 + } 1.35 + 1.36 + @Override 1.37 + protected void onHandleIntent(Intent intent) { 1.38 + // Intent can, in theory, be null. Bug 1025937. 1.39 + if (intent == null) { 1.40 + Logger.debug(LOG_TAG, "Short-circuiting on null intent."); 1.41 + return; 1.42 + } 1.43 + 1.44 + final Context context = this; 1.45 + 1.46 + long intentVersion = intent.getLongExtra(Constants.JSON_KEY_VERSION, 0); 1.47 + long expectedVersion = SyncConstants.SYNC_ACCOUNT_DELETED_INTENT_VERSION; 1.48 + if (intentVersion != expectedVersion) { 1.49 + Logger.warn(LOG_TAG, "Intent malformed: version " + intentVersion + " given but version " + expectedVersion + "expected. " + 1.50 + "Not cleaning up after deleted Account."); 1.51 + return; 1.52 + } 1.53 + 1.54 + String accountName = intent.getStringExtra(Constants.JSON_KEY_ACCOUNT); // Android Account name, not Sync encoded account name. 1.55 + if (accountName == null) { 1.56 + Logger.warn(LOG_TAG, "Intent malformed: no account name given. Not cleaning up after deleted Account."); 1.57 + return; 1.58 + } 1.59 + 1.60 + // Delete the Account pickle. 1.61 + Logger.info(LOG_TAG, "Sync account named " + accountName + " being removed; " + 1.62 + "deleting saved pickle file '" + Constants.ACCOUNT_PICKLE_FILENAME + "'."); 1.63 + deletePickle(context); 1.64 + 1.65 + SyncAccountParameters params; 1.66 + try { 1.67 + String payload = intent.getStringExtra(Constants.JSON_KEY_PAYLOAD); 1.68 + if (payload == null) { 1.69 + Logger.warn(LOG_TAG, "Intent malformed: no payload given. Not deleting client record."); 1.70 + return; 1.71 + } 1.72 + ExtendedJSONObject o = ExtendedJSONObject.parseJSONObject(payload); 1.73 + params = new SyncAccountParameters(context, AccountManager.get(context), o); 1.74 + } catch (Exception e) { 1.75 + Logger.warn(LOG_TAG, "Got exception fetching account parameters from intent data; not deleting client record."); 1.76 + return; 1.77 + } 1.78 + 1.79 + // Bug 770785: delete the Account's client record. 1.80 + Logger.info(LOG_TAG, "Account named " + accountName + " being removed; " + 1.81 + "deleting client record from server."); 1.82 + deleteClientRecord(context, accountName, params.password, params.serverURL); 1.83 + } 1.84 + 1.85 + public static void deletePickle(final Context context) { 1.86 + try { 1.87 + AccountPickler.deletePickle(context, Constants.ACCOUNT_PICKLE_FILENAME); 1.88 + } catch (Exception e) { 1.89 + // This should never happen, but we really don't want to die in a background thread. 1.90 + Logger.warn(LOG_TAG, "Got exception deleting saved pickle file; ignoring.", e); 1.91 + } 1.92 + } 1.93 + 1.94 + public static void deleteClientRecord(final Context context, final String accountName, 1.95 + final String password, final String serverURL) { 1.96 + String encodedUsername; 1.97 + try { 1.98 + encodedUsername = Utils.usernameFromAccount(accountName); 1.99 + } catch (Exception e) { 1.100 + Logger.warn(LOG_TAG, "Got exception deleting client record from server; ignoring.", e); 1.101 + return; 1.102 + } 1.103 + 1.104 + if (accountName == null || encodedUsername == null || password == null || serverURL == null) { 1.105 + Logger.warn(LOG_TAG, "Account parameters were null; not deleting client record from server."); 1.106 + return; 1.107 + } 1.108 + 1.109 + // This is not exactly modular. We need to get some information about 1.110 + // the account, namely the current clusterURL and client GUID, and we 1.111 + // extract it by hand. We're not worried about the Account being 1.112 + // deleted out from under us since the prefs remain even after Account 1.113 + // deletion. 1.114 + final String product = GlobalConstants.BROWSER_INTENT_PACKAGE; 1.115 + final String profile = Constants.DEFAULT_PROFILE; 1.116 + final long version = SyncConfiguration.CURRENT_PREFS_VERSION; 1.117 + 1.118 + SharedPreferences prefs; 1.119 + try { 1.120 + prefs = Utils.getSharedPreferences(context, product, encodedUsername, serverURL, profile, version); 1.121 + } catch (Exception e) { 1.122 + Logger.warn(LOG_TAG, "Caught exception fetching preferences; not deleting client record from server.", e); 1.123 + return; 1.124 + } 1.125 + 1.126 + try { 1.127 + final String clientGUID = prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null); 1.128 + if (clientGUID == null) { 1.129 + Logger.warn(LOG_TAG, "Client GUID was null; not deleting client record from server."); 1.130 + return; 1.131 + } 1.132 + 1.133 + BasicAuthHeaderProvider authHeaderProvider = new BasicAuthHeaderProvider(encodedUsername, password); 1.134 + SyncConfiguration configuration = new Sync11Configuration(encodedUsername, authHeaderProvider, prefs); 1.135 + if (configuration.getClusterURL() == null) { 1.136 + Logger.warn(LOG_TAG, "Cluster URL was null; not deleting client record from server."); 1.137 + return; 1.138 + } 1.139 + 1.140 + try { 1.141 + ClientRecordTerminator.deleteClientRecord(configuration, clientGUID); 1.142 + } catch (Exception e) { 1.143 + // This should never happen, but we really don't want to die in a background thread. 1.144 + Logger.warn(LOG_TAG, "Got exception deleting client record from server; ignoring.", e); 1.145 + } 1.146 + } finally { 1.147 + // Finally, a good place to do this. 1.148 + prefs.edit().clear().commit(); 1.149 + } 1.150 + } 1.151 +}