summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamie Walch <jamiewalch@chromium.org>2015-06-10 15:22:10 -0700
committerJamie Walch <jamiewalch@chromium.org>2015-06-10 22:24:17 +0000
commit787c019e398cf0da6073ff60a687a0e47910159c (patch)
tree6676bd450689ad38a7d3db43709bb24c25b54e53
parent65380f6680684c1265321ac696142c4c1d351389 (diff)
downloadchromium_src-787c019e398cf0da6073ff60a687a0e47910159c.zip
chromium_src-787c019e398cf0da6073ff60a687a0e47910159c.tar.gz
chromium_src-787c019e398cf0da6073ff60a687a0e47910159c.tar.bz2
Add more host-side connection state logging for IT2Me.
This CL adds INITIALIZING, CONNECTING, FAILED and CANCELED states to the host-side IT2Me connection set-up. It has the following components: * BufferedSignalStrategy: A new class to wrap an underlying SignalStrategy so that messages can be logged before the XMPP connection is established. Doing otherwise would slow down connections unnecessarily, but a consequence is that we aren't guaranteed that the new messages will actually be logged; still it's better than the previous situation. * Support for host-side logging in LogToServer. * Minimal refactoring to make the code that reads the local host version publicly callable. Note that some of this code, in particular the BufferedSignalStrategy class should go away if we implement logging using XHRs. BUG=497876 TBR=kelvinp@chromium.org Review URL: https://codereview.chromium.org/1176693002 Cr-Commit-Position: refs/heads/master@{#333771} (cherry picked from commit 9ea60d8ecacbccac0221c7f576ef19d6635de1cd) Review URL: https://codereview.chromium.org/1177033002. Cr-Commit-Position: refs/branch-heads/2403@{#271} Cr-Branched-From: f54b8097a9c45ed4ad308133d49f05325d6c5070-refs/heads/master@{#330231}
-rw-r--r--remoting/remoting_webapp_files.gypi1
-rw-r--r--remoting/webapp/base/js/log_to_server.js16
-rw-r--r--remoting/webapp/base/js/server_log_entry.js8
-rw-r--r--remoting/webapp/crd/js/buffered_signal_strategy.js107
-rw-r--r--remoting/webapp/crd/js/host_controller.js50
-rw-r--r--remoting/webapp/crd/js/host_screen.js99
-rw-r--r--remoting/webapp/files.gni1
7 files changed, 229 insertions, 53 deletions
diff --git a/remoting/remoting_webapp_files.gypi b/remoting/remoting_webapp_files.gypi
index 6ffdbf7..88f3fbc 100644
--- a/remoting/remoting_webapp_files.gypi
+++ b/remoting/remoting_webapp_files.gypi
@@ -249,6 +249,7 @@
# Files for controlling the local machine as a host.
# Includes both it2me and me2me files.
'remoting_webapp_js_host_control_files': [
+ 'webapp/crd/js/buffered_signal_strategy.js',
'webapp/crd/js/host_controller.js',
'webapp/crd/js/host_daemon_facade.js',
'webapp/crd/js/host_screen.js',
diff --git a/remoting/webapp/base/js/log_to_server.js b/remoting/webapp/base/js/log_to_server.js
index e68a001..34d4db4 100644
--- a/remoting/webapp/base/js/log_to_server.js
+++ b/remoting/webapp/base/js/log_to_server.js
@@ -14,9 +14,11 @@ var remoting = remoting || {};
/**
* @param {remoting.SignalStrategy} signalStrategy Signal strategy.
+ * @param {boolean=} opt_isHost True if this instance should log role=host
+ * events rather than role=client.
* @constructor
*/
-remoting.LogToServer = function(signalStrategy) {
+remoting.LogToServer = function(signalStrategy, opt_isHost) {
/** @private */
this.statsAccumulator_ = new remoting.StatsAccumulator();
/** @private */
@@ -35,8 +37,10 @@ remoting.LogToServer = function(signalStrategy) {
this.hostVersion_ = '';
/** @private */
this.logEntryMode_ = remoting.ServerLogEntry.VALUE_MODE_UNKNOWN;
+ /** @private */
+ this.role_ = opt_isHost ? 'host' : 'client';
- this.setSessionId_();
+ this.setSessionId();
signalStrategy.sendConnectionSetupResults(this);
};
@@ -65,7 +69,7 @@ remoting.LogToServer.prototype.logClientSessionStateChange =
this.maybeExpireSessionId_();
// Log the session state change.
var entry = remoting.ServerLogEntry.makeClientSessionStateChange(
- state, connectionError, this.logEntryMode_);
+ state, connectionError, this.logEntryMode_, this.role_);
entry.addClientOSFields();
entry.addChromeVersionField();
entry.addWebappVersionField();
@@ -219,10 +223,8 @@ remoting.LogToServer.prototype.log_ = function(entry) {
/**
* Sets the session ID to a random string.
- *
- * @private
*/
-remoting.LogToServer.prototype.setSessionId_ = function() {
+remoting.LogToServer.prototype.setSessionId = function() {
this.sessionId_ = remoting.LogToServer.generateSessionId_();
this.sessionIdGenerationTime_ = new Date().getTime();
};
@@ -254,7 +256,7 @@ remoting.LogToServer.prototype.maybeExpireSessionId_ = function() {
this.logEntryMode_);
this.log_(entry);
// Generate a new session ID.
- this.setSessionId_();
+ this.setSessionId();
// Log the new session ID.
entry = remoting.ServerLogEntry.makeSessionIdNew(this.sessionId_,
this.logEntryMode_);
diff --git a/remoting/webapp/base/js/server_log_entry.js b/remoting/webapp/base/js/server_log_entry.js
index ec771a8..5f41155 100644
--- a/remoting/webapp/base/js/server_log_entry.js
+++ b/remoting/webapp/base/js/server_log_entry.js
@@ -222,13 +222,14 @@ remoting.ServerLogEntry.prototype.toDebugLog = function(indentLevel) {
* @param {remoting.ClientSession.State} state
* @param {!remoting.Error} connectionError
* @param {string} mode The current app mode (It2Me, Me2Me, AppRemoting).
+ * @param {string} role 'client' if the app is acting as a Chromoting client
+ * or 'host' if it is acting as a host (IT2Me)
* @return {remoting.ServerLogEntry}
*/
remoting.ServerLogEntry.makeClientSessionStateChange = function(state,
- connectionError, mode) {
+ connectionError, mode, role) {
var entry = new remoting.ServerLogEntry();
- entry.set_(remoting.ServerLogEntry.KEY_ROLE_,
- remoting.ServerLogEntry.VALUE_ROLE_CLIENT_);
+ entry.set_(remoting.ServerLogEntry.KEY_ROLE_, role);
entry.set_(remoting.ServerLogEntry.KEY_EVENT_NAME_,
remoting.ServerLogEntry.VALUE_EVENT_NAME_SESSION_STATE_);
entry.set_(remoting.ServerLogEntry.KEY_SESSION_STATE_,
@@ -507,4 +508,3 @@ remoting.ServerLogEntry.prototype.addModeField = function(mode) {
remoting.ServerLogEntry.prototype.addApplicationId = function() {
this.set_(remoting.ServerLogEntry.KEY_APP_ID_, chrome.runtime.id);
};
-
diff --git a/remoting/webapp/crd/js/buffered_signal_strategy.js b/remoting/webapp/crd/js/buffered_signal_strategy.js
new file mode 100644
index 0000000..0dba7b5
--- /dev/null
+++ b/remoting/webapp/crd/js/buffered_signal_strategy.js
@@ -0,0 +1,107 @@
+// 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.
+
+'use strict';
+
+/** @suppress {duplicate} */
+var remoting = remoting || {};
+
+/**
+ * Simplified SignalStrategy implementation that wraps an underlying signal
+ * strategy and forwards messages when it is CONNECTED. It is used only to
+ * log status messages during IT2Me connection setup, and only those methods
+ * required for that are implemented.
+ *
+ * TODO(jamiewalch): Remove this class once a signal strategy is no longer
+ * required for logging (crbug.com/497269).
+ *
+ * @constructor
+ * @param {remoting.SignalStrategy} underlying The underlying implementation.
+ * @implements {remoting.SignalStrategy}
+ */
+remoting.BufferedSignalStrategy = function(underlying) {
+ /** @private */
+ this.underlying_ = underlying;
+ /** @private {Array<string>} */
+ this.pendingMessages_ = [];
+
+ this.underlying_.setStateChangedCallback(this.flush_.bind(this));
+};
+
+remoting.BufferedSignalStrategy.prototype.dispose = function() {
+ this.underlying_.dispose();
+};
+
+/**
+ * Sends a message. Can be called only in CONNECTED state.
+ * @param {string} message
+ */
+remoting.BufferedSignalStrategy.prototype.sendMessage = function(message) {
+ this.pendingMessages_.push(message);
+ this.flush_();
+};
+
+/**
+ * Send any messages accumulated during connection set-up.
+ *
+ * @param {remoting.LogToServer} logToServer The LogToServer instance for the
+ * connection.
+ */
+remoting.BufferedSignalStrategy.prototype.sendConnectionSetupResults =
+ function(logToServer) {
+ this.underlying_.sendConnectionSetupResults(logToServer);
+};
+
+/**
+ * If the underlying implementation is connected, flush all pending messages.
+ * @private
+ */
+remoting.BufferedSignalStrategy.prototype.flush_ = function() {
+ if (this.underlying_.getState() !== remoting.SignalStrategy.State.CONNECTED) {
+ return;
+ }
+ for (var i = 0; i < this.pendingMessages_.length; ++i) {
+ this.underlying_.sendMessage(this.pendingMessages_[i]);
+ }
+ this.pendingMessages_ = [];
+};
+
+
+// The following methods are not used by LogToServer and are not implemented.
+
+remoting.BufferedSignalStrategy.prototype.setStateChangedCallback =
+ function(onStateChangedCallback) {
+ base.debug.assert(false);
+};
+
+remoting.BufferedSignalStrategy.prototype.setIncomingStanzaCallback =
+ function(onIncomingStanzaCallback) {
+ base.debug.assert(false);
+};
+
+remoting.BufferedSignalStrategy.prototype.connect =
+ function(server, username, authToken) {
+ base.debug.assert(false);
+};
+
+remoting.BufferedSignalStrategy.prototype.sendConnectionSetupResults =
+ function(logToServer) {
+ base.debug.assert(false);
+};
+
+remoting.BufferedSignalStrategy.prototype.getState = function() {
+ base.debug.assert(false);
+};
+
+remoting.BufferedSignalStrategy.prototype.getError = function() {
+ base.debug.assert(false);
+};
+
+remoting.BufferedSignalStrategy.prototype.getJid = function() {
+ base.debug.assert(false);
+};
+
+remoting.BufferedSignalStrategy.prototype.getType = function() {
+ base.debug.assert(false);
+};
diff --git a/remoting/webapp/crd/js/host_controller.js b/remoting/webapp/crd/js/host_controller.js
index a3ae6e6..cdc8dfc 100644
--- a/remoting/webapp/crd/js/host_controller.js
+++ b/remoting/webapp/crd/js/host_controller.js
@@ -9,7 +9,23 @@ var remoting = remoting || {};
/** @constructor */
remoting.HostController = function() {
- this.hostDaemonFacade_ = this.createDaemonFacade_();
+ /** @type {remoting.HostDaemonFacade} @private */
+ this.hostDaemonFacade_ = new remoting.HostDaemonFacade();
+
+ /** @param {string} version */
+ var printVersion = function(version) {
+ if (version == '') {
+ console.log('Host not installed.');
+ } else {
+ console.log('Host version: ' + version);
+ }
+ };
+
+ this.getLocalHostVersion()
+ .then(printVersion)
+ .catch(function() {
+ console.log('Host version not available.');
+ });
};
// The values in the enums below are duplicated in daemon_controller.h except
@@ -56,30 +72,6 @@ remoting.HostController.AsyncResult.fromString = function(result) {
}
/**
- * @return {remoting.HostDaemonFacade}
- * @private
- */
-remoting.HostController.prototype.createDaemonFacade_ = function() {
- /** @type {remoting.HostDaemonFacade} @private */
- var hostDaemonFacade = new remoting.HostDaemonFacade();
-
- /** @param {string} version */
- var printVersion = function(version) {
- if (version == '') {
- console.log('Host not installed.');
- } else {
- console.log('Host version: ' + version);
- }
- };
-
- hostDaemonFacade.getDaemonVersion().then(printVersion, function() {
- console.log('Host version not available.');
- });
-
- return hostDaemonFacade;
-};
-
-/**
* Set of features for which hasFeature() can be used to test.
*
* @enum {string}
@@ -410,6 +402,14 @@ remoting.HostController.prototype.getLocalHostId = function(onDone) {
};
/**
+ * @return {Promise<string>} Promise that resolves with the host version, if
+ * installed, or rejects otherwise.
+ */
+remoting.HostController.prototype.getLocalHostVersion = function() {
+ return this.hostDaemonFacade_.getDaemonVersion();
+};
+
+/**
* Fetch the list of paired clients for this host.
*
* @param {function(Array<remoting.PairedClient>):void} onDone
diff --git a/remoting/webapp/crd/js/host_screen.js b/remoting/webapp/crd/js/host_screen.js
index 7845863..e959043 100644
--- a/remoting/webapp/crd/js/host_screen.js
+++ b/remoting/webapp/crd/js/host_screen.js
@@ -24,12 +24,27 @@ var hostSession_ = null;
var lastShareWasCancelled_ = false;
/**
+ * @type {remoting.LogToServer} Logging instance for IT2Me host connection
+ * status.
+ */
+var it2meLogger = null;
+
+/**
* Start a host session. This is the main entry point for the host screen,
* called directly from the onclick action of a button on the home screen.
* It first verifies that the native host components are installed and asks
* to install them if necessary.
*/
remoting.tryShare = function() {
+ ensureIT2MeLogger_().then(tryShareWithLogger_);
+};
+
+function tryShareWithLogger_() {
+ it2meLogger.setSessionId();
+ it2meLogger.logClientSessionStateChange(
+ remoting.ClientSession.State.INITIALIZING,
+ remoting.Error.none());
+
/** @type {remoting.It2MeHostFacade} */
var hostFacade = new remoting.It2MeHostFacade();
@@ -51,21 +66,12 @@ remoting.tryShare = function() {
var hasHostDialog = (hostInstallDialog !== null); /** jscompile hack */
if (!hasHostDialog) {
hostInstallDialog = new remoting.HostInstallDialog();
- hostInstallDialog.show(tryInitializeFacade, onInstallError);
+ hostInstallDialog.show(tryInitializeFacade, showShareError_);
} else {
hostInstallDialog.tryAgain();
}
};
- /** @param {!remoting.Error} error */
- var onInstallError = function(error) {
- if (error.hasTag(remoting.Error.Tag.CANCELLED)) {
- remoting.setMode(remoting.AppMode.HOME);
- } else {
- showShareError_(error);
- }
- };
-
tryInitializeFacade();
};
@@ -74,9 +80,10 @@ remoting.tryShare = function() {
*/
remoting.startHostUsingFacade_ = function(hostFacade) {
console.log('Attempting to share...');
- remoting.identity.getToken().then(
- remoting.tryShareWithToken_.bind(null, hostFacade),
- remoting.Error.handler(remoting.showErrorMessage));
+ setHostVersion_()
+ .then(remoting.identity.getToken.bind(remoting.identity))
+ .then(remoting.tryShareWithToken_.bind(null, hostFacade),
+ remoting.Error.handler(showShareError_));
}
/**
@@ -89,6 +96,9 @@ remoting.tryShareWithToken_ = function(hostFacade, token) {
lastShareWasCancelled_ = false;
onNatTraversalPolicyChanged_(true); // Hide warning by default.
remoting.setMode(remoting.AppMode.HOST_WAITING_FOR_CODE);
+ it2meLogger.logClientSessionStateChange(
+ remoting.ClientSession.State.CONNECTING,
+ remoting.Error.none());
document.getElementById('cancel-share-button').disabled = false;
disableTimeoutCountdown_();
@@ -194,10 +204,21 @@ function logDebugInfo_(msg) {
* @return {void} Nothing.
*/
function showShareError_(error) {
- var errorDiv = document.getElementById('host-plugin-error');
- l10n.localizeElementFromTag(errorDiv, error.getTag());
- console.error('Sharing error: ' + error.toString());
- remoting.setMode(remoting.AppMode.HOST_SHARE_FAILED);
+ if (error.hasTag(remoting.Error.Tag.CANCELLED)) {
+ remoting.setMode(remoting.AppMode.HOME);
+ it2meLogger.logClientSessionStateChange(
+ remoting.ClientSession.State.CONNECTION_CANCELED,
+ remoting.Error.none());
+ } else {
+ var errorDiv = document.getElementById('host-plugin-error');
+ l10n.localizeElementFromTag(errorDiv, error.getTag());
+ console.error('Sharing error: ' + error.toString());
+ remoting.setMode(remoting.AppMode.HOST_SHARE_FAILED);
+ it2meLogger.logClientSessionStateChange(
+ remoting.ClientSession.State.FAILED,
+ error);
+ }
+
cleanUp();
}
@@ -230,6 +251,9 @@ remoting.cancelShare = function() {
remoting.lastShareWasCancelled = true;
try {
hostSession_.disconnect();
+ it2meLogger.logClientSessionStateChange(
+ remoting.ClientSession.State.CONNECTION_CANCELED,
+ remoting.Error.none());
} catch (/** @type {*} */ error) {
console.error('Error disconnecting: ' + error +
'. The host probably crashed.');
@@ -338,4 +362,45 @@ function onNatTraversalPolicyChanged_(enabled) {
}
}
+/**
+ * Create an IT2Me LogToServer instance if one does not already exist.
+ *
+ * @return {Promise} Promise that resolves when the host version (if available),
+ * has been set on the logger instance.
+ */
+function ensureIT2MeLogger_() {
+ if (it2meLogger) {
+ return Promise.resolve();
+ }
+
+ var xmppConnection = new remoting.XmppConnection();
+ var tokenPromise = remoting.identity.getToken();
+ var emailPromise = remoting.identity.getEmail();
+ tokenPromise.then(function(/** string */ token) {
+ emailPromise.then(function(/** string */ email) {
+ xmppConnection.connect(remoting.settings.XMPP_SERVER, email, token);
+ });
+ });
+
+ var bufferedSignalStrategy =
+ new remoting.BufferedSignalStrategy(xmppConnection);
+ it2meLogger = new remoting.LogToServer(bufferedSignalStrategy, true);
+ it2meLogger.setLogEntryMode(remoting.ServerLogEntry.VALUE_MODE_IT2ME);
+
+ return setHostVersion_();
+};
+
+/**
+ * @return {Promise} Promise that resolves when the host version (if available),
+ * has been set on the logger instance.
+ */
+function setHostVersion_() {
+ return remoting.hostController.getLocalHostVersion().then(
+ function(/** string */ version) {
+ it2meLogger.setHostVersion(version);
+ }).catch(
+ base.doNothing
+ );
+};
+
})();
diff --git a/remoting/webapp/files.gni b/remoting/webapp/files.gni
index 08e34271..fc337ef 100644
--- a/remoting/webapp/files.gni
+++ b/remoting/webapp/files.gni
@@ -250,6 +250,7 @@ remoting_webapp_js_gnubby_auth_files = [ "crd/js/gnubby_auth_handler.js" ]
# Files for controlling the local machine as a host.
# Includes both it2me and me2me files.
remoting_webapp_js_host_control_files = [
+ "crd/js/buffered_signal_strategy.js",
"crd/js/host_controller.js",
"crd/js/host_daemon_facade.js",
"crd/js/host_screen.js",