Chromium Code Reviews| 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 |