summaryrefslogtreecommitdiffstats
path: root/remoting/webapp
diff options
context:
space:
mode:
Diffstat (limited to 'remoting/webapp')
-rw-r--r--remoting/webapp/all_js_load.gtestjs1
-rw-r--r--remoting/webapp/client_plugin.js585
-rw-r--r--remoting/webapp/client_plugin_async.js654
-rw-r--r--remoting/webapp/client_session.js2
-rw-r--r--remoting/webapp/main.html1
5 files changed, 521 insertions, 722 deletions
diff --git a/remoting/webapp/all_js_load.gtestjs b/remoting/webapp/all_js_load.gtestjs
index c00cc0b..89a14a8 100644
--- a/remoting/webapp/all_js_load.gtestjs
+++ b/remoting/webapp/all_js_load.gtestjs
@@ -18,7 +18,6 @@ AllJsLoadTest.prototype = {
'browser_globals.gtestjs',
// All of our Javascript files should be listed here unless they are
// only used by JSCompiler
- 'client_plugin_async.js',
'client_plugin.js',
'client_screen.js',
'client_session.js',
diff --git a/remoting/webapp/client_plugin.js b/remoting/webapp/client_plugin.js
index 8cd8f1c..cc621f2 100644
--- a/remoting/webapp/client_plugin.js
+++ b/remoting/webapp/client_plugin.js
@@ -2,54 +2,80 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+/**
+ * @fileoverview
+ * Class that wraps low-level details of interacting with the client plugin.
+ *
+ * This abstracts a <embed> element and controls the plugin which does
+ * the actual remoting work. It also handles differences between
+ * client plugins versions when it is necessary.
+ */
+
+'use strict';
+
/** @suppress {duplicate} */
var remoting = remoting || {};
/**
- * Interface used for ClientPlugin objects.
- * @interface
+ * @param {remoting.ViewerPlugin} plugin The plugin embed element.
+ * @constructor
*/
-remoting.ClientPlugin = function() {
-};
+remoting.ClientPlugin = function(plugin) {
+ this.plugin = plugin;
-/** @type {number} Desktop width */
-remoting.ClientPlugin.prototype.desktopWidth;
-/** @type {number} Desktop height */
-remoting.ClientPlugin.prototype.desktopHeight;
-/** @type {number} Desktop x DPI */
-remoting.ClientPlugin.prototype.desktopXDpi;
-/** @type {number} Desktop y DPI */
-remoting.ClientPlugin.prototype.desktopYDpi;
+ this.desktopWidth = 0;
+ this.desktopHeight = 0;
+ this.desktopXDpi = 96;
+ this.desktopYDpi = 96;
-/** @type {function(string): void} Outgoing signaling message callback. */
-remoting.ClientPlugin.prototype.onOutgoingIqHandler;
-/** @type {function(string): void} Debug messages callback. */
-remoting.ClientPlugin.prototype.onDebugMessageHandler;
-/** @type {function(number, number): void} State change callback. */
-remoting.ClientPlugin.prototype.onConnectionStatusUpdateHandler;
-/** @type {function(boolean): void} Connection ready state callback. */
-remoting.ClientPlugin.prototype.onConnectionReadyHandler;
-/** @type {function(): void} Desktop size change callback. */
-remoting.ClientPlugin.prototype.onDesktopSizeUpdateHandler;
-/** @type {function(!Array.<string>): void} Capabilities negotiated callback. */
-remoting.ClientPlugin.prototype.onSetCapabilitiesHandler;
-/** @type {function(boolean): void} Request a PIN from the user. */
-remoting.ClientPlugin.prototype.fetchPinHandler;
+ /** @param {string} iq The Iq stanza received from the host. */
+ this.onOutgoingIqHandler = function (iq) {};
+ /** @param {string} message Log message. */
+ this.onDebugMessageHandler = function (message) {};
+ /**
+ * @param {number} state The connection state.
+ * @param {number} error The error code, if any.
+ */
+ this.onConnectionStatusUpdateHandler = function(state, error) {};
+ /** @param {boolean} ready Connection ready state. */
+ this.onConnectionReadyHandler = function(ready) {};
+ /**
+ * @param {string} tokenUrl Token-request URL, received from the host.
+ * @param {string} hostPublicKey Public key for the host.
+ * @param {string} scope OAuth scope to request the token for.
+ */
+ this.fetchThirdPartyTokenHandler = function(
+ tokenUrl, hostPublicKey, scope) {};
+ this.onDesktopSizeUpdateHandler = function () {};
+ /** @param {!Array.<string>} capabilities The negotiated capabilities. */
+ this.onSetCapabilitiesHandler = function (capabilities) {};
+ this.fetchPinHandler = function (supportsPairing) {};
-/**
- * Initializes the plugin asynchronously and calls specified function
- * when done.
- *
- * @param {function(boolean): void} onDone Function to be called when
- * the plugin is initialized. Parameter is set to true when the plugin
- * is loaded successfully.
- */
-remoting.ClientPlugin.prototype.initialize = function(onDone) {};
+ /** @type {number} */
+ this.pluginApiVersion_ = -1;
+ /** @type {Array.<string>} */
+ this.pluginApiFeatures_ = [];
+ /** @type {number} */
+ this.pluginApiMinVersion_ = -1;
+ /** @type {!Array.<string>} */
+ this.capabilities_ = [];
+ /** @type {boolean} */
+ this.helloReceived_ = false;
+ /** @type {function(boolean)|null} */
+ this.onInitializedCallback_ = null;
+ /** @type {function(string, string):void} */
+ this.onPairingComplete_ = function(clientId, sharedSecret) {};
+ /** @type {remoting.ClientSession.PerfStats} */
+ this.perfStats_ = new remoting.ClientSession.PerfStats();
-/**
- * @return {boolean} True if the plugin and web-app versions are compatible.
- */
-remoting.ClientPlugin.prototype.isSupportedVersion = function() {};
+ /** @type {remoting.ClientPlugin} */
+ var that = this;
+ /** @param {Event} event Message event from the plugin. */
+ this.plugin.addEventListener('message', function(event) {
+ that.handleMessage_(event.data);
+ }, false);
+ window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500);
+};
/**
* Set of features for which hasFeature() can be used to test.
@@ -71,26 +97,329 @@ remoting.ClientPlugin.Feature = {
};
/**
- * @param {remoting.ClientPlugin.Feature} feature The feature to test for.
- * @return {boolean} True if the plugin supports the named feature.
+ * Chromoting session API version (for this javascript).
+ * This is compared with the plugin API version to verify that they are
+ * compatible.
+ *
+ * @const
+ * @private
*/
-remoting.ClientPlugin.prototype.hasFeature = function(feature) {};
+remoting.ClientPlugin.prototype.API_VERSION_ = 6;
/**
- * @return {HTMLEmbedElement} HTML element that corresponds to the plugin.
+ * The oldest API version that we support.
+ * This will differ from the |API_VERSION_| if we maintain backward
+ * compatibility with older API versions.
+ *
+ * @const
+ * @private
*/
-remoting.ClientPlugin.prototype.element = function() {};
+remoting.ClientPlugin.prototype.API_MIN_VERSION_ = 5;
+
+/**
+ * @param {string} messageStr Message from the plugin.
+ */
+remoting.ClientPlugin.prototype.handleMessage_ = function(messageStr) {
+ var message = /** @type {{method:string, data:Object.<string,string>}} */
+ jsonParseSafe(messageStr);
+
+ if (!message || !('method' in message) || !('data' in message)) {
+ console.error('Received invalid message from the plugin: ' + messageStr);
+ return;
+ }
+
+ /**
+ * Splits a string into a list of words delimited by spaces.
+ * @param {string} str String that should be split.
+ * @return {!Array.<string>} List of words.
+ */
+ var tokenize = function(str) {
+ /** @type {Array.<string>} */
+ var tokens = str.match(/\S+/g);
+ return tokens ? tokens : [];
+ };
+
+ if (message.method == 'hello') {
+ // Reset the size in case we had to enlarge it to support click-to-play.
+ this.plugin.width = 0;
+ this.plugin.height = 0;
+ if (typeof message.data['apiVersion'] != 'number' ||
+ typeof message.data['apiMinVersion'] != 'number') {
+ console.error('Received invalid hello message: ' + messageStr);
+ return;
+ }
+ this.pluginApiVersion_ = /** @type {number} */ message.data['apiVersion'];
+
+ if (this.pluginApiVersion_ >= 7) {
+ if (typeof message.data['apiFeatures'] != 'string') {
+ console.error('Received invalid hello message: ' + messageStr);
+ return;
+ }
+ this.pluginApiFeatures_ =
+ /** @type {Array.<string>} */ tokenize(message.data['apiFeatures']);
+
+ // Negotiate capabilities.
+
+ /** @type {!Array.<string>} */
+ var requestedCapabilities = [];
+ if ('requestedCapabilities' in message.data) {
+ if (typeof message.data['requestedCapabilities'] != 'string') {
+ console.error('Received invalid hello message: ' + messageStr);
+ return;
+ }
+ requestedCapabilities = tokenize(message.data['requestedCapabilities']);
+ }
+
+ /** @type {!Array.<string>} */
+ var supportedCapabilities = [];
+ if ('supportedCapabilities' in message.data) {
+ if (typeof message.data['supportedCapabilities'] != 'string') {
+ console.error('Received invalid hello message: ' + messageStr);
+ return;
+ }
+ supportedCapabilities = tokenize(message.data['supportedCapabilities']);
+ }
+
+ // At the moment the webapp does not recognize any of
+ // 'requestedCapabilities' capabilities (so they all should be disabled)
+ // and do not care about any of 'supportedCapabilities' capabilities (so
+ // they all can be enabled).
+ this.capabilities_ = supportedCapabilities;
+
+ // Let the host know that the webapp can be requested to always send
+ // the client's dimensions.
+ this.capabilities_.push(
+ remoting.ClientSession.Capability.SEND_INITIAL_RESOLUTION);
+
+ // Let the host know that we're interested in knowing whether or not
+ // it rate-limits desktop-resize requests.
+ this.capabilities_.push(
+ remoting.ClientSession.Capability.RATE_LIMIT_RESIZE_REQUESTS);
+ } else if (this.pluginApiVersion_ >= 6) {
+ this.pluginApiFeatures_ = ['highQualityScaling', 'injectKeyEvent'];
+ } else {
+ this.pluginApiFeatures_ = ['highQualityScaling'];
+ }
+ this.pluginApiMinVersion_ =
+ /** @type {number} */ message.data['apiMinVersion'];
+ this.helloReceived_ = true;
+ if (this.onInitializedCallback_ != null) {
+ this.onInitializedCallback_(true);
+ this.onInitializedCallback_ = null;
+ }
+ } else if (message.method == 'sendOutgoingIq') {
+ if (typeof message.data['iq'] != 'string') {
+ console.error('Received invalid sendOutgoingIq message: ' + messageStr);
+ return;
+ }
+ this.onOutgoingIqHandler(message.data['iq']);
+ } else if (message.method == 'logDebugMessage') {
+ if (typeof message.data['message'] != 'string') {
+ console.error('Received invalid logDebugMessage message: ' + messageStr);
+ return;
+ }
+ this.onDebugMessageHandler(message.data['message']);
+ } else if (message.method == 'onConnectionStatus') {
+ if (typeof message.data['state'] != 'string' ||
+ !remoting.ClientSession.State.hasOwnProperty(message.data['state']) ||
+ typeof message.data['error'] != 'string') {
+ console.error('Received invalid onConnectionState message: ' +
+ messageStr);
+ return;
+ }
+
+ /** @type {remoting.ClientSession.State} */
+ var state = remoting.ClientSession.State[message.data['state']];
+ var error;
+ if (remoting.ClientSession.ConnectionError.hasOwnProperty(
+ message.data['error'])) {
+ error = /** @type {remoting.ClientSession.ConnectionError} */
+ remoting.ClientSession.ConnectionError[message.data['error']];
+ } else {
+ error = remoting.ClientSession.ConnectionError.UNKNOWN;
+ }
+
+ this.onConnectionStatusUpdateHandler(state, error);
+ } else if (message.method == 'onDesktopSize') {
+ if (typeof message.data['width'] != 'number' ||
+ typeof message.data['height'] != 'number') {
+ console.error('Received invalid onDesktopSize message: ' + messageStr);
+ return;
+ }
+ this.desktopWidth = /** @type {number} */ message.data['width'];
+ this.desktopHeight = /** @type {number} */ message.data['height'];
+ this.desktopXDpi = (typeof message.data['x_dpi'] == 'number') ?
+ /** @type {number} */ (message.data['x_dpi']) : 96;
+ this.desktopYDpi = (typeof message.data['y_dpi'] == 'number') ?
+ /** @type {number} */ (message.data['y_dpi']) : 96;
+ this.onDesktopSizeUpdateHandler();
+ } else if (message.method == 'onPerfStats') {
+ if (typeof message.data['videoBandwidth'] != 'number' ||
+ typeof message.data['videoFrameRate'] != 'number' ||
+ typeof message.data['captureLatency'] != 'number' ||
+ typeof message.data['encodeLatency'] != 'number' ||
+ typeof message.data['decodeLatency'] != 'number' ||
+ typeof message.data['renderLatency'] != 'number' ||
+ typeof message.data['roundtripLatency'] != 'number') {
+ console.error('Received incorrect onPerfStats message: ' + messageStr);
+ return;
+ }
+ this.perfStats_ =
+ /** @type {remoting.ClientSession.PerfStats} */ message.data;
+ } else if (message.method == 'injectClipboardItem') {
+ if (typeof message.data['mimeType'] != 'string' ||
+ typeof message.data['item'] != 'string') {
+ console.error('Received incorrect injectClipboardItem message.');
+ return;
+ }
+ if (remoting.clipboard) {
+ remoting.clipboard.fromHost(message.data['mimeType'],
+ message.data['item']);
+ }
+ } else if (message.method == 'onFirstFrameReceived') {
+ if (remoting.clientSession) {
+ remoting.clientSession.onFirstFrameReceived();
+ }
+ } else if (message.method == 'onConnectionReady') {
+ if (typeof message.data['ready'] != 'boolean') {
+ console.error('Received incorrect onConnectionReady message.');
+ return;
+ }
+ var ready = /** @type {boolean} */ message.data['ready'];
+ this.onConnectionReadyHandler(ready);
+ } else if (message.method == 'fetchPin') {
+ // The pairingSupported value in the dictionary indicates whether both
+ // client and host support pairing. If the client doesn't support pairing,
+ // then the value won't be there at all, so give it a default of false.
+ /** @type {boolean} */
+ var pairingSupported = false;
+ if ('pairingSupported' in message.data) {
+ pairingSupported =
+ /** @type {boolean} */ message.data['pairingSupported'];
+ if (typeof pairingSupported != 'boolean') {
+ console.error('Received incorrect fetchPin message.');
+ return;
+ }
+ }
+ this.fetchPinHandler(pairingSupported);
+ } else if (message.method == 'setCapabilities') {
+ if (typeof message.data['capabilities'] != 'string') {
+ console.error('Received incorrect setCapabilities message.');
+ return;
+ }
+
+ /** @type {!Array.<string>} */
+ var capabilities = tokenize(message.data['capabilities']);
+ this.onSetCapabilitiesHandler(capabilities);
+ } else if (message.method == 'fetchThirdPartyToken') {
+ if (typeof message.data['tokenUrl'] != 'string' ||
+ typeof message.data['hostPublicKey'] != 'string' ||
+ typeof message.data['scope'] != 'string') {
+ console.error('Received incorrect fetchThirdPartyToken message.');
+ return;
+ }
+ var tokenUrl = /** @type {string} */ message.data['tokenUrl'];
+ var hostPublicKey =
+ /** @type {string} */ message.data['hostPublicKey'];
+ var scope = /** @type {string} */ message.data['scope'];
+ this.fetchThirdPartyTokenHandler(tokenUrl, hostPublicKey, scope);
+ } else if (message.method == 'pairingResponse') {
+ var clientId = /** @type {string} */ message.data['clientId'];
+ var sharedSecret = /** @type {string} */ message.data['sharedSecret'];
+ if (typeof clientId != 'string' || typeof sharedSecret != 'string') {
+ console.error('Received incorrect pairingResponse message.');
+ return;
+ }
+ this.onPairingComplete_(clientId, sharedSecret);
+ } else if (message.method == 'extensionMessage') {
+ if (typeof(message.data['type']) != 'string' ||
+ typeof(message.data['data']) != 'string') {
+ console.error('Invalid extension message:', message.data);
+ return;
+ }
+ switch (message.data['type']) {
+ case 'test-echo-reply':
+ console.log('Got echo reply: ' + message.data['data']);
+ break;
+ default:
+ console.log('Unexpected message received: ' +
+ message.data['type'] + ': ' + message.data['data']);
+ }
+ }
+};
/**
* Deletes the plugin.
*/
-remoting.ClientPlugin.prototype.cleanup = function() {};
+remoting.ClientPlugin.prototype.cleanup = function() {
+ this.plugin.parentNode.removeChild(this.plugin);
+};
+
+/**
+ * @return {HTMLEmbedElement} HTML element that correspods to the plugin.
+ */
+remoting.ClientPlugin.prototype.element = function() {
+ return this.plugin;
+};
+
+/**
+ * @param {function(boolean): void} onDone
+ */
+remoting.ClientPlugin.prototype.initialize = function(onDone) {
+ if (this.helloReceived_) {
+ onDone(true);
+ } else {
+ this.onInitializedCallback_ = onDone;
+ }
+};
+
+/**
+ * @return {boolean} True if the plugin and web-app versions are compatible.
+ */
+remoting.ClientPlugin.prototype.isSupportedVersion = function() {
+ if (!this.helloReceived_) {
+ console.error(
+ "isSupportedVersion() is called before the plugin is initialized.");
+ return false;
+ }
+ return this.API_VERSION_ >= this.pluginApiMinVersion_ &&
+ this.pluginApiVersion_ >= this.API_MIN_VERSION_;
+};
+
+/**
+ * @param {remoting.ClientPlugin.Feature} feature The feature to test for.
+ * @return {boolean} True if the plugin supports the named feature.
+ */
+remoting.ClientPlugin.prototype.hasFeature = function(feature) {
+ if (!this.helloReceived_) {
+ console.error(
+ "hasFeature() is called before the plugin is initialized.");
+ return false;
+ }
+ return this.pluginApiFeatures_.indexOf(feature) > -1;
+};
+
+/**
+ * @return {boolean} True if the plugin supports the injectKeyEvent API.
+ */
+remoting.ClientPlugin.prototype.isInjectKeyEventSupported = function() {
+ return this.pluginApiVersion_ >= 6;
+};
/**
- * Must be called for each incoming stanza received from the host.
* @param {string} iq Incoming IQ stanza.
*/
-remoting.ClientPlugin.prototype.onIncomingIq = function(iq) {};
+remoting.ClientPlugin.prototype.onIncomingIq = function(iq) {
+ if (this.plugin && this.plugin.postMessage) {
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'incomingIq', data: { iq: iq } }));
+ } else {
+ // plugin.onIq may not be set after the plugin has been shut
+ // down. Particularly this happens when we receive response to
+ // session-terminate stanza.
+ console.warn('plugin.onIq is not set so dropping incoming message.');
+ }
+};
/**
* @param {string} hostJid The jid of the host to connect to.
@@ -111,12 +440,29 @@ remoting.ClientPlugin.prototype.onIncomingIq = function(iq) {};
remoting.ClientPlugin.prototype.connect = function(
hostJid, hostPublicKey, localJid, sharedSecret,
authenticationMethods, authenticationTag,
- clientPairingId, clientPairedSecret) {};
+ clientPairingId, clientPairedSecret) {
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'connect', data: {
+ hostJid: hostJid,
+ hostPublicKey: hostPublicKey,
+ localJid: localJid,
+ sharedSecret: sharedSecret,
+ authenticationMethods: authenticationMethods,
+ authenticationTag: authenticationTag,
+ capabilities: this.capabilities_.join(" "),
+ clientPairingId: clientPairingId,
+ clientPairedSecret: clientPairedSecret
+ }
+ }));
+};
/**
* Release all currently pressed keys.
*/
-remoting.ClientPlugin.prototype.releaseAllKeys = function() {};
+remoting.ClientPlugin.prototype.releaseAllKeys = function() {
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'releaseAllKeys', data: {} }));
+};
/**
* Send a key event to the host.
@@ -125,7 +471,13 @@ remoting.ClientPlugin.prototype.releaseAllKeys = function() {};
* @param {boolean} pressed True to inject a key press, False for a release.
*/
remoting.ClientPlugin.prototype.injectKeyEvent =
- function(usbKeycode, pressed) {};
+ function(usbKeycode, pressed) {
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'injectKeyEvent', data: {
+ 'usbKeycode': usbKeycode,
+ 'pressed': pressed}
+ }));
+};
/**
* Remap one USB keycode to another in all subsequent key events.
@@ -134,7 +486,13 @@ remoting.ClientPlugin.prototype.injectKeyEvent =
* @param {number} toKeycode The USB-style code to remap the key to.
*/
remoting.ClientPlugin.prototype.remapKey =
- function(fromKeycode, toKeycode) {};
+ function(fromKeycode, toKeycode) {
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'remapKey', data: {
+ 'fromKeycode': fromKeycode,
+ 'toKeycode': toKeycode}
+ }));
+};
/**
* Enable/disable redirection of the specified key to the web-app.
@@ -142,14 +500,22 @@ remoting.ClientPlugin.prototype.remapKey =
* @param {number} keycode The USB-style code of the key.
* @param {Boolean} trap True to enable trapping, False to disable.
*/
-remoting.ClientPlugin.prototype.trapKey = function(keycode, trap) {};
+remoting.ClientPlugin.prototype.trapKey = function(keycode, trap) {
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'trapKey', data: {
+ 'keycode': keycode,
+ 'trap': trap}
+ }));
+};
/**
- * Returns an associative array with a set of stats for this connection.
+ * Returns an associative array with a set of stats for this connecton.
*
* @return {remoting.ClientSession.PerfStats} The connection statistics.
*/
-remoting.ClientPlugin.prototype.getPerfStats = function() {};
+remoting.ClientPlugin.prototype.getPerfStats = function() {
+ return this.perfStats_;
+};
/**
* Sends a clipboard item to the host.
@@ -157,7 +523,14 @@ remoting.ClientPlugin.prototype.getPerfStats = function() {};
* @param {string} mimeType The MIME type of the clipboard item.
* @param {string} item The clipboard item.
*/
-remoting.ClientPlugin.prototype.sendClipboardItem = function(mimeType, item) {};
+remoting.ClientPlugin.prototype.sendClipboardItem =
+ function(mimeType, item) {
+ if (!this.hasFeature(remoting.ClientPlugin.Feature.SEND_CLIPBOARD_ITEM))
+ return;
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'sendClipboardItem',
+ data: { mimeType: mimeType, item: item }}));
+};
/**
* Notifies the host that the client has the specified size and pixel density.
@@ -167,7 +540,16 @@ remoting.ClientPlugin.prototype.sendClipboardItem = function(mimeType, item) {};
* @param {number} device_scale The number of device pixels per DIP.
*/
remoting.ClientPlugin.prototype.notifyClientResolution =
- function(width, height, device_scale) {};
+ function(width, height, device_scale) {
+ if (this.hasFeature(remoting.ClientPlugin.Feature.NOTIFY_CLIENT_RESOLUTION)) {
+ var dpi = Math.floor(device_scale * 96);
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'notifyClientResolution',
+ data: { width: Math.floor(width * device_scale),
+ height: Math.floor(height * device_scale),
+ x_dpi: dpi, y_dpi: dpi }}));
+ }
+};
/**
* Requests that the host pause or resume sending video updates.
@@ -175,7 +557,12 @@ remoting.ClientPlugin.prototype.notifyClientResolution =
* @param {boolean} pause True to suspend video updates, false otherwise.
*/
remoting.ClientPlugin.prototype.pauseVideo =
- function(pause) {};
+ function(pause) {
+ if (!this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_VIDEO))
+ return;
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'pauseVideo', data: { pause: pause }}));
+};
/**
* Requests that the host pause or resume sending audio updates.
@@ -183,19 +570,38 @@ remoting.ClientPlugin.prototype.pauseVideo =
* @param {boolean} pause True to suspend audio updates, false otherwise.
*/
remoting.ClientPlugin.prototype.pauseAudio =
- function(pause) {};
+ function(pause) {
+ if (!this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_AUDIO))
+ return;
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'pauseAudio', data: { pause: pause }}));
+};
/**
- * Gives the client authenticator the PIN.
+ * Called when a PIN is obtained from the user.
*
* @param {string} pin The PIN.
*/
-remoting.ClientPlugin.prototype.onPinFetched = function(pin) {};
+remoting.ClientPlugin.prototype.onPinFetched =
+ function(pin) {
+ if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) {
+ return;
+ }
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'onPinFetched', data: { pin: pin }}));
+};
/**
* Tells the plugin to ask for the PIN asynchronously.
*/
-remoting.ClientPlugin.prototype.useAsyncPinDialog = function() {};
+remoting.ClientPlugin.prototype.useAsyncPinDialog =
+ function() {
+ if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) {
+ return;
+ }
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'useAsyncPinDialog', data: {} }));
+};
/**
* Sets the third party authentication token and shared secret.
@@ -203,8 +609,12 @@ remoting.ClientPlugin.prototype.useAsyncPinDialog = function() {};
* @param {string} token The token received from the token URL.
* @param {string} sharedSecret Shared secret received from the token URL.
*/
-remoting.ClientPlugin.prototype.onThirdPartyTokenFetched =
- function(token, sharedSecret) {};
+remoting.ClientPlugin.prototype.onThirdPartyTokenFetched = function(
+ token, sharedSecret) {
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'onThirdPartyTokenFetched',
+ data: { token: token, sharedSecret: sharedSecret}}));
+};
/**
* Request pairing with the host for PIN-less authentication.
@@ -213,5 +623,50 @@ remoting.ClientPlugin.prototype.onThirdPartyTokenFetched =
* @param {function(string, string):void} onDone, Callback to receive the
* client id and shared secret when they are available.
*/
-remoting.ClientPlugin.prototype.requestPairing = function(
- clientName, onDone) {};
+remoting.ClientPlugin.prototype.requestPairing =
+ function(clientName, onDone) {
+ if (!this.hasFeature(remoting.ClientPlugin.Feature.PINLESS_AUTH)) {
+ return;
+ }
+ this.onPairingComplete_ = onDone;
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'requestPairing', data: { clientName: clientName } }));
+};
+
+/**
+ * Send an extension message to the host.
+ *
+ * @param {string} type The message type.
+ * @param {Object} message The message payload.
+ */
+remoting.ClientPlugin.prototype.sendClientMessage =
+ function(type, message) {
+ if (!this.hasFeature(remoting.ClientPlugin.Feature.EXTENSION_MESSAGE)) {
+ return;
+ }
+ this.plugin.postMessage(JSON.stringify(
+ { method: 'extensionMessage',
+ data: { type: type, data: JSON.stringify(message) } }));
+
+};
+
+/**
+ * If we haven't yet received a "hello" message from the plugin, change its
+ * size so that the user can confirm it if click-to-play is enabled, or can
+ * see the "this plugin is disabled" message if it is actually disabled.
+ * @private
+ */
+remoting.ClientPlugin.prototype.showPluginForClickToPlay_ = function() {
+ if (!this.helloReceived_) {
+ var width = 200;
+ var height = 200;
+ this.plugin.width = width;
+ this.plugin.height = height;
+ // Center the plugin just underneath the "Connnecting..." dialog.
+ var parentNode = this.plugin.parentNode;
+ var dialog = document.getElementById('client-dialog');
+ var dialogRect = dialog.getBoundingClientRect();
+ parentNode.style.top = (dialogRect.bottom + 16) + 'px';
+ parentNode.style.left = (window.innerWidth - width) / 2 + 'px';
+ }
+};
diff --git a/remoting/webapp/client_plugin_async.js b/remoting/webapp/client_plugin_async.js
deleted file mode 100644
index 3e0461f..0000000
--- a/remoting/webapp/client_plugin_async.js
+++ /dev/null
@@ -1,654 +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 that wraps low-level details of interacting with the client plugin.
- *
- * This abstracts a <embed> element and controls the plugin which does
- * the actual remoting work. It also handles differences between
- * client plugins versions when it is necessary.
- */
-
-'use strict';
-
-/** @suppress {duplicate} */
-var remoting = remoting || {};
-
-/**
- * @param {remoting.ViewerPlugin} plugin The plugin embed element.
- * @constructor
- * @implements {remoting.ClientPlugin}
- */
-remoting.ClientPluginAsync = function(plugin) {
- this.plugin = plugin;
-
- this.desktopWidth = 0;
- this.desktopHeight = 0;
- this.desktopXDpi = 96;
- this.desktopYDpi = 96;
-
- /** @param {string} iq The Iq stanza received from the host. */
- this.onOutgoingIqHandler = function (iq) {};
- /** @param {string} message Log message. */
- this.onDebugMessageHandler = function (message) {};
- /**
- * @param {number} state The connection state.
- * @param {number} error The error code, if any.
- */
- this.onConnectionStatusUpdateHandler = function(state, error) {};
- /** @param {boolean} ready Connection ready state. */
- this.onConnectionReadyHandler = function(ready) {};
- /**
- * @param {string} tokenUrl Token-request URL, received from the host.
- * @param {string} hostPublicKey Public key for the host.
- * @param {string} scope OAuth scope to request the token for.
- */
- this.fetchThirdPartyTokenHandler = function(
- tokenUrl, hostPublicKey, scope) {};
- this.onDesktopSizeUpdateHandler = function () {};
- /** @param {!Array.<string>} capabilities The negotiated capabilities. */
- this.onSetCapabilitiesHandler = function (capabilities) {};
- this.fetchPinHandler = function (supportsPairing) {};
-
- /** @type {number} */
- this.pluginApiVersion_ = -1;
- /** @type {Array.<string>} */
- this.pluginApiFeatures_ = [];
- /** @type {number} */
- this.pluginApiMinVersion_ = -1;
- /** @type {!Array.<string>} */
- this.capabilities_ = [];
- /** @type {boolean} */
- this.helloReceived_ = false;
- /** @type {function(boolean)|null} */
- this.onInitializedCallback_ = null;
- /** @type {function(string, string):void} */
- this.onPairingComplete_ = function(clientId, sharedSecret) {};
- /** @type {remoting.ClientSession.PerfStats} */
- this.perfStats_ = new remoting.ClientSession.PerfStats();
-
- /** @type {remoting.ClientPluginAsync} */
- var that = this;
- /** @param {Event} event Message event from the plugin. */
- this.plugin.addEventListener('message', function(event) {
- that.handleMessage_(event.data);
- }, false);
- window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500);
-};
-
-/**
- * Chromoting session API version (for this javascript).
- * This is compared with the plugin API version to verify that they are
- * compatible.
- *
- * @const
- * @private
- */
-remoting.ClientPluginAsync.prototype.API_VERSION_ = 6;
-
-/**
- * The oldest API version that we support.
- * This will differ from the |API_VERSION_| if we maintain backward
- * compatibility with older API versions.
- *
- * @const
- * @private
- */
-remoting.ClientPluginAsync.prototype.API_MIN_VERSION_ = 5;
-
-/**
- * @param {string} messageStr Message from the plugin.
- */
-remoting.ClientPluginAsync.prototype.handleMessage_ = function(messageStr) {
- var message = /** @type {{method:string, data:Object.<string,string>}} */
- jsonParseSafe(messageStr);
-
- if (!message || !('method' in message) || !('data' in message)) {
- console.error('Received invalid message from the plugin: ' + messageStr);
- return;
- }
-
- /**
- * Splits a string into a list of words delimited by spaces.
- * @param {string} str String that should be split.
- * @return {!Array.<string>} List of words.
- */
- var tokenize = function(str) {
- /** @type {Array.<string>} */
- var tokens = str.match(/\S+/g);
- return tokens ? tokens : [];
- };
-
- if (message.method == 'hello') {
- // Reset the size in case we had to enlarge it to support click-to-play.
- this.plugin.width = 0;
- this.plugin.height = 0;
- if (typeof message.data['apiVersion'] != 'number' ||
- typeof message.data['apiMinVersion'] != 'number') {
- console.error('Received invalid hello message: ' + messageStr);
- return;
- }
- this.pluginApiVersion_ = /** @type {number} */ message.data['apiVersion'];
-
- if (this.pluginApiVersion_ >= 7) {
- if (typeof message.data['apiFeatures'] != 'string') {
- console.error('Received invalid hello message: ' + messageStr);
- return;
- }
- this.pluginApiFeatures_ =
- /** @type {Array.<string>} */ tokenize(message.data['apiFeatures']);
-
- // Negotiate capabilities.
-
- /** @type {!Array.<string>} */
- var requestedCapabilities = [];
- if ('requestedCapabilities' in message.data) {
- if (typeof message.data['requestedCapabilities'] != 'string') {
- console.error('Received invalid hello message: ' + messageStr);
- return;
- }
- requestedCapabilities = tokenize(message.data['requestedCapabilities']);
- }
-
- /** @type {!Array.<string>} */
- var supportedCapabilities = [];
- if ('supportedCapabilities' in message.data) {
- if (typeof message.data['supportedCapabilities'] != 'string') {
- console.error('Received invalid hello message: ' + messageStr);
- return;
- }
- supportedCapabilities = tokenize(message.data['supportedCapabilities']);
- }
-
- // At the moment the webapp does not recognize any of
- // 'requestedCapabilities' capabilities (so they all should be disabled)
- // and do not care about any of 'supportedCapabilities' capabilities (so
- // they all can be enabled).
- this.capabilities_ = supportedCapabilities;
-
- // Let the host know that the webapp can be requested to always send
- // the client's dimensions.
- this.capabilities_.push(
- remoting.ClientSession.Capability.SEND_INITIAL_RESOLUTION);
-
- // Let the host know that we're interested in knowing whether or not
- // it rate-limits desktop-resize requests.
- this.capabilities_.push(
- remoting.ClientSession.Capability.RATE_LIMIT_RESIZE_REQUESTS);
- } else if (this.pluginApiVersion_ >= 6) {
- this.pluginApiFeatures_ = ['highQualityScaling', 'injectKeyEvent'];
- } else {
- this.pluginApiFeatures_ = ['highQualityScaling'];
- }
- this.pluginApiMinVersion_ =
- /** @type {number} */ message.data['apiMinVersion'];
- this.helloReceived_ = true;
- if (this.onInitializedCallback_ != null) {
- this.onInitializedCallback_(true);
- this.onInitializedCallback_ = null;
- }
- } else if (message.method == 'sendOutgoingIq') {
- if (typeof message.data['iq'] != 'string') {
- console.error('Received invalid sendOutgoingIq message: ' + messageStr);
- return;
- }
- this.onOutgoingIqHandler(message.data['iq']);
- } else if (message.method == 'logDebugMessage') {
- if (typeof message.data['message'] != 'string') {
- console.error('Received invalid logDebugMessage message: ' + messageStr);
- return;
- }
- this.onDebugMessageHandler(message.data['message']);
- } else if (message.method == 'onConnectionStatus') {
- if (typeof message.data['state'] != 'string' ||
- !remoting.ClientSession.State.hasOwnProperty(message.data['state']) ||
- typeof message.data['error'] != 'string') {
- console.error('Received invalid onConnectionState message: ' +
- messageStr);
- return;
- }
-
- /** @type {remoting.ClientSession.State} */
- var state = remoting.ClientSession.State[message.data['state']];
- var error;
- if (remoting.ClientSession.ConnectionError.hasOwnProperty(
- message.data['error'])) {
- error = /** @type {remoting.ClientSession.ConnectionError} */
- remoting.ClientSession.ConnectionError[message.data['error']];
- } else {
- error = remoting.ClientSession.ConnectionError.UNKNOWN;
- }
-
- this.onConnectionStatusUpdateHandler(state, error);
- } else if (message.method == 'onDesktopSize') {
- if (typeof message.data['width'] != 'number' ||
- typeof message.data['height'] != 'number') {
- console.error('Received invalid onDesktopSize message: ' + messageStr);
- return;
- }
- this.desktopWidth = /** @type {number} */ message.data['width'];
- this.desktopHeight = /** @type {number} */ message.data['height'];
- this.desktopXDpi = (typeof message.data['x_dpi'] == 'number') ?
- /** @type {number} */ (message.data['x_dpi']) : 96;
- this.desktopYDpi = (typeof message.data['y_dpi'] == 'number') ?
- /** @type {number} */ (message.data['y_dpi']) : 96;
- this.onDesktopSizeUpdateHandler();
- } else if (message.method == 'onPerfStats') {
- if (typeof message.data['videoBandwidth'] != 'number' ||
- typeof message.data['videoFrameRate'] != 'number' ||
- typeof message.data['captureLatency'] != 'number' ||
- typeof message.data['encodeLatency'] != 'number' ||
- typeof message.data['decodeLatency'] != 'number' ||
- typeof message.data['renderLatency'] != 'number' ||
- typeof message.data['roundtripLatency'] != 'number') {
- console.error('Received incorrect onPerfStats message: ' + messageStr);
- return;
- }
- this.perfStats_ =
- /** @type {remoting.ClientSession.PerfStats} */ message.data;
- } else if (message.method == 'injectClipboardItem') {
- if (typeof message.data['mimeType'] != 'string' ||
- typeof message.data['item'] != 'string') {
- console.error('Received incorrect injectClipboardItem message.');
- return;
- }
- if (remoting.clipboard) {
- remoting.clipboard.fromHost(message.data['mimeType'],
- message.data['item']);
- }
- } else if (message.method == 'onFirstFrameReceived') {
- if (remoting.clientSession) {
- remoting.clientSession.onFirstFrameReceived();
- }
- } else if (message.method == 'onConnectionReady') {
- if (typeof message.data['ready'] != 'boolean') {
- console.error('Received incorrect onConnectionReady message.');
- return;
- }
- var ready = /** @type {boolean} */ message.data['ready'];
- this.onConnectionReadyHandler(ready);
- } else if (message.method == 'fetchPin') {
- // The pairingSupported value in the dictionary indicates whether both
- // client and host support pairing. If the client doesn't support pairing,
- // then the value won't be there at all, so give it a default of false.
- /** @type {boolean} */
- var pairingSupported = false;
- if ('pairingSupported' in message.data) {
- pairingSupported =
- /** @type {boolean} */ message.data['pairingSupported'];
- if (typeof pairingSupported != 'boolean') {
- console.error('Received incorrect fetchPin message.');
- return;
- }
- }
- this.fetchPinHandler(pairingSupported);
- } else if (message.method == 'setCapabilities') {
- if (typeof message.data['capabilities'] != 'string') {
- console.error('Received incorrect setCapabilities message.');
- return;
- }
-
- /** @type {!Array.<string>} */
- var capabilities = tokenize(message.data['capabilities']);
- this.onSetCapabilitiesHandler(capabilities);
- } else if (message.method == 'fetchThirdPartyToken') {
- if (typeof message.data['tokenUrl'] != 'string' ||
- typeof message.data['hostPublicKey'] != 'string' ||
- typeof message.data['scope'] != 'string') {
- console.error('Received incorrect fetchThirdPartyToken message.');
- return;
- }
- var tokenUrl = /** @type {string} */ message.data['tokenUrl'];
- var hostPublicKey =
- /** @type {string} */ message.data['hostPublicKey'];
- var scope = /** @type {string} */ message.data['scope'];
- this.fetchThirdPartyTokenHandler(tokenUrl, hostPublicKey, scope);
- } else if (message.method == 'pairingResponse') {
- var clientId = /** @type {string} */ message.data['clientId'];
- var sharedSecret = /** @type {string} */ message.data['sharedSecret'];
- if (typeof clientId != 'string' || typeof sharedSecret != 'string') {
- console.error('Received incorrect pairingResponse message.');
- return;
- }
- this.onPairingComplete_(clientId, sharedSecret);
- } else if (message.method == 'extensionMessage') {
- if (typeof(message.data['type']) != 'string' ||
- typeof(message.data['data']) != 'string') {
- console.error('Invalid extension message:', message.data);
- return;
- }
- switch (message.data['type']) {
- case 'test-echo-reply':
- console.log('Got echo reply: ' + message.data['data']);
- break;
- default:
- console.log('Unexpected message received: ' +
- message.data['type'] + ': ' + message.data['data']);
- }
- }
-};
-
-/**
- * Deletes the plugin.
- */
-remoting.ClientPluginAsync.prototype.cleanup = function() {
- this.plugin.parentNode.removeChild(this.plugin);
-};
-
-/**
- * @return {HTMLEmbedElement} HTML element that correspods to the plugin.
- */
-remoting.ClientPluginAsync.prototype.element = function() {
- return this.plugin;
-};
-
-/**
- * @param {function(boolean): void} onDone
- */
-remoting.ClientPluginAsync.prototype.initialize = function(onDone) {
- if (this.helloReceived_) {
- onDone(true);
- } else {
- this.onInitializedCallback_ = onDone;
- }
-};
-
-/**
- * @return {boolean} True if the plugin and web-app versions are compatible.
- */
-remoting.ClientPluginAsync.prototype.isSupportedVersion = function() {
- if (!this.helloReceived_) {
- console.error(
- "isSupportedVersion() is called before the plugin is initialized.");
- return false;
- }
- return this.API_VERSION_ >= this.pluginApiMinVersion_ &&
- this.pluginApiVersion_ >= this.API_MIN_VERSION_;
-};
-
-/**
- * @param {remoting.ClientPlugin.Feature} feature The feature to test for.
- * @return {boolean} True if the plugin supports the named feature.
- */
-remoting.ClientPluginAsync.prototype.hasFeature = function(feature) {
- if (!this.helloReceived_) {
- console.error(
- "hasFeature() is called before the plugin is initialized.");
- return false;
- }
- return this.pluginApiFeatures_.indexOf(feature) > -1;
-};
-
-/**
- * @return {boolean} True if the plugin supports the injectKeyEvent API.
- */
-remoting.ClientPluginAsync.prototype.isInjectKeyEventSupported = function() {
- return this.pluginApiVersion_ >= 6;
-};
-
-/**
- * @param {string} iq Incoming IQ stanza.
- */
-remoting.ClientPluginAsync.prototype.onIncomingIq = function(iq) {
- if (this.plugin && this.plugin.postMessage) {
- this.plugin.postMessage(JSON.stringify(
- { method: 'incomingIq', data: { iq: iq } }));
- } else {
- // plugin.onIq may not be set after the plugin has been shut
- // down. Particularly this happens when we receive response to
- // session-terminate stanza.
- console.warn('plugin.onIq is not set so dropping incoming message.');
- }
-};
-
-/**
- * @param {string} hostJid The jid of the host to connect to.
- * @param {string} hostPublicKey The base64 encoded version of the host's
- * public key.
- * @param {string} localJid Local jid.
- * @param {string} sharedSecret The access code for IT2Me or the PIN
- * for Me2Me.
- * @param {string} authenticationMethods Comma-separated list of
- * authentication methods the client should attempt to use.
- * @param {string} authenticationTag A host-specific tag to mix into
- * authentication hashes.
- * @param {string} clientPairingId For paired Me2Me connections, the
- * pairing id for this client, as issued by the host.
- * @param {string} clientPairedSecret For paired Me2Me connections, the
- * paired secret for this client, as issued by the host.
- */
-remoting.ClientPluginAsync.prototype.connect = function(
- hostJid, hostPublicKey, localJid, sharedSecret,
- authenticationMethods, authenticationTag,
- clientPairingId, clientPairedSecret) {
- this.plugin.postMessage(JSON.stringify(
- { method: 'connect', data: {
- hostJid: hostJid,
- hostPublicKey: hostPublicKey,
- localJid: localJid,
- sharedSecret: sharedSecret,
- authenticationMethods: authenticationMethods,
- authenticationTag: authenticationTag,
- capabilities: this.capabilities_.join(" "),
- clientPairingId: clientPairingId,
- clientPairedSecret: clientPairedSecret
- }
- }));
-};
-
-/**
- * Release all currently pressed keys.
- */
-remoting.ClientPluginAsync.prototype.releaseAllKeys = function() {
- this.plugin.postMessage(JSON.stringify(
- { method: 'releaseAllKeys', data: {} }));
-};
-
-/**
- * Send a key event to the host.
- *
- * @param {number} usbKeycode The USB-style code of the key to inject.
- * @param {boolean} pressed True to inject a key press, False for a release.
- */
-remoting.ClientPluginAsync.prototype.injectKeyEvent =
- function(usbKeycode, pressed) {
- this.plugin.postMessage(JSON.stringify(
- { method: 'injectKeyEvent', data: {
- 'usbKeycode': usbKeycode,
- 'pressed': pressed}
- }));
-};
-
-/**
- * Remap one USB keycode to another in all subsequent key events.
- *
- * @param {number} fromKeycode The USB-style code of the key to remap.
- * @param {number} toKeycode The USB-style code to remap the key to.
- */
-remoting.ClientPluginAsync.prototype.remapKey =
- function(fromKeycode, toKeycode) {
- this.plugin.postMessage(JSON.stringify(
- { method: 'remapKey', data: {
- 'fromKeycode': fromKeycode,
- 'toKeycode': toKeycode}
- }));
-};
-
-/**
- * Enable/disable redirection of the specified key to the web-app.
- *
- * @param {number} keycode The USB-style code of the key.
- * @param {Boolean} trap True to enable trapping, False to disable.
- */
-remoting.ClientPluginAsync.prototype.trapKey = function(keycode, trap) {
- this.plugin.postMessage(JSON.stringify(
- { method: 'trapKey', data: {
- 'keycode': keycode,
- 'trap': trap}
- }));
-};
-
-/**
- * Returns an associative array with a set of stats for this connecton.
- *
- * @return {remoting.ClientSession.PerfStats} The connection statistics.
- */
-remoting.ClientPluginAsync.prototype.getPerfStats = function() {
- return this.perfStats_;
-};
-
-/**
- * Sends a clipboard item to the host.
- *
- * @param {string} mimeType The MIME type of the clipboard item.
- * @param {string} item The clipboard item.
- */
-remoting.ClientPluginAsync.prototype.sendClipboardItem =
- function(mimeType, item) {
- if (!this.hasFeature(remoting.ClientPlugin.Feature.SEND_CLIPBOARD_ITEM))
- return;
- this.plugin.postMessage(JSON.stringify(
- { method: 'sendClipboardItem',
- data: { mimeType: mimeType, item: item }}));
-};
-
-/**
- * Notifies the host that the client has the specified size and pixel density.
- *
- * @param {number} width The available client width in DIPs.
- * @param {number} height The available client height in DIPs.
- * @param {number} device_scale The number of device pixels per DIP.
- */
-remoting.ClientPluginAsync.prototype.notifyClientResolution =
- function(width, height, device_scale) {
- if (this.hasFeature(remoting.ClientPlugin.Feature.NOTIFY_CLIENT_RESOLUTION)) {
- var dpi = Math.floor(device_scale * 96);
- this.plugin.postMessage(JSON.stringify(
- { method: 'notifyClientResolution',
- data: { width: Math.floor(width * device_scale),
- height: Math.floor(height * device_scale),
- x_dpi: dpi, y_dpi: dpi }}));
- }
-};
-
-/**
- * Requests that the host pause or resume sending video updates.
- *
- * @param {boolean} pause True to suspend video updates, false otherwise.
- */
-remoting.ClientPluginAsync.prototype.pauseVideo =
- function(pause) {
- if (!this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_VIDEO))
- return;
- this.plugin.postMessage(JSON.stringify(
- { method: 'pauseVideo', data: { pause: pause }}));
-};
-
-/**
- * Requests that the host pause or resume sending audio updates.
- *
- * @param {boolean} pause True to suspend audio updates, false otherwise.
- */
-remoting.ClientPluginAsync.prototype.pauseAudio =
- function(pause) {
- if (!this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_AUDIO))
- return;
- this.plugin.postMessage(JSON.stringify(
- { method: 'pauseAudio', data: { pause: pause }}));
-};
-
-/**
- * Called when a PIN is obtained from the user.
- *
- * @param {string} pin The PIN.
- */
-remoting.ClientPluginAsync.prototype.onPinFetched =
- function(pin) {
- if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) {
- return;
- }
- this.plugin.postMessage(JSON.stringify(
- { method: 'onPinFetched', data: { pin: pin }}));
-};
-
-/**
- * Tells the plugin to ask for the PIN asynchronously.
- */
-remoting.ClientPluginAsync.prototype.useAsyncPinDialog =
- function() {
- if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) {
- return;
- }
- this.plugin.postMessage(JSON.stringify(
- { method: 'useAsyncPinDialog', data: {} }));
-};
-
-/**
- * Sets the third party authentication token and shared secret.
- *
- * @param {string} token The token received from the token URL.
- * @param {string} sharedSecret Shared secret received from the token URL.
- */
-remoting.ClientPluginAsync.prototype.onThirdPartyTokenFetched = function(
- token, sharedSecret) {
- this.plugin.postMessage(JSON.stringify(
- { method: 'onThirdPartyTokenFetched',
- data: { token: token, sharedSecret: sharedSecret}}));
-};
-
-/**
- * Request pairing with the host for PIN-less authentication.
- *
- * @param {string} clientName The human-readable name of the client.
- * @param {function(string, string):void} onDone, Callback to receive the
- * client id and shared secret when they are available.
- */
-remoting.ClientPluginAsync.prototype.requestPairing =
- function(clientName, onDone) {
- if (!this.hasFeature(remoting.ClientPlugin.Feature.PINLESS_AUTH)) {
- return;
- }
- this.onPairingComplete_ = onDone;
- this.plugin.postMessage(JSON.stringify(
- { method: 'requestPairing', data: { clientName: clientName } }));
-};
-
-/**
- * Send an extension message to the host.
- *
- * @param {string} type The message type.
- * @param {Object} message The message payload.
- */
-remoting.ClientPluginAsync.prototype.sendClientMessage =
- function(type, message) {
- if (!this.hasFeature(remoting.ClientPlugin.Feature.EXTENSION_MESSAGE)) {
- return;
- }
- this.plugin.postMessage(JSON.stringify(
- { method: 'extensionMessage',
- data: { type: type, data: JSON.stringify(message) } }));
-
-};
-
-/**
- * If we haven't yet received a "hello" message from the plugin, change its
- * size so that the user can confirm it if click-to-play is enabled, or can
- * see the "this plugin is disabled" message if it is actually disabled.
- * @private
- */
-remoting.ClientPluginAsync.prototype.showPluginForClickToPlay_ = function() {
- if (!this.helloReceived_) {
- var width = 200;
- var height = 200;
- this.plugin.width = width;
- this.plugin.height = height;
- // Center the plugin just underneath the "Connnecting..." dialog.
- var parentNode = this.plugin.parentNode;
- var dialog = document.getElementById('client-dialog');
- var dialogRect = dialog.getBoundingClientRect();
- parentNode.style.top = (dialogRect.bottom + 16) + 'px';
- parentNode.style.left = (window.innerWidth - width) / 2 + 'px';
- }
-};
diff --git a/remoting/webapp/client_session.js b/remoting/webapp/client_session.js
index a6bc3bd..2d3e88d 100644
--- a/remoting/webapp/client_session.js
+++ b/remoting/webapp/client_session.js
@@ -322,7 +322,7 @@ remoting.ClientSession.prototype.createClientPlugin_ = function(container, id) {
plugin.tabIndex = 0; // Required, otherwise focus() doesn't work.
container.appendChild(plugin);
- return new remoting.ClientPluginAsync(plugin);
+ return new remoting.ClientPlugin(plugin);
};
/**
diff --git a/remoting/webapp/main.html b/remoting/webapp/main.html
index a42c353..066d906 100644
--- a/remoting/webapp/main.html
+++ b/remoting/webapp/main.html
@@ -17,7 +17,6 @@ found in the LICENSE file.
<link rel="stylesheet" href="toolbar.css">
<script src="butter_bar.js"></script>
<script src="client_plugin.js"></script>
- <script src="client_plugin_async.js"></script>
<script src="client_screen.js"></script>
<script src="client_session.js"></script>
<script src="clipboard.js"></script>