diff options
4 files changed, 39 insertions, 35 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java index 27e2d12..1224d4a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java @@ -131,7 +131,12 @@ public final class OAuth2TokenService { Context context, String username, String scope, final long nativeCallback) { Account account = getAccountOrNullFromUsername(context, username); if (account == null) { - nativeOAuth2TokenFetched(null, false, nativeCallback); + ThreadUtils.postOnUiThread(new Runnable() { + @Override + public void run() { + nativeOAuth2TokenFetched(null, nativeCallback); + } + }); return; } String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope; @@ -141,7 +146,7 @@ public final class OAuth2TokenService { null, account, oauth2Scope, new AccountManagerHelper.GetAuthTokenCallback() { @Override public void tokenAvailable(String token) { - nativeOAuth2TokenFetched(token, token != null, nativeCallback); + nativeOAuth2TokenFetched(token, nativeCallback); } }); } @@ -301,7 +306,7 @@ public final class OAuth2TokenService { private static native Object nativeGetForProfile(Profile profile); private static native void nativeOAuth2TokenFetched( - String authToken, boolean result, long nativeCallback); + String authToken, long nativeCallback); private native void nativeValidateAccounts( long nativeAndroidProfileOAuth2TokenService, String currentlySignedInAccount, diff --git a/chrome/browser/signin/android_profile_oauth2_token_service.cc b/chrome/browser/signin/android_profile_oauth2_token_service.cc index e62353c..1d955be 100644 --- a/chrome/browser/signin/android_profile_oauth2_token_service.cc +++ b/chrome/browser/signin/android_profile_oauth2_token_service.cc @@ -457,7 +457,6 @@ void OAuth2TokenFetched( JNIEnv* env, jclass clazz, jstring authToken, - jboolean result, jlong nativeCallback) { std::string token; if (authToken) @@ -466,7 +465,7 @@ void OAuth2TokenFetched( reinterpret_cast<FetchOAuth2TokenCallback*>(nativeCallback)); // Android does not provide enough information to know if the credentials are // wrong, so assume any error is transient by using CONNECTION_FAILED. - GoogleServiceAuthError err(result ? + GoogleServiceAuthError err(authToken ? GoogleServiceAuthError::NONE : GoogleServiceAuthError::CONNECTION_FAILED); heap_callback->Run(err, token, base::Time()); diff --git a/google_apis/gaia/oauth2_token_service.cc b/google_apis/gaia/oauth2_token_service.cc index 5245646..f2a163d 100644 --- a/google_apis/gaia/oauth2_token_service.cc +++ b/google_apis/gaia/oauth2_token_service.cc @@ -99,9 +99,9 @@ OAuth2TokenService::ScopedBatchChange::~ScopedBatchChange() { // // The Fetcher will call back the service by calling // OAuth2TokenService::OnFetchComplete() when it completes fetching, if it is -// not destructed before it completes fetching; if the Fetcher is destructed +// not destroyed before it completes fetching; if the Fetcher is destroyed // before it completes fetching, the service will never be called back. The -// Fetcher destructs itself after calling back the service when finishes +// Fetcher destroys itself after calling back the service when it finishes // fetching. // // Requests that are waiting for the fetching results of this Fetcher can be @@ -110,13 +110,13 @@ OAuth2TokenService::ScopedBatchChange::~ScopedBatchChange() { // completes fetching. // // The waiting requests are taken as weak pointers and they can be deleted. -// The waiting requests will be called back with fetching results if they are -// not deleted -// - when the Fetcher completes fetching, if the Fetcher is not destructed -// before it completes fetching, or -// - when the Fetcher is destructed if the Fetcher is destructed before it -// completes fetching (in this case, the waiting requests will be called -// back with error). +// They will be called back with the result when either the Fetcher completes +// fetching or is destroyed, whichever comes first. In the latter case, the +// waiting requests will be called back with an error. +// +// The OAuth2TokenService and the waiting requests will never be called back on +// the same turn of the message loop as when the fetcher is started, even if an +// immediate error occurred. class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { public: // Creates a Fetcher and starts fetching an OAuth2 access token for @@ -256,10 +256,13 @@ void OAuth2TokenService::Fetcher::Start() { fetcher_.reset(oauth2_token_service_->CreateAccessTokenFetcher( account_id_, getter_.get(), this)); DCHECK(fetcher_); + + // Stop the timer before starting the fetch, as defense in depth against the + // fetcher calling us back synchronously (which might restart the timer). + retry_timer_.Stop(); fetcher_->Start(client_id_, client_secret_, std::vector<std::string>(scopes_.begin(), scopes_.end())); - retry_timer_.Stop(); } void OAuth2TokenService::Fetcher::OnGetTokenSuccess( diff --git a/sync/android/java/src/org/chromium/sync/signin/AccountManagerHelper.java b/sync/android/java/src/org/chromium/sync/signin/AccountManagerHelper.java index 4d32375..e7304c5 100644 --- a/sync/android/java/src/org/chromium/sync/signin/AccountManagerHelper.java +++ b/sync/android/java/src/org/chromium/sync/signin/AccountManagerHelper.java @@ -292,32 +292,29 @@ public class AccountManagerHelper { final ConnectionRetry retry) { // Return null token for no USE_CREDENTIALS permission. if (!hasUseCredentialsPermission()) { - callback.tokenAvailable(null); + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + callback.tokenAvailable(null); + } + }); return; } final AccountManagerFuture<Bundle> future = mAccountManager.getAuthToken( account, authTokenType, true, null, null); errorEncountered.set(false); - // On ICS onPostExecute is never called when running an AsyncTask from a different thread - // than the UI thread. - if (ThreadUtils.runningOnUiThread()) { - new AsyncTask<Void, Void, String>() { - @Override - public String doInBackground(Void... params) { - return getAuthTokenInner(future, errorEncountered); - } - @Override - public void onPostExecute(String authToken) { - onGotAuthTokenResult(account, authTokenType, authToken, callback, numTries, - errorEncountered, retry); - } - }.execute(); - } else { - String authToken = getAuthTokenInner(future, errorEncountered); - onGotAuthTokenResult(account, authTokenType, authToken, callback, numTries, - errorEncountered, retry); - } + new AsyncTask<Void, Void, String>() { + @Override + public String doInBackground(Void... params) { + return getAuthTokenInner(future, errorEncountered); + } + @Override + public void onPostExecute(String authToken) { + onGotAuthTokenResult(account, authTokenType, authToken, callback, numTries, + errorEncountered, retry); + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } private void onGotAuthTokenResult(Account account, String authTokenType, String authToken, |