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

Unified Diff: remoting/webapp/session_connector.js

Issue 552403004: Interfaceify ClientPlugin in preparation for mocking it. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Renamed interfaces. Created 6 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: remoting/webapp/session_connector.js
diff --git a/remoting/webapp/session_connector.js b/remoting/webapp/session_connector.js
index 04fe425e21634d38e4dd7579a1ed8f8d9f8c30f5..dfdcda6eb1eac0cf40003cb5f268a921b43610e9 100644
--- a/remoting/webapp/session_connector.js
+++ b/remoting/webapp/session_connector.js
@@ -1,10 +1,10 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
- * Connect set-up state machine for Me2Me and IT2Me
+ * Interface abstracting the SessionConnector functionality.
Sergey Ulanov 2014/09/20 00:35:25 Now that the implementation is called SessionConne
Jamie 2014/09/20 00:54:22 Done.
*/
'use strict';
@@ -13,179 +13,15 @@
var remoting = remoting || {};
/**
- * @param {HTMLElement} clientContainer Container element for the client view.
- * @param {function(remoting.ClientSession):void} onConnected Callback on
- * success.
- * @param {function(remoting.Error):void} onError Callback on error.
- * @param {function(string, string):boolean} onExtensionMessage The handler for
- * protocol extension messages. Returns true if a message is recognized;
- * false otherwise.
- * @constructor
+ * @interface
*/
-remoting.SessionConnector = function(clientContainer, onConnected, onError,
- onExtensionMessage) {
- /**
- * @type {HTMLElement}
- * @private
- */
- this.clientContainer_ = clientContainer;
-
- /**
- * @type {function(remoting.ClientSession):void}
- * @private
- */
- this.onConnected_ = onConnected;
-
- /**
- * @type {function(remoting.Error):void}
- * @private
- */
- this.onError_ = onError;
-
- /**
- * @type {function(string, string):boolean}
- * @private
- */
- this.onExtensionMessage_ = onExtensionMessage;
-
- /**
- * @type {string}
- * @private
- */
- this.clientJid_ = '';
-
- /**
- * @type {remoting.ClientSession.Mode}
- * @private
- */
- this.connectionMode_ = remoting.ClientSession.Mode.ME2ME;
-
- /**
- * @type {remoting.SignalStrategy}
- * @private
- */
- this.signalStrategy_ = null;
-
- /**
- * @type {remoting.SmartReconnector}
- * @private
- */
- this.reconnector_ = null;
-
- /**
- * @private
- */
- this.bound_ = {
- onStateChange : this.onStateChange_.bind(this)
- };
-
- // Initialize/declare per-connection state.
- this.reset();
-};
+remoting.SessionConnector = function() {};
/**
* Reset the per-connection state so that the object can be re-used for a
* second connection. Note the none of the shared WCS state is reset.
*/
-remoting.SessionConnector.prototype.reset = function() {
- /**
- * Set to true to indicate that the user requested pairing when entering
- * their PIN for a Me2Me connection.
- *
- * @type {boolean}
- */
- this.pairingRequested = false;
-
- /**
- * String used to identify the host to which to connect. For IT2Me, this is
- * the first 7 digits of the access code; for Me2Me it is the host identifier.
- *
- * @type {string}
- * @private
- */
- this.hostId_ = '';
-
- /**
- * For paired connections, the client id of this device, issued by the host.
- *
- * @type {string}
- * @private
- */
- this.clientPairingId_ = '';
-
- /**
- * For paired connections, the paired secret for this device, issued by the
- * host.
- *
- * @type {string}
- * @private
- */
- this.clientPairedSecret_ = '';
-
- /**
- * String used to authenticate to the host on connection. For IT2Me, this is
- * the access code; for Me2Me it is the PIN.
- *
- * @type {string}
- * @private
- */
- this.passPhrase_ = '';
-
- /**
- * @type {string}
- * @private
- */
- this.hostJid_ = '';
-
- /**
- * @type {string}
- * @private
- */
- this.hostPublicKey_ = '';
-
- /**
- * @type {boolean}
- * @private
- */
- this.refreshHostJidIfOffline_ = false;
-
- /**
- * @type {remoting.ClientSession}
- * @private
- */
- this.clientSession_ = null;
-
- /**
- * @type {XMLHttpRequest}
- * @private
- */
- this.pendingXhr_ = null;
-
- /**
- * Function to interactively obtain the PIN from the user.
- * @type {function(boolean, function(string):void):void}
- * @private
- */
- this.fetchPin_ = function(onPinFetched) {};
-
- /**
- * @type {function(string, string, string,
- * function(string, string):void): void}
- * @private
- */
- this.fetchThirdPartyToken_ = function(
- tokenUrl, scope, onThirdPartyTokenFetched) {};
-
- /**
- * Host 'name', as displayed in the client tool-bar. For a Me2Me connection,
- * this is the name of the host; for an IT2Me connection, it is the email
- * address of the person sharing their computer.
- *
- * @type {string}
- * @private
- */
- this.hostDisplayName_ = '';
-};
+remoting.SessionConnector.prototype.reset = function() {};
/**
* Initiate a Me2Me connection.
@@ -205,12 +41,7 @@ remoting.SessionConnector.prototype.reset = function() {
*/
remoting.SessionConnector.prototype.connectMe2Me =
function(host, fetchPin, fetchThirdPartyToken,
- clientPairingId, clientPairedSecret) {
- this.connectMe2MeInternal_(
- host.hostId, host.jabberId, host.publicKey, host.hostName,
- fetchPin, fetchThirdPartyToken,
- clientPairingId, clientPairedSecret, true);
-};
+ clientPairingId, clientPairedSecret) {};
/**
* Update the pairing info so that the reconnect function will work correctly.
@@ -219,53 +50,7 @@ remoting.SessionConnector.prototype.connectMe2Me =
* @param {string} sharedSecret The shared secret.
*/
remoting.SessionConnector.prototype.updatePairingInfo =
- function(clientId, sharedSecret) {
- this.clientPairingId_ = clientId;
- this.clientPairedSecret_ = sharedSecret;
-};
-
-/**
- * Initiate a Me2Me connection.
- *
- * @param {string} hostId ID of the Me2Me host.
- * @param {string} hostJid XMPP JID of the host.
- * @param {string} hostPublicKey Public Key of the host.
- * @param {string} hostDisplayName Display name (friendly name) of the host.
- * @param {function(boolean, function(string):void):void} fetchPin Function to
- * interactively obtain the PIN from the user.
- * @param {function(string, string, string,
- * function(string, string): void): void}
- * fetchThirdPartyToken Function to obtain a token from a third party
- * authenticaiton server.
- * @param {string} clientPairingId The client id issued by the host when
- * this device was paired, if it is already paired.
- * @param {string} clientPairedSecret The shared secret issued by the host when
- * this device was paired, if it is already paired.
- * @param {boolean} refreshHostJidIfOffline Whether to refresh the JID and retry
- * the connection if the current JID is offline.
- * @return {void} Nothing.
- * @private
- */
-remoting.SessionConnector.prototype.connectMe2MeInternal_ =
- function(hostId, hostJid, hostPublicKey, hostDisplayName,
- fetchPin, fetchThirdPartyToken,
- clientPairingId, clientPairedSecret,
- refreshHostJidIfOffline) {
- // Cancel any existing connect operation.
- this.cancel();
-
- this.hostId_ = hostId;
- this.hostJid_ = hostJid;
- this.hostPublicKey_ = hostPublicKey;
- this.fetchPin_ = fetchPin;
- this.fetchThirdPartyToken_ = fetchThirdPartyToken;
- this.hostDisplayName_ = hostDisplayName;
- this.connectionMode_ = remoting.ClientSession.Mode.ME2ME;
- this.refreshHostJidIfOffline_ = refreshHostJidIfOffline;
- this.updatePairingInfo(clientPairingId, clientPairedSecret);
-
- this.connectSignaling_();
-}
+ function(clientId, sharedSecret) {};
/**
* Initiate an IT2Me connection.
@@ -273,322 +58,55 @@ remoting.SessionConnector.prototype.connectMe2MeInternal_ =
* @param {string} accessCode The access code as entered by the user.
* @return {void} Nothing.
*/
-remoting.SessionConnector.prototype.connectIT2Me = function(accessCode) {
- var kSupportIdLen = 7;
- var kHostSecretLen = 5;
- var kAccessCodeLen = kSupportIdLen + kHostSecretLen;
-
- // Cancel any existing connect operation.
- this.cancel();
-
- var normalizedAccessCode = this.normalizeAccessCode_(accessCode);
- if (normalizedAccessCode.length != kAccessCodeLen) {
- this.onError_(remoting.Error.INVALID_ACCESS_CODE);
- return;
- }
-
- this.hostId_ = normalizedAccessCode.substring(0, kSupportIdLen);
- this.passPhrase_ = normalizedAccessCode;
- this.connectionMode_ = remoting.ClientSession.Mode.IT2ME;
- remoting.identity.callWithToken(this.connectIT2MeWithToken_.bind(this),
- this.onError_);
-};
+remoting.SessionConnector.prototype.connectIT2Me =
+ function(accessCode) {};
/**
* Reconnect a closed connection.
*
* @return {void} Nothing.
*/
-remoting.SessionConnector.prototype.reconnect = function() {
- if (this.connectionMode_ == remoting.ClientSession.Mode.IT2ME) {
- console.error('reconnect not supported for IT2Me.');
- return;
- }
- this.connectMe2MeInternal_(
- this.hostId_, this.hostJid_, this.hostPublicKey_, this.hostDisplayName_,
- this.fetchPin_, this.fetchThirdPartyToken_,
- this.clientPairingId_, this.clientPairedSecret_, true);
-};
+remoting.SessionConnector.prototype.reconnect = function() {};
/**
* Cancel a connection-in-progress.
*/
-remoting.SessionConnector.prototype.cancel = function() {
- if (this.clientSession_) {
- this.clientSession_.removePlugin();
- this.clientSession_ = null;
- }
- if (this.pendingXhr_) {
- this.pendingXhr_.abort();
- this.pendingXhr_ = null;
- }
- this.reset();
-};
+remoting.SessionConnector.prototype.cancel = function() {};
/**
* Get the connection mode (Me2Me or IT2Me)
*
* @return {remoting.ClientSession.Mode}
*/
-remoting.SessionConnector.prototype.getConnectionMode = function() {
- return this.connectionMode_;
-};
+remoting.SessionConnector.prototype.getConnectionMode = function() {};
/**
* Get host ID.
*
* @return {string}
*/
-remoting.SessionConnector.prototype.getHostId = function() {
- return this.hostId_;
-};
-
-/**
- * @private
- */
-remoting.SessionConnector.prototype.connectSignaling_ = function() {
- base.dispose(this.signalStrategy_);
- this.signalStrategy_ = null;
-
- /** @type {remoting.SessionConnector} */
- var that = this;
-
- /** @param {string} token */
- function connectSignalingWithToken(token) {
- remoting.identity.getEmail(
- connectSignalingWithTokenAndEmail.bind(null, token), that.onError_);
- }
-
- /**
- * @param {string} token
- * @param {string} email
- */
- function connectSignalingWithTokenAndEmail(token, email) {
- that.signalStrategy_.connect(
- remoting.settings.XMPP_SERVER_ADDRESS, email, token);
- }
-
- // Only use XMPP when TCP API is available and TLS support is enabled. That's
- // not the case for V1 app (socket API is available only to platform apps)
- // and for Chrome releases before 38.
- if (chrome.socket && chrome.socket.secure) {
- this.signalStrategy_ = /** @type {remoting.SignalStrategy} */
- (new remoting.XmppConnection(this.onSignalingState_.bind(this)));
- } else {
- this.signalStrategy_ = /** @type {remoting.SignalStrategy} */
- (new remoting.WcsAdapter(this.onSignalingState_.bind(this)));
- }
-
- remoting.identity.callWithToken(connectSignalingWithToken, this.onError_);
-};
-
-/**
- * @private
- * @param {remoting.SignalStrategy.State} state
- */
-remoting.SessionConnector.prototype.onSignalingState_ = function(state) {
- switch (state) {
- case remoting.SignalStrategy.State.CONNECTED:
- // Proceed only if the connection hasn't been canceled.
- if (this.hostJid_) {
- this.createSession_();
- }
- break;
-
- case remoting.SignalStrategy.State.FAILED:
- this.onError_(this.signalStrategy_.getError());
- break;
- }
-};
-
-/**
- * Continue an IT2Me connection once an access token has been obtained.
- *
- * @param {string} token An OAuth2 access token.
- * @return {void} Nothing.
- * @private
- */
-remoting.SessionConnector.prototype.connectIT2MeWithToken_ = function(token) {
- // Resolve the host id to get the host JID.
- this.pendingXhr_ = remoting.xhr.get(
- remoting.settings.DIRECTORY_API_BASE_URL + '/support-hosts/' +
- encodeURIComponent(this.hostId_),
- this.onIT2MeHostInfo_.bind(this),
- '',
- { 'Authorization': 'OAuth ' + token });
-};
+remoting.SessionConnector.prototype.getHostId = function() {};
-/**
- * Continue an IT2Me connection once the host JID has been looked up.
- *
- * @param {XMLHttpRequest} xhr The server response to the support-hosts query.
- * @return {void} Nothing.
- * @private
- */
-remoting.SessionConnector.prototype.onIT2MeHostInfo_ = function(xhr) {
- this.pendingXhr_ = null;
- if (xhr.status == 200) {
- var host = /** @type {{data: {jabberId: string, publicKey: string}}} */
- jsonParseSafe(xhr.responseText);
- if (host && host.data && host.data.jabberId && host.data.publicKey) {
- this.hostJid_ = host.data.jabberId;
- this.hostPublicKey_ = host.data.publicKey;
- this.hostDisplayName_ = this.hostJid_.split('/')[0];
- this.createSession_();
- return;
- } else {
- console.error('Invalid "support-hosts" response from server.');
- }
- } else {
- this.onError_(this.translateSupportHostsError(xhr.status));
- }
-};
/**
- * Creates ClientSession object.
+ * @interface
*/
-remoting.SessionConnector.prototype.createSession_ = function() {
- // In some circumstances, the WCS <iframe> can get reloaded, which results
- // in a new clientJid and a new callback. In this case, remove the old
- // client plugin before instantiating a new one.
- if (this.clientSession_) {
- this.clientSession_.removePlugin();
- this.clientSession_ = null;
- }
-
- var authenticationMethods =
- 'third_party,spake2_pair,spake2_hmac,spake2_plain';
- this.clientSession_ = new remoting.ClientSession(
- this.signalStrategy_, this.clientContainer_, this.hostDisplayName_,
- this.passPhrase_, this.fetchPin_, this.fetchThirdPartyToken_,
- authenticationMethods, this.hostId_, this.hostJid_, this.hostPublicKey_,
- this.connectionMode_, this.clientPairingId_, this.clientPairedSecret_);
- this.clientSession_.logHostOfflineErrors(!this.refreshHostJidIfOffline_);
- this.clientSession_.addEventListener(
- remoting.ClientSession.Events.stateChanged,
- this.bound_.onStateChange);
- this.clientSession_.createPluginAndConnect(this.onExtensionMessage_);
-};
+remoting.SessionConnectorFactory = function() {};
/**
- * Handle a change in the state of the client session prior to successful
- * connection (after connection, this class no longer handles state change
- * events). Errors that occur while connecting either trigger a reconnect
- * or notify the onError handler.
- *
- * @param {remoting.ClientSession.StateEvent} event
- * @return {void} Nothing.
- * @private
- */
-remoting.SessionConnector.prototype.onStateChange_ = function(event) {
- switch (event.current) {
- case remoting.ClientSession.State.CONNECTED:
- // When the connection succeeds, deregister for state-change callbacks
- // and pass the session to the onConnected callback. It is expected that
- // it will register a new state-change callback to handle disconnect
- // or error conditions.
- this.clientSession_.removeEventListener(
- remoting.ClientSession.Events.stateChanged,
- this.bound_.onStateChange);
-
- base.dispose(this.reconnector_);
- if (this.connectionMode_ != remoting.ClientSession.Mode.IT2ME) {
- this.reconnector_ =
- new remoting.SmartReconnector(this, this.clientSession_);
- }
- this.onConnected_(this.clientSession_);
- break;
-
- case remoting.ClientSession.State.CREATED:
- console.log('Created plugin');
- break;
-
- case remoting.ClientSession.State.CONNECTING:
- console.log('Connecting as ' + remoting.identity.getCachedEmail());
- break;
-
- case remoting.ClientSession.State.INITIALIZING:
- console.log('Initializing connection');
- break;
-
- case remoting.ClientSession.State.CLOSED:
- // This class deregisters for state-change callbacks when the CONNECTED
- // state is reached, so it only sees the CLOSED state in exceptional
- // circumstances. For example, a CONNECTING -> CLOSED transition happens
- // if the host closes the connection without an error message instead of
- // accepting it. Since there's no way of knowing exactly what went wrong,
- // we rely on server-side logs in this case and report a generic error
- // message.
- this.onError_(remoting.Error.UNEXPECTED);
- break;
-
- case remoting.ClientSession.State.FAILED:
- var error = this.clientSession_.getError();
- console.error('Client plugin reported connection failed: ' + error);
- if (error == null) {
- error = remoting.Error.UNEXPECTED;
- }
- if (error == remoting.Error.HOST_IS_OFFLINE &&
- this.refreshHostJidIfOffline_) {
- // The plugin will be re-created when the host finished refreshing
- remoting.hostList.refresh(this.onHostListRefresh_.bind(this));
- } else {
- this.onError_(error);
- }
- break;
-
- default:
- console.error('Unexpected client plugin state: ' + event.current);
- // This should only happen if the web-app and client plugin get out of
- // sync, and even then the version check should ensure compatibility.
- this.onError_(remoting.Error.MISSING_PLUGIN);
- }
-};
-
-/**
- * @param {boolean} success True if the host list was successfully refreshed;
- * false if an error occurred.
- * @private
- */
-remoting.SessionConnector.prototype.onHostListRefresh_ = function(success) {
- if (success) {
- var host = remoting.hostList.getHostForId(this.hostId_);
- if (host) {
- this.connectMe2MeInternal_(
- host.hostId, host.jabberId, host.publicKey, host.hostName,
- this.fetchPin_, this.fetchThirdPartyToken_,
- this.clientPairingId_, this.clientPairedSecret_, false);
- return;
- }
- }
- this.onError_(remoting.Error.HOST_IS_OFFLINE);
-};
-
-/**
- * @param {number} error An HTTP error code returned by the support-hosts
- * endpoint.
- * @return {remoting.Error} The equivalent remoting.Error code.
- * @private
+ * @param {HTMLElement} clientContainer Container element for the client view.
+ * @param {function(remoting.ClientSession):void} onConnected Callback on
+ * success.
+ * @param {function(remoting.Error):void} onError Callback on error.
+ * @param {function(string, string):boolean} onExtensionMessage The handler for
+ * protocol extension messages. Returns true if a message is recognized;
+ * false otherwise.
+ * @return {remoting.SessionConnector}
*/
-remoting.SessionConnector.prototype.translateSupportHostsError =
- function(error) {
- switch (error) {
- case 0: return remoting.Error.NETWORK_FAILURE;
- case 404: return remoting.Error.INVALID_ACCESS_CODE;
- case 502: // No break
- case 503: return remoting.Error.SERVICE_UNAVAILABLE;
- default: return remoting.Error.UNEXPECTED;
- }
-};
+remoting.SessionConnectorFactory.prototype.createConnector =
+ function(clientContainer, onConnected, onError, onExtensionMessage) {};
/**
- * Normalize the access code entered by the user.
- *
- * @param {string} accessCode The access code, as entered by the user.
- * @return {string} The normalized form of the code (whitespace removed).
+ * @type {remoting.SessionConnectorFactory}
*/
-remoting.SessionConnector.prototype.normalizeAccessCode_ =
- function(accessCode) {
- // Trim whitespace.
- return accessCode.replace(/\s/g, '');
-};
+remoting.SessionConnector.factory = null;

Powered by Google App Engine
This is Rietveld 408576698