summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorkelvinp <kelvinp@chromium.org>2015-04-17 17:39:45 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-18 00:40:06 +0000
commitcb655c2ca0a46c9402c65e74ef736037ed6bd3a8 (patch)
tree54f7fcd1e364cf61b345b565936f33cb449484fa /remoting
parent9bb592340bc912b5c8d09432b139e04aa8713842 (diff)
downloadchromium_src-cb655c2ca0a46c9402c65e74ef736037ed6bd3a8.zip
chromium_src-cb655c2ca0a46c9402c65e74ef736037ed6bd3a8.tar.gz
chromium_src-cb655c2ca0a46c9402c65e74ef736037ed6bd3a8.tar.bz2
Revert of [Webapp Refactor] Remove remoting.SessionConnector. (patchset #3 id:60001 of https://codereview.chromium.org/1047413006/)
Reason for revert: Bad merge with a previous version that will cause compilation failure. Original issue's description: > [Webapp Refactor] Remove remoting.SessionConnector. > > remoting.SessionConnector is currently responsible for creating > the plugin, the signal strategy and the clientSession. It also > magically disposes the plugin when the clientSession finishes. > > However, the session is not exposed to the caller elsewhere, which makes > it hard for the caller to dispose of the session before it is connected, > e.g. Cancel a PIN entry. > > It is currently a stateful object that keeps track of the host, > credentials provider, strategy of the created session, which is redundant. > > This CL > 1. Offloads the creation of the clientSession to the > remoting.ClientSessionFactory. It also allow the caller to configure > a clientSession prior to connecting. The remoting.ClientSessionFactory > is essentially stateless except for a few predefined ClientSession > construction parameters. > 2. Allow the caller to have a different instance of > ClientSession.EventHandler for each instance ClientSession created. > 3. Revives remoting.MockClientPlugin and uses it for remoting.ClientSessionFactory > unittests. > > Ownership graph before: > Activity -> SessionConenctor -> ClientSession > > Ownership graph after: > Activity -> ClientSession > > BUG=477522 > TEST=All browser tests passed on > https://chromium-swarm.appspot.com/user/tasks?sort=created_ts&state=all&limit=10&task_name=chromoting_integration_tests > > Committed: https://crrev.com/4c69287fc3e0ad6663ab98f02ef57c570f8992e3 > Cr-Commit-Position: refs/heads/master@{#325745} TBR=jamiewalch@chromium.org,garykac@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=477522 Review URL: https://codereview.chromium.org/1096883002 Cr-Commit-Position: refs/heads/master@{#325748}
Diffstat (limited to 'remoting')
-rw-r--r--remoting/remoting_webapp_files.gypi6
-rw-r--r--remoting/webapp/app_remoting/js/app_remoting_activity.js24
-rw-r--r--remoting/webapp/base/js/application.js2
-rw-r--r--remoting/webapp/base/js/protocol_extension.js2
-rw-r--r--remoting/webapp/crd/js/client_session.js98
-rw-r--r--remoting/webapp/crd/js/client_session_factory.js134
-rw-r--r--remoting/webapp/crd/js/client_session_factory_unittest.js100
-rw-r--r--remoting/webapp/crd/js/desktop_remoting_activity.js26
-rw-r--r--remoting/webapp/crd/js/it2me_activity.js10
-rw-r--r--remoting/webapp/crd/js/me2me_activity.js11
-rw-r--r--remoting/webapp/crd/js/mock_client_plugin.js82
-rw-r--r--remoting/webapp/crd/js/mock_session_connector.js171
-rw-r--r--remoting/webapp/crd/js/session_connector.js52
-rw-r--r--remoting/webapp/crd/js/session_connector_impl.js291
14 files changed, 599 insertions, 410 deletions
diff --git a/remoting/remoting_webapp_files.gypi b/remoting/remoting_webapp_files.gypi
index c65ea7f..e327d72 100644
--- a/remoting/remoting_webapp_files.gypi
+++ b/remoting/remoting_webapp_files.gypi
@@ -39,6 +39,7 @@
'webapp/crd/js/mock_host_list_api.js',
'webapp/crd/js/mock_identity.js',
'webapp/crd/js/mock_oauth2_api.js',
+ 'webapp/crd/js/mock_session_connector.js',
'webapp/crd/js/mock_signal_strategy.js',
],
'remoting_webapp_browsertest_js_proto_files': [
@@ -73,7 +74,6 @@
'webapp/base/js/protocol_extension_manager_unittest.js',
'webapp/crd/js/apps_v2_migration_unittest.js',
'webapp/crd/js/desktop_viewport_unittest.js',
- 'webapp/crd/js/client_session_factory_unittest.js',
'webapp/crd/js/dns_blackhole_checker_unittest.js',
'webapp/crd/js/error_unittest.js',
'webapp/crd/js/fallback_signal_strategy_unittest.js',
@@ -95,7 +95,6 @@
'remoting_webapp_unittests_js_mock_files': [
# Some proto files can be repurposed as simple mocks for the unittests.
# Note that some defs in chrome_proto are overwritten by chrome_mocks.
- 'webapp/crd/js/mock_client_plugin.js',
'webapp/crd/js/mock_host_daemon_facade.js',
'webapp/crd/js/mock_signal_strategy.js',
'webapp/js_proto/chrome_proto.js',
@@ -158,13 +157,14 @@
'webapp/crd/js/client_plugin_impl.js',
'webapp/crd/js/client_plugin_host_desktop_impl.js',
'webapp/crd/js/client_session.js',
- 'webapp/crd/js/client_session_factory.js',
'webapp/crd/js/clipboard.js',
'webapp/crd/js/connected_view.js',
'webapp/crd/js/connection_info.js',
'webapp/crd/js/credentials_provider.js',
'webapp/crd/js/desktop_connected_view.js',
'webapp/crd/js/host_desktop.js',
+ 'webapp/crd/js/session_connector.js',
+ 'webapp/crd/js/session_connector_impl.js',
'webapp/crd/js/smart_reconnector.js',
'webapp/crd/js/video_frame_recorder.js',
],
diff --git a/remoting/webapp/app_remoting/js/app_remoting_activity.js b/remoting/webapp/app_remoting/js/app_remoting_activity.js
index fecd55d..3685946 100644
--- a/remoting/webapp/app_remoting/js/app_remoting_activity.js
+++ b/remoting/webapp/app_remoting/js/app_remoting_activity.js
@@ -35,9 +35,9 @@ remoting.AppRemotingActivity = function(appCapabilities) {
this.connectedView_ = null;
/** @private */
- this.sessionFactory_ = new remoting.ClientSessionFactory(
- document.querySelector('#client-container .client-plugin-container'),
- appCapabilities);
+ this.connector_ = remoting.SessionConnector.factory.createConnector(
+ document.getElementById('client-container'), appCapabilities,
+ this);
/** @private {remoting.ClientSession} */
this.session_ = null;
@@ -69,7 +69,6 @@ remoting.AppRemotingActivity.prototype.stop = function() {
remoting.AppRemotingActivity.prototype.cleanup_ = function() {
base.dispose(this.connectedView_);
this.connectedView_ = null;
- base.dispose(this.session_);
this.session_ = null;
};
@@ -128,17 +127,11 @@ remoting.AppRemotingActivity.prototype.onAppHostResponse_ =
host['sharedSecret']);
};
- remoting.app.setConnectionMode(remoting.Application.Mode.APP_REMOTING);
- var credentialsProvider = new remoting.CredentialsProvider(
- {fetchThirdPartyToken: fetchThirdPartyToken});
- var that = this;
-
- this.sessionFactory_.createSession(this).then(
- function(/** remoting.ClientSession */ session) {
- that.session_ = session;
- session.logHostOfflineErrors(true);
- session.connect(host, credentialsProvider);
- });
+ this.connector_.connect(
+ remoting.Application.Mode.APP_REMOTING, host,
+ new remoting.CredentialsProvider(
+ {fetchThirdPartyToken: fetchThirdPartyToken}));
+
} else if (response && response.status == 'pending') {
this.onError(new remoting.Error(
remoting.Error.Tag.SERVICE_UNAVAILABLE));
@@ -156,6 +149,7 @@ remoting.AppRemotingActivity.prototype.onConnected = function(connectionInfo) {
this.connectedView_ = new remoting.AppConnectedView(
document.getElementById('client-container'), connectionInfo);
+ this.session_ = connectionInfo.session();
var idleDetector = new remoting.IdleDetector(
document.getElementById('idle-dialog'), this.stop.bind(this));
diff --git a/remoting/webapp/base/js/application.js b/remoting/webapp/base/js/application.js
index 48a4f61..63cafa0 100644
--- a/remoting/webapp/base/js/application.js
+++ b/remoting/webapp/base/js/application.js
@@ -25,6 +25,8 @@ remoting.testEvents;
remoting.Application = function() {
// Create global factories.
remoting.ClientPlugin.factory = new remoting.DefaultClientPluginFactory();
+ remoting.SessionConnector.factory =
+ new remoting.DefaultSessionConnectorFactory();
/** @protected {remoting.Application.Mode} */
this.connectionMode_ = remoting.Application.Mode.ME2ME;
diff --git a/remoting/webapp/base/js/protocol_extension.js b/remoting/webapp/base/js/protocol_extension.js
index 11d8aa6..28103f7 100644
--- a/remoting/webapp/base/js/protocol_extension.js
+++ b/remoting/webapp/base/js/protocol_extension.js
@@ -5,7 +5,7 @@
/**
* @fileoverview
* Interface abstracting the protocol extension functionality.
- * Instances of this class can be registered with the ProtocolExtensionManager
+ * Instances of this class can be registered with the SessionConnector
* to enhance the communication protocol between the host and client.
* Note that corresponding support on the host side is required.
*/
diff --git a/remoting/webapp/crd/js/client_session.js b/remoting/webapp/crd/js/client_session.js
index b31d69f..f76069e 100644
--- a/remoting/webapp/crd/js/client_session.js
+++ b/remoting/webapp/crd/js/client_session.js
@@ -8,8 +8,9 @@
*
* The ClientSession class controls lifetime of the client plugin
* object and provides the plugin with the functionality it needs to
- * establish connection, e.g. delivers incoming/outgoing signaling
- * messages.
+ * establish connection. Specifically it:
+ * - Delivers incoming/outgoing signaling messages,
+ * - Adjusts plugin size and position when destop resolution changes,
*
* This class should not access the plugin directly, instead it should
* do it through ClientPlugin class which abstracts plugin version
@@ -23,15 +24,15 @@ var remoting = remoting || {};
/**
* @param {remoting.ClientPlugin} plugin
+ * @param {remoting.Host} host The host to connect to.
* @param {remoting.SignalStrategy} signalStrategy Signal strategy.
- * @param {remoting.ClientSession.EventHandler} listener
*
* @constructor
* @extends {base.EventSourceImpl}
* @implements {base.Disposable}
* @implements {remoting.ClientPlugin.ConnectionEventHandler}
*/
-remoting.ClientSession = function(plugin, signalStrategy, listener) {
+remoting.ClientSession = function(plugin, host, signalStrategy) {
base.inherits(this, base.EventSourceImpl);
/** @private */
@@ -40,17 +41,11 @@ remoting.ClientSession = function(plugin, signalStrategy, listener) {
/** @private {!remoting.Error} */
this.error_ = remoting.Error.none();
- /** @private {remoting.Host} */
- this.host_ = null;
-
- /** @private {remoting.CredentialsProvider} */
- this.credentialsProvider_ = null;
-
/** @private */
- this.sessionId_ = '';
+ this.host_ = host;
/** @private */
- this.listener_ = listener;
+ this.sessionId_ = '';
/** @private */
this.hasReceivedFrame_ = false;
@@ -63,8 +58,9 @@ remoting.ClientSession = function(plugin, signalStrategy, listener) {
this.signalStrategy_.setIncomingStanzaCallback(
this.onIncomingMessage_.bind(this));
- /** @private {remoting.FormatIq} */
- this.iqFormatter_ = null;
+ /** @private */
+ this.iqFormatter_ =
+ new remoting.FormatIq(this.signalStrategy_.getJid(), host.jabberId);
/**
* Allow host-offline error reporting to be suppressed in situations where it
@@ -259,21 +255,6 @@ remoting.ClientSession.Capability = {
};
/**
- * Connects to |host| using |credentialsProvider| as the credentails.
- *
- * @param {remoting.Host} host
- * @param {remoting.CredentialsProvider} credentialsProvider
- */
-remoting.ClientSession.prototype.connect = function(host, credentialsProvider) {
- this.host_ = host;
- this.credentialsProvider_ = credentialsProvider;
- this.iqFormatter_ =
- new remoting.FormatIq(this.signalStrategy_.getJid(), host.jabberId);
- this.plugin_.connect(this.host_, this.signalStrategy_.getJid(),
- credentialsProvider);
-};
-
-/**
* Disconnect the current session with a particular |error|. The session will
* raise a |stateChanged| event in response to it. The caller should then call
* dispose() to remove and destroy the <embed> element.
@@ -316,7 +297,6 @@ remoting.ClientSession.prototype.disconnect = function(error) {
remoting.ClientSession.prototype.dispose = function() {
base.dispose(this.connectedDisposables_);
this.connectedDisposables_ = null;
- base.dispose(this.plugin_);
this.plugin_ = null;
};
@@ -508,65 +488,7 @@ remoting.ClientSession.prototype.setState_ = function(newState) {
this.connectedDisposables_ = null;
}
- this.notifyStateChanges_(oldState, this.state_);
this.logToServer.logClientSessionStateChange(this.state_, this.error_);
-};
-
-/**
- * @param {remoting.ClientSession.State} oldState The new state for the session.
- * @param {remoting.ClientSession.State} newState The new state for the session.
- * @private
- */
-remoting.ClientSession.prototype.notifyStateChanges_ =
- function(oldState, newState) {
- /** @type {remoting.Error} */
- var error;
- switch (this.state_) {
- case remoting.ClientSession.State.CONNECTED:
- console.log('Connection established.');
- var connectionInfo = new remoting.ConnectionInfo(
- this.host_, this.credentialsProvider_, this, this.plugin_);
- this.listener_.onConnected(connectionInfo);
- break;
-
- case remoting.ClientSession.State.CONNECTING:
- remoting.identity.getEmail().then(function(/** string */ email) {
- console.log('Connecting as ' + email);
- });
- break;
-
- case remoting.ClientSession.State.AUTHENTICATED:
- console.log('Connection authenticated.');
- break;
-
- case remoting.ClientSession.State.INITIALIZING:
- console.log('Connection initializing .');
- break;
-
- case remoting.ClientSession.State.CLOSED:
- console.log('Connection closed.');
- this.listener_.onDisconnected();
- break;
-
- case remoting.ClientSession.State.FAILED:
- error = this.getError();
- console.error('Connection failed: ' + error.toString());
- this.listener_.onConnectionFailed(error);
- break;
-
- case remoting.ClientSession.State.CONNECTION_DROPPED:
- error = this.getError();
- console.error('Connection dropped: ' + error.toString());
- this.listener_.onError(error);
- break;
-
- default:
- console.error('Unexpected client plugin state: ' + newState);
- // 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.listener_.onError(
- new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
- }
this.raiseEvent(remoting.ClientSession.Events.stateChanged,
new remoting.ClientSession.StateEvent(newState, oldState)
diff --git a/remoting/webapp/crd/js/client_session_factory.js b/remoting/webapp/crd/js/client_session_factory.js
deleted file mode 100644
index 24cfa2a..0000000
--- a/remoting/webapp/crd/js/client_session_factory.js
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2015 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.
-
-/** @suppress {duplicate} */
-var remoting = remoting || {};
-
-(function() {
-
-'use strict';
-
-/**
- * @param {Element} container parent element for the plugin to be created.
- * @param {Array<string>} capabilities capabilities required by this
- * application.
- * @constructor
- */
-remoting.ClientSessionFactory = function(container, capabilities) {
- /** @private */
- this.container_ = /** @type {HTMLElement} */ (container);
-
- /** @private {Array<string>} */
- this.requiredCapabilities_ = [
- remoting.ClientSession.Capability.SEND_INITIAL_RESOLUTION,
- remoting.ClientSession.Capability.RATE_LIMIT_RESIZE_REQUESTS,
- remoting.ClientSession.Capability.VIDEO_RECORDER
- ];
-
- // Append the app-specific capabilities.
- this.requiredCapabilities_.push.apply(this.requiredCapabilities_,
- capabilities);
-};
-
-/**
- * Creates a session.
- *
- * @param {remoting.ClientSession.EventHandler} listener
- * @return {Promise<!remoting.ClientSession>} Resolves with the client session
- * if succeeded or rejects with remoting.Error on failure.
- */
-remoting.ClientSessionFactory.prototype.createSession = function(listener) {
- var that = this;
- /** @type {string} */
- var token;
- /** @type {remoting.SignalStrategy} */
- var signalStrategy;
- /** @type {remoting.ClientPlugin} */
- var clientPlugin;
-
- function OnError(/** remoting.Error */ error) {
- base.dispose(signalStrategy);
- base.dispose(clientPlugin);
- throw error;
- }
-
- var promise = remoting.identity.getToken().then(
- function(/** string */ authToken) {
- token = authToken;
- return remoting.identity.getUserInfo();
- }).then(function(/** {email: string, name: string} */ userInfo) {
- return connectSignaling(userInfo.email, token);
- }).then(function(/** remoting.SignalStrategy */ strategy) {
- signalStrategy = strategy;
- return createPlugin(that.container_, that.requiredCapabilities_);
- }).then(function(/** remoting.ClientPlugin */ plugin) {
- clientPlugin = plugin;
- return new remoting.ClientSession(plugin, signalStrategy, listener);
- }).catch(
- remoting.Error.handler(OnError)
- );
-
- return /** @type {Promise<!remoting.ClientSession>} */ (promise);
-};
-
-/**
- * @param {string} email
- * @param {string} token
- * @return {Promise<!remoting.SignalStrategy>}
- */
-function connectSignaling(email, token) {
- var signalStrategy = remoting.SignalStrategy.create();
- var deferred = new base.Deferred();
- function onSignalingState(/** remoting.SignalStrategy.State */ state) {
- switch (state) {
- case remoting.SignalStrategy.State.CONNECTED:
- deferred.resolve(signalStrategy);
- break;
-
- case remoting.SignalStrategy.State.FAILED:
- var error = signalStrategy.getError();
- signalStrategy.dispose();
- deferred.reject(error);
- break;
- }
- }
- signalStrategy.setStateChangedCallback(onSignalingState);
- signalStrategy.connect(remoting.settings.XMPP_SERVER, email, token);
- return deferred.promise();
-}
-
-/**
- * Creates the plugin.
- * @param {HTMLElement} container parent element for the plugin.
- * @param {Array<string>} capabilities capabilities required by this
- * application.
- * @return {Promise<!remoting.ClientPlugin>}
- */
-function createPlugin(container, capabilities) {
- var plugin = remoting.ClientPlugin.factory.createPlugin(
- container, capabilities);
- var deferred = new base.Deferred();
-
- function onInitialized(/** boolean */ initialized) {
- if (!initialized) {
- console.error('ERROR: remoting plugin not loaded');
- plugin.dispose();
- deferred.reject(new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
- return;
- }
-
- if (!plugin.isSupportedVersion()) {
- console.error('ERROR: bad plugin version');
- plugin.dispose();
- deferred.reject(
- new remoting.Error(remoting.Error.Tag.BAD_PLUGIN_VERSION));
- return;
- }
- deferred.resolve(plugin);
- }
- plugin.initialize(onInitialized);
- return deferred.promise();
-}
-
-})();
diff --git a/remoting/webapp/crd/js/client_session_factory_unittest.js b/remoting/webapp/crd/js/client_session_factory_unittest.js
deleted file mode 100644
index f0e884c..0000000
--- a/remoting/webapp/crd/js/client_session_factory_unittest.js
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2015 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.
-
-(function() {
-
-'use strict';
-
-var originalPluginFactory;
-var originalIdentity;
-var originalSettings;
-
-/** @type {remoting.MockSignalStrategy} */
-var mockSignalStrategy;
-/** @type {remoting.ClientSessionFactory} */
-var factory;
-/** @type {remoting.ClientSession.EventHandler} */
-var listener;
-/** @type {sinon.TestStub} */
-var createSignalStrategyStub;
-
-/**
- * @constructor
- * @implements {remoting.ClientSession.EventHandler}
- */
-var SessionListener = function() {};
-SessionListener.prototype.onConnectionFailed = function(error) {};
-SessionListener.prototype.onConnected = function(connectionInfo) {};
-SessionListener.prototype.onDisconnected = function() {};
-SessionListener.prototype.onError = function(error) {};
-
-QUnit.module('ClientSessionFactory', {
- beforeEach: function() {
- originalPluginFactory = remoting.ClientPlugin.factory;
- remoting.ClientPlugin.factory = new remoting.MockClientPluginFactory();
-
- mockSignalStrategy = new remoting.MockSignalStrategy(
- 'jid', remoting.SignalStrategy.Type.XMPP);
- createSignalStrategyStub = sinon.stub(remoting.SignalStrategy, 'create');
- createSignalStrategyStub.returns(mockSignalStrategy);
- listener = new SessionListener();
-
- originalIdentity = remoting.identity;
- remoting.identity = new remoting.Identity();
- chromeMocks.activate(['identity']);
- chromeMocks.identity.mock$setToken('fake_token');
-
- originalSettings = remoting.settings;
- remoting.settings = new remoting.Settings();
-
- remoting.identity.getUserInfo = function() {
- return { email: 'email', userName: 'userName'};
- };
-
- factory = new remoting.ClientSessionFactory(
- document.createElement('div'), ['fake_capability']);
- },
- afterEach: function() {
- remoting.settings = originalSettings;
- remoting.identity = originalIdentity;
- chromeMocks.restore();
- remoting.identity = null;
- remoting.ClientPlugin.factory = originalPluginFactory;
- createSignalStrategyStub.restore();
- }
-});
-
-QUnit.test('createSession() should return a remoting.ClientSession',
- function(assert) {
-
- mockSignalStrategy.connect = function() {
- mockSignalStrategy.setStateForTesting(
- remoting.SignalStrategy.State.CONNECTED);
- };
-
- return factory.createSession(listener).then(
- function(/** remoting.ClientSession */ session){
- assert.ok(session instanceof remoting.ClientSession);
- });
-});
-
-QUnit.test('createSession() should reject on signal strategy failure',
- function(assert) {
-
- mockSignalStrategy.connect = function() {
- mockSignalStrategy.setStateForTesting(remoting.SignalStrategy.State.FAILED);
- };
-
- var signalStrategyDispose =
- /** @type {sinon.Spy} */ (sinon.spy(mockSignalStrategy, 'dispose'));
-
- return factory.createSession(listener).then(
- assert.ok.bind(assert, false, 'Expect createSession to fail')
- ).catch(function(/** remoting.Error */ error) {
- assert.ok(signalStrategyDispose.called);
- assert.equal(error.getDetail(), 'setStateForTesting');
- });
-});
-
-})();
diff --git a/remoting/webapp/crd/js/desktop_remoting_activity.js b/remoting/webapp/crd/js/desktop_remoting_activity.js
index 1e64621..369b228 100644
--- a/remoting/webapp/crd/js/desktop_remoting_activity.js
+++ b/remoting/webapp/crd/js/desktop_remoting_activity.js
@@ -24,33 +24,10 @@ remoting.DesktopRemotingActivity = function(parentActivity) {
this.parentActivity_ = parentActivity;
/** @private {remoting.DesktopConnectedView} */
this.connectedView_ = null;
- /** @private */
- this.sessionFactory_ = new remoting.ClientSessionFactory(
- document.querySelector('#client-container .client-plugin-container'),
- remoting.app_capabilities());
/** @private {remoting.ClientSession} */
this.session_ = null;
};
-/**
- * Initiates a connection.
- *
- * @param {remoting.Host} host the Host to connect to.
- * @param {remoting.CredentialsProvider} credentialsProvider
- * @param {boolean=} opt_suppressOfflineError
- * @return {void} Nothing.
- */
-remoting.DesktopRemotingActivity.prototype.start =
- function(host, credentialsProvider, opt_suppressOfflineError) {
- var that = this;
- this.sessionFactory_.createSession(this).then(
- function(/** remoting.ClientSession */ session) {
- that.session_ = session;
- session.logHostOfflineErrors(!opt_suppressOfflineError);
- session.connect(host, credentialsProvider);
- });
-};
-
remoting.DesktopRemotingActivity.prototype.stop = function() {
if (this.session_) {
this.session_.disconnect(remoting.Error.none());
@@ -69,6 +46,8 @@ remoting.DesktopRemotingActivity.prototype.onConnected =
remoting.toolbar.preview();
}
+ this.session_ = connectionInfo.session();
+
this.connectedView_ = new remoting.DesktopConnectedView(
document.getElementById('client-container'), connectionInfo);
@@ -121,7 +100,6 @@ remoting.DesktopRemotingActivity.prototype.onError = function(error) {
remoting.DesktopRemotingActivity.prototype.dispose = function() {
base.dispose(this.connectedView_);
this.connectedView_ = null;
- base.dispose(this.session_);
this.session_ = null;
};
diff --git a/remoting/webapp/crd/js/it2me_activity.js b/remoting/webapp/crd/js/it2me_activity.js
index e5dc2db..4ee50c3 100644
--- a/remoting/webapp/crd/js/it2me_activity.js
+++ b/remoting/webapp/crd/js/it2me_activity.js
@@ -185,9 +185,13 @@ remoting.It2MeActivity.prototype.onHostInfo_ = function(xhrResponse) {
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(
- host, new remoting.CredentialsProvider({ accessCode: this.passCode_ }));
+ var sessionConnector = remoting.SessionConnector.factory.createConnector(
+ document.getElementById('client-container'),
+ remoting.app_capabilities(),
+ this.desktopActivity_);
+ sessionConnector.connect(
+ remoting.Application.Mode.IT2ME, host,
+ new remoting.CredentialsProvider({ accessCode: this.passCode_ }));
};
/**
diff --git a/remoting/webapp/crd/js/me2me_activity.js b/remoting/webapp/crd/js/me2me_activity.js
index 7d2b090..7f91246 100644
--- a/remoting/webapp/crd/js/me2me_activity.js
+++ b/remoting/webapp/crd/js/me2me_activity.js
@@ -72,9 +72,14 @@ remoting.Me2MeActivity.prototype.connect_ = function(suppressHostOfflineError) {
remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
base.dispose(this.desktopActivity_);
this.desktopActivity_ = new remoting.DesktopRemotingActivity(this);
- remoting.app.setConnectionMode(remoting.Application.Mode.ME2ME);
- this.desktopActivity_.start(this.host_, this.createCredentialsProvider_(),
- suppressHostOfflineError);
+ var connector = remoting.SessionConnector.factory.createConnector(
+ document.getElementById('client-container'),
+ remoting.app_capabilities(),
+ this.desktopActivity_);
+
+ connector.connect(
+ remoting.Application.Mode.ME2ME,
+ this.host_, this.createCredentialsProvider_(), suppressHostOfflineError);
};
/**
diff --git a/remoting/webapp/crd/js/mock_client_plugin.js b/remoting/webapp/crd/js/mock_client_plugin.js
index 749a68b..965e213 100644
--- a/remoting/webapp/crd/js/mock_client_plugin.js
+++ b/remoting/webapp/crd/js/mock_client_plugin.js
@@ -5,6 +5,7 @@
/**
* @fileoverview
* Mock implementation of ClientPlugin for testing.
+ * @suppress {checkTypes}
*/
'use strict';
@@ -19,16 +20,12 @@ var remoting = remoting || {};
*/
remoting.MockClientPlugin = function(container) {
this.container_ = container;
- this.element_ = /** @type {HTMLElement} */ (document.createElement('div'));
+ this.element_ = document.createElement('div');
this.element_.style.backgroundImage = 'linear-gradient(45deg, blue, red)';
+ this.connectionStatusUpdateHandler_ = null;
+ this.desktopSizeUpdateHandler_ = null;
this.container_.appendChild(this.element_);
this.hostDesktop_ = new remoting.MockClientPlugin.HostDesktop();
- this.extensions_ = new remoting.ProtocolExtensionManager(base.doNothing);
- /** @type {remoting.ClientPlugin.ConnectionEventHandler} */
- this.connectionEventHandler = null;
-
- // Fake initialization result to return.
- this.mock$initializationResult = true;
};
remoting.MockClientPlugin.prototype.dispose = function() {
@@ -37,10 +34,6 @@ remoting.MockClientPlugin.prototype.dispose = function() {
this.connectionStatusUpdateHandler_ = null;
};
-remoting.MockClientPlugin.prototype.extensions = function() {
- return this.extensions_;
-};
-
remoting.MockClientPlugin.prototype.hostDesktop = function() {
return this.hostDesktop_;
};
@@ -50,31 +43,24 @@ remoting.MockClientPlugin.prototype.element = function() {
};
remoting.MockClientPlugin.prototype.initialize = function(onDone) {
- var that = this;
- Promise.resolve().then(function() {
- onDone(that.mock$initializationResult);
- });
+ window.setTimeout(onDone.bind(null, true), 0);
};
remoting.MockClientPlugin.prototype.connect =
function(host, localJid, credentialsProvider) {
- base.debug.assert(this.connectionEventHandler !== null);
- var that = this;
- window.requestAnimationFrame(function() {
- that.connectionEventHandler.onConnectionStatusUpdate(
+ base.debug.assert(this.connectionStatusUpdateHandler_ != null);
+ window.setTimeout(
+ this.connectionStatusUpdateHandler_.bind(
+ this,
remoting.ClientSession.State.CONNECTED,
- remoting.ClientSession.ConnectionError.NONE);
- });
+ remoting.ClientSession.ConnectionError.NONE),
+ 0);
};
-remoting.MockClientPlugin.prototype.injectKeyCombination = function(keys) {};
-
remoting.MockClientPlugin.prototype.injectKeyEvent =
function(key, down) {};
-remoting.MockClientPlugin.prototype.setRemapKeys = function(remappings) {};
-
remoting.MockClientPlugin.prototype.remapKey = function(from, to) {};
remoting.MockClientPlugin.prototype.releaseAllKeys = function() {};
@@ -95,8 +81,6 @@ remoting.MockClientPlugin.prototype.sendClipboardItem =
remoting.MockClientPlugin.prototype.requestPairing =
function(clientName, onDone) {};
-remoting.MockClientPlugin.prototype.allowMouseLock = function() {};
-
remoting.MockClientPlugin.prototype.pauseAudio = function(pause) {};
remoting.MockClientPlugin.prototype.pauseVideo = function(pause) {};
@@ -113,17 +97,41 @@ remoting.MockClientPlugin.prototype.getPerfStats = function() {
return result;
};
-remoting.MockClientPlugin.prototype.setConnectionEventHandler =
+remoting.MockClientPlugin.prototype.sendClientMessage =
+ function(name, data) {};
+
+remoting.MockClientPlugin.prototype.setOnOutgoingIqHandler =
+ function(handler) {};
+
+remoting.MockClientPlugin.prototype.setOnDebugMessageHandler =
+ function(handler) {};
+
+/**
+ * @param {function(number, number):void} handler
+ * @private
+ */
+remoting.MockClientPlugin.prototype.setConnectionStatusUpdateHandler =
function(handler) {
- this.connetionEventHandler = handler;
+ /** @type {function(number, number):void} */
+ this.connectionStatusUpdateHandler_ = handler;
};
-remoting.MockClientPlugin.prototype.setMouseCursorHandler =
+remoting.MockClientPlugin.prototype.setRouteChangedHandler =
+ function(handler) {};
+
+remoting.MockClientPlugin.prototype.setConnectionReadyHandler =
+ function(handler) {};
+
+remoting.MockClientPlugin.prototype.setCapabilitiesHandler =
+ function(handler) {};
+
+remoting.MockClientPlugin.prototype.setGnubbyAuthHandler =
function(handler) {};
-remoting.MockClientPlugin.prototype.setClipboardHandler = function(handler) {};
+remoting.MockClientPlugin.prototype.setCastExtensionHandler =
+ function(handler) {};
-remoting.MockClientPlugin.prototype.setDebugDirtyRegionHandler =
+remoting.MockClientPlugin.prototype.setMouseCursorHandler =
function(handler) {};
/**
@@ -184,17 +192,13 @@ remoting.MockClientPlugin.HostDesktop.prototype.resize =
/**
* @constructor
- * @implements {remoting.ClientPluginFactory}
+ * @extends {remoting.ClientPluginFactory}
*/
-remoting.MockClientPluginFactory = function() {
- /** @private {remoting.MockClientPlugin} */
- this.plugin_ = null;
-};
+remoting.MockClientPluginFactory = function() {};
remoting.MockClientPluginFactory.prototype.createPlugin =
function(container, onExtensionMessage) {
- this.plugin_ = new remoting.MockClientPlugin(container);
- return this.plugin_;
+ return new remoting.MockClientPlugin(container);
};
remoting.MockClientPluginFactory.prototype.preloadPlugin = function() {};
diff --git a/remoting/webapp/crd/js/mock_session_connector.js b/remoting/webapp/crd/js/mock_session_connector.js
new file mode 100644
index 0000000..ae7d184
--- /dev/null
+++ b/remoting/webapp/crd/js/mock_session_connector.js
@@ -0,0 +1,171 @@
+// 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
+ * Mock implementation of SessionConnector for testing.
+ * @suppress {checkTypes}
+ */
+
+'use strict';
+
+/** @suppress {duplicate} */
+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.
+ * @param {function(!remoting.Error):void} onConnectionFailed Callback for when
+ * the connection fails.
+ * @param {Array<string>} requiredCapabilities Connector capabilities
+ * required by this application.
+ * @param {string} defaultRemapKeys The default set of key mappings for the
+ * client session to use.
+ * @constructor
+ * @implements {remoting.SessionConnector}
+ */
+remoting.MockSessionConnector = function(clientContainer, onConnected, onError,
+ onExtensionMessage,
+ onConnectionFailed,
+ requiredCapabilities,
+ defaultRemapKeys) {
+ this.clientContainer_ = clientContainer;
+ /** @type {function(remoting.ClientSession):void} */
+ this.onConnected_ = onConnected;
+ this.onError = onError;
+ this.onExtensionMessage_ = onExtensionMessage;
+ this.onConnectionFailed_ = onConnectionFailed;
+ this.requiredCapabilities_ = requiredCapabilities;
+ this.defaultRemapKeys_ = defaultRemapKeys;
+
+ this.reset();
+};
+
+remoting.MockSessionConnector.prototype.reset = function() {
+ /** @type {string} @private */
+ this.hostId_ = '';
+};
+
+remoting.MockSessionConnector.prototype.connectMe2Me =
+ function(host, fetchPin, fetchThirdPartyToken,
+ clientPairingId, clientPairedSecret) {
+ this.connect_();
+};
+
+remoting.MockSessionConnector.prototype.retryConnectMe2Me =
+ function(host, fetchPin, fetchThirdPartyToken,
+ clientPairingId, clientPairedSecret) {
+ this.connect_();
+};
+
+remoting.MockSessionConnector.prototype.connectMe2App =
+ function(host, fetchThirdPartyToken) {
+ this.connect_();
+};
+
+remoting.MockSessionConnector.prototype.updatePairingInfo =
+ function(clientId, sharedSecret) {
+};
+
+remoting.MockSessionConnector.prototype.connectIT2Me =
+ function(accessCode) {
+ this.connect_();
+};
+
+remoting.MockSessionConnector.prototype.reconnect = function() {
+ this.connect_();
+};
+
+remoting.MockSessionConnector.prototype.cancel = function() {
+};
+
+remoting.MockSessionConnector.prototype.getHostId = function() {
+ return this.hostId_;
+};
+
+remoting.MockSessionConnector.prototype.connect_ = function() {
+ var signalling = new remoting.MockSignalStrategy();
+ signalling.setStateForTesting(remoting.SignalStrategy.State.CONNECTED);
+ var hostName = 'Mock host';
+ var accessCode = '';
+ var authenticationMethods = '';
+ var hostId = '';
+ var hostJid = '';
+ var hostPublicKey = '';
+ var clientPairingId = '';
+ var clientPairedSecret = '';
+
+ /**
+ * @param {boolean} offerPairing
+ * @param {function(string):void} callback
+ */
+ var fetchPin = function(offerPairing, callback) {
+ window.setTimeout(function() { callback('') }, 0);
+ };
+
+ /**
+ * @param {string} tokenUrl
+ * @param {string} hostPublicKey
+ * @param {string} scope
+ * @param {function(string, string):void} callback
+ */
+ var fetchThirdPartyToken = function(tokenUrl, hostPublicKey, scope,
+ callback) {
+ window.setTimeout(function() { callback('', '') }, 0);
+ };
+
+ var clientSession = new remoting.ClientSession(
+ signalling, this.clientContainer_, hostName,
+ accessCode, fetchPin, fetchThirdPartyToken,
+ authenticationMethods, hostId, hostJid, hostPublicKey,
+ clientPairingId, clientPairedSecret);
+
+ var that = this;
+ /** @param {remoting.ClientSession.StateEvent} event */
+ var onStateChange = function(event) {
+ if (event.current == remoting.ClientSession.State.CONNECTED) {
+ that.onConnected_(clientSession);
+ }
+ };
+
+ clientSession.addEventListener(
+ remoting.ClientSession.Events.stateChanged,
+ onStateChange);
+};
+
+
+/**
+ * @constructor
+ * @extends {remoting.SessionConnectorFactory}
+ */
+remoting.MockSessionConnectorFactory = function() {};
+
+/**
+ * @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.
+ * @param {function(!remoting.Error):void} onConnectionFailed Callback for when
+ * the connection fails.
+ * @param {Array<string>} requiredCapabilities Connector capabilities
+ * required by this application.
+ * @param {string} defaultRemapKeys The default set of key mappings to use
+ * in the client session.
+ * @return {remoting.MockSessionConnector}
+ */
+remoting.MockSessionConnectorFactory.prototype.createConnector =
+ function(clientContainer, onConnected, onError, onExtensionMessage,
+ onConnectionFailed, requiredCapabilities, defaultRemapKeys) {
+ return new remoting.MockSessionConnector(
+ clientContainer, onConnected, onError, onExtensionMessage,
+ onConnectionFailed, requiredCapabilities, defaultRemapKeys);
+};
diff --git a/remoting/webapp/crd/js/session_connector.js b/remoting/webapp/crd/js/session_connector.js
new file mode 100644
index 0000000..4481f5c
--- /dev/null
+++ b/remoting/webapp/crd/js/session_connector.js
@@ -0,0 +1,52 @@
+// 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
+ * Interface abstracting the SessionConnector functionality.
+ */
+
+'use strict';
+
+/** @suppress {duplicate} */
+var remoting = remoting || {};
+
+/**
+ * @interface
+ */
+remoting.SessionConnector = function() {};
+
+/**
+ * Initiates a remote connection.
+ *
+ * @param {remoting.Application.Mode} mode
+ * @param {remoting.Host} host
+ * @param {remoting.CredentialsProvider} credentialsProvider
+ * @param {boolean=} opt_suppressOfflineError Suppress the host offline error
+ * as we use stale JID's when initiating a Me2Me. This parameter will be
+ * removed when we get rid of sessionConnector altogether in a future CL.
+ * @return {void} Nothing.
+ */
+remoting.SessionConnector.prototype.connect =
+ function(mode, host, credentialsProvider, opt_suppressOfflineError) {};
+
+/**
+ * @interface
+ */
+remoting.SessionConnectorFactory = function() {};
+
+/**
+ * @param {HTMLElement} clientContainer Container element for the client view.
+ * @param {Array<string>} requiredCapabilities Connector capabilities
+ * required by this application.
+ * @param {remoting.ClientSession.EventHandler} handler
+ * @return {remoting.SessionConnector}
+ */
+remoting.SessionConnectorFactory.prototype.createConnector =
+ function(clientContainer, requiredCapabilities, handler) {};
+
+/**
+ * @type {remoting.SessionConnectorFactory}
+ */
+remoting.SessionConnector.factory = null;
diff --git a/remoting/webapp/crd/js/session_connector_impl.js b/remoting/webapp/crd/js/session_connector_impl.js
new file mode 100644
index 0000000..438a1f0
--- /dev/null
+++ b/remoting/webapp/crd/js/session_connector_impl.js
@@ -0,0 +1,291 @@
+// Copyright 2013 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
+ */
+
+'use strict';
+
+/** @suppress {duplicate} */
+var remoting = remoting || {};
+
+/**
+ * @param {HTMLElement} clientContainer Container element for the client view.
+ * @param {Array<string>} requiredCapabilities Connector capabilities
+ * required by this application.
+ * @param {remoting.ClientSession.EventHandler} handler
+ * @constructor
+ * @implements {remoting.SessionConnector}
+ */
+remoting.SessionConnectorImpl =
+ function(clientContainer, requiredCapabilities, handler) {
+ /** @private {HTMLElement} */
+ this.clientContainer_ = clientContainer;
+
+ /** @private */
+ this.onError_ = handler.onError.bind(handler);
+
+ /** @private */
+ this.handler_ = handler;
+
+ /** @private {Array<string>} */
+ this.requiredCapabilities_ = [
+ remoting.ClientSession.Capability.SEND_INITIAL_RESOLUTION,
+ remoting.ClientSession.Capability.RATE_LIMIT_RESIZE_REQUESTS,
+ remoting.ClientSession.Capability.VIDEO_RECORDER
+ ];
+
+ // Append the app-specific capabilities.
+ this.requiredCapabilities_.push.apply(this.requiredCapabilities_,
+ requiredCapabilities);
+
+ // Initialize/declare per-connection state.
+ this.closeSession_();
+};
+
+/**
+ * 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.
+ * @private
+ */
+remoting.SessionConnectorImpl.prototype.closeSession_ = function() {
+ // It's OK to initialize these member variables here because the
+ // constructor calls this method.
+
+ base.dispose(this.eventHook_);
+ /** @private {base.Disposable} */
+ this.eventHook_ = null;
+
+ /** @private {remoting.Host} */
+ this.host_ = null;
+
+ /** @private {boolean} */
+ this.logHostOfflineErrors_ = false;
+
+ base.dispose(this.clientSession_);
+ /** @private {remoting.ClientSession} */
+ this.clientSession_ = null;
+
+ base.dispose(this.plugin_);
+ /** @private {remoting.ClientPlugin} */
+ this.plugin_ = null;
+
+ /** @private {remoting.CredentialsProvider} */
+ this.credentialsProvider_ = null;
+
+ base.dispose(this.signalStrategy_);
+ /** @private {remoting.SignalStrategy} */
+ this.signalStrategy_ = null;
+};
+
+/**
+ * Initiates a connection.
+ *
+ * @param {remoting.Application.Mode} mode
+ * @param {remoting.Host} host the Host to connect to.
+ * @param {remoting.CredentialsProvider} credentialsProvider
+ * @param {boolean=} opt_suppressOfflineError
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnectorImpl.prototype.connect =
+ function(mode, host, credentialsProvider, opt_suppressOfflineError) {
+ // In some circumstances, the WCS <iframe> can get reloaded, which results
+ // in a new clientJid and a new callback. In this case, cancel any existing
+ // connect operation and remove the old client plugin before instantiating a
+ // new one.
+ this.closeSession_();
+ remoting.app.setConnectionMode(mode);
+ this.host_ = host;
+ this.credentialsProvider_ = credentialsProvider;
+ this.logHostOfflineErrors_ = !Boolean(opt_suppressOfflineError);
+ this.connectSignaling_();
+};
+
+/**
+ * @private
+ */
+remoting.SessionConnectorImpl.prototype.connectSignaling_ = function() {
+ base.dispose(this.signalStrategy_);
+ this.signalStrategy_ = null;
+
+ /** @type {remoting.SessionConnectorImpl} */
+ var that = this;
+
+ /** @param {string} token */
+ function connectSignalingWithToken(token) {
+ remoting.identity.getUserInfo().then(
+ connectSignalingWithTokenAndUserInfo.bind(null, token),
+ remoting.Error.handler(that.onError_));
+ }
+
+ /**
+ * Success callback for when the email and fullName have been retrieved
+ * for this user.
+ * Note that the full name will be null unless the webapp has requested
+ * and been granted the userinfo.profile permission.
+ *
+ * @param {string} token
+ * @param {{email: string, name: string}} userInfo
+ */
+ function connectSignalingWithTokenAndUserInfo(token, userInfo) {
+ that.signalStrategy_.connect(remoting.settings.XMPP_SERVER, userInfo.email,
+ token);
+ }
+
+ this.signalStrategy_ = remoting.SignalStrategy.create();
+ this.signalStrategy_.setStateChangedCallback(
+ this.onSignalingState_.bind(this));
+
+ remoting.identity.getToken().then(
+ connectSignalingWithToken,
+ remoting.Error.handler(this.onError_));
+};
+
+/**
+ * @private
+ * @param {remoting.SignalStrategy.State} state
+ */
+remoting.SessionConnectorImpl.prototype.onSignalingState_ = function(state) {
+ switch (state) {
+ case remoting.SignalStrategy.State.CONNECTED:
+ // Proceed only if the connection hasn't been canceled.
+ if (this.host_.jabberId) {
+ this.createSession_();
+ }
+ break;
+
+ case remoting.SignalStrategy.State.FAILED:
+ this.onError_(this.signalStrategy_.getError());
+ break;
+ }
+};
+
+/**
+ * Creates ClientSession object.
+ */
+remoting.SessionConnectorImpl.prototype.createSession_ = function() {
+ var pluginContainer = this.clientContainer_.querySelector(
+ '.client-plugin-container');
+
+ this.plugin_ = remoting.ClientPlugin.factory.createPlugin(
+ pluginContainer, this.requiredCapabilities_);
+
+ var that = this;
+ this.host_.options.load().then(function(){
+ that.plugin_.initialize(that.onPluginInitialized_.bind(that));
+ });
+};
+
+/**
+ * @param {boolean} initialized
+ * @private
+ */
+remoting.SessionConnectorImpl.prototype.onPluginInitialized_ = function(
+ initialized) {
+ if (!initialized) {
+ console.error('ERROR: remoting plugin not loaded');
+ this.pluginError_(new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
+ return;
+ }
+
+ if (!this.plugin_.isSupportedVersion()) {
+ console.error('ERROR: bad plugin version');
+ this.pluginError_(new remoting.Error(
+ remoting.Error.Tag.BAD_PLUGIN_VERSION));
+ return;
+ }
+
+ this.clientSession_ = new remoting.ClientSession(
+ this.plugin_, this.host_, this.signalStrategy_);
+
+ this.clientSession_.logHostOfflineErrors(this.logHostOfflineErrors_);
+ this.eventHook_ = new base.EventHook(
+ this.clientSession_, 'stateChanged', this.onStateChange_.bind(this));
+ this.plugin_.connect(
+ this.host_, this.signalStrategy_.getJid(), this.credentialsProvider_);
+};
+
+/**
+ * @param {!remoting.Error} error
+ * @private
+ */
+remoting.SessionConnectorImpl.prototype.pluginError_ = function(error) {
+ this.signalStrategy_.setIncomingStanzaCallback(null);
+ this.closeSession_();
+};
+
+/**
+ * Handle a change in the state of the client session.
+ *
+ * @param {remoting.ClientSession.StateEvent=} event
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnectorImpl.prototype.onStateChange_ = function(event) {
+ switch (event.current) {
+ case remoting.ClientSession.State.CONNECTED:
+ var connectionInfo = new remoting.ConnectionInfo(
+ this.host_, this.credentialsProvider_, this.clientSession_,
+ this.plugin_);
+ this.handler_.onConnected(connectionInfo);
+ break;
+
+ case remoting.ClientSession.State.CONNECTING:
+ remoting.identity.getEmail().then(function(/** string */ email) {
+ console.log('Connecting as ' + email);
+ });
+ break;
+
+ case remoting.ClientSession.State.AUTHENTICATED:
+ console.log('Connection authenticated');
+ break;
+
+ case remoting.ClientSession.State.INITIALIZING:
+ console.log('Initializing connection');
+ break;
+
+ case remoting.ClientSession.State.CLOSED:
+ this.handler_.onDisconnected();
+ break;
+
+ case remoting.ClientSession.State.FAILED:
+ var error = this.clientSession_.getError();
+ console.error('Client plugin reported connection failed: ' +
+ error.toString());
+ this.handler_.onConnectionFailed(error || remoting.Error.unexpected());
+ 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_(new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
+ }
+
+ if (this.clientSession_.isFinished()) {
+ this.closeSession_();
+ }
+};
+
+/**
+ * @constructor
+ * @implements {remoting.SessionConnectorFactory}
+ */
+remoting.DefaultSessionConnectorFactory = function() {};
+
+/**
+ * @param {HTMLElement} clientContainer Container element for the client view.
+ * @param {Array<string>} requiredCapabilities Connector capabilities
+ * required by this application.
+ * @param {remoting.ClientSession.EventHandler} handler
+ * @return {remoting.SessionConnector}
+ */
+remoting.DefaultSessionConnectorFactory.prototype.createConnector =
+ function(clientContainer, requiredCapabilities, handler) {
+ return new remoting.SessionConnectorImpl(clientContainer,
+ requiredCapabilities, handler);
+};