1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.volley.toolbox;
18
19import com.android.volley.AuthFailureError;
20
21import android.accounts.Account;
22import android.accounts.AccountManager;
23import android.accounts.AccountManagerFuture;
24import android.content.Context;
25import android.content.Intent;
26import android.os.Bundle;
27
28/**
29 * An Authenticator that uses {@link AccountManager} to get auth
30 * tokens of a specified type for a specified account.
31 */
32public class AndroidAuthenticator implements Authenticator {
33    private final Context mContext;
34    private final Account mAccount;
35    private final String mAuthTokenType;
36    private final boolean mNotifyAuthFailure;
37
38    /**
39     * Creates a new authenticator.
40     * @param context Context for accessing AccountManager
41     * @param account Account to authenticate as
42     * @param authTokenType Auth token type passed to AccountManager
43     */
44    public AndroidAuthenticator(Context context, Account account, String authTokenType) {
45        this(context, account, authTokenType, false);
46    }
47
48    /**
49     * Creates a new authenticator.
50     * @param context Context for accessing AccountManager
51     * @param account Account to authenticate as
52     * @param authTokenType Auth token type passed to AccountManager
53     * @param notifyAuthFailure Whether to raise a notification upon auth failure
54     */
55    public AndroidAuthenticator(Context context, Account account, String authTokenType,
56            boolean notifyAuthFailure) {
57        mContext = context;
58        mAccount = account;
59        mAuthTokenType = authTokenType;
60        mNotifyAuthFailure = notifyAuthFailure;
61    }
62
63    /**
64     * Returns the Account being used by this authenticator.
65     */
66    public Account getAccount() {
67        return mAccount;
68    }
69
70    @Override
71    public String getAuthToken() throws AuthFailureError {
72        final AccountManager accountManager = AccountManager.get(mContext);
73        AccountManagerFuture<Bundle> future = accountManager.getAuthToken(mAccount,
74                mAuthTokenType, mNotifyAuthFailure, null, null);
75        Bundle result;
76        try {
77            result = future.getResult();
78        } catch (Exception e) {
79            throw new AuthFailureError("Error while retrieving auth token", e);
80        }
81        String authToken = null;
82        if (future.isDone() && !future.isCancelled()) {
83            if (result.containsKey(AccountManager.KEY_INTENT)) {
84                Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
85                throw new AuthFailureError(intent);
86            }
87            authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
88        }
89        if (authToken == null) {
90            throw new AuthFailureError("Got null auth token for type: " + mAuthTokenType);
91        }
92
93        return authToken;
94    }
95
96    @Override
97    public void invalidateAuthToken(String authToken) {
98        AccountManager.get(mContext).invalidateAuthToken(mAccount.type, authToken);
99    }
100}
101