diff options
author | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-09 07:43:37 +0000 |
---|---|---|
committer | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-09 07:43:37 +0000 |
commit | 2e20b9f69d2a979d679d2e3fe7bb4df0b2a031ce (patch) | |
tree | acee1f7149bae9017ac796ee99f95b5bdc172b16 /remoting/android | |
parent | bb0eada558417510c6c9268b751f2f7d456ffd15 (diff) | |
download | chromium_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.java | 72 | ||||
-rw-r--r-- | remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java | 139 |
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. */ |