Commit e45afacc authored by kelvinp's avatar kelvinp Committed by Commit bot

[Webapp Refactor] Reliably cancels a connection.

Prior to this CL, clicking cancel on the connecting dialog simply
returns the user to the home screen, without disconnecting the session or
cleaning up any related resources.

This CL provides a cleaner way to cancel a session with by implementing
remoting.ConnectingDialog which calls stop() on the activity.

BUG=477522

Review URL: https://codereview.chromium.org/1101613003

Cr-Commit-Position: refs/heads/master@{#326926}
parent 375d6d1d
...@@ -56,17 +56,17 @@ remoting.InputDialog.prototype.show = function() { ...@@ -56,17 +56,17 @@ remoting.InputDialog.prototype.show = function() {
/** @return {HTMLElement} */ /** @return {HTMLElement} */
remoting.InputDialog.prototype.inputField = function() { remoting.InputDialog.prototype.inputField = function() {
return this.inputField_; return this.inputField_;
} };
/** @private */ /** @private */
remoting.InputDialog.prototype.onSubmit_ = function() { remoting.InputDialog.prototype.onSubmit_ = function() {
this.deferred_.resolve(this.inputField_.value); this.deferred_.resolve(this.inputField_.value);
} };
/** @private */ /** @private */
remoting.InputDialog.prototype.onCancel_ = function() { remoting.InputDialog.prototype.onCancel_ = function() {
this.deferred_.reject(new remoting.Error(remoting.Error.Tag.CANCELLED)); this.deferred_.reject(new remoting.Error(remoting.Error.Tag.CANCELLED));
} };
/** /**
* @param {function():void} handler * @param {function():void} handler
...@@ -97,7 +97,9 @@ remoting.InputDialog.prototype.createFormEventHandler_ = function(handler) { ...@@ -97,7 +97,9 @@ remoting.InputDialog.prototype.createFormEventHandler_ = function(handler) {
* @param {remoting.AppMode} mode * @param {remoting.AppMode} mode
* @param {HTMLElement} primaryButton * @param {HTMLElement} primaryButton
* @param {HTMLElement=} opt_secondaryButton * @param {HTMLElement=} opt_secondaryButton
*
* @constructor * @constructor
* @implements {base.Disposable}
*/ */
remoting.MessageDialog = function(mode, primaryButton, opt_secondaryButton) { remoting.MessageDialog = function(mode, primaryButton, opt_secondaryButton) {
/** @private @const */ /** @private @const */
...@@ -136,6 +138,15 @@ remoting.MessageDialog.prototype.show = function() { ...@@ -136,6 +138,15 @@ remoting.MessageDialog.prototype.show = function() {
return this.deferred_.promise(); return this.deferred_.promise();
}; };
remoting.MessageDialog.prototype.dispose = function() {
base.dispose(this.eventHooks_);
this.eventHooks_ = null;
if (this.deferred_) {
this.deferred_.reject(new remoting.Error(remoting.Error.Tag.CANCELLED));
}
this.deferred_ = null;
};
/** /**
* @param {remoting.MessageDialog.Result} result * @param {remoting.MessageDialog.Result} result
* @return {Function} * @return {Function}
...@@ -143,9 +154,35 @@ remoting.MessageDialog.prototype.show = function() { ...@@ -143,9 +154,35 @@ remoting.MessageDialog.prototype.show = function() {
*/ */
remoting.MessageDialog.prototype.onClicked_ = function(result) { remoting.MessageDialog.prototype.onClicked_ = function(result) {
this.deferred_.resolve(result); this.deferred_.resolve(result);
base.dispose(this.eventHooks_);
this.eventHooks_ = null;
this.deferred_ = null; this.deferred_ = null;
this.dispose();
};
/**
* @param {Function} cancelCallback The callback to invoke when the user clicks
* on the cancel button.
* @constructor
*/
remoting.ConnectingDialog = function(cancelCallback) {
/** @private */
this.dialog_ = new remoting.MessageDialog(
remoting.AppMode.CLIENT_CONNECTING,
document.getElementById('cancel-connect-button'));
/** @private */
this.onCancel_ = cancelCallback;
};
remoting.ConnectingDialog.prototype.show = function() {
var that = this;
this.dialog_.show().then(function() {
remoting.setMode(remoting.AppMode.HOME);
that.onCancel_();
// The promise rejects when the dialog is hidden. Don't report that as error.
}).catch(remoting.Error.handler(base.doNothing));
};
remoting.ConnectingDialog.prototype.hide = function() {
this.dialog_.dispose();
}; };
})(); })();
......
...@@ -269,6 +269,8 @@ remoting.ClientSession.prototype.connect = function(host, credentialsProvider) { ...@@ -269,6 +269,8 @@ remoting.ClientSession.prototype.connect = function(host, credentialsProvider) {
*/ */
remoting.ClientSession.prototype.disconnect = function(error) { remoting.ClientSession.prototype.disconnect = function(error) {
if (this.isFinished()) { if (this.isFinished()) {
// Do not send the session-terminate Iq if disconnect() is already called or
// if it is initiated by the host.
return; return;
} }
......
...@@ -11,13 +11,6 @@ remoting.initElementEventHandlers = function() { ...@@ -11,13 +11,6 @@ remoting.initElementEventHandlers = function() {
var goHome = function() { var goHome = function() {
remoting.setMode(remoting.AppMode.HOME); remoting.setMode(remoting.AppMode.HOME);
}; };
var goFinishedIT2Me = function() {
if (remoting.currentMode == remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME) {
remoting.setMode(remoting.AppMode.CLIENT_UNCONNECTED);
} else {
goHome();
}
};
/** @type {Array<{event: string, id: string, fn: function(Event):void}>} */ /** @type {Array<{event: string, id: string, fn: function(Event):void}>} */
var it2me_actions = [ var it2me_actions = [
{ event: 'click', id: 'cancel-share-button', fn: remoting.cancelShare }, { event: 'click', id: 'cancel-share-button', fn: remoting.cancelShare },
...@@ -44,7 +37,6 @@ remoting.initElementEventHandlers = function() { ...@@ -44,7 +37,6 @@ remoting.initElementEventHandlers = function() {
]; ];
/** @type {Array<{event: string, id: string, fn: function(Event):void}>} */ /** @type {Array<{event: string, id: string, fn: function(Event):void}>} */
var auth_actions = [ var auth_actions = [
{ event: 'click', id: 'cancel-connect-button', fn: goHome },
{ event: 'click', id: 'sign-out', fn:remoting.signOut }, { event: 'click', id: 'sign-out', fn:remoting.signOut },
{ event: 'click', id: 'token-refresh-error-ok', fn: goHome }, { event: 'click', id: 'token-refresh-error-ok', fn: goHome },
{ event: 'click', id: 'token-refresh-error-sign-in', { event: 'click', id: 'token-refresh-error-sign-in',
......
...@@ -209,7 +209,7 @@ remoting.DesktopRemoting.prototype.disconnect_ = function() { ...@@ -209,7 +209,7 @@ remoting.DesktopRemoting.prototype.disconnect_ = function() {
remoting.DesktopRemoting.prototype.connectMe2Me_ = function(hostId) { remoting.DesktopRemoting.prototype.connectMe2Me_ = function(hostId) {
var host = remoting.hostList.getHostForId(hostId); var host = remoting.hostList.getHostForId(hostId);
base.dispose(this.activity_); base.dispose(this.activity_);
this.activity_ = new remoting.Me2MeActivity(host); this.activity_ = new remoting.Me2MeActivity(host, remoting.hostList);
this.activity_.start(); this.activity_.start();
}; };
......
...@@ -30,6 +30,9 @@ remoting.DesktopRemotingActivity = function(parentActivity) { ...@@ -30,6 +30,9 @@ remoting.DesktopRemotingActivity = function(parentActivity) {
remoting.app_capabilities()); remoting.app_capabilities());
/** @private {remoting.ClientSession} */ /** @private {remoting.ClientSession} */
this.session_ = null; this.session_ = null;
/** @private {remoting.ConnectingDialog} */
this.connectingDialog_ =
new remoting.ConnectingDialog(parentActivity.stop.bind(parentActivity));
}; };
/** /**
...@@ -49,7 +52,10 @@ remoting.DesktopRemotingActivity.prototype.start = ...@@ -49,7 +52,10 @@ remoting.DesktopRemotingActivity.prototype.start =
session.logHostOfflineErrors(!opt_suppressOfflineError); session.logHostOfflineErrors(!opt_suppressOfflineError);
session.getLogger().setHostVersion(host.hostVersion); session.getLogger().setHostVersion(host.hostVersion);
session.connect(host, credentialsProvider); session.connect(host, credentialsProvider);
}); }).catch(remoting.Error.handler(
function(/** !remoting.Error */ error) {
that.parentActivity_.onConnectionFailed(error);
}));
}; };
remoting.DesktopRemotingActivity.prototype.stop = function() { remoting.DesktopRemotingActivity.prototype.stop = function() {
...@@ -64,6 +70,7 @@ remoting.DesktopRemotingActivity.prototype.stop = function() { ...@@ -64,6 +70,7 @@ remoting.DesktopRemotingActivity.prototype.stop = function() {
*/ */
remoting.DesktopRemotingActivity.prototype.onConnected = remoting.DesktopRemotingActivity.prototype.onConnected =
function(connectionInfo) { function(connectionInfo) {
this.connectingDialog_.hide();
remoting.setMode(remoting.AppMode.IN_SESSION); remoting.setMode(remoting.AppMode.IN_SESSION);
if (!base.isAppsV2()) { if (!base.isAppsV2()) {
remoting.toolbar.center(); remoting.toolbar.center();
...@@ -126,6 +133,7 @@ remoting.DesktopRemotingActivity.prototype.dispose = function() { ...@@ -126,6 +133,7 @@ remoting.DesktopRemotingActivity.prototype.dispose = function() {
this.connectedView_ = null; this.connectedView_ = null;
base.dispose(this.session_); base.dispose(this.session_);
this.session_ = null; this.session_ = null;
this.connectingDialog_.hide();
}; };
/** @return {remoting.DesktopConnectedView} */ /** @return {remoting.DesktopConnectedView} */
...@@ -140,4 +148,9 @@ remoting.DesktopRemotingActivity.prototype.getSession = function() { ...@@ -140,4 +148,9 @@ remoting.DesktopRemotingActivity.prototype.getSession = function() {
return this.session_; return this.session_;
}; };
/** @return {remoting.ConnectingDialog} */
remoting.DesktopRemotingActivity.prototype.getConnectingDialog = function() {
return this.connectingDialog_;
};
})(); })();
...@@ -44,8 +44,11 @@ remoting.It2MeActivity.prototype.dispose = function() { ...@@ -44,8 +44,11 @@ remoting.It2MeActivity.prototype.dispose = function() {
remoting.It2MeActivity.prototype.start = function() { remoting.It2MeActivity.prototype.start = function() {
var that = this; var that = this;
this.desktopActivity_ = new remoting.DesktopRemotingActivity(this);
remoting.app.setConnectionMode(remoting.Application.Mode.IT2ME);
this.accessCodeDialog_.show().then(function(/** string */ accessCode) { this.accessCodeDialog_.show().then(function(/** string */ accessCode) {
remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); that.desktopActivity_.getConnectingDialog().show();
return that.verifyAccessCode_(accessCode); return that.verifyAccessCode_(accessCode);
}).then(function() { }).then(function() {
return remoting.identity.getToken(); return remoting.identity.getToken();
...@@ -55,7 +58,7 @@ remoting.It2MeActivity.prototype.start = function() { ...@@ -55,7 +58,7 @@ remoting.It2MeActivity.prototype.start = function() {
return that.onHostInfo_(response); return that.onHostInfo_(response);
}).then(function(/** remoting.Host */ host) { }).then(function(/** remoting.Host */ host) {
that.connect_(host); that.connect_(host);
}).catch(function(/** remoting.Error */ error) { }).catch(remoting.Error.handler(function(/** remoting.Error */ error) {
if (error.hasTag(remoting.Error.Tag.CANCELLED)) { if (error.hasTag(remoting.Error.Tag.CANCELLED)) {
remoting.setMode(remoting.AppMode.HOME); remoting.setMode(remoting.AppMode.HOME);
} else { } else {
...@@ -63,7 +66,7 @@ remoting.It2MeActivity.prototype.start = function() { ...@@ -63,7 +66,7 @@ remoting.It2MeActivity.prototype.start = function() {
l10n.localizeElementFromTag(errorDiv, error.getTag()); l10n.localizeElementFromTag(errorDiv, error.getTag());
remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME); remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME);
} }
}); }));
}; };
remoting.It2MeActivity.prototype.stop = function() { remoting.It2MeActivity.prototype.stop = function() {
...@@ -193,9 +196,6 @@ remoting.It2MeActivity.prototype.onHostInfo_ = function(xhrResponse) { ...@@ -193,9 +196,6 @@ remoting.It2MeActivity.prototype.onHostInfo_ = function(xhrResponse) {
* @private * @private
*/ */
remoting.It2MeActivity.prototype.connect_ = function(host) { remoting.It2MeActivity.prototype.connect_ = function(host) {
base.dispose(this.desktopActivity_);
this.desktopActivity_ = new remoting.DesktopRemotingActivity(this);
remoting.app.setConnectionMode(remoting.Application.Mode.IT2ME);
this.desktopActivity_.start( this.desktopActivity_.start(
host, new remoting.CredentialsProvider({ accessCode: this.passCode_ })); host, new remoting.CredentialsProvider({ accessCode: this.passCode_ }));
}; };
......
...@@ -11,14 +11,17 @@ var remoting = remoting || {}; ...@@ -11,14 +11,17 @@ var remoting = remoting || {};
/** /**
* @param {remoting.Host} host * @param {remoting.Host} host
* @param {remoting.HostList} hostList
* *
* @constructor * @constructor
* @implements {remoting.Activity} * @implements {remoting.Activity}
*/ */
remoting.Me2MeActivity = function(host) { remoting.Me2MeActivity = function(host, hostList) {
/** @private */ /** @private */
this.host_ = host; this.host_ = host;
/** @private */ /** @private */
this.hostList_ = hostList;
/** @private */
this.pinDialog_ = this.pinDialog_ =
new remoting.PinDialog(document.getElementById('pin-dialog'), host); new remoting.PinDialog(document.getElementById('pin-dialog'), host);
/** @private */ /** @private */
...@@ -48,11 +51,11 @@ remoting.Me2MeActivity.prototype.start = function() { ...@@ -48,11 +51,11 @@ remoting.Me2MeActivity.prototype.start = function() {
return that.host_.options.load(); return that.host_.options.load();
}).then(function() { }).then(function() {
that.connect_(true); that.connect_(true);
}).catch(function(/** remoting.Error */ error) { }).catch(remoting.Error.handler(function(/** remoting.Error */ error) {
if (error.hasTag(remoting.Error.Tag.CANCELLED)) { if (error.hasTag(remoting.Error.Tag.CANCELLED)) {
remoting.setMode(remoting.AppMode.HOME); remoting.setMode(remoting.AppMode.HOME);
} }
}); }));
}; };
remoting.Me2MeActivity.prototype.stop = function() { remoting.Me2MeActivity.prototype.stop = function() {
...@@ -69,9 +72,9 @@ remoting.Me2MeActivity.prototype.getDesktopActivity = function() { ...@@ -69,9 +72,9 @@ remoting.Me2MeActivity.prototype.getDesktopActivity = function() {
* @private * @private
*/ */
remoting.Me2MeActivity.prototype.connect_ = function(suppressHostOfflineError) { remoting.Me2MeActivity.prototype.connect_ = function(suppressHostOfflineError) {
remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
base.dispose(this.desktopActivity_); base.dispose(this.desktopActivity_);
this.desktopActivity_ = new remoting.DesktopRemotingActivity(this); this.desktopActivity_ = new remoting.DesktopRemotingActivity(this);
this.desktopActivity_.getConnectingDialog().show();
remoting.app.setConnectionMode(remoting.Application.Mode.ME2ME); remoting.app.setConnectionMode(remoting.Application.Mode.ME2ME);
this.desktopActivity_.start(this.host_, this.createCredentialsProvider_(), this.desktopActivity_.start(this.host_, this.createCredentialsProvider_(),
suppressHostOfflineError); suppressHostOfflineError);
...@@ -106,16 +109,18 @@ remoting.Me2MeActivity.prototype.createCredentialsProvider_ = function() { ...@@ -106,16 +109,18 @@ remoting.Me2MeActivity.prototype.createCredentialsProvider_ = function() {
var requestPin = function(supportsPairing, onPinFetched) { var requestPin = function(supportsPairing, onPinFetched) {
// Set time when PIN was requested. // Set time when PIN was requested.
var authStartTime = new Date().getTime(); var authStartTime = new Date().getTime();
that.desktopActivity_.getConnectingDialog().hide();
that.pinDialog_.show(supportsPairing).then(function(/** string */ pin) { that.pinDialog_.show(supportsPairing).then(function(/** string */ pin) {
remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
// Done obtaining PIN information. Log time taken for PIN entry. // Done obtaining PIN information. Log time taken for PIN entry.
var logToServer = that.desktopActivity_.getSession().getLogger(); var logToServer = that.desktopActivity_.getSession().getLogger();
logToServer.setAuthTotalTime(new Date().getTime() - authStartTime); logToServer.setAuthTotalTime(new Date().getTime() - authStartTime);
onPinFetched(pin); onPinFetched(pin);
}).catch(function(/** remoting.Error */ error) { }).catch(remoting.Error.handler(function(/** remoting.Error */ error) {
base.debug.assert(error.hasTag(remoting.Error.Tag.CANCELLED)); base.debug.assert(error.hasTag(remoting.Error.Tag.CANCELLED));
remoting.setMode(remoting.AppMode.HOME); remoting.setMode(remoting.AppMode.HOME);
}); that.stop();
}));
}; };
return new remoting.CredentialsProvider({ return new remoting.CredentialsProvider({
...@@ -136,7 +141,7 @@ remoting.Me2MeActivity.prototype.onConnectionFailed = function(error) { ...@@ -136,7 +141,7 @@ remoting.Me2MeActivity.prototype.onConnectionFailed = function(error) {
var onHostListRefresh = function(/** boolean */ success) { var onHostListRefresh = function(/** boolean */ success) {
if (success) { if (success) {
// Get the host from the hostList for the refreshed JID. // Get the host from the hostList for the refreshed JID.
that.host_ = remoting.hostList.getHostForId(that.host_.hostId); that.host_ = that.hostList_.getHostForId(that.host_.hostId);
that.connect_(false); that.connect_(false);
return; return;
} }
...@@ -145,7 +150,7 @@ remoting.Me2MeActivity.prototype.onConnectionFailed = function(error) { ...@@ -145,7 +150,7 @@ remoting.Me2MeActivity.prototype.onConnectionFailed = function(error) {
this.retryOnHostOffline_ = false; this.retryOnHostOffline_ = false;
// The plugin will be re-created when the host finished refreshing // The plugin will be re-created when the host finished refreshing
remoting.hostList.refresh(onHostListRefresh); this.hostList_.refresh(onHostListRefresh);
} else if (!error.isNone()) { } else if (!error.isNone()) {
this.showErrorMessage_(error); this.showErrorMessage_(error);
} }
...@@ -170,6 +175,7 @@ remoting.Me2MeActivity.prototype.onConnected = function(connectionInfo) { ...@@ -170,6 +175,7 @@ remoting.Me2MeActivity.prototype.onConnected = function(connectionInfo) {
base.dispose(this.reconnector_); base.dispose(this.reconnector_);
this.reconnector_ = new remoting.SmartReconnector( this.reconnector_ = new remoting.SmartReconnector(
this.desktopActivity_.getConnectingDialog(),
this.connect_.bind(this, false), this.connect_.bind(this, false),
this.stop.bind(this), this.stop.bind(this),
connectionInfo.session()); connectionInfo.session());
......
...@@ -21,6 +21,7 @@ var remoting = remoting || {}; ...@@ -21,6 +21,7 @@ var remoting = remoting || {};
/** /**
* @constructor * @constructor
* @param {remoting.ConnectingDialog} connectingDialog
* @param {function()} reconnectCallback * @param {function()} reconnectCallback
* @param {function()} disconnectCallback * @param {function()} disconnectCallback
* @param {remoting.ClientSession} clientSession This represents the current * @param {remoting.ClientSession} clientSession This represents the current
...@@ -28,8 +29,8 @@ var remoting = remoting || {}; ...@@ -28,8 +29,8 @@ var remoting = remoting || {};
* connection state. * connection state.
* @implements {base.Disposable} * @implements {base.Disposable}
*/ */
remoting.SmartReconnector = remoting.SmartReconnector = function(connectingDialog, reconnectCallback,
function(reconnectCallback, disconnectCallback, clientSession) { disconnectCallback, clientSession) {
/** @private */ /** @private */
this.reconnectCallback_ = reconnectCallback; this.reconnectCallback_ = reconnectCallback;
...@@ -47,6 +48,9 @@ remoting.SmartReconnector = ...@@ -47,6 +48,9 @@ remoting.SmartReconnector =
*/ */
this.pending_ = null; this.pending_ = null;
/** @private */
this.connectingDialog_ = connectingDialog;
var Events = remoting.ClientSession.Events; var Events = remoting.ClientSession.Events;
/** @private */ /** @private */
this.eventHook_ = this.eventHook_ =
...@@ -66,13 +70,12 @@ var CONNECTION_TIMEOUT_MS = 10000; ...@@ -66,13 +70,12 @@ var CONNECTION_TIMEOUT_MS = 10000;
remoting.SmartReconnector.prototype.reconnect_ = function() { remoting.SmartReconnector.prototype.reconnect_ = function() {
this.cancelPending_(); this.cancelPending_();
this.disconnectCallback_(); this.disconnectCallback_();
remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
this.reconnectCallback_(); this.reconnectCallback_();
}; };
remoting.SmartReconnector.prototype.reconnectAsync_ = function() { remoting.SmartReconnector.prototype.reconnectAsync_ = function() {
this.cancelPending_(); this.cancelPending_();
remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); this.connectingDialog_.show();
this.pending_ = this.pending_ =
new base.OneShotTimer(this.reconnect_.bind(this), RECONNECT_DELAY_MS); new base.OneShotTimer(this.reconnect_.bind(this), RECONNECT_DELAY_MS);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment