var remoting = remoting || {};
/**
+ * @param {HTMLElement} container Container element for the client view.
+ * @param {string} hostDisplayName A human-readable name for the host.
* @param {string} accessCode The IT2Me access code. Blank for Me2Me.
* @param {function(boolean, function(string): void): void} fetchPin
* Called by Me2Me connections when a PIN needs to be obtained
* @constructor
* @extends {base.EventSource}
*/
-remoting.ClientSession = function(accessCode, fetchPin, fetchThirdPartyToken,
- authenticationMethods,
- hostId, hostJid, hostPublicKey, mode,
- clientPairingId, clientPairedSecret) {
+remoting.ClientSession = function(container, hostDisplayName, accessCode,
+ fetchPin, fetchThirdPartyToken,
+ authenticationMethods, hostId, hostJid,
+ hostPublicKey, mode, clientPairingId,
+ clientPairedSecret) {
/** @private */
this.state_ = remoting.ClientSession.State.CREATED;
/** @private */
this.error_ = remoting.Error.NONE;
+ /** @type {HTMLElement}
+ * @private */
+ this.container_ = container;
+
+ /** @private */
+ this.hostDisplayName_ = hostDisplayName;
/** @private */
this.hostJid_ = hostJid;
/** @private */
/** @type {number?} @private */
this.bumpScrollTimer_ = null;
+ // Bump-scroll test variables. Override to use a fake value for the width
+ // and height of the client plugin so that bump-scrolling can be tested
+ // without relying on the actual size of the host desktop.
+ /** @type {number} @private */
+ this.pluginWidthForBumpScrollTesting = 0;
+ /** @type {number} @private */
+ this.pluginHeightForBumpScrollTesting = 0;
+
/**
* Allow host-offline error reporting to be suppressed in situations where it
* would not be useful, for example, when using a cached host JID.
/** @private */
this.callPluginGotFocus_ = this.pluginGotFocus_.bind(this);
/** @private */
- this.callSetScreenMode_ = this.onSetScreenMode_.bind(this);
- /** @private */
this.callToggleFullScreen_ = remoting.fullscreen.toggle.bind(
remoting.fullscreen);
/** @private */
this.video_ = null;
/** @type {Element} @private */
- this.container_ = document.getElementById('video-container');
-
- /** @type {Element} @private */
this.mouseCursorOverlay_ =
this.container_.querySelector('.mouse-cursor-overlay');
this.resizeToClientButton_.hidden = true;
} else {
this.resizeToClientButton_.hidden = false;
- this.resizeToClientButton_.addEventListener(
- 'click', this.callSetScreenMode_, false);
}
- this.shrinkToFitButton_.addEventListener(
- 'click', this.callSetScreenMode_, false);
this.fullScreenButton_.addEventListener(
'click', this.callToggleFullScreen_, false);
this.defineEvents(Object.keys(remoting.ClientSession.Events));
/** @enum {string} */
remoting.ClientSession.Events = {
stateChanged: 'stateChanged',
- videoChannelStateChanged: 'videoChannelStateChanged'
+ videoChannelStateChanged: 'videoChannelStateChanged',
+ bumpScrollStarted: 'bumpScrollStarted',
+ bumpScrollStopped: 'bumpScrollStopped'
+};
+
+/**
+ * Get host display name.
+ *
+ * @return {string}
+ */
+remoting.ClientSession.prototype.getHostDisplayName = function() {
+ return this.hostDisplayName_;
};
/**
}
};
+/**
+ * @return {boolean} True if shrink-to-fit is enabled; false otherwise.
+ */
+remoting.ClientSession.prototype.getShrinkToFit = function() {
+ return this.shrinkToFit_;
+};
+
+/**
+ * @return {boolean} True if resize-to-client is enabled; false otherwise.
+ */
+remoting.ClientSession.prototype.getResizeToClient = function() {
+ return this.resizeToClient_;
+};
+
// Note that the positive values in both of these enums are copied directly
// from chromoting_scriptable_object.h and must be kept in sync. The negative
// values represent state transitions that occur within the web-app that have
remoting.ClientSession.KEY_SHRINK_TO_FIT = 'shrinkToFit';
/**
- * The id of the client plugin
- *
- * @const
- */
-remoting.ClientSession.prototype.PLUGIN_ID = 'session-client-plugin';
-
-/**
* Set of capabilities for which hasCapability_() can be used to test.
*
* @enum {string}
// resolution to the host once connection has been established. See
// this.plugin_.notifyClientResolution().
SEND_INITIAL_RESOLUTION: 'sendInitialResolution',
- RATE_LIMIT_RESIZE_REQUESTS: 'rateLimitResizeRequests'
+ RATE_LIMIT_RESIZE_REQUESTS: 'rateLimitResizeRequests',
+ VIDEO_RECORDER: 'videoRecorder'
};
/**
};
/**
- * @param {Element} container The element to add the plugin to.
- * @param {string} id Id to use for the plugin element .
- * @param {function(string, string):boolean} onExtensionMessage The handler for
- * protocol extension messages. Returns true if a message is recognized;
- * false otherwise.
- * @return {remoting.ClientPlugin} Create plugin object for the locally
- * installed plugin.
- */
-remoting.ClientSession.prototype.createClientPlugin_ =
- function(container, id, onExtensionMessage) {
- var plugin = /** @type {remoting.ViewerPlugin} */
- document.createElement('embed');
-
- plugin.id = id;
- if (remoting.settings.CLIENT_PLUGIN_TYPE == 'pnacl') {
- plugin.src = 'remoting_client_pnacl.nmf';
- plugin.type = 'application/x-pnacl';
- } else if (remoting.settings.CLIENT_PLUGIN_TYPE == 'nacl') {
- plugin.src = 'remoting_client_nacl.nmf';
- plugin.type = 'application/x-nacl';
- } else {
- plugin.src = 'about://none';
- plugin.type = 'application/vnd.chromium.remoting-viewer';
- }
-
- plugin.width = 0;
- plugin.height = 0;
- plugin.tabIndex = 0; // Required, otherwise focus() doesn't work.
- container.appendChild(plugin);
-
- return new remoting.ClientPlugin(plugin, onExtensionMessage);
-};
-
-/**
* Callback function called when the plugin element gets focus.
*/
remoting.ClientSession.prototype.pluginGotFocus_ = function() {
// Due to crbug.com/246335, we can't restore the focus immediately,
// otherwise the plugin gets confused about whether or not it has focus.
window.setTimeout(
- this.plugin_.element().focus.bind(this.plugin_.element()),
- 0);
+ this.plugin_.element().focus.bind(this.plugin_.element()), 0);
}
}
};
/**
* Adds <embed> element to |container| and readies the sesion object.
*
- * @param {Element} container The element to add the plugin to.
* @param {function(string, string):boolean} onExtensionMessage The handler for
* protocol extension messages. Returns true if a message is recognized;
* false otherwise.
*/
remoting.ClientSession.prototype.createPluginAndConnect =
- function(container, onExtensionMessage) {
- this.plugin_ = this.createClientPlugin_(container, this.PLUGIN_ID,
- onExtensionMessage);
+ function(onExtensionMessage) {
+ this.plugin_ = new remoting.ClientPlugin(
+ this.container_.querySelector('.client-plugin-container'),
+ onExtensionMessage);
remoting.HostSettings.load(this.hostId_,
this.onHostSettingsLoaded_.bind(this));
};
*/
remoting.ClientSession.prototype.resetWithError_ = function(error) {
this.plugin_.cleanup();
- delete this.plugin_;
+ this.plugin_ = null;
this.error_ = error;
this.setState_(remoting.ClientSession.State.FAILED);
}
this.plugin_.hasFeature(
remoting.ClientPlugin.Feature.MEDIA_SOURCE_RENDERING)) {
this.video_ = /** @type {HTMLMediaElement} */(
- document.getElementById('mediasource-video-output'));
+ this.container_.querySelector('video'));
// Make sure that the <video> element is hidden until we get the first
// frame.
this.video_.style.width = '0px';
var renderer = new remoting.MediaSourceRenderer(this.video_);
this.plugin_.enableMediaSourceRendering(renderer);
- /** @type {HTMLElement} */(document.getElementById('video-container'))
- .classList.add('mediasource-rendering');
+ this.container_.classList.add('mediasource-rendering');
} else {
- /** @type {HTMLElement} */(document.getElementById('video-container'))
- .classList.remove('mediasource-rendering');
+ this.container_.classList.remove('mediasource-rendering');
}
/** @param {string} msg The IQ stanza to send. */
}
// Delete event handlers that aren't relevent when not connected.
- this.resizeToClientButton_.removeEventListener(
- 'click', this.callSetScreenMode_, false);
- this.shrinkToFitButton_.removeEventListener(
- 'click', this.callSetScreenMode_, false);
this.fullScreenButton_.removeEventListener(
'click', this.callToggleFullScreen_, false);
remoting.fullscreen.removeListener(listener);
});
if (remoting.windowFrame) {
- remoting.windowFrame.setConnected(false);
+ remoting.windowFrame.setClientSession(null);
+ } else {
+ remoting.toolbar.setClientSession(null);
}
- // Remove mediasource-rendering class from video-contained - this will also
+ // Remove mediasource-rendering class from the container - this will also
// hide the <video> element.
- /** @type {HTMLElement} */(document.getElementById('video-container'))
- .classList.remove('mediasource-rendering');
+ this.container_.classList.remove('mediasource-rendering');
this.container_.removeEventListener('mousemove',
this.updateMouseCursorPosition_,
* @return {void} Nothing.
*/
remoting.ClientSession.prototype.sendCtrlAltDel = function() {
+ console.log('Sending Ctrl-Alt-Del.');
this.sendKeyCombination_([0x0700e0, 0x0700e2, 0x07004c]);
}
* @return {void} Nothing.
*/
remoting.ClientSession.prototype.sendPrintScreen = function() {
+ console.log('Sending Print Screen.');
this.sendKeyCombination_([0x070046]);
}
}
/**
- * Callback for the two "screen mode" related menu items: Resize desktop to
- * fit and Shrink to fit.
- *
- * @param {Event} event The click event indicating which mode was selected.
- * @return {void} Nothing.
- * @private
- */
-remoting.ClientSession.prototype.onSetScreenMode_ = function(event) {
- var shrinkToFit = this.shrinkToFit_;
- var resizeToClient = this.resizeToClient_;
- if (event.target == this.shrinkToFitButton_) {
- shrinkToFit = !shrinkToFit;
- }
- if (event.target == this.resizeToClientButton_) {
- resizeToClient = !resizeToClient;
- }
- this.setScreenMode_(shrinkToFit, resizeToClient);
-};
-
-/**
* Set the shrink-to-fit and resize-to-client flags and save them if this is
* a Me2Me connection.
*
* false to disable this behaviour for subsequent window resizes--the
* current host desktop size is not restored in this case.
* @return {void} Nothing.
- * @private
*/
-remoting.ClientSession.prototype.setScreenMode_ =
+remoting.ClientSession.prototype.setScreenMode =
function(shrinkToFit, resizeToClient) {
if (resizeToClient && !this.resizeToClient_) {
var clientArea = this.getClientArea_();
remoting.fullscreen.addListener(this.callOnFullScreenChanged_);
remoting.fullscreen.syncWithMaximize(true);
if (remoting.windowFrame) {
- remoting.windowFrame.setConnected(true);
+ remoting.windowFrame.setClientSession(this);
+ } else {
+ remoting.toolbar.setClientSession(this);
}
this.container_.addEventListener('mousemove',
* @param {boolean} ready True if the connection is ready.
*/
remoting.ClientSession.prototype.onConnectionReady_ = function(ready) {
- var container = /** @type {HTMLMediaElement} */(
- document.getElementById('video-container'));
if (!ready) {
- container.classList.add('session-client-inactive');
+ this.container_.classList.add('session-client-inactive');
} else {
- container.classList.remove('session-client-inactive');
+ this.container_.classList.remove('session-client-inactive');
}
this.raiseEvent(remoting.ClientSession.Events.videoChannelStateChanged,
var stopX = { stop: false };
var clientArea = this.getClientArea_();
- style.marginLeft = adjustMargin(style.marginLeft, dx,
- clientArea.width, plugin.clientWidth, stopX);
+ style.marginLeft = adjustMargin(style.marginLeft, dx, clientArea.width,
+ this.pluginWidthForBumpScrollTesting || plugin.clientWidth, stopX);
var stopY = { stop: false };
style.marginTop = adjustMargin(
- style.marginTop, dy, clientArea.height, plugin.clientHeight, stopY);
+ style.marginTop, dy, clientArea.height,
+ this.pluginHeightForBumpScrollTesting || plugin.clientHeight, stopY);
return stopX.stop && stopY.stop;
};
var dy = computeDelta(event.y, clientArea.height);
if (dx != 0 || dy != 0) {
+ this.raiseEvent(remoting.ClientSession.Events.bumpScrollStarted);
/** @type {remoting.ClientSession} */
var that = this;
/**
/** @type {number} */
var timeout = 10;
var lateAdjustment = 1 + (now - expected) / timeout;
- if (!that.scroll_(lateAdjustment * dx, lateAdjustment * dy)) {
+ if (that.scroll_(lateAdjustment * dx, lateAdjustment * dy)) {
+ that.raiseEvent(remoting.ClientSession.Events.bumpScrollStopped);
+ } else {
that.bumpScrollTimer_ = window.setTimeout(
function() { repeatScroll(now + timeout); },
timeout);
this.mouseCursorOverlay_.style.marginTop = '-' + hotspotY + 'px';
this.mouseCursorOverlay_.src = url;
}
- };
+};
+
+/**
+ * @return {{top: number, left:number}} The top-left corner of the plugin.
+ */
+remoting.ClientSession.prototype.getPluginPositionForTesting = function() {
+ var plugin = this.plugin_.element();
+ var style = plugin.style;
+ return {
+ top: parseFloat(style.marginTop),
+ left: parseFloat(style.marginLeft)
+ };
+};