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

Unified Diff: remoting/webapp/crd/js/fallback_signal_strategy.js

Issue 815943004: Implement FallbackSignalStrategy. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 11 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
« no previous file with comments | « remoting/remoting_webapp_files.gypi ('k') | remoting/webapp/crd/js/signal_strategy.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/webapp/crd/js/fallback_signal_strategy.js
diff --git a/remoting/webapp/crd/js/fallback_signal_strategy.js b/remoting/webapp/crd/js/fallback_signal_strategy.js
new file mode 100644
index 0000000000000000000000000000000000000000..bb58e4d45ae63da3adcf558a4581b61009ffb3bd
--- /dev/null
+++ b/remoting/webapp/crd/js/fallback_signal_strategy.js
@@ -0,0 +1,329 @@
+// 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.
+
+'use strict';
+
+/** @suppress {duplicate} */
+var remoting = remoting || {};
+
+/**
+ * A signal strategy encapsulating a primary and a back-up strategy. If the
+ * primary fails or times out, then the secondary is used. Information about
+ * which strategy was used, and why, is returned via |onProgressCallback|.
+ *
+ * @param {function(
+ * function(remoting.SignalStrategy.State)
+ * ):remoting.SignalStrategy} primaryFactory
+ * @param {function(
+ * function(remoting.SignalStrategy.State)
+ * ):remoting.SignalStrategy} secondaryFactory
+ * @param {function(remoting.SignalStrategy.State):void} onStateChangedCallback
+ * @param {function(remoting.FallbackSignalStrategy.Progress)}
+ * onProgressCallback
+ *
+ * @implements {remoting.SignalStrategy}
+ * @constructor
+ */
+remoting.FallbackSignalStrategy = function(
+ primaryFactory, secondaryFactory,
+ onStateChangedCallback, onProgressCallback) {
+ /**
+ * @type {remoting.SignalStrategy}
+ * @private
+ */
+ this.primary_ = primaryFactory(this.onPrimaryStateChanged_.bind(this));
+
+ /**
+ * @type {remoting.SignalStrategy}
+ * @private
+ */
+ this.secondary_ = secondaryFactory(this.onSecondaryStateChanged_.bind(this));
+
+ /**
+ * @type {function(remoting.SignalStrategy.State)}
+ * @private
+ */
+ this.onStateChangedCallback_ = onStateChangedCallback;
+
+ /**
+ * @type {function(remoting.FallbackSignalStrategy.Progress)}
+ * @private
+ */
+ this.onProgressCallback_ = onProgressCallback;
+
+ /**
+ * @type {?function(Element):void}
+ * @private
+ */
+ this.onIncomingStanzaCallback_ = null;
+
+ /**
+ * @type {number}
+ * @private
+ * @const
+ */
+ this.PRIMARY_CONNECT_TIMEOUT_MS_ = 10 * 1000;
+
+ /**
+ * @enum {string}
+ * @private
+ */
+ this.State = {
+ NOT_CONNECTED: 'not-connected',
+ PRIMARY_PENDING: 'primary-pending',
+ PRIMARY_SUCCEEDED: 'primary-succeeded',
+ SECONDARY_PENDING: 'secondary-pending',
+ SECONDARY_SUCCEEDED: 'secondary-succeeded',
+ SECONDARY_FAILED: 'secondary-failed',
+ CLOSED: 'closed'
+ };
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.state_ = this.State.NOT_CONNECTED;
+
+ /**
+ * @type {?remoting.SignalStrategy.State}
+ * @private
+ */
+ this.externalState_ = null;
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.server_ = '';
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.username_ = '';
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.authToken_ = '';
+
+ /**
+ * @type {number}
+ * @private
+ */
+ this.primaryConnectTimerId_ = 0;
+};
+
+/**
+ * @enum {string}
+ */
+remoting.FallbackSignalStrategy.Progress = {
+ PRIMARY_SUCCEEDED: 'primary-succeeded',
+ PRIMARY_FAILED: 'primary-failed',
+ PRIMARY_TIMED_OUT: 'primary-timed-out',
+ PRIMARY_SUCCEEDED_LATE: 'primary-succeeded-late',
+ PRIMARY_FAILED_LATE: 'primary-failed-late',
+ SECONDARY_SUCCEEDED: 'secondary-succeeded',
+ SECONDARY_FAILED: 'secondary-failed'
+};
+
+remoting.FallbackSignalStrategy.prototype.dispose = function() {
+ this.primary_.dispose();
+ this.secondary_.dispose();
+};
+
+/**
+ * @param {?function(Element):void} onIncomingStanzaCallback Callback to call on
+ * incoming messages.
+ */
+remoting.FallbackSignalStrategy.prototype.setIncomingStanzaCallback =
+ function(onIncomingStanzaCallback) {
+ this.onIncomingStanzaCallback_ = onIncomingStanzaCallback;
+ if (this.state_ == this.State.PRIMARY_PENDING ||
+ this.state_ == this.State.PRIMARY_SUCCEEDED) {
+ this.primary_.setIncomingStanzaCallback(onIncomingStanzaCallback);
+ } else if (this.state_ == this.State.SECONDARY_PENDING ||
+ this.state_ == this.State.SECONDARY_SUCCEEDED) {
+ this.secondary_.setIncomingStanzaCallback(onIncomingStanzaCallback);
+ }
+};
+
+/**
+ * @param {string} server
+ * @param {string} username
+ * @param {string} authToken
+ */
+remoting.FallbackSignalStrategy.prototype.connect =
+ function(server, username, authToken) {
+ base.debug.assert(this.state_ == this.State.NOT_CONNECTED);
+ this.server_ = server;
+ this.username_ = username;
+ this.authToken_ = authToken;
+ this.state_ = this.State.PRIMARY_PENDING;
+ this.primary_.setIncomingStanzaCallback(this.onIncomingStanzaCallback_);
+ this.primary_.connect(server, username, authToken);
+ this.primaryConnectTimerId_ =
+ window.setTimeout(this.onPrimaryTimeout_.bind(this),
+ this.PRIMARY_CONNECT_TIMEOUT_MS_);
+};
+
+/**
+ * Sends a message. Can be called only in CONNECTED state.
+ * @param {string} message
+ */
+remoting.FallbackSignalStrategy.prototype.sendMessage = function(message) {
+ this.getConnectedSignalStrategy_().sendMessage(message);
+};
+
+/** @return {remoting.SignalStrategy.State} Current state */
+remoting.FallbackSignalStrategy.prototype.getState = function() {
+ return (this.externalState_ === null)
+ ? remoting.SignalStrategy.State.NOT_CONNECTED
+ : this.externalState_;
+};
+
+/** @return {remoting.Error} Error when in FAILED state. */
+remoting.FallbackSignalStrategy.prototype.getError = function() {
+ base.debug.assert(this.state_ == this.State.SECONDARY_FAILED);
+ base.debug.assert(
+ this.secondary_.getState() == remoting.SignalStrategy.State.FAILED);
+ return this.secondary_.getError();
+};
+
+/** @return {string} Current JID when in CONNECTED state. */
+remoting.FallbackSignalStrategy.prototype.getJid = function() {
+ return this.getConnectedSignalStrategy_().getJid();
+};
+
+/**
+ * @return {remoting.SignalStrategy} The active signal strategy, if the
+ * connection has succeeded.
+ * @private
+ */
+remoting.FallbackSignalStrategy.prototype.getConnectedSignalStrategy_ =
+ function() {
+ if (this.state_ == this.State.PRIMARY_SUCCEEDED) {
+ base.debug.assert(
+ this.primary_.getState() == remoting.SignalStrategy.State.CONNECTED);
+ return this.primary_;
+ } else if (this.state_ == this.State.SECONDARY_SUCCEEDED) {
+ base.debug.assert(
+ this.secondary_.getState() == remoting.SignalStrategy.State.CONNECTED);
+ return this.secondary_;
+ } else {
+ base.debug.assert(
+ false,
+ 'getConnectedSignalStrategy called in unconnected state');
+ return null;
+ }
+};
+
+/**
+ * @param {remoting.SignalStrategy.State} state
+ * @private
+ */
+remoting.FallbackSignalStrategy.prototype.onPrimaryStateChanged_ =
+ function(state) {
+ switch (state) {
+ case remoting.SignalStrategy.State.CONNECTED:
+ if (this.state_ == this.State.PRIMARY_PENDING) {
+ window.clearTimeout(this.primaryConnectTimerId_);
+ this.onProgressCallback_(
+ remoting.FallbackSignalStrategy.Progress.PRIMARY_SUCCEEDED);
+ this.state_ = this.State.PRIMARY_SUCCEEDED;
+ } else {
+ this.onProgressCallback_(
+ remoting.FallbackSignalStrategy.Progress.PRIMARY_SUCCEEDED_LATE);
+ }
+ break;
+
+ case remoting.SignalStrategy.State.FAILED:
+ if (this.state_ == this.State.PRIMARY_PENDING) {
+ window.clearTimeout(this.primaryConnectTimerId_);
+ this.onProgressCallback_(
+ remoting.FallbackSignalStrategy.Progress.PRIMARY_FAILED);
+ this.connectSecondary_();
+ } else {
+ this.onProgressCallback_(
+ remoting.FallbackSignalStrategy.Progress.PRIMARY_FAILED_LATE);
+ }
+ return; // Don't notify the external callback
+
+ case remoting.SignalStrategy.State.CLOSED:
+ this.state_ = this.State.CLOSED;
+ break;
+ }
+
+ this.notifyExternalCallback_(state);
+};
+
+/**
+ * @param {remoting.SignalStrategy.State} state
+ * @private
+ */
+remoting.FallbackSignalStrategy.prototype.onSecondaryStateChanged_ =
+ function(state) {
+ switch (state) {
+ case remoting.SignalStrategy.State.CONNECTED:
+ this.onProgressCallback_(
+ remoting.FallbackSignalStrategy.Progress.SECONDARY_SUCCEEDED);
+ this.state_ = this.State.SECONDARY_SUCCEEDED;
+ break;
+
+ case remoting.SignalStrategy.State.FAILED:
+ this.onProgressCallback_(
+ remoting.FallbackSignalStrategy.Progress.SECONDARY_FAILED);
+ this.state_ = this.State.SECONDARY_FAILED;
+ break;
+
+ case remoting.SignalStrategy.State.CLOSED:
+ this.state_ = this.State.CLOSED;
+ break;
+ }
+
+ this.notifyExternalCallback_(state);
+};
+
+/**
+ * Notify the external callback of a change in state if it's consistent with
+ * the allowed state transitions (ie, if it represents a later stage in the
+ * connection process). Suppress state transitions that would violate this,
+ * for example a CONNECTING -> NOT_CONNECTED transition when we switch from
+ * the primary to the secondary signal strategy.
+ *
+ * @param {remoting.SignalStrategy.State} state
+ * @private
+ */
+remoting.FallbackSignalStrategy.prototype.notifyExternalCallback_ =
+ function(state) {
+ if (this.externalState_ === null || state > this.externalState_) {
+ this.externalState_ = state;
+ this.onStateChangedCallback_(state);
+ }
+};
+
+/**
+ * @private
+ */
+remoting.FallbackSignalStrategy.prototype.connectSecondary_ = function() {
+ base.debug.assert(this.state_ == this.State.PRIMARY_PENDING);
+ base.debug.assert(this.server_ != '');
+ base.debug.assert(this.username_ != '');
+ base.debug.assert(this.authToken_ != '');
+
+ this.state_ = this.State.SECONDARY_PENDING;
+ this.primary_.setIncomingStanzaCallback(null);
+ this.secondary_.setIncomingStanzaCallback(this.onIncomingStanzaCallback_);
+ this.secondary_.connect(this.server_, this.username_, this.authToken_);
+};
+
+/**
+ * @private
+ */
+remoting.FallbackSignalStrategy.prototype.onPrimaryTimeout_ = function() {
+ this.onProgressCallback_(
+ remoting.FallbackSignalStrategy.Progress.PRIMARY_TIMED_OUT);
+ this.connectSecondary_();
+};
« no previous file with comments | « remoting/remoting_webapp_files.gypi ('k') | remoting/webapp/crd/js/signal_strategy.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698