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

Side by Side Diff: remoting/android/java/src/org/chromium/chromoting/Chromoting.java

Issue 1976853002: [Remoting Android] Refactor OAuth Token Fetching Code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 unified diff | Download patch
OLDNEW
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.annotation.SuppressLint; 7 import android.annotation.SuppressLint;
8 import android.app.ProgressDialog; 8 import android.app.ProgressDialog;
9 import android.content.DialogInterface; 9 import android.content.DialogInterface;
10 import android.content.Intent; 10 import android.content.Intent;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 public static final int CARDBOARD_DESKTOP_ACTIVITY = 1; 65 public static final int CARDBOARD_DESKTOP_ACTIVITY = 1;
66 66
67 /** Preference names for storing selected and recent accounts. */ 67 /** Preference names for storing selected and recent accounts. */
68 private static final String PREFERENCE_SELECTED_ACCOUNT = "account_name"; 68 private static final String PREFERENCE_SELECTED_ACCOUNT = "account_name";
69 private static final String PREFERENCE_RECENT_ACCOUNT_PREFIX = "recent_accou nt_"; 69 private static final String PREFERENCE_RECENT_ACCOUNT_PREFIX = "recent_accou nt_";
70 private static final String PREFERENCE_EXPERIMENTAL_FLAGS = "flags"; 70 private static final String PREFERENCE_EXPERIMENTAL_FLAGS = "flags";
71 71
72 /** User's account name (email). */ 72 /** User's account name (email). */
73 private String mAccount; 73 private String mAccount;
74 74
75 /** Account auth token. */
76 private String mToken;
77
78 /** Helper for fetching the host list. */ 75 /** Helper for fetching the host list. */
79 private HostListManager mHostListManager; 76 private HostListManager mHostListManager;
80 77
81 /** List of hosts. */ 78 /** List of hosts. */
82 private HostInfo[] mHosts = new HostInfo[0]; 79 private HostInfo[] mHosts = new HostInfo[0];
83 80
84 /** Refresh button. */ 81 /** Refresh button. */
85 private MenuItem mRefreshButton; 82 private MenuItem mRefreshButton;
86 83
87 /** Host list chooser view shown when at least one host is configured. */ 84 /** Host list chooser view shown when at least one host is configured. */
88 private ListView mHostListView; 85 private ListView mHostListView;
89 86
90 /** View shown when the user has no configured hosts or host list couldn't b e retrieved. */ 87 /** View shown when the user has no configured hosts or host list couldn't b e retrieved. */
91 private View mEmptyView; 88 private View mEmptyView;
92 89
93 /** Progress view shown instead of the host list when the host list is loadi ng. */ 90 /** Progress view shown instead of the host list when the host list is loadi ng. */
94 private View mProgressView; 91 private View mProgressView;
95 92
96 /** Dialog for reporting connection progress. */ 93 /** Dialog for reporting connection progress. */
97 private ProgressDialog mProgressIndicator; 94 private ProgressDialog mProgressIndicator;
98 95
99 /** 96 /**
100 * Helper used by SessionConnection for session authentication. Receives onN ewIntent() 97 * Helper used by SessionConnection for session authentication. Receives onN ewIntent()
101 * notifications to handle third-party authentication. 98 * notifications to handle third-party authentication.
102 */ 99 */
103 private SessionAuthenticator mAuthenticator; 100 private SessionAuthenticator mAuthenticator;
104 101
105 /** 102 private OAuthTokenConsumer mHostConnectingConsumer;
106 * This is set when receiving an authentication error from the HostListManag er. If that occurs,
107 * this flag is set and a fresh authentication token is fetched from the Acc ountsService, and
108 * used to request the host list a second time.
109 */
110 boolean mTriedNewAuthToken;
111 103
112 /** 104 private OAuthTokenConsumer mHostListRetrievingConsumer;
113 * Flag to track whether a call to AccountManager.getAuthToken() is currentl y pending. 105
114 * This avoids infinitely-nested calls in case onStart() gets triggered a se cond time 106 private OAuthTokenConsumer mHostDeletingConsumer;
115 * while a token is being fetched.
116 */
117 private boolean mWaitingForAuthToken = false;
118 107
119 private DrawerLayout mDrawerLayout; 108 private DrawerLayout mDrawerLayout;
120 109
121 private ActionBarDrawerToggle mDrawerToggle; 110 private ActionBarDrawerToggle mDrawerToggle;
122 111
123 private AccountSwitcher mAccountSwitcher; 112 private AccountSwitcher mAccountSwitcher;
124 113
125 /** The currently-connected Client, if any. */ 114 /** The currently-connected Client, if any. */
126 private Client mClient; 115 private Client mClient;
127 116
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 * authentication token from the system. 173 * authentication token from the system.
185 */ 174 */
186 @Override 175 @Override
187 public void onCreate(Bundle savedInstanceState) { 176 public void onCreate(Bundle savedInstanceState) {
188 super.onCreate(savedInstanceState); 177 super.onCreate(savedInstanceState);
189 setContentView(R.layout.main); 178 setContentView(R.layout.main);
190 179
191 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 180 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
192 setSupportActionBar(toolbar); 181 setSupportActionBar(toolbar);
193 182
194 mTriedNewAuthToken = false;
195 mHostListManager = new HostListManager(); 183 mHostListManager = new HostListManager();
196 184
197 // Get ahold of our view widgets. 185 // Get ahold of our view widgets.
198 mHostListView = (ListView) findViewById(R.id.hostList_chooser); 186 mHostListView = (ListView) findViewById(R.id.hostList_chooser);
199 mEmptyView = findViewById(R.id.hostList_empty); 187 mEmptyView = findViewById(R.id.hostList_empty);
200 mHostListView.setOnItemClickListener( 188 mHostListView.setOnItemClickListener(
201 new AdapterView.OnItemClickListener() { 189 new AdapterView.OnItemClickListener() {
202 @Override 190 @Override
203 public void onItemClick(AdapterView<?> parent, View view, in t position, 191 public void onItemClick(AdapterView<?> parent, View view, in t position,
204 long id) { 192 long id) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 261
274 mAccountSwitcher = AccountSwitcherFactory.getInstance().createAccountSwi tcher(this, this); 262 mAccountSwitcher = AccountSwitcherFactory.getInstance().createAccountSwi tcher(this, this);
275 mAccountSwitcher.setNavigation(navigationMenu); 263 mAccountSwitcher.setNavigation(navigationMenu);
276 LinearLayout navigationDrawer = (LinearLayout) findViewById(R.id.navigat ion_drawer); 264 LinearLayout navigationDrawer = (LinearLayout) findViewById(R.id.navigat ion_drawer);
277 mAccountSwitcher.setDrawer(navigationDrawer); 265 mAccountSwitcher.setDrawer(navigationDrawer);
278 View switcherView = mAccountSwitcher.getView(); 266 View switcherView = mAccountSwitcher.getView();
279 switcherView.setLayoutParams(new LinearLayout.LayoutParams( 267 switcherView.setLayoutParams(new LinearLayout.LayoutParams(
280 LinearLayout.LayoutParams.MATCH_PARENT, 268 LinearLayout.LayoutParams.MATCH_PARENT,
281 LinearLayout.LayoutParams.WRAP_CONTENT)); 269 LinearLayout.LayoutParams.WRAP_CONTENT));
282 navigationDrawer.addView(switcherView, 0); 270 navigationDrawer.addView(switcherView, 0);
271
272 mHostConnectingConsumer = new OAuthTokenConsumer(this, TOKEN_SCOPE);
273 mHostListRetrievingConsumer = new OAuthTokenConsumer(this, TOKEN_SCOPE);
274 mHostDeletingConsumer = new OAuthTokenConsumer(this, TOKEN_SCOPE);
283 } 275 }
284 276
285 @Override 277 @Override
286 protected void onPostCreate(Bundle savedInstanceState) { 278 protected void onPostCreate(Bundle savedInstanceState) {
287 super.onPostCreate(savedInstanceState); 279 super.onPostCreate(savedInstanceState);
288 mDrawerToggle.syncState(); 280 mDrawerToggle.syncState();
289 } 281 }
290 282
291 @Override 283 @Override
292 protected void onNewIntent(Intent intent) { 284 protected void onNewIntent(Intent intent) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 356
365 /** Called when a child Activity exits and sends a result back to this Activ ity. */ 357 /** Called when a child Activity exits and sends a result back to this Activ ity. */
366 @Override 358 @Override
367 public void onActivityResult(int requestCode, int resultCode, Intent data) { 359 public void onActivityResult(int requestCode, int resultCode, Intent data) {
368 mAccountSwitcher.onActivityResult(requestCode, resultCode, data); 360 mAccountSwitcher.onActivityResult(requestCode, resultCode, data);
369 361
370 if (requestCode == OAuthTokenFetcher.REQUEST_CODE_RECOVER_FROM_OAUTH_ERR OR) { 362 if (requestCode == OAuthTokenFetcher.REQUEST_CODE_RECOVER_FROM_OAUTH_ERR OR) {
371 if (resultCode == RESULT_OK) { 363 if (resultCode == RESULT_OK) {
372 // User gave OAuth permission to this app (or recovered from any OAuth failure), 364 // User gave OAuth permission to this app (or recovered from any OAuth failure),
373 // so retry fetching the token. 365 // so retry fetching the token.
374 requestAuthToken(false); 366 refreshHostList();
375 } else { 367 } else {
376 // User denied permission or cancelled the dialog, so cancel the request. 368 // User denied permission or cancelled the dialog, so cancel the request.
377 mWaitingForAuthToken = false;
378 updateHostListView(); 369 updateHostListView();
379 } 370 }
380 } 371 }
381 } 372 }
382 373
383 /** Called when a permissions request has returned. */ 374 /** Called when a permissions request has returned. */
384 @Override 375 @Override
385 public void onRequestPermissionsResult(int requestCode, String[] permissions , 376 public void onRequestPermissionsResult(int requestCode, String[] permissions ,
386 int[] grantResults) { 377 int[] grantResults) {
387 // This is currently only used by AccountSwitcherBasic. 378 // This is currently only used by AccountSwitcherBasic.
388 // Check that the user has granted the needed permission, and reload the accounts. 379 // Check that the user has granted the needed permission, and reload the accounts.
389 // Otherwise, assume something unexpected occurred, or the user cancelle d the request. 380 // Otherwise, assume something unexpected occurred, or the user cancelle d the request.
390 if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMIS SION_GRANTED) { 381 if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMIS SION_GRANTED) {
391 mAccountSwitcher.reloadAccounts(); 382 mAccountSwitcher.reloadAccounts();
392 } else if (permissions.length == 0) { 383 } else if (permissions.length == 0) {
393 Log.e(TAG, "User cancelled the permission request."); 384 Log.e(TAG, "User cancelled the permission request.");
394 } else { 385 } else {
395 Log.e(TAG, "Permission %s was not granted.", permissions[0]); 386 Log.e(TAG, "Permission %s was not granted.", permissions[0]);
396 } 387 }
397 } 388 }
398 389
399 /** Called when the display is rotated (as registered in the manifest). */ 390 /** Called when the display is rotated (as registered in the manifest). */
400 @Override 391 @Override
401 public void onConfigurationChanged(Configuration newConfig) { 392 public void onConfigurationChanged(Configuration newConfig) {
402 super.onConfigurationChanged(newConfig); 393 super.onConfigurationChanged(newConfig);
403 394
404 mDrawerToggle.onConfigurationChanged(newConfig); 395 mDrawerToggle.onConfigurationChanged(newConfig);
405 } 396 }
406 397
407 /** Called to initialize the action bar. */ 398 /** Called to initialize the action bar. */
Yuwei 2016/05/13 00:30:17 Not sure how the tab comes but I'll remove it...
Yuwei 2016/05/13 17:20:28 Done.
408 @Override 399 @Override
409 public boolean onCreateOptionsMenu(Menu menu) { 400 public boolean onCreateOptionsMenu(Menu menu) {
410 getMenuInflater().inflate(R.menu.chromoting_actionbar, menu); 401 getMenuInflater().inflate(R.menu.chromoting_actionbar, menu);
411 mRefreshButton = menu.findItem(R.id.actionbar_directoryrefresh); 402 mRefreshButton = menu.findItem(R.id.actionbar_directoryrefresh);
412 403
413 if (mAccount == null) { 404 if (mAccount == null) {
414 // If there is no account, don't allow the user to refresh the listi ng. 405 // If there is no account, don't allow the user to refresh the listi ng.
415 mRefreshButton.setEnabled(false); 406 mRefreshButton.setEnabled(false);
416 } 407 }
417 408
(...skipping 27 matching lines...) Expand all
445 private void onHostClicked(int index) { 436 private void onHostClicked(int index) {
446 HostInfo host = mHosts[index]; 437 HostInfo host = mHosts[index];
447 if (host.isOnline) { 438 if (host.isOnline) {
448 connectToHost(host); 439 connectToHost(host);
449 } else { 440 } else {
450 String tooltip = host.getHostOfflineReasonText(this); 441 String tooltip = host.getHostOfflineReasonText(this);
451 Toast.makeText(this, tooltip, Toast.LENGTH_SHORT).show(); 442 Toast.makeText(this, tooltip, Toast.LENGTH_SHORT).show();
452 } 443 }
453 } 444 }
454 445
455 private void connectToHost(HostInfo host) { 446 private void connectToHost(final HostInfo host) {
456 if (mClient != null) { 447 if (mClient != null) {
457 mClient.destroy(); 448 mClient.destroy();
458 } 449 }
459 450
460 mClient = new Client(); 451 mClient = new Client();
461 mProgressIndicator = ProgressDialog.show( 452 mProgressIndicator = ProgressDialog.show(
462 this, 453 this,
463 host.name, 454 host.name,
464 getString(R.string.footer_connecting), 455 getString(R.string.footer_connecting),
465 true, 456 true,
466 true, 457 true,
467 new DialogInterface.OnCancelListener() { 458 new DialogInterface.OnCancelListener() {
468 @Override 459 @Override
469 public void onCancel(DialogInterface dialog) { 460 public void onCancel(DialogInterface dialog) {
470 if (mClient != null) { 461 if (mClient != null) {
471 mClient.destroy(); 462 mClient.destroy();
472 mClient = null; 463 mClient = null;
473 } 464 }
474 } 465 }
475 }); 466 });
476 467
477 SessionConnector connector = new SessionConnector(mClient, this, this, m HostListManager); 468 final SessionConnector connector =
469 new SessionConnector(mClient, this, this, mHostListManager);
478 mAuthenticator = new SessionAuthenticator(this, mClient, host); 470 mAuthenticator = new SessionAuthenticator(this, mClient, host);
479 connector.connectToHost(mAccount, mToken, host, mAuthenticator, 471 mHostConnectingConsumer.consume(mAccount, new OAuthTokenFetcher.Callback () {
480 getPreferences(MODE_PRIVATE).getString(PREFERENCE_EXPERIMENTAL_F LAGS, "")); 472 @Override
473 public void onTokenFetched(String token) {
474 connector.connectToHost(mAccount, token, host, mAuthenticator,
475 getPreferences(MODE_PRIVATE).getString(PREFERENCE_EXPERI MENTAL_FLAGS, ""));
476 }
477
478 @Override
479 public void onError(OAuthTokenFetcher.Error error) {
480 showAuthErrorMessage(error);
481 }
482 });
483 }
484
485 private void showAuthErrorMessage(OAuthTokenFetcher.Error error) {
486 String explanation = getString(error == OAuthTokenFetcher.Error.NETWORK
487 ? R.string.error_network_error : R.string.error_unexpected);
488 Toast.makeText(Chromoting.this, explanation, Toast.LENGTH_LONG).show();
481 } 489 }
482 490
483 private void refreshHostList() { 491 private void refreshHostList() {
484 if (mWaitingForAuthToken) {
485 return;
486 }
487
488 mTriedNewAuthToken = false;
489 showHostListLoadingIndicator(); 492 showHostListLoadingIndicator();
490 493
491 // The refresh button simply makes use of the currently-chosen account. 494 // The refresh button simply makes use of the currently-chosen account.
492 requestAuthToken(false); 495 mHostListRetrievingConsumer.consume(mAccount, new OAuthTokenFetcher.Call back() {
496 @Override
497 public void onTokenFetched(String token) {
498 mHostListManager.retrieveHostList(token, Chromoting.this);
499 }
500
501 @Override
502 public void onError(OAuthTokenFetcher.Error error) {
503 showAuthErrorMessage(error);
504 updateHostListView();
505 }
506 });
493 } 507 }
494 508
495 private void requestAuthToken(boolean expireCurrentToken) { 509 private void deleteHost(final String hostId) {
496 mWaitingForAuthToken = true; 510 showHostListLoadingIndicator();
497 511
498 OAuthTokenFetcher fetcher = new OAuthTokenFetcher(this, mAccount, TOKEN_ SCOPE, 512 mHostDeletingConsumer.consume(mAccount, new OAuthTokenFetcher.Callback() {
499 new OAuthTokenFetcher.Callback() { 513 @Override
500 @Override 514 public void onTokenFetched(String token) {
501 public void onTokenFetched(String token) { 515 mHostListManager.deleteHost(token, hostId, Chromoting.this);
502 mWaitingForAuthToken = false; 516 }
503 mToken = token;
504 mHostListManager.retrieveHostList(mToken, Chromoting.thi s);
505 }
506 517
507 @Override 518 @Override
508 public void onError(OAuthTokenFetcher.Error error) { 519 public void onError(OAuthTokenFetcher.Error error) {
509 mWaitingForAuthToken = false; 520 showAuthErrorMessage(error);
Yuwei 2016/05/13 00:30:17 Looks like I also need to do updateHostListView he
Lambros 2016/05/13 01:11:31 I think so, to hide the host-list-loading progress
Yuwei 2016/05/13 17:20:29 Done.
510 updateHostListView(); 521 }
511 String explanation = getString(error == OAuthTokenFetche r.Error.NETWORK 522 });
512 ? R.string.error_network_error : R.string.error_ unexpected);
513 Toast.makeText(Chromoting.this, explanation, Toast.LENGT H_LONG).show();
514 }
515 });
516
517 if (expireCurrentToken) {
518 fetcher.clearAndFetch(mToken);
519 mToken = null;
520 } else {
521 fetcher.fetch();
522 }
523 } 523 }
524 524
525 @Override 525 @Override
526 public void onAccountSelected(String accountName) { 526 public void onAccountSelected(String accountName) {
527 mAccount = accountName; 527 mAccount = accountName;
528 528
529 // The current host list is no longer valid for the new account, so clea r the list. 529 // The current host list is no longer valid for the new account, so clea r the list.
530 mHosts = new HostInfo[0]; 530 mHosts = new HostInfo[0];
531 updateUi(); 531 updateUi();
532 refreshHostList(); 532 refreshHostList();
(...skipping 18 matching lines...) Expand all
551 updateUi(); 551 updateUi();
552 } 552 }
553 553
554 @Override 554 @Override
555 public void onHostUpdated() { 555 public void onHostUpdated() {
556 // Not implemented Yet. 556 // Not implemented Yet.
557 } 557 }
558 558
559 @Override 559 @Override
560 public void onHostDeleted() { 560 public void onHostDeleted() {
561 // Not implemented Yet. 561 // Refresh the host list. there is no need to refetch the auth token aga in.
562 mHostListManager.retrieveHostList(mHostDeletingConsumer.getLastToken(), this);
562 } 563 }
563 564
564 @Override 565 @Override
565 public void onError(HostListManager.Error error) { 566 public void onError(HostListManager.Error error) {
566 String explanation = null; 567 String explanation = null;
567 switch (error) { 568 switch (error) {
568 case AUTH_FAILED: 569 case AUTH_FAILED:
569 break; 570 break;
570 case NETWORK_ERROR: 571 case NETWORK_ERROR:
571 explanation = getString(R.string.error_network_error); 572 explanation = getString(R.string.error_network_error);
572 break; 573 break;
573 case UNEXPECTED_RESPONSE: 574 case UNEXPECTED_RESPONSE:
574 case SERVICE_UNAVAILABLE: 575 case SERVICE_UNAVAILABLE:
575 case UNKNOWN: 576 case UNKNOWN:
576 explanation = getString(R.string.error_unexpected); 577 explanation = getString(R.string.error_unexpected);
577 break; 578 break;
578 default: 579 default:
579 // Unreachable. 580 // Unreachable.
580 return; 581 return;
581 } 582 }
582 583
583 if (explanation != null) { 584 if (explanation != null) {
584 Toast.makeText(this, explanation, Toast.LENGTH_LONG).show(); 585 Toast.makeText(this, explanation, Toast.LENGTH_LONG).show();
585 updateHostListView(); 586 updateHostListView();
586 return; 587 return;
587 } 588 }
588 589
589 // This is the AUTH_FAILED case. 590 Log.e(TAG, "Fresh auth token was rejected.");
590 591 explanation = getString(R.string.error_authentication_failed);
591 if (!mTriedNewAuthToken) { 592 Toast.makeText(this, explanation, Toast.LENGTH_LONG).show();
592 // This was our first connection attempt. 593 updateHostListView();
593 mTriedNewAuthToken = true;
594 requestAuthToken(true);
595
596 // We're not in an error state *yet*.
597 return;
598 } else {
599 // Authentication truly failed.
600 Log.e(TAG, "Fresh auth token was rejected.");
601 explanation = getString(R.string.error_authentication_failed);
602 Toast.makeText(this, explanation, Toast.LENGTH_LONG).show();
603 updateHostListView();
604 }
605 } 594 }
606 595
607 /** 596 /**
608 * Updates the infotext and host list display. 597 * Updates the infotext and host list display.
609 */ 598 */
610 private void updateUi() { 599 private void updateUi() {
611 if (mRefreshButton != null) { 600 if (mRefreshButton != null) {
612 mRefreshButton.setEnabled(mAccount != null); 601 mRefreshButton.setEnabled(mAccount != null);
613 } 602 }
614 ArrayAdapter<HostInfo> displayer = new HostListAdapter(this, mHosts); 603 ArrayAdapter<HostInfo> displayer = new HostListAdapter(this, mHosts);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 // Unreachable, but required by Google Java style and findbugs. 639 // Unreachable, but required by Google Java style and findbugs.
651 assert false : "Unreached"; 640 assert false : "Unreached";
652 } 641 }
653 642
654 if (dismissProgress && mProgressIndicator != null) { 643 if (dismissProgress && mProgressIndicator != null) {
655 mProgressIndicator.dismiss(); 644 mProgressIndicator.dismiss();
656 mProgressIndicator = null; 645 mProgressIndicator = null;
657 } 646 }
658 } 647 }
659 } 648 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698