Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2933)

Unified Diff: blimp/client/android/java/src/org/chromium/blimp/auth/RetryingTokenSource.java

Issue 1373943002: Add sign-in and token retrieval to Blimp (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: blimp/client/android/java/src/org/chromium/blimp/auth/RetryingTokenSource.java
diff --git a/blimp/client/android/java/src/org/chromium/blimp/auth/RetryingTokenSource.java b/blimp/client/android/java/src/org/chromium/blimp/auth/RetryingTokenSource.java
new file mode 100644
index 0000000000000000000000000000000000000000..cae7e4b7e910646dc997be2229b985be4b38b480
--- /dev/null
+++ b/blimp/client/android/java/src/org/chromium/blimp/auth/RetryingTokenSource.java
@@ -0,0 +1,126 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.blimp.auth;
+
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+
+import org.chromium.base.VisibleForTesting;
+
+/**
+ * Wraps an existing {@link TokenSource} and adds exponential fallback retry support to it. The
+ * underlying {@link TokenSource} will be queried and all calls will be proxied except transient
+ * failures, which will cause a retry after an exponentially increasing delay.
+ */
+public class RetryingTokenSource extends Handler implements TokenSource, TokenSource.Callback {
+ private static final int MSG_QUERY_TOKEN = 1;
+ private static final long MIN_BACKOFF_DELAY_MS = 500;
+
+ /** The maximum number of times to attempt connection before failing. */
+ @VisibleForTesting
+ public static final int MAX_NUMBER_OF_RETRIES = 8;
+
+ private final TokenSource mTokenSource;
+
+ private TokenSource.Callback mCallback;
+ private long mAttemptNumber;
+
+ /**
+ * Creates a {@link RetryingTokenSource} that proxies most {@link TokenSource} communication to
+ * {@code tokenSource}.
+ * @param tokenSource A {@link TokenSource} that does the actual underlying token management.
+ */
+ public RetryingTokenSource(TokenSource tokenSource) {
+ mTokenSource = tokenSource;
+ mTokenSource.setCallback(this);
+ }
+
+ // TokenSource implementation.
+ @Override
+ public void destroy() {
+ mTokenSource.destroy();
+ removeMessages(MSG_QUERY_TOKEN);
+ }
+
+ @Override
+ public void setCallback(TokenSource.Callback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void getToken() {
+ // Reset all exponential backoff states.
nyquist 2015/09/29 23:38:40 Do we need any thread safety for the public method
David Trainor- moved to gerrit 2015/10/05 15:19:07 Done.
+ removeMessages(MSG_QUERY_TOKEN);
+ mAttemptNumber = 0;
+
+ // Start the TokenSource#getToken() exponential backoff calls.
+ getTokenWithBackoff();
+ }
+
+ @Override
+ public boolean isRetrievingToken() {
+ return mTokenSource.isRetrievingToken() || hasMessages(MSG_QUERY_TOKEN);
+ }
+
+ @Override
+ public int tokenIsInvalid(String token) {
+ return mTokenSource.tokenIsInvalid(token);
+ }
+
+ @Override
+ public void onAccountSelected(Intent data) {
+ mTokenSource.onAccountSelected(data);
+ }
+
+ // TokenSource.Callback implementation.
+ @Override
+ public void onTokenReceived(String token) {
+ mCallback.onTokenReceived(token);
+ }
+
+ @Override
+ public void onTokenUnavailable(boolean isTransient) {
+ if (isTransient && mAttemptNumber < MAX_NUMBER_OF_RETRIES) {
+ getTokenWithBackoff();
+ } else {
+ mCallback.onTokenUnavailable(false);
+ }
+ }
+
+ @Override
+ public void onNeedsAccountToBeSelected(Intent intent) {
+ mCallback.onNeedsAccountToBeSelected(intent);
+ }
+
+ // Handler overrides.
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what != MSG_QUERY_TOKEN) return;
+ mTokenSource.getToken();
+ }
+
+ /**
+ * @param delay The suggested time (in ms) to wait before attempting to query for the token
+ * again.
+ * @return The actual time (in ms) to wait before attempting to query for a token again.
+ */
+ @VisibleForTesting
+ protected long finalizeRetryDelay(long delay) {
+ return delay;
+ }
+
+ private void getTokenWithBackoff() {
nyquist 2015/09/29 23:38:40 Could we make this a bit randomized? See https://c
David Trainor- moved to gerrit 2015/10/05 15:19:07 Done.
+ long delayMs = 0;
+
+ // For the first attempt, don't delay.
+ if (mAttemptNumber > 0) {
+ delayMs = (long) Math.pow(2, (mAttemptNumber - 1)) * MIN_BACKOFF_DELAY_MS;
+ }
+
+ sendEmptyMessageDelayed(MSG_QUERY_TOKEN, finalizeRetryDelay(delayMs));
+ mAttemptNumber++;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698