OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chromoting; | 5 package org.chromium.chromoting; |
6 | 6 |
7 import android.accounts.Account; | 7 import android.accounts.Account; |
8 import android.accounts.AccountManager; | 8 import android.accounts.AccountManager; |
9 import android.accounts.AccountManagerCallback; | 9 import android.accounts.AccountManagerCallback; |
10 import android.accounts.AccountManagerFuture; | 10 import android.accounts.AccountManagerFuture; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 /** Object for fetching OAuth2 access tokens from third party authorization servers. */ | 89 /** Object for fetching OAuth2 access tokens from third party authorization servers. */ |
90 private ThirdPartyTokenFetcher mTokenFetcher; | 90 private ThirdPartyTokenFetcher mTokenFetcher; |
91 | 91 |
92 /** | 92 /** |
93 * This is set when receiving an authentication error from the HostListLoade r. If that occurs, | 93 * This is set when receiving an authentication error from the HostListLoade r. If that occurs, |
94 * this flag is set and a fresh authentication token is fetched from the Acc ountsService, and | 94 * this flag is set and a fresh authentication token is fetched from the Acc ountsService, and |
95 * used to request the host list a second time. | 95 * used to request the host list a second time. |
96 */ | 96 */ |
97 boolean mTriedNewAuthToken; | 97 boolean mTriedNewAuthToken; |
98 | 98 |
99 /** | |
100 * Flag to track whether a call to AccountManager.getAuthToken() is currentl y pending. | |
101 * This avoids infinitely-nested calls in case onStart() gets triggered a se cond time | |
102 * while a token is being fetched. | |
103 */ | |
104 private boolean mWaitingForAuthToken = false; | |
105 | |
99 /** Shows a warning explaining that a Google account is required, then close s the activity. */ | 106 /** Shows a warning explaining that a Google account is required, then close s the activity. */ |
100 private void showNoAccountsDialog() { | 107 private void showNoAccountsDialog() { |
101 AlertDialog.Builder builder = new AlertDialog.Builder(this); | 108 AlertDialog.Builder builder = new AlertDialog.Builder(this); |
102 builder.setMessage(R.string.noaccounts_message); | 109 builder.setMessage(R.string.noaccounts_message); |
103 builder.setPositiveButton(R.string.noaccounts_add_account, | 110 builder.setPositiveButton(R.string.noaccounts_add_account, |
104 new DialogInterface.OnClickListener() { | 111 new DialogInterface.OnClickListener() { |
105 @SuppressLint("InlinedApi") | 112 @SuppressLint("InlinedApi") |
106 @Override | 113 @Override |
107 public void onClick(DialogInterface dialog, int id) { | 114 public void onClick(DialogInterface dialog, int id) { |
108 Intent intent = new Intent(Settings.ACTION_ADD_ACCOUNT); | 115 Intent intent = new Intent(Settings.ACTION_ADD_ACCOUNT); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 mTokenFetcher = null; | 292 mTokenFetcher = null; |
286 } | 293 } |
287 }); | 294 }); |
288 SessionConnector connector = new SessionConnector(this, this, mHostListL oader); | 295 SessionConnector connector = new SessionConnector(this, this, mHostListL oader); |
289 assert mTokenFetcher == null; | 296 assert mTokenFetcher == null; |
290 mTokenFetcher = createTokenFetcher(host); | 297 mTokenFetcher = createTokenFetcher(host); |
291 connector.connectToHost(mAccount.name, mToken, host); | 298 connector.connectToHost(mAccount.name, mToken, host); |
292 } | 299 } |
293 | 300 |
294 private void refreshHostList() { | 301 private void refreshHostList() { |
302 if (mWaitingForAuthToken) { | |
303 return; | |
304 } | |
305 | |
295 mTriedNewAuthToken = false; | 306 mTriedNewAuthToken = false; |
296 setHostListProgressVisible(true); | 307 setHostListProgressVisible(true); |
297 | 308 |
298 // The refresh button simply makes use of the currently-chosen account. | 309 // The refresh button simply makes use of the currently-chosen account. |
310 requestAuthToken(); | |
311 } | |
312 | |
313 private void requestAuthToken() { | |
299 AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, this, this, null); | 314 AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, this, this, null); |
315 mWaitingForAuthToken = true; | |
300 } | 316 } |
301 | 317 |
302 @Override | 318 @Override |
303 public void run(AccountManagerFuture<Bundle> future) { | 319 public void run(AccountManagerFuture<Bundle> future) { |
304 Log.i("auth", "User finished with auth dialogs"); | 320 Log.i("auth", "User finished with auth dialogs"); |
321 mWaitingForAuthToken = false; | |
322 | |
305 Bundle result = null; | 323 Bundle result = null; |
306 String explanation = null; | 324 String explanation = null; |
307 try { | 325 try { |
308 // Here comes our auth token from the Android system. | 326 // Here comes our auth token from the Android system. |
309 result = future.getResult(); | 327 result = future.getResult(); |
310 } catch (OperationCanceledException ex) { | 328 } catch (OperationCanceledException ex) { |
311 // User canceled authentication. No need to report an error. | 329 // User canceled authentication. No need to report an error. |
312 } catch (AuthenticatorException ex) { | 330 } catch (AuthenticatorException ex) { |
313 explanation = getString(R.string.error_unexpected); | 331 explanation = getString(R.string.error_unexpected); |
314 } catch (IOException ex) { | 332 } catch (IOException ex) { |
315 explanation = getString(R.string.error_network_error); | 333 explanation = getString(R.string.error_network_error); |
316 } | 334 } |
317 | 335 |
318 if (result == null) { | 336 if (result == null) { |
337 setHostListProgressVisible(false); | |
319 if (explanation != null) { | 338 if (explanation != null) { |
320 Toast.makeText(this, explanation, Toast.LENGTH_LONG).show(); | 339 Toast.makeText(this, explanation, Toast.LENGTH_LONG).show(); |
321 } | 340 } |
322 return; | 341 return; |
323 } | 342 } |
324 | 343 |
325 mToken = result.getString(AccountManager.KEY_AUTHTOKEN); | 344 mToken = result.getString(AccountManager.KEY_AUTHTOKEN); |
326 Log.i("auth", "Received an auth token from system"); | 345 Log.i("auth", "Received an auth token from system"); |
327 | 346 |
328 mHostListLoader.retrieveHostList(mToken, this); | 347 mHostListLoader.retrieveHostList(mToken, this); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
380 | 399 |
381 if (!mTriedNewAuthToken) { | 400 if (!mTriedNewAuthToken) { |
382 // This was our first connection attempt. | 401 // This was our first connection attempt. |
383 | 402 |
384 AccountManager authenticator = AccountManager.get(this); | 403 AccountManager authenticator = AccountManager.get(this); |
385 mTriedNewAuthToken = true; | 404 mTriedNewAuthToken = true; |
386 | 405 |
387 Log.w("auth", "Requesting renewal of rejected auth token"); | 406 Log.w("auth", "Requesting renewal of rejected auth token"); |
388 authenticator.invalidateAuthToken(mAccount.type, mToken); | 407 authenticator.invalidateAuthToken(mAccount.type, mToken); |
389 mToken = null; | 408 mToken = null; |
390 authenticator.getAuthToken(mAccount, TOKEN_SCOPE, null, this, this, null); | 409 requestAuthToken(); |
Jamie
2014/09/26 21:31:17
Does this not also need to be guarded against reen
Lambros
2014/09/26 22:36:34
No, because we've got the token at this point, so
| |
391 | 410 |
392 // We're not in an error state *yet*. | 411 // We're not in an error state *yet*. |
393 return; | 412 return; |
394 } else { | 413 } else { |
395 // Authentication truly failed. | 414 // Authentication truly failed. |
396 Log.e("auth", "Fresh auth token was also rejected"); | 415 Log.e("auth", "Fresh auth token was also rejected"); |
397 explanation = getString(R.string.error_authentication_failed); | 416 explanation = getString(R.string.error_authentication_failed); |
398 Toast.makeText(this, explanation, Toast.LENGTH_LONG).show(); | 417 Toast.makeText(this, explanation, Toast.LENGTH_LONG).show(); |
399 setHostListProgressVisible(false); | 418 setHostListProgressVisible(false); |
400 } | 419 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 } | 491 } |
473 }; | 492 }; |
474 return new ThirdPartyTokenFetcher(this, host.getTokenUrlPatterns(), call back); | 493 return new ThirdPartyTokenFetcher(this, host.getTokenUrlPatterns(), call back); |
475 } | 494 } |
476 | 495 |
477 public void fetchThirdPartyToken(String tokenUrl, String clientId, String sc ope) { | 496 public void fetchThirdPartyToken(String tokenUrl, String clientId, String sc ope) { |
478 assert mTokenFetcher != null; | 497 assert mTokenFetcher != null; |
479 mTokenFetcher.fetchToken(tokenUrl, clientId, scope); | 498 mTokenFetcher.fetchToken(tokenUrl, clientId, scope); |
480 } | 499 } |
481 } | 500 } |
OLD | NEW |