summaryrefslogtreecommitdiffstats
path: root/remoting/android
diff options
context:
space:
mode:
authorlambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-09 07:43:37 +0000
committerlambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-09 07:43:37 +0000
commit2e20b9f69d2a979d679d2e3fe7bb4df0b2a031ce (patch)
treeacee1f7149bae9017ac796ee99f95b5bdc172b16 /remoting/android
parentbb0eada558417510c6c9268b751f2f7d456ffd15 (diff)
downloadchromium_src-2e20b9f69d2a979d679d2e3fe7bb4df0b2a031ce.zip
chromium_src-2e20b9f69d2a979d679d2e3fe7bb4df0b2a031ce.tar.gz
chromium_src-2e20b9f69d2a979d679d2e3fe7bb4df0b2a031ce.tar.bz2
Android Chromoting - Close the Desktop view on disconnection
If the session becomes disconnected, this hides the desktop display instead of leaving it visible and non-interactive. BUG=325593 TEST=Disconnect the session by killing the host process. Review URL: https://codereview.chromium.org/105943010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243800 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/android')
-rw-r--r--remoting/android/java/src/org/chromium/chromoting/Chromoting.java72
-rw-r--r--remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java139
2 files changed, 139 insertions, 72 deletions
diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
index 520690d..8ae7928 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
@@ -11,6 +11,8 @@ import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
@@ -38,7 +40,7 @@ import java.util.Scanner;
* The user interface for querying and displaying a user's host list from the directory server. It
* also requests and renews authentication tokens using the system account manager.
*/
-public class Chromoting extends Activity {
+public class Chromoting extends Activity implements JniInterface.ConnectionListener {
/** Only accounts of this type will be selectable for authentication. */
private static final String ACCOUNT_TYPE = "com.google";
@@ -78,6 +80,9 @@ public class Chromoting extends Activity {
/** Callback handler to be used for network operations. */
private Handler mNetwork;
+ /** Dialog for reporting connection progress. */
+ private ProgressDialog mProgressIndicator;
+
/**
* Called when the activity is first created. Loads the native library and requests an
* authentication token from the system.
@@ -187,13 +192,7 @@ public class Chromoting extends Activity {
try {
synchronized (mLock) {
JniInterface.connectToHost(mAccount.name, mToken, host.getString("jabberId"),
- host.getString("hostId"), host.getString("publicKey"),
- new Runnable() {
- @Override
- public void run() {
- startActivity(new Intent(Chromoting.this, Desktop.class));
- }
- });
+ host.getString("hostId"), host.getString("publicKey"), this);
}
} catch (JSONException ex) {
Log.w("host", ex);
@@ -363,4 +362,61 @@ public class Chromoting extends Activity {
finish();
}
}
+
+ @Override
+ public void onConnectionState(JniInterface.ConnectionListener.State state,
+ JniInterface.ConnectionListener.Error error) {
+ String stateText = getResources().getStringArray(R.array.protoc_states)[state.value()];
+ boolean dismissProgress = false;
+ switch (state) {
+ case INITIALIZING:
+ case CONNECTING:
+ case AUTHENTICATED:
+ // The connection is still being established, so we'll report the current progress.
+ if (mProgressIndicator == null) {
+ mProgressIndicator = ProgressDialog.show(this,
+ getString(R.string.progress_title), stateText, true, true,
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ JniInterface.disconnectFromHost();
+ }
+ });
+ } else {
+ mProgressIndicator.setMessage(stateText);
+ }
+ break;
+
+ case CONNECTED:
+ dismissProgress = true;
+ Toast.makeText(this, stateText, Toast.LENGTH_SHORT).show();
+
+ // Display the remote desktop.
+ startActivityForResult(new Intent(this, Desktop.class), 0);
+ break;
+
+ case FAILED:
+ dismissProgress = true;
+ Toast.makeText(this, stateText + ": "
+ + getResources().getStringArray(R.array.protoc_errors)[error.value()],
+ Toast.LENGTH_LONG).show();
+
+ // Close the Desktop view, if it is currently running.
+ finishActivity(0);
+ break;
+
+ case CLOSED:
+ // No need to show toast in this case. Either the connection will have failed
+ // because of an error, which will trigger toast already. Or the disconnection will
+ // have been initiated by the user.
+ dismissProgress = true;
+ finishActivity(0);
+ break;
+ }
+
+ if (dismissProgress && mProgressIndicator != null) {
+ mProgressIndicator.dismiss();
+ mProgressIndicator = null;
+ }
+ }
}
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
index ada7248..33f4136 100644
--- a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
+++ b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
@@ -6,7 +6,6 @@ package org.chromium.chromoting.jni;
import android.app.Activity;
import android.app.AlertDialog;
-import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
@@ -33,9 +32,6 @@ import java.nio.ByteOrder;
*/
@JNINamespace("remoting")
public class JniInterface {
- /** The status code indicating successful connection. */
- private static final int SUCCESSFUL_CONNECTION = 3;
-
/*
* Library-loading state machine.
*/
@@ -45,22 +41,80 @@ public class JniInterface {
/** The application context. Accessed on the UI thread. */
private static Activity sContext = null;
+ /** Interface used for connection state notifications. */
+ public interface ConnectionListener {
+ /**
+ * This enum must match the C++ enumeration remoting::protocol::ConnectionToHost::State.
+ */
+ public enum State {
+ INITIALIZING(0),
+ CONNECTING(1),
+ AUTHENTICATED(2),
+ CONNECTED(3),
+ FAILED(4),
+ CLOSED(5);
+
+ private final int mValue;
+
+ State(int value) {
+ mValue = value;
+ }
+
+ public int value() {
+ return mValue;
+ }
+
+ public static State fromValue(int value) {
+ return values()[value];
+ }
+ }
+
+ /**
+ * This enum must match the C++ enumeration remoting::protocol::ErrorCode.
+ */
+ public enum Error {
+ OK(0),
+ PEER_IS_OFFLINE(1),
+ SESSION_REJECTED(2),
+ INCOMPATIBLE_PROTOCOL(3),
+ AUTHENTICATION_FAILED(4),
+ CHANNEL_CONNECTION_ERROR(5),
+ SIGNALING_ERROR(6),
+ SIGNALING_TIMEOUT(7),
+ HOST_OVERLOAD(8),
+ UNKNOWN_ERROR(9);
+
+ private final int mValue;
+
+ Error(int value) {
+ mValue = value;
+ }
+
+ public int value() {
+ return mValue;
+ }
+
+ public static Error fromValue(int value) {
+ return values()[value];
+ }
+ }
+
+ /**
+ * Notified on connection state change.
+ * @param state The new connection state.
+ * @param error The error code, if state is STATE_FAILED.
+ */
+ void onConnectionState(State state, Error error);
+ }
+
/*
* Connection-initiating state machine.
*/
/** Whether the native code is attempting a connection. Accessed on the UI thread. */
private static boolean sConnected = false;
- /** Callback to signal upon successful connection. Accessed on the UI thread. */
- private static Runnable sSuccessCallback = null;
-
- /** Dialog for reporting connection progress. Accessed on the UI thread. */
- private static ProgressDialog sProgressIndicator = null;
-
- // Protects access to |sProgressIndicator|. Used only to silence FindBugs warnings - the
- // variable it protects is only accessed on a single thread.
- // TODO(lambroslambrou): Refactor the ProgressIndicator into a separate class.
- private static Object sProgressIndicatorLock = new Object();
+ /** Notified upon successful connection or disconnection. Accessed on the UI thread. */
+ private static ConnectionListener sConnectionListener = null;
/**
* Callback invoked on the graphics thread to repaint the desktop. Accessed on the UI and
@@ -108,10 +162,10 @@ public class JniInterface {
/** Attempts to form a connection to the user-selected host. Called on the UI thread. */
public static void connectToHost(String username, String authToken,
- String hostJid, String hostId, String hostPubkey, Runnable successCallback) {
+ String hostJid, String hostId, String hostPubkey, ConnectionListener listener) {
disconnectFromHost();
- sSuccessCallback = successCallback;
+ sConnectionListener = listener;
SharedPreferences prefs = sContext.getPreferences(Activity.MODE_PRIVATE);
nativeConnect(username, authToken, hostJid, hostId, hostPubkey,
prefs.getString(hostId + "_id", ""), prefs.getString(hostId + "_secret", ""));
@@ -126,15 +180,11 @@ public class JniInterface {
public static void disconnectFromHost() {
if (!sConnected) return;
- synchronized (sProgressIndicatorLock) {
- if (sProgressIndicator != null) {
- sProgressIndicator.dismiss();
- sProgressIndicator = null;
- }
- }
+ sConnectionListener.onConnectionState(ConnectionListener.State.CLOSED,
+ ConnectionListener.Error.OK);
nativeDisconnect();
- sSuccessCallback = null;
+ sConnectionListener = null;
sConnected = false;
// Drop the reference to free the Bitmap for GC.
@@ -149,47 +199,8 @@ public class JniInterface {
/** Reports whenever the connection status changes. Called on the UI thread. */
@CalledByNative
private static void reportConnectionStatus(int state, int error) {
- if (state < SUCCESSFUL_CONNECTION && error == 0) {
- // The connection is still being established, so we'll report the current progress.
- synchronized (sProgressIndicatorLock) {
- if (sProgressIndicator == null) {
- sProgressIndicator = ProgressDialog.show(sContext, sContext.
- getString(R.string.progress_title), sContext.getResources().
- getStringArray(R.array.protoc_states)[state], true, true,
- new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- Log.i("jniiface", "User canceled connection initiation");
- disconnectFromHost();
- }
- });
- } else {
- sProgressIndicator.setMessage(
- sContext.getResources().getStringArray(R.array.protoc_states)[state]);
- }
- }
- } else {
- // The connection is complete or has failed, so we can lose the progress indicator.
- synchronized (sProgressIndicatorLock) {
- if (sProgressIndicator != null) {
- sProgressIndicator.dismiss();
- sProgressIndicator = null;
- }
- }
-
- if (state == SUCCESSFUL_CONNECTION) {
- Toast.makeText(sContext, sContext.getResources().
- getStringArray(R.array.protoc_states)[state], Toast.LENGTH_SHORT).show();
-
- // Actually display the remote desktop.
- sSuccessCallback.run();
- } else {
- Toast.makeText(sContext, sContext.getResources().getStringArray(
- R.array.protoc_states)[state] + (error == 0 ? "" : ": " +
- sContext.getResources().getStringArray(R.array.protoc_errors)[error]),
- Toast.LENGTH_LONG).show();
- }
- }
+ sConnectionListener.onConnectionState(ConnectionListener.State.fromValue(state),
+ ConnectionListener.Error.fromValue(error));
}
/** Prompts the user to enter a PIN. Called on the UI thread. */