/** * Copyright (c) 2012 Todoroo Inc * * See the file "LICENSE" for the full license governing this code. */ package com.todoroo.astrid.gtasks.auth; import java.io.IOException; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerFuture; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import com.google.api.client.googleapis.extensions.android2.auth.GoogleAccountManager; import com.timsu.astrid.R; import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.gtasks.GtasksPreferenceService; import com.todoroo.astrid.gtasks.api.GoogleTasksException; import com.todoroo.astrid.gtasks.api.GtasksInvoker; @SuppressWarnings("nls") public class GtasksTokenValidator { private static final String TOKEN_INTENT_RECEIVED = "intent!"; //$NON-NLS-1$ private static final int REVALIDATION_TRIES = 4; /** * Invalidates and then revalidates the auth token for the currently logged in user * Shouldn't be called from the main thread--will block on network calls * @param token * @return valid token on success, null on failure */ public static synchronized String validateAuthToken(Context c, String token) throws GoogleTasksException { GoogleAccountManager accountManager = new GoogleAccountManager(ContextManager.getContext()); if(testToken(token)) return token; // If fail, token may have expired -- get a new one and return that String accountName = Preferences.getStringValue(GtasksPreferenceService.PREF_USER_NAME); Account a = accountManager.getAccountByName(accountName); if (a == null) { throw new GoogleTasksException(c.getString(R.string.gtasks_error_accountNotFound, accountName), "account-not-found"); } for (int i = 0; i < REVALIDATION_TRIES; i++) { accountManager.invalidateAuthToken(token); // try with notify-auth-failure = false AccountManagerFuture<Bundle> future = accountManager.manager.getAuthToken(a, GtasksInvoker.AUTH_TOKEN_TYPE, false, null, null); token = getTokenFromFuture(c, future); if(TOKEN_INTENT_RECEIVED.equals(token)) return null; else if(token != null && testToken(token)) return token; } throw new GoogleTasksException(c.getString(R.string.gtasks_error_authRefresh), "auth-token-refresh"); } private static boolean testToken(String token) { GtasksInvoker testService = new GtasksInvoker(token); try { testService.ping(); return true; } catch (IOException i) { return false; } } private static String getTokenFromFuture(Context c, AccountManagerFuture<Bundle> future) throws GoogleTasksException { Bundle result; try { result = future.getResult(); if(result == null) throw new NullPointerException("Future result was null."); //$NON-NLS-1$ } catch (Exception e) { throw new GoogleTasksException(e.getLocalizedMessage(), "future-error"); } // check what kind of result was returned String token; if (result.containsKey(AccountManager.KEY_AUTHTOKEN)) { token = result.getString(AccountManager.KEY_AUTHTOKEN); } else if (result.containsKey(AccountManager.KEY_INTENT)) { Intent intent = (Intent) result.get(AccountManager.KEY_INTENT); if (c instanceof Activity) c.startActivity(intent); else throw new GoogleTasksException(c.getString(R.string.gtasks_error_background_sync_auth), "background-auth-error"); return TOKEN_INTENT_RECEIVED; } else { throw new GoogleTasksException(c.getString(R.string.gtasks_error_accountManager), "account-manager-error"); } return token; } }