Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / remoting / webapp / client_session.js
index 75ff0cb..d4c5708 100644 (file)
@@ -23,6 +23,8 @@
 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
@@ -46,16 +48,23 @@ var remoting = remoting || {};
  * @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 */
@@ -96,6 +105,14 @@ remoting.ClientSession = function(accessCode, fetchPin, fetchThirdPartyToken,
   /** @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.
@@ -109,8 +126,6 @@ remoting.ClientSession = function(accessCode, fetchPin, fetchThirdPartyToken,
   /** @private */
   this.callPluginGotFocus_ = this.pluginGotFocus_.bind(this);
   /** @private */
-  this.callSetScreenMode_ = this.onSetScreenMode_.bind(this);
-  /** @private */
   this.callToggleFullScreen_ = remoting.fullscreen.toggle.bind(
       remoting.fullscreen);
   /** @private */
@@ -129,9 +144,6 @@ remoting.ClientSession = function(accessCode, fetchPin, fetchThirdPartyToken,
   this.video_ = null;
 
   /** @type {Element} @private */
-  this.container_ = document.getElementById('video-container');
-
-  /** @type {Element} @private */
   this.mouseCursorOverlay_ =
       this.container_.querySelector('.mouse-cursor-overlay');
 
@@ -159,12 +171,8 @@ remoting.ClientSession = function(accessCode, fetchPin, fetchThirdPartyToken,
     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));
@@ -175,7 +183,18 @@ base.extend(remoting.ClientSession, base.EventSource);
 /** @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_;
 };
 
 /**
@@ -217,6 +236,20 @@ remoting.ClientSession.prototype.updateScrollbarVisibility = function() {
   }
 };
 
+/**
+ * @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
@@ -323,13 +356,6 @@ remoting.ClientSession.KEY_RESIZE_TO_CLIENT = 'resizeToClient';
 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}
@@ -339,7 +365,8 @@ remoting.ClientSession.Capability = {
   // 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'
 };
 
 /**
@@ -364,40 +391,6 @@ remoting.ClientSession.prototype.hasCapability_ = function(capability) {
 };
 
 /**
- * @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() {
@@ -416,8 +409,7 @@ remoting.ClientSession.prototype.pluginLostFocus_ = 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);
     }
   }
 };
@@ -425,15 +417,15 @@ remoting.ClientSession.prototype.pluginLostFocus_ = function() {
 /**
  * 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));
 };
@@ -484,7 +476,7 @@ remoting.ClientSession.prototype.setFocusHandlers_ = function() {
  */
 remoting.ClientSession.prototype.resetWithError_ = function(error) {
   this.plugin_.cleanup();
-  delete this.plugin_;
+  this.plugin_ = null;
   this.error_ = error;
   this.setState_(remoting.ClientSession.State.FAILED);
 }
@@ -528,7 +520,7 @@ remoting.ClientSession.prototype.onPluginInitialized_ = function(initialized) {
       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';
@@ -536,11 +528,9 @@ remoting.ClientSession.prototype.onPluginInitialized_ = function(initialized) {
 
     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. */
@@ -579,10 +569,6 @@ remoting.ClientSession.prototype.removePlugin = function() {
   }
 
   // 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);
 
@@ -595,13 +581,14 @@ remoting.ClientSession.prototype.removePlugin = function() {
         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_,
@@ -696,6 +683,7 @@ remoting.ClientSession.prototype.sendKeyCombination_ = function(keys) {
  * @return {void} Nothing.
  */
 remoting.ClientSession.prototype.sendCtrlAltDel = function() {
+  console.log('Sending Ctrl-Alt-Del.');
   this.sendKeyCombination_([0x0700e0, 0x0700e2, 0x07004c]);
 }
 
@@ -705,6 +693,7 @@ remoting.ClientSession.prototype.sendCtrlAltDel = function() {
  * @return {void} Nothing.
  */
 remoting.ClientSession.prototype.sendPrintScreen = function() {
+  console.log('Sending Print Screen.');
   this.sendKeyCombination_([0x070046]);
 }
 
@@ -767,26 +756,6 @@ remoting.ClientSession.prototype.applyRemapKeys_ = function(apply) {
 }
 
 /**
- * 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.
  *
@@ -798,9 +767,8 @@ remoting.ClientSession.prototype.onSetScreenMode_ = function(event) {
  *     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_();
@@ -1000,7 +968,9 @@ remoting.ClientSession.prototype.onConnectionStatusUpdate_ =
     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',
@@ -1039,12 +1009,10 @@ remoting.ClientSession.prototype.onConnectionStatusUpdate_ =
  * @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,
@@ -1386,12 +1354,13 @@ remoting.ClientSession.prototype.scroll_ = function(dx, dy) {
 
   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;
 };
 
@@ -1453,6 +1422,7 @@ remoting.ClientSession.prototype.onMouseMove_ = function(event) {
   var dy = computeDelta(event.y, clientArea.height);
 
   if (dx != 0 || dy != 0) {
+    this.raiseEvent(remoting.ClientSession.Events.bumpScrollStarted);
     /** @type {remoting.ClientSession} */
     var that = this;
     /**
@@ -1466,7 +1436,9 @@ remoting.ClientSession.prototype.onMouseMove_ = function(event) {
       /** @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);
@@ -1554,4 +1526,16 @@ remoting.ClientSession.prototype.updateMouseCursorImage_ =
     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)
+  };
+};