michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.fxa.authenticator; michael@0: michael@0: import org.mozilla.gecko.background.common.log.Logger; michael@0: import org.mozilla.gecko.fxa.FxAccountConstants; michael@0: import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity; michael@0: michael@0: import android.accounts.AbstractAccountAuthenticator; michael@0: import android.accounts.Account; michael@0: import android.accounts.AccountAuthenticatorResponse; michael@0: import android.accounts.AccountManager; michael@0: import android.accounts.NetworkErrorException; michael@0: import android.content.Context; michael@0: import android.content.Intent; michael@0: import android.os.Bundle; michael@0: michael@0: public class FxAccountAuthenticator extends AbstractAccountAuthenticator { michael@0: public static final String LOG_TAG = FxAccountAuthenticator.class.getSimpleName(); michael@0: michael@0: protected final Context context; michael@0: protected final AccountManager accountManager; michael@0: michael@0: public FxAccountAuthenticator(Context context) { michael@0: super(context); michael@0: this.context = context; michael@0: this.accountManager = AccountManager.get(context); michael@0: } michael@0: michael@0: @Override michael@0: public Bundle addAccount(AccountAuthenticatorResponse response, michael@0: String accountType, String authTokenType, String[] requiredFeatures, michael@0: Bundle options) michael@0: throws NetworkErrorException { michael@0: Logger.debug(LOG_TAG, "addAccount"); michael@0: michael@0: final Bundle res = new Bundle(); michael@0: michael@0: if (!FxAccountConstants.ACCOUNT_TYPE.equals(accountType)) { michael@0: res.putInt(AccountManager.KEY_ERROR_CODE, -1); michael@0: res.putString(AccountManager.KEY_ERROR_MESSAGE, "Not adding unknown account type."); michael@0: return res; michael@0: } michael@0: michael@0: Intent intent = new Intent(context, FxAccountGetStartedActivity.class); michael@0: res.putParcelable(AccountManager.KEY_INTENT, intent); michael@0: return res; michael@0: } michael@0: michael@0: @Override michael@0: public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) michael@0: throws NetworkErrorException { michael@0: Logger.debug(LOG_TAG, "confirmCredentials"); michael@0: michael@0: return null; michael@0: } michael@0: michael@0: @Override michael@0: public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) { michael@0: Logger.debug(LOG_TAG, "editProperties"); michael@0: michael@0: return null; michael@0: } michael@0: michael@0: @Override michael@0: public Bundle getAuthToken(final AccountAuthenticatorResponse response, michael@0: final Account account, final String authTokenType, final Bundle options) michael@0: throws NetworkErrorException { michael@0: Logger.debug(LOG_TAG, "getAuthToken"); michael@0: michael@0: Logger.warn(LOG_TAG, "Returning null bundle for getAuthToken."); michael@0: michael@0: return null; michael@0: } michael@0: michael@0: @Override michael@0: public String getAuthTokenLabel(String authTokenType) { michael@0: Logger.debug(LOG_TAG, "getAuthTokenLabel"); michael@0: michael@0: return null; michael@0: } michael@0: michael@0: @Override michael@0: public Bundle hasFeatures(AccountAuthenticatorResponse response, michael@0: Account account, String[] features) throws NetworkErrorException { michael@0: Logger.debug(LOG_TAG, "hasFeatures"); michael@0: michael@0: return null; michael@0: } michael@0: michael@0: @Override michael@0: public Bundle updateCredentials(AccountAuthenticatorResponse response, michael@0: Account account, String authTokenType, Bundle options) michael@0: throws NetworkErrorException { michael@0: Logger.debug(LOG_TAG, "updateCredentials"); michael@0: michael@0: return null; michael@0: } michael@0: michael@0: /** michael@0: * If the account is going to be removed, broadcast an "account deleted" michael@0: * intent. This allows us to clean up the account. michael@0: *

michael@0: * It is preferable to receive Android's LOGIN_ACCOUNTS_CHANGED_ACTION broadcast michael@0: * than to create our own hacky broadcast here, but that doesn't include enough michael@0: * information about which Accounts changed to correctly identify whether a Sync michael@0: * account has been removed (when some Firefox channels are installed on the SD michael@0: * card). We can work around this by storing additional state but it's both messy michael@0: * and expensive because the broadcast is noisy. michael@0: *

michael@0: * Note that this is not called when an Android Account is blown away michael@0: * due to the SD card being unmounted. michael@0: */ michael@0: @Override michael@0: public Bundle getAccountRemovalAllowed(final AccountAuthenticatorResponse response, Account account) michael@0: throws NetworkErrorException { michael@0: Bundle result = super.getAccountRemovalAllowed(response, account); michael@0: michael@0: if (result == null || michael@0: !result.containsKey(AccountManager.KEY_BOOLEAN_RESULT) || michael@0: result.containsKey(AccountManager.KEY_INTENT)) { michael@0: return result; michael@0: } michael@0: michael@0: final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); michael@0: if (!removalAllowed) { michael@0: return result; michael@0: } michael@0: michael@0: // Broadcast a message to all Firefox channels sharing this Android michael@0: // Account type telling that this Firefox account has been deleted. michael@0: // michael@0: // Broadcast intents protected with permissions are secure, so it's okay michael@0: // to include private information such as a password. michael@0: final Intent intent = AndroidFxAccount.makeDeletedAccountIntent(context, account); michael@0: Logger.info(LOG_TAG, "Account named " + account.name + " being removed; " + michael@0: "broadcasting secure intent " + intent.getAction() + "."); michael@0: context.sendBroadcast(intent, FxAccountConstants.PER_ACCOUNT_TYPE_PERMISSION); michael@0: michael@0: return result; michael@0: } michael@0: }