| 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.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 30 matching lines...) Expand all Loading... |
| 41 import org.chromium.chromoting.jni.ConnectionListener; | 41 import org.chromium.chromoting.jni.ConnectionListener; |
| 42 | 42 |
| 43 import java.util.ArrayList; | 43 import java.util.ArrayList; |
| 44 import java.util.Arrays; | 44 import java.util.Arrays; |
| 45 | 45 |
| 46 /** | 46 /** |
| 47 * The user interface for querying and displaying a user's host list from the di
rectory server. It | 47 * The user interface for querying and displaying a user's host list from the di
rectory server. It |
| 48 * also requests and renews authentication tokens using the system account manag
er. | 48 * also requests and renews authentication tokens using the system account manag
er. |
| 49 */ | 49 */ |
| 50 public class Chromoting extends AppCompatActivity implements ConnectionListener, | 50 public class Chromoting extends AppCompatActivity implements ConnectionListener, |
| 51 AccountSwitcher.Callback, HostListLoader.Callback, View.OnClickListener
{ | 51 AccountSwitcher.Callback, HostListManager.Callback, View.OnClickListener
{ |
| 52 private static final String TAG = "Chromoting"; | 52 private static final String TAG = "Chromoting"; |
| 53 | 53 |
| 54 /** Only accounts of this type will be selectable for authentication. */ | 54 /** Only accounts of this type will be selectable for authentication. */ |
| 55 private static final String ACCOUNT_TYPE = "com.google"; | 55 private static final String ACCOUNT_TYPE = "com.google"; |
| 56 | 56 |
| 57 /** Scope to use when fetching the OAuth token. */ | 57 /** Scope to use when fetching the OAuth token. */ |
| 58 private static final String TOKEN_SCOPE = "oauth2:https://www.googleapis.com
/auth/chromoting " | 58 private static final String TOKEN_SCOPE = "oauth2:https://www.googleapis.com
/auth/chromoting " |
| 59 + "https://www.googleapis.com/auth/googletalk"; | 59 + "https://www.googleapis.com/auth/googletalk"; |
| 60 | 60 |
| 61 /** Result code used for starting {@link DesktopActivity}. */ | 61 /** Result code used for starting {@link DesktopActivity}. */ |
| 62 public static final int DESKTOP_ACTIVITY = 0; | 62 public static final int DESKTOP_ACTIVITY = 0; |
| 63 | 63 |
| 64 /** Result code used for starting {@link CardboardDesktopActivity}. */ | 64 /** Result code used for starting {@link CardboardDesktopActivity}. */ |
| 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. */ | 75 /** Account auth token. */ |
| 76 private String mToken; | 76 private String mToken; |
| 77 | 77 |
| 78 /** Helper for fetching the host list. */ | 78 /** Helper for fetching the host list. */ |
| 79 private HostListLoader mHostListLoader; | 79 private HostListManager mHostListManager; |
| 80 | 80 |
| 81 /** List of hosts. */ | 81 /** List of hosts. */ |
| 82 private HostInfo[] mHosts = new HostInfo[0]; | 82 private HostInfo[] mHosts = new HostInfo[0]; |
| 83 | 83 |
| 84 /** Refresh button. */ | 84 /** Refresh button. */ |
| 85 private MenuItem mRefreshButton; | 85 private MenuItem mRefreshButton; |
| 86 | 86 |
| 87 /** Host list chooser view shown when at least one host is configured. */ | 87 /** Host list chooser view shown when at least one host is configured. */ |
| 88 private ListView mHostListView; | 88 private ListView mHostListView; |
| 89 | 89 |
| 90 /** View shown when the user has no configured hosts or host list couldn't b
e retrieved. */ | 90 /** View shown when the user has no configured hosts or host list couldn't b
e retrieved. */ |
| 91 private View mEmptyView; | 91 private View mEmptyView; |
| 92 | 92 |
| 93 /** Progress view shown instead of the host list when the host list is loadi
ng. */ | 93 /** Progress view shown instead of the host list when the host list is loadi
ng. */ |
| 94 private View mProgressView; | 94 private View mProgressView; |
| 95 | 95 |
| 96 /** Dialog for reporting connection progress. */ | 96 /** Dialog for reporting connection progress. */ |
| 97 private ProgressDialog mProgressIndicator; | 97 private ProgressDialog mProgressIndicator; |
| 98 | 98 |
| 99 /** | 99 /** |
| 100 * Helper used by SessionConnection for session authentication. Receives onN
ewIntent() | 100 * Helper used by SessionConnection for session authentication. Receives onN
ewIntent() |
| 101 * notifications to handle third-party authentication. | 101 * notifications to handle third-party authentication. |
| 102 */ | 102 */ |
| 103 private SessionAuthenticator mAuthenticator; | 103 private SessionAuthenticator mAuthenticator; |
| 104 | 104 |
| 105 /** | 105 /** |
| 106 * This is set when receiving an authentication error from the HostListLoade
r. If that occurs, | 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 | 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. | 108 * used to request the host list a second time. |
| 109 */ | 109 */ |
| 110 boolean mTriedNewAuthToken; | 110 boolean mTriedNewAuthToken; |
| 111 | 111 |
| 112 /** | 112 /** |
| 113 * Flag to track whether a call to AccountManager.getAuthToken() is currentl
y pending. | 113 * Flag to track whether a call to AccountManager.getAuthToken() is currentl
y pending. |
| 114 * This avoids infinitely-nested calls in case onStart() gets triggered a se
cond time | 114 * This avoids infinitely-nested calls in case onStart() gets triggered a se
cond time |
| 115 * while a token is being fetched. | 115 * while a token is being fetched. |
| 116 */ | 116 */ |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 */ | 185 */ |
| 186 @Override | 186 @Override |
| 187 public void onCreate(Bundle savedInstanceState) { | 187 public void onCreate(Bundle savedInstanceState) { |
| 188 super.onCreate(savedInstanceState); | 188 super.onCreate(savedInstanceState); |
| 189 setContentView(R.layout.main); | 189 setContentView(R.layout.main); |
| 190 | 190 |
| 191 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); | 191 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); |
| 192 setSupportActionBar(toolbar); | 192 setSupportActionBar(toolbar); |
| 193 | 193 |
| 194 mTriedNewAuthToken = false; | 194 mTriedNewAuthToken = false; |
| 195 mHostListLoader = new HostListLoader(); | 195 mHostListManager = new HostListManager(); |
| 196 | 196 |
| 197 // Get ahold of our view widgets. | 197 // Get ahold of our view widgets. |
| 198 mHostListView = (ListView) findViewById(R.id.hostList_chooser); | 198 mHostListView = (ListView) findViewById(R.id.hostList_chooser); |
| 199 mEmptyView = findViewById(R.id.hostList_empty); | 199 mEmptyView = findViewById(R.id.hostList_empty); |
| 200 mHostListView.setOnItemClickListener( | 200 mHostListView.setOnItemClickListener( |
| 201 new AdapterView.OnItemClickListener() { | 201 new AdapterView.OnItemClickListener() { |
| 202 @Override | 202 @Override |
| 203 public void onItemClick(AdapterView<?> parent, View view, in
t position, | 203 public void onItemClick(AdapterView<?> parent, View view, in
t position, |
| 204 long id) { | 204 long id) { |
| 205 onHostClicked(position); | 205 onHostClicked(position); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 new DialogInterface.OnCancelListener() { | 467 new DialogInterface.OnCancelListener() { |
| 468 @Override | 468 @Override |
| 469 public void onCancel(DialogInterface dialog) { | 469 public void onCancel(DialogInterface dialog) { |
| 470 if (mClient != null) { | 470 if (mClient != null) { |
| 471 mClient.destroy(); | 471 mClient.destroy(); |
| 472 mClient = null; | 472 mClient = null; |
| 473 } | 473 } |
| 474 } | 474 } |
| 475 }); | 475 }); |
| 476 | 476 |
| 477 SessionConnector connector = new SessionConnector(mClient, this, this, m
HostListLoader); | 477 SessionConnector connector = new SessionConnector(mClient, this, this, m
HostListManager); |
| 478 mAuthenticator = new SessionAuthenticator(this, mClient, host); | 478 mAuthenticator = new SessionAuthenticator(this, mClient, host); |
| 479 connector.connectToHost(mAccount, mToken, host, mAuthenticator, | 479 connector.connectToHost(mAccount, mToken, host, mAuthenticator, |
| 480 getPreferences(MODE_PRIVATE).getString(PREFERENCE_EXPERIMENTAL_F
LAGS, "")); | 480 getPreferences(MODE_PRIVATE).getString(PREFERENCE_EXPERIMENTAL_F
LAGS, "")); |
| 481 } | 481 } |
| 482 | 482 |
| 483 private void refreshHostList() { | 483 private void refreshHostList() { |
| 484 if (mWaitingForAuthToken) { | 484 if (mWaitingForAuthToken) { |
| 485 return; | 485 return; |
| 486 } | 486 } |
| 487 | 487 |
| 488 mTriedNewAuthToken = false; | 488 mTriedNewAuthToken = false; |
| 489 showHostListLoadingIndicator(); | 489 showHostListLoadingIndicator(); |
| 490 | 490 |
| 491 // The refresh button simply makes use of the currently-chosen account. | 491 // The refresh button simply makes use of the currently-chosen account. |
| 492 requestAuthToken(false); | 492 requestAuthToken(false); |
| 493 } | 493 } |
| 494 | 494 |
| 495 private void requestAuthToken(boolean expireCurrentToken) { | 495 private void requestAuthToken(boolean expireCurrentToken) { |
| 496 mWaitingForAuthToken = true; | 496 mWaitingForAuthToken = true; |
| 497 | 497 |
| 498 OAuthTokenFetcher fetcher = new OAuthTokenFetcher(this, mAccount, TOKEN_
SCOPE, | 498 OAuthTokenFetcher fetcher = new OAuthTokenFetcher(this, mAccount, TOKEN_
SCOPE, |
| 499 new OAuthTokenFetcher.Callback() { | 499 new OAuthTokenFetcher.Callback() { |
| 500 @Override | 500 @Override |
| 501 public void onTokenFetched(String token) { | 501 public void onTokenFetched(String token) { |
| 502 mWaitingForAuthToken = false; | 502 mWaitingForAuthToken = false; |
| 503 mToken = token; | 503 mToken = token; |
| 504 mHostListLoader.retrieveHostList(mToken, Chromoting.this
); | 504 mHostListManager.retrieveHostList(mToken, Chromoting.thi
s); |
| 505 } | 505 } |
| 506 | 506 |
| 507 @Override | 507 @Override |
| 508 public void onError(OAuthTokenFetcher.Error error) { | 508 public void onError(OAuthTokenFetcher.Error error) { |
| 509 mWaitingForAuthToken = false; | 509 mWaitingForAuthToken = false; |
| 510 updateHostListView(); | 510 updateHostListView(); |
| 511 String explanation = getString(error == OAuthTokenFetche
r.Error.NETWORK | 511 String explanation = getString(error == OAuthTokenFetche
r.Error.NETWORK |
| 512 ? R.string.error_network_error : R.string.error_
unexpected); | 512 ? R.string.error_network_error : R.string.error_
unexpected); |
| 513 Toast.makeText(Chromoting.this, explanation, Toast.LENGT
H_LONG).show(); | 513 Toast.makeText(Chromoting.this, explanation, Toast.LENGT
H_LONG).show(); |
| 514 } | 514 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 537 showNoAccountsDialog(); | 537 showNoAccountsDialog(); |
| 538 } | 538 } |
| 539 | 539 |
| 540 @Override | 540 @Override |
| 541 public void onRequestCloseDrawer() { | 541 public void onRequestCloseDrawer() { |
| 542 mDrawerLayout.closeDrawers(); | 542 mDrawerLayout.closeDrawers(); |
| 543 } | 543 } |
| 544 | 544 |
| 545 @Override | 545 @Override |
| 546 public void onHostListReceived(HostInfo[] hosts) { | 546 public void onHostListReceived(HostInfo[] hosts) { |
| 547 // Store a copy of the array, so that it can't be mutated by the HostLis
tLoader. HostInfo | 547 // Store a copy of the array, so that it can't be mutated by the HostLis
tManager. HostInfo |
| 548 // is an immutable type, so a shallow copy of the array is sufficient he
re. | 548 // is an immutable type, so a shallow copy of the array is sufficient he
re. |
| 549 mHosts = Arrays.copyOf(hosts, hosts.length); | 549 mHosts = Arrays.copyOf(hosts, hosts.length); |
| 550 updateHostListView(); | 550 updateHostListView(); |
| 551 updateUi(); | 551 updateUi(); |
| 552 } | 552 } |
| 553 | 553 |
| 554 @Override | 554 @Override |
| 555 public void onError(HostListLoader.Error error) { | 555 public void onHostUpdated() { |
| 556 // Not implemented Yet. |
| 557 } |
| 558 |
| 559 @Override |
| 560 public void onHostDeleted() { |
| 561 // Not implemented Yet. |
| 562 } |
| 563 |
| 564 @Override |
| 565 public void onError(HostListManager.Error error) { |
| 556 String explanation = null; | 566 String explanation = null; |
| 557 switch (error) { | 567 switch (error) { |
| 558 case AUTH_FAILED: | 568 case AUTH_FAILED: |
| 559 break; | 569 break; |
| 560 case NETWORK_ERROR: | 570 case NETWORK_ERROR: |
| 561 explanation = getString(R.string.error_network_error); | 571 explanation = getString(R.string.error_network_error); |
| 562 break; | 572 break; |
| 563 case UNEXPECTED_RESPONSE: | 573 case UNEXPECTED_RESPONSE: |
| 564 case SERVICE_UNAVAILABLE: | 574 case SERVICE_UNAVAILABLE: |
| 565 case UNKNOWN: | 575 case UNKNOWN: |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 // Unreachable, but required by Google Java style and findbugs. | 650 // Unreachable, but required by Google Java style and findbugs. |
| 641 assert false : "Unreached"; | 651 assert false : "Unreached"; |
| 642 } | 652 } |
| 643 | 653 |
| 644 if (dismissProgress && mProgressIndicator != null) { | 654 if (dismissProgress && mProgressIndicator != null) { |
| 645 mProgressIndicator.dismiss(); | 655 mProgressIndicator.dismiss(); |
| 646 mProgressIndicator = null; | 656 mProgressIndicator = null; |
| 647 } | 657 } |
| 648 } | 658 } |
| 649 } | 659 } |
| OLD | NEW |