| Index: remoting/webapp/crd/js/client_session.js
|
| diff --git a/remoting/webapp/crd/js/client_session.js b/remoting/webapp/crd/js/client_session.js
|
| deleted file mode 100644
|
| index db13e65fa54a9ad382909f79cfab4103d5de8436..0000000000000000000000000000000000000000
|
| --- a/remoting/webapp/crd/js/client_session.js
|
| +++ /dev/null
|
| @@ -1,607 +0,0 @@
|
| -// Copyright (c) 2012 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
|
| - * Class handling creation and teardown of a remoting client session.
|
| - *
|
| - * 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.
|
| - *
|
| - * This class should not access the plugin directly, instead it should
|
| - * do it through ClientPlugin class which abstracts plugin version
|
| - * differences.
|
| - */
|
| -
|
| -'use strict';
|
| -
|
| -/** @suppress {duplicate} */
|
| -var remoting = remoting || {};
|
| -
|
| -/**
|
| - * @param {remoting.ClientPlugin} plugin
|
| - * @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) {
|
| - base.inherits(this, base.EventSourceImpl);
|
| -
|
| - /** @private */
|
| - this.state_ = remoting.ClientSession.State.INITIALIZING;
|
| -
|
| - /** @private {!remoting.Error} */
|
| - this.error_ = remoting.Error.none();
|
| -
|
| - /** @private {remoting.Host} */
|
| - this.host_ = null;
|
| -
|
| - /** @private {remoting.CredentialsProvider} */
|
| - this.credentialsProvider_ = null;
|
| -
|
| - /** @private */
|
| - this.sessionId_ = '';
|
| -
|
| - /** @private */
|
| - this.listener_ = listener;
|
| -
|
| - /** @private */
|
| - this.hasReceivedFrame_ = false;
|
| -
|
| - /** @private */
|
| - this.logToServer_ = new remoting.LogToServer(signalStrategy);
|
| -
|
| - /** @private */
|
| - this.signalStrategy_ = signalStrategy;
|
| - base.debug.assert(this.signalStrategy_.getState() ==
|
| - remoting.SignalStrategy.State.CONNECTED);
|
| - this.signalStrategy_.setIncomingStanzaCallback(
|
| - this.onIncomingMessage_.bind(this));
|
| -
|
| - /** @private {remoting.FormatIq} */
|
| - this.iqFormatter_ = null;
|
| -
|
| - /**
|
| - * Allow host-offline error reporting to be suppressed in situations where it
|
| - * would not be useful, for example, when using a cached host JID.
|
| - *
|
| - * @type {boolean} @private
|
| - */
|
| - this.logHostOfflineErrors_ = true;
|
| -
|
| - /** @private {remoting.ClientPlugin} */
|
| - this.plugin_ = plugin;
|
| - plugin.setConnectionEventHandler(this);
|
| -
|
| - /** @private */
|
| - this.connectedDisposables_ = new base.Disposables();
|
| -
|
| - this.defineEvents(Object.keys(remoting.ClientSession.Events));
|
| -};
|
| -
|
| -/** @enum {string} */
|
| -remoting.ClientSession.Events = {
|
| - videoChannelStateChanged: 'videoChannelStateChanged'
|
| -};
|
| -
|
| -/**
|
| - * @interface
|
| - * [START]-------> [onConnected] ------> [onDisconnected]
|
| - * |
|
| - * |-----> [OnConnectionFailed]
|
| - *
|
| - */
|
| -remoting.ClientSession.EventHandler = function() {};
|
| -
|
| -/**
|
| - * Called when the connection failed before it is connected.
|
| - *
|
| - * @param {!remoting.Error} error
|
| - */
|
| -remoting.ClientSession.EventHandler.prototype.onConnectionFailed =
|
| - function(error) {};
|
| -
|
| -/**
|
| - * Called when a new session has been connected. The |connectionInfo| will be
|
| - * valid until onDisconnected() is called.
|
| - *
|
| - * @param {!remoting.ConnectionInfo} connectionInfo
|
| - */
|
| -remoting.ClientSession.EventHandler.prototype.onConnected =
|
| - function(connectionInfo) {};
|
| -
|
| -/**
|
| - * Called when the current session has been disconnected.
|
| - *
|
| - * @param {!remoting.Error} reason Reason that the session is disconnected.
|
| - * Set to remoting.Error.none() if there is no error.
|
| - */
|
| -remoting.ClientSession.EventHandler.prototype.onDisconnected =
|
| - function(reason) {};
|
| -
|
| -// Note that the positive values in both of these enums are copied directly
|
| -// from connection_to_host.h and must be kept in sync. Code in
|
| -// chromoting_instance.cc converts the C++ enums into strings that must match
|
| -// the names given here.
|
| -// The negative values represent state transitions that occur within the
|
| -// web-app that have no corresponding plugin state transition.
|
| -/** @enum {number} */
|
| -remoting.ClientSession.State = {
|
| - CONNECTION_CANCELED: -3, // Connection closed (gracefully) before connecting.
|
| - CONNECTION_DROPPED: -2, // Succeeded, but subsequently closed with an error.
|
| - CREATED: -1,
|
| - UNKNOWN: 0,
|
| - INITIALIZING: 1,
|
| - CONNECTING: 2,
|
| - // We don't currently receive AUTHENTICATED from the host - it comes through
|
| - // as 'CONNECTING' instead.
|
| - // TODO(garykac) Update chromoting_instance.cc to send this once we've
|
| - // shipped a webapp release with support for AUTHENTICATED.
|
| - AUTHENTICATED: 3,
|
| - CONNECTED: 4,
|
| - CLOSED: 5,
|
| - FAILED: 6
|
| -};
|
| -
|
| -/**
|
| - * @param {string} state The state name.
|
| - * @return {remoting.ClientSession.State} The session state enum value.
|
| - */
|
| -remoting.ClientSession.State.fromString = function(state) {
|
| - if (!remoting.ClientSession.State.hasOwnProperty(state)) {
|
| - throw "Invalid ClientSession.State: " + state;
|
| - }
|
| - return remoting.ClientSession.State[state];
|
| -};
|
| -
|
| -/** @enum {number} */
|
| -remoting.ClientSession.ConnectionError = {
|
| - UNKNOWN: -1,
|
| - NONE: 0,
|
| - HOST_IS_OFFLINE: 1,
|
| - SESSION_REJECTED: 2,
|
| - INCOMPATIBLE_PROTOCOL: 3,
|
| - NETWORK_FAILURE: 4,
|
| - HOST_OVERLOAD: 5
|
| -};
|
| -
|
| -/**
|
| - * @param {string} error The connection error name.
|
| - * @return {remoting.ClientSession.ConnectionError} The connection error enum.
|
| - */
|
| -remoting.ClientSession.ConnectionError.fromString = function(error) {
|
| - if (!remoting.ClientSession.ConnectionError.hasOwnProperty(error)) {
|
| - console.error('Unexpected ClientSession.ConnectionError string: ', error);
|
| - return remoting.ClientSession.ConnectionError.UNKNOWN;
|
| - }
|
| - return remoting.ClientSession.ConnectionError[error];
|
| -}
|
| -
|
| -/**
|
| - * Type used for performance statistics collected by the plugin.
|
| - * @constructor
|
| - */
|
| -remoting.ClientSession.PerfStats = function() {};
|
| -/** @type {number} */
|
| -remoting.ClientSession.PerfStats.prototype.videoBandwidth;
|
| -/** @type {number} */
|
| -remoting.ClientSession.PerfStats.prototype.videoFrameRate;
|
| -/** @type {number} */
|
| -remoting.ClientSession.PerfStats.prototype.captureLatency;
|
| -/** @type {number} */
|
| -remoting.ClientSession.PerfStats.prototype.encodeLatency;
|
| -/** @type {number} */
|
| -remoting.ClientSession.PerfStats.prototype.decodeLatency;
|
| -/** @type {number} */
|
| -remoting.ClientSession.PerfStats.prototype.renderLatency;
|
| -/** @type {number} */
|
| -remoting.ClientSession.PerfStats.prototype.roundtripLatency;
|
| -
|
| -// Keys for connection statistics.
|
| -remoting.ClientSession.STATS_KEY_VIDEO_BANDWIDTH = 'videoBandwidth';
|
| -remoting.ClientSession.STATS_KEY_VIDEO_FRAME_RATE = 'videoFrameRate';
|
| -remoting.ClientSession.STATS_KEY_CAPTURE_LATENCY = 'captureLatency';
|
| -remoting.ClientSession.STATS_KEY_ENCODE_LATENCY = 'encodeLatency';
|
| -remoting.ClientSession.STATS_KEY_DECODE_LATENCY = 'decodeLatency';
|
| -remoting.ClientSession.STATS_KEY_RENDER_LATENCY = 'renderLatency';
|
| -remoting.ClientSession.STATS_KEY_ROUNDTRIP_LATENCY = 'roundtripLatency';
|
| -
|
| -/**
|
| - * Set of capabilities for which hasCapability() can be used to test.
|
| - *
|
| - * @enum {string}
|
| - */
|
| -remoting.ClientSession.Capability = {
|
| - // When enabled this capability causes the client to send its screen
|
| - // resolution to the host once connection has been established. See
|
| - // this.plugin_.notifyClientResolution().
|
| - SEND_INITIAL_RESOLUTION: 'sendInitialResolution',
|
| -
|
| - // Let the host know that we're interested in knowing whether or not it
|
| - // rate limits desktop-resize requests.
|
| - // TODO(kelvinp): This has been supported since M-29. Currently we only have
|
| - // <1000 users on M-29 or below. Remove this and the capability on the host.
|
| - RATE_LIMIT_RESIZE_REQUESTS: 'rateLimitResizeRequests',
|
| -
|
| - // Indicates that host/client supports Google Drive integration, and that the
|
| - // client should send to the host the OAuth tokens to be used by Google Drive
|
| - // on the host.
|
| - GOOGLE_DRIVE: 'googleDrive',
|
| -
|
| - // Indicates that the client supports the video frame-recording extension.
|
| - VIDEO_RECORDER: 'videoRecorder',
|
| -
|
| - // Indicates that the client supports 'cast'ing the video stream to a
|
| - // cast-enabled device.
|
| - CAST: 'casting',
|
| -};
|
| -
|
| -/**
|
| - * 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.
|
| - *
|
| - * @param {!remoting.Error} error The reason for the disconnection. Use
|
| - * remoting.Error.none() if there is no error.
|
| - * @return {void} Nothing.
|
| - */
|
| -remoting.ClientSession.prototype.disconnect = function(error) {
|
| - if (this.isFinished()) {
|
| - // Do not send the session-terminate Iq if disconnect() is already called or
|
| - // if it is initiated by the host.
|
| - return;
|
| - }
|
| -
|
| - this.sendIq_(
|
| - '<cli:iq ' +
|
| - 'to="' + this.host_.jabberId + '" ' +
|
| - 'type="set" ' +
|
| - 'id="session-terminate" ' +
|
| - 'xmlns:cli="jabber:client">' +
|
| - '<jingle ' +
|
| - 'xmlns="urn:xmpp:jingle:1" ' +
|
| - 'action="session-terminate" ' +
|
| - 'sid="' + this.sessionId_ + '">' +
|
| - '<reason><success/></reason>' +
|
| - '</jingle>' +
|
| - '</cli:iq>');
|
| -
|
| - var state = error.isNone() ?
|
| - remoting.ClientSession.State.CLOSED :
|
| - remoting.ClientSession.State.FAILED;
|
| - this.error_ = error;
|
| - this.setState_(state);
|
| -};
|
| -
|
| -/**
|
| - * Deletes the <embed> element from the container and disconnects.
|
| - *
|
| - * @return {void} Nothing.
|
| - */
|
| -remoting.ClientSession.prototype.dispose = function() {
|
| - base.dispose(this.connectedDisposables_);
|
| - this.connectedDisposables_ = null;
|
| - base.dispose(this.plugin_);
|
| - this.plugin_ = null;
|
| -};
|
| -
|
| -/**
|
| - * @return {remoting.ClientSession.State} The current state.
|
| - */
|
| -remoting.ClientSession.prototype.getState = function() {
|
| - return this.state_;
|
| -};
|
| -
|
| -/**
|
| - * @return {remoting.LogToServer}.
|
| - */
|
| -remoting.ClientSession.prototype.getLogger = function() {
|
| - return this.logToServer_;
|
| -};
|
| -
|
| -/**
|
| - * @return {!remoting.Error} The current error code.
|
| - */
|
| -remoting.ClientSession.prototype.getError = function() {
|
| - return this.error_;
|
| -};
|
| -
|
| -/**
|
| - * Called when the client receives its first frame.
|
| - *
|
| - * @return {void} Nothing.
|
| - */
|
| -remoting.ClientSession.prototype.onFirstFrameReceived = function() {
|
| - this.hasReceivedFrame_ = true;
|
| -};
|
| -
|
| -/**
|
| - * @return {boolean} Whether the client has received a video buffer.
|
| - */
|
| -remoting.ClientSession.prototype.hasReceivedFrame = function() {
|
| - return this.hasReceivedFrame_;
|
| -};
|
| -
|
| -/**
|
| - * Sends a signaling message.
|
| - *
|
| - * @param {string} message XML string of IQ stanza to send to server.
|
| - * @return {void} Nothing.
|
| - * @private
|
| - */
|
| -remoting.ClientSession.prototype.sendIq_ = function(message) {
|
| - // Extract the session id, so we can close the session later.
|
| - var parser = new DOMParser();
|
| - var iqNode = parser.parseFromString(message, 'text/xml').firstChild;
|
| - var jingleNode = iqNode.firstChild;
|
| - if (jingleNode) {
|
| - var action = jingleNode.getAttribute('action');
|
| - if (jingleNode.nodeName == 'jingle' && action == 'session-initiate') {
|
| - this.sessionId_ = jingleNode.getAttribute('sid');
|
| - }
|
| - }
|
| -
|
| - console.log(base.timestamp() + this.iqFormatter_.prettifySendIq(message));
|
| - if (this.signalStrategy_.getState() !=
|
| - remoting.SignalStrategy.State.CONNECTED) {
|
| - console.log("Message above is dropped because signaling is not connected.");
|
| - return;
|
| - }
|
| -
|
| - this.signalStrategy_.sendMessage(message);
|
| -};
|
| -
|
| -/**
|
| - * @param {string} message XML string of IQ stanza to send to server.
|
| - */
|
| -remoting.ClientSession.prototype.onOutgoingIq = function(message) {
|
| - this.sendIq_(message);
|
| -};
|
| -
|
| -/**
|
| - * @param {string} msg
|
| - */
|
| -remoting.ClientSession.prototype.onDebugMessage = function(msg) {
|
| - console.log('plugin: ' + msg.trimRight());
|
| -};
|
| -
|
| -/**
|
| - * @param {Element} message
|
| - * @private
|
| - */
|
| -remoting.ClientSession.prototype.onIncomingMessage_ = function(message) {
|
| - if (!this.plugin_) {
|
| - return;
|
| - }
|
| - var formatted = new XMLSerializer().serializeToString(message);
|
| - console.log(base.timestamp() +
|
| - this.iqFormatter_.prettifyReceiveIq(formatted));
|
| - this.plugin_.onIncomingIq(formatted);
|
| -};
|
| -
|
| -/**
|
| - * Callback that the plugin invokes to indicate that the connection
|
| - * status has changed.
|
| - *
|
| - * @param {remoting.ClientSession.State} status The plugin's status.
|
| - * @param {remoting.ClientSession.ConnectionError} error The plugin's error
|
| - * state, if any.
|
| - */
|
| -remoting.ClientSession.prototype.onConnectionStatusUpdate =
|
| - function(status, error) {
|
| - if (status == remoting.ClientSession.State.FAILED) {
|
| - switch (error) {
|
| - case remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE:
|
| - this.error_ = new remoting.Error(
|
| - remoting.Error.Tag.HOST_IS_OFFLINE);
|
| - break;
|
| - case remoting.ClientSession.ConnectionError.SESSION_REJECTED:
|
| - this.error_ = new remoting.Error(
|
| - remoting.Error.Tag.INVALID_ACCESS_CODE);
|
| - break;
|
| - case remoting.ClientSession.ConnectionError.INCOMPATIBLE_PROTOCOL:
|
| - this.error_ = new remoting.Error(
|
| - remoting.Error.Tag.INCOMPATIBLE_PROTOCOL);
|
| - break;
|
| - case remoting.ClientSession.ConnectionError.NETWORK_FAILURE:
|
| - this.error_ = new remoting.Error(
|
| - remoting.Error.Tag.P2P_FAILURE);
|
| - break;
|
| - case remoting.ClientSession.ConnectionError.HOST_OVERLOAD:
|
| - this.error_ = new remoting.Error(
|
| - remoting.Error.Tag.HOST_OVERLOAD);
|
| - break;
|
| - default:
|
| - this.error_ = remoting.Error.unexpected();
|
| - }
|
| - }
|
| - this.setState_(status);
|
| -};
|
| -
|
| -/**
|
| - * Callback that the plugin invokes to indicate that the connection type for
|
| - * a channel has changed.
|
| - *
|
| - * @param {string} channel The channel name.
|
| - * @param {string} connectionType The new connection type.
|
| - * @private
|
| - */
|
| -remoting.ClientSession.prototype.onRouteChanged =
|
| - function(channel, connectionType) {
|
| - console.log('plugin: Channel ' + channel + ' using ' +
|
| - connectionType + ' connection.');
|
| - this.logToServer_.setConnectionType(connectionType);
|
| -};
|
| -
|
| -/**
|
| - * Callback that the plugin invokes to indicate when the connection is
|
| - * ready.
|
| - *
|
| - * @param {boolean} ready True if the connection is ready.
|
| - */
|
| -remoting.ClientSession.prototype.onConnectionReady = function(ready) {
|
| - // TODO(jamiewalch): Currently, the logic for determining whether or not the
|
| - // connection is available is based solely on whether or not any video frames
|
| - // have been received recently. which leads to poor UX on slow connections.
|
| - // Re-enable this once crbug.com/435315 has been fixed.
|
| - var ignoreVideoChannelState = true;
|
| - if (ignoreVideoChannelState) {
|
| - console.log('Video channel ' + (ready ? '' : 'not ') + 'ready.');
|
| - return;
|
| - }
|
| -
|
| - this.raiseEvent(remoting.ClientSession.Events.videoChannelStateChanged,
|
| - ready);
|
| -};
|
| -
|
| -/** @return {boolean} */
|
| -remoting.ClientSession.prototype.isFinished = function() {
|
| - var finishedStates = [
|
| - remoting.ClientSession.State.CLOSED,
|
| - remoting.ClientSession.State.FAILED,
|
| - remoting.ClientSession.State.CONNECTION_CANCELED,
|
| - remoting.ClientSession.State.CONNECTION_DROPPED
|
| - ];
|
| - return finishedStates.indexOf(this.getState()) !== -1;
|
| -};
|
| -/**
|
| - * @param {remoting.ClientSession.State} newState The new state for the session.
|
| - * @return {void} Nothing.
|
| - * @private
|
| - */
|
| -remoting.ClientSession.prototype.setState_ = function(newState) {
|
| - var oldState = this.state_;
|
| - this.state_ = this.translateState_(oldState, newState);
|
| -
|
| - if (newState == remoting.ClientSession.State.CONNECTED) {
|
| - this.connectedDisposables_.add(
|
| - new base.RepeatingTimer(this.reportStatistics.bind(this), 1000));
|
| - } else if (this.isFinished()) {
|
| - base.dispose(this.connectedDisposables_);
|
| - 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(remoting.Error.none());
|
| - break;
|
| -
|
| - case remoting.ClientSession.State.CONNECTION_CANCELED:
|
| - case remoting.ClientSession.State.FAILED:
|
| - error = this.getError();
|
| - if (!error.isNone()) {
|
| - 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_.onDisconnected(error);
|
| - break;
|
| -
|
| - default:
|
| - console.error('Unexpected client plugin state: ' + newState);
|
| - }
|
| -};
|
| -
|
| -/**
|
| - * @param {remoting.ClientSession.State} previous
|
| - * @param {remoting.ClientSession.State} current
|
| - * @return {remoting.ClientSession.State}
|
| - * @private
|
| - */
|
| -remoting.ClientSession.prototype.translateState_ = function(previous, current) {
|
| - var State = remoting.ClientSession.State;
|
| - if (previous == State.CONNECTING || previous == State.AUTHENTICATED) {
|
| - if (current == State.CLOSED) {
|
| - return remoting.ClientSession.State.CONNECTION_CANCELED;
|
| - } else if (current == State.FAILED &&
|
| - this.error_.hasTag(remoting.Error.Tag.HOST_IS_OFFLINE) &&
|
| - !this.logHostOfflineErrors_) {
|
| - // The application requested host-offline errors to be suppressed, for
|
| - // example, because this connection attempt is using a cached host JID.
|
| - console.log('Suppressing host-offline error.');
|
| - return State.CONNECTION_CANCELED;
|
| - }
|
| - } else if (previous == State.CONNECTED && current == State.FAILED) {
|
| - return State.CONNECTION_DROPPED;
|
| - }
|
| - return current;
|
| -};
|
| -
|
| -/** @private */
|
| -remoting.ClientSession.prototype.reportStatistics = function() {
|
| - this.logToServer_.logStatistics(this.plugin_.getPerfStats());
|
| -};
|
| -
|
| -/**
|
| - * Enable or disable logging of connection errors due to a host being offline.
|
| - * For example, if attempting a connection using a cached JID, host-offline
|
| - * errors should not be logged because the JID will be refreshed and the
|
| - * connection retried.
|
| - *
|
| - * @param {boolean} enable True to log host-offline errors; false to suppress.
|
| - */
|
| -remoting.ClientSession.prototype.logHostOfflineErrors = function(enable) {
|
| - this.logHostOfflineErrors_ = enable;
|
| -};
|
| -
|
|
|