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

Side by Side Diff: blimp/client/app/android/java/src/org/chromium/blimp/auth/RetryingTokenSource.java

Issue 2493333002: Move Java Blimp shell code to app subpackage (Closed)
Patch Set: Merge branch 'refs/heads/master' into blimp-shell-integration Created 4 years, 1 month 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.blimp.auth;
6
7 import android.content.Intent;
8 import android.os.Handler;
9 import android.os.Message;
10
11 import org.chromium.base.ThreadUtils;
12 import org.chromium.base.VisibleForTesting;
13
14 import java.util.Random;
15
16 /**
17 * Wraps an existing {@link TokenSource} and adds exponential fallback retry sup port to it. The
18 * underlying {@link TokenSource} will be queried and all calls will be proxied except transient
19 * failures, which will cause a retry after a random exponentially increasing de lay.
20 *
21 * Because callbacks to {@link TokenSource#Callback#onTokenUnavailable(boolean)} with
22 * {@code isTransient} set to {@code true} will be captured here, this {@link To kenSource} currently
23 * won't expose any transient errors to the caller.
24 */
25 public class RetryingTokenSource extends Handler implements TokenSource, TokenSo urce.Callback {
26 private static final int MSG_QUERY_TOKEN = 1;
27 private static final int BASE_BACKOFF_DELAY_MS = 500;
28 private static final int MAX_EXPONENT = 10;
29
30 private static final Random sRandom = new Random();
31
32 /** The maximum number of times to attempt connection before failing. */
33 @VisibleForTesting
34 public static final int MAX_NUMBER_OF_RETRIES = 8;
35
36 private final TokenSource mTokenSource;
37
38 private TokenSource.Callback mCallback;
39 private int mAttemptNumber;
40
41 /**
42 * Creates a {@link RetryingTokenSource} that proxies most {@link TokenSourc e} communication to
43 * {@code tokenSource}.
44 * @param tokenSource A {@link TokenSource} that does the actual underlying token management.
45 */
46 public RetryingTokenSource(TokenSource tokenSource) {
47 mTokenSource = tokenSource;
48 mTokenSource.setCallback(this);
49 }
50
51 // TokenSource implementation.
52 @Override
53 public void destroy() {
54 ThreadUtils.assertOnUiThread();
55
56 mTokenSource.destroy();
57 removeMessages(MSG_QUERY_TOKEN);
58 }
59
60 @Override
61 public void setCallback(TokenSource.Callback callback) {
62 ThreadUtils.assertOnUiThread();
63
64 mCallback = callback;
65 }
66
67 @Override
68 public void getToken() {
69 ThreadUtils.assertOnUiThread();
70
71 // Reset all exponential backoff states.
72 removeMessages(MSG_QUERY_TOKEN);
73 mAttemptNumber = 0;
74
75 // Start the TokenSource#getToken() exponential backoff calls.
76 getTokenWithBackoff();
77 }
78
79 @Override
80 public boolean isRetrievingToken() {
81 ThreadUtils.assertOnUiThread();
82
83 return mTokenSource.isRetrievingToken() || hasMessages(MSG_QUERY_TOKEN);
84 }
85
86 @Override
87 public int tokenIsInvalid(String token) {
88 ThreadUtils.assertOnUiThread();
89
90 return mTokenSource.tokenIsInvalid(token);
91 }
92
93 @Override
94 public void onAccountSelected(Intent data) {
95 ThreadUtils.assertOnUiThread();
96
97 mTokenSource.onAccountSelected(data);
98 }
99
100 // TokenSource.Callback implementation.
101 @Override
102 public void onTokenReceived(String token) {
103 mCallback.onTokenReceived(token);
104 }
105
106 @Override
107 public void onTokenUnavailable(boolean isTransient) {
108 if (isTransient && mAttemptNumber < MAX_NUMBER_OF_RETRIES) {
109 getTokenWithBackoff();
110 } else {
111 mCallback.onTokenUnavailable(false);
112 }
113 }
114
115 @Override
116 public void onNeedsAccountToBeSelected(Intent intent) {
117 mCallback.onNeedsAccountToBeSelected(intent);
118 }
119
120 // Handler overrides.
121 @Override
122 public void handleMessage(Message msg) {
123 if (msg.what != MSG_QUERY_TOKEN) return;
124 mTokenSource.getToken();
125 }
126
127 /**
128 * @param delay The suggested time (in ms) to wait before attempting to quer y for the token
129 * again.
130 * @return The actual time (in ms) to wait before attempting to query f or a token again.
131 */
132 @VisibleForTesting
133 protected int finalizeRetryDelay(int delay) {
134 return delay;
135 }
136
137 private void getTokenWithBackoff() {
138 int delayMs = 0;
139
140 // For the first attempt, don't delay.
141 if (mAttemptNumber > 0) {
142 // Find a random value between the previous and current max delay va lues.
143 int prevMaxDelay = getMaxDelay(mAttemptNumber - 1);
144 int currMaxDelay = getMaxDelay(mAttemptNumber);
145
146 assert currMaxDelay > prevMaxDelay;
147 int delayWindow = currMaxDelay - prevMaxDelay;
148
149 delayMs = sRandom.nextInt(delayWindow) + prevMaxDelay;
150 }
151
152 sendEmptyMessageDelayed(MSG_QUERY_TOKEN, finalizeRetryDelay(delayMs));
153 mAttemptNumber++;
154 }
155
156 /**
157 * Helper method for calculating the max delay for any given attempt.
158 * @param attempt The current attempt at calling {@link TokenSource#getToken ()} on the internal
159 * {@link TokenSource}
160 * @return The maximum possible delay (in ms) to use for this attempt .
161 */
162 private static int getMaxDelay(int attempt) {
163 // For the first attempt, use no delay.
164 if (attempt == 0) return 0;
165
166 // Figure out the delay multiplier 2^(retry attempt number).
167 int multiplier = 1 << Math.min(MAX_EXPONENT, attempt - 1);
168 return multiplier * BASE_BACKOFF_DELAY_MS;
169 }
170 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698