Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(652)

Side by Side Diff: remoting/webapp/client_plugin.js

Issue 138503007: Remove remoting.ClientPlugin interface (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/webapp/all_js_load.gtestjs ('k') | remoting/webapp/client_plugin_async.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /**
6 * @fileoverview
7 * Class that wraps low-level details of interacting with the client plugin.
8 *
9 * This abstracts a <embed> element and controls the plugin which does
10 * the actual remoting work. It also handles differences between
11 * client plugins versions when it is necessary.
12 */
13
14 'use strict';
15
5 /** @suppress {duplicate} */ 16 /** @suppress {duplicate} */
6 var remoting = remoting || {}; 17 var remoting = remoting || {};
7 18
8 /** 19 /**
9 * Interface used for ClientPlugin objects. 20 * @param {remoting.ViewerPlugin} plugin The plugin embed element.
10 * @interface 21 * @constructor
11 */ 22 */
12 remoting.ClientPlugin = function() { 23 remoting.ClientPlugin = function(plugin) {
24 this.plugin = plugin;
25
26 this.desktopWidth = 0;
27 this.desktopHeight = 0;
28 this.desktopXDpi = 96;
29 this.desktopYDpi = 96;
30
31 /** @param {string} iq The Iq stanza received from the host. */
32 this.onOutgoingIqHandler = function (iq) {};
33 /** @param {string} message Log message. */
34 this.onDebugMessageHandler = function (message) {};
35 /**
36 * @param {number} state The connection state.
37 * @param {number} error The error code, if any.
38 */
39 this.onConnectionStatusUpdateHandler = function(state, error) {};
40 /** @param {boolean} ready Connection ready state. */
41 this.onConnectionReadyHandler = function(ready) {};
42 /**
43 * @param {string} tokenUrl Token-request URL, received from the host.
44 * @param {string} hostPublicKey Public key for the host.
45 * @param {string} scope OAuth scope to request the token for.
46 */
47 this.fetchThirdPartyTokenHandler = function(
48 tokenUrl, hostPublicKey, scope) {};
49 this.onDesktopSizeUpdateHandler = function () {};
50 /** @param {!Array.<string>} capabilities The negotiated capabilities. */
51 this.onSetCapabilitiesHandler = function (capabilities) {};
52 this.fetchPinHandler = function (supportsPairing) {};
53
54 /** @type {number} */
55 this.pluginApiVersion_ = -1;
56 /** @type {Array.<string>} */
57 this.pluginApiFeatures_ = [];
58 /** @type {number} */
59 this.pluginApiMinVersion_ = -1;
60 /** @type {!Array.<string>} */
61 this.capabilities_ = [];
62 /** @type {boolean} */
63 this.helloReceived_ = false;
64 /** @type {function(boolean)|null} */
65 this.onInitializedCallback_ = null;
66 /** @type {function(string, string):void} */
67 this.onPairingComplete_ = function(clientId, sharedSecret) {};
68 /** @type {remoting.ClientSession.PerfStats} */
69 this.perfStats_ = new remoting.ClientSession.PerfStats();
70
71 /** @type {remoting.ClientPlugin} */
72 var that = this;
73 /** @param {Event} event Message event from the plugin. */
74 this.plugin.addEventListener('message', function(event) {
75 that.handleMessage_(event.data);
76 }, false);
77 window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500);
13 }; 78 };
14 79
15 /** @type {number} Desktop width */
16 remoting.ClientPlugin.prototype.desktopWidth;
17 /** @type {number} Desktop height */
18 remoting.ClientPlugin.prototype.desktopHeight;
19 /** @type {number} Desktop x DPI */
20 remoting.ClientPlugin.prototype.desktopXDpi;
21 /** @type {number} Desktop y DPI */
22 remoting.ClientPlugin.prototype.desktopYDpi;
23
24 /** @type {function(string): void} Outgoing signaling message callback. */
25 remoting.ClientPlugin.prototype.onOutgoingIqHandler;
26 /** @type {function(string): void} Debug messages callback. */
27 remoting.ClientPlugin.prototype.onDebugMessageHandler;
28 /** @type {function(number, number): void} State change callback. */
29 remoting.ClientPlugin.prototype.onConnectionStatusUpdateHandler;
30 /** @type {function(boolean): void} Connection ready state callback. */
31 remoting.ClientPlugin.prototype.onConnectionReadyHandler;
32 /** @type {function(): void} Desktop size change callback. */
33 remoting.ClientPlugin.prototype.onDesktopSizeUpdateHandler;
34 /** @type {function(!Array.<string>): void} Capabilities negotiated callback. */
35 remoting.ClientPlugin.prototype.onSetCapabilitiesHandler;
36 /** @type {function(boolean): void} Request a PIN from the user. */
37 remoting.ClientPlugin.prototype.fetchPinHandler;
38
39 /**
40 * Initializes the plugin asynchronously and calls specified function
41 * when done.
42 *
43 * @param {function(boolean): void} onDone Function to be called when
44 * the plugin is initialized. Parameter is set to true when the plugin
45 * is loaded successfully.
46 */
47 remoting.ClientPlugin.prototype.initialize = function(onDone) {};
48
49 /**
50 * @return {boolean} True if the plugin and web-app versions are compatible.
51 */
52 remoting.ClientPlugin.prototype.isSupportedVersion = function() {};
53
54 /** 80 /**
55 * Set of features for which hasFeature() can be used to test. 81 * Set of features for which hasFeature() can be used to test.
56 * 82 *
57 * @enum {string} 83 * @enum {string}
58 */ 84 */
59 remoting.ClientPlugin.Feature = { 85 remoting.ClientPlugin.Feature = {
60 INJECT_KEY_EVENT: 'injectKeyEvent', 86 INJECT_KEY_EVENT: 'injectKeyEvent',
61 NOTIFY_CLIENT_RESOLUTION: 'notifyClientResolution', 87 NOTIFY_CLIENT_RESOLUTION: 'notifyClientResolution',
62 ASYNC_PIN: 'asyncPin', 88 ASYNC_PIN: 'asyncPin',
63 PAUSE_VIDEO: 'pauseVideo', 89 PAUSE_VIDEO: 'pauseVideo',
64 PAUSE_AUDIO: 'pauseAudio', 90 PAUSE_AUDIO: 'pauseAudio',
65 REMAP_KEY: 'remapKey', 91 REMAP_KEY: 'remapKey',
66 SEND_CLIPBOARD_ITEM: 'sendClipboardItem', 92 SEND_CLIPBOARD_ITEM: 'sendClipboardItem',
67 THIRD_PARTY_AUTH: 'thirdPartyAuth', 93 THIRD_PARTY_AUTH: 'thirdPartyAuth',
68 TRAP_KEY: 'trapKey', 94 TRAP_KEY: 'trapKey',
69 PINLESS_AUTH: 'pinlessAuth', 95 PINLESS_AUTH: 'pinlessAuth',
70 EXTENSION_MESSAGE: 'extensionMessage' 96 EXTENSION_MESSAGE: 'extensionMessage'
71 }; 97 };
72 98
73 /** 99 /**
100 * Chromoting session API version (for this javascript).
101 * This is compared with the plugin API version to verify that they are
102 * compatible.
103 *
104 * @const
105 * @private
106 */
107 remoting.ClientPlugin.prototype.API_VERSION_ = 6;
108
109 /**
110 * The oldest API version that we support.
111 * This will differ from the |API_VERSION_| if we maintain backward
112 * compatibility with older API versions.
113 *
114 * @const
115 * @private
116 */
117 remoting.ClientPlugin.prototype.API_MIN_VERSION_ = 5;
118
119 /**
120 * @param {string} messageStr Message from the plugin.
121 */
122 remoting.ClientPlugin.prototype.handleMessage_ = function(messageStr) {
123 var message = /** @type {{method:string, data:Object.<string,string>}} */
124 jsonParseSafe(messageStr);
125
126 if (!message || !('method' in message) || !('data' in message)) {
127 console.error('Received invalid message from the plugin: ' + messageStr);
128 return;
129 }
130
131 /**
132 * Splits a string into a list of words delimited by spaces.
133 * @param {string} str String that should be split.
134 * @return {!Array.<string>} List of words.
135 */
136 var tokenize = function(str) {
137 /** @type {Array.<string>} */
138 var tokens = str.match(/\S+/g);
139 return tokens ? tokens : [];
140 };
141
142 if (message.method == 'hello') {
143 // Reset the size in case we had to enlarge it to support click-to-play.
144 this.plugin.width = 0;
145 this.plugin.height = 0;
146 if (typeof message.data['apiVersion'] != 'number' ||
147 typeof message.data['apiMinVersion'] != 'number') {
148 console.error('Received invalid hello message: ' + messageStr);
149 return;
150 }
151 this.pluginApiVersion_ = /** @type {number} */ message.data['apiVersion'];
152
153 if (this.pluginApiVersion_ >= 7) {
154 if (typeof message.data['apiFeatures'] != 'string') {
155 console.error('Received invalid hello message: ' + messageStr);
156 return;
157 }
158 this.pluginApiFeatures_ =
159 /** @type {Array.<string>} */ tokenize(message.data['apiFeatures']);
160
161 // Negotiate capabilities.
162
163 /** @type {!Array.<string>} */
164 var requestedCapabilities = [];
165 if ('requestedCapabilities' in message.data) {
166 if (typeof message.data['requestedCapabilities'] != 'string') {
167 console.error('Received invalid hello message: ' + messageStr);
168 return;
169 }
170 requestedCapabilities = tokenize(message.data['requestedCapabilities']);
171 }
172
173 /** @type {!Array.<string>} */
174 var supportedCapabilities = [];
175 if ('supportedCapabilities' in message.data) {
176 if (typeof message.data['supportedCapabilities'] != 'string') {
177 console.error('Received invalid hello message: ' + messageStr);
178 return;
179 }
180 supportedCapabilities = tokenize(message.data['supportedCapabilities']);
181 }
182
183 // At the moment the webapp does not recognize any of
184 // 'requestedCapabilities' capabilities (so they all should be disabled)
185 // and do not care about any of 'supportedCapabilities' capabilities (so
186 // they all can be enabled).
187 this.capabilities_ = supportedCapabilities;
188
189 // Let the host know that the webapp can be requested to always send
190 // the client's dimensions.
191 this.capabilities_.push(
192 remoting.ClientSession.Capability.SEND_INITIAL_RESOLUTION);
193
194 // Let the host know that we're interested in knowing whether or not
195 // it rate-limits desktop-resize requests.
196 this.capabilities_.push(
197 remoting.ClientSession.Capability.RATE_LIMIT_RESIZE_REQUESTS);
198 } else if (this.pluginApiVersion_ >= 6) {
199 this.pluginApiFeatures_ = ['highQualityScaling', 'injectKeyEvent'];
200 } else {
201 this.pluginApiFeatures_ = ['highQualityScaling'];
202 }
203 this.pluginApiMinVersion_ =
204 /** @type {number} */ message.data['apiMinVersion'];
205 this.helloReceived_ = true;
206 if (this.onInitializedCallback_ != null) {
207 this.onInitializedCallback_(true);
208 this.onInitializedCallback_ = null;
209 }
210 } else if (message.method == 'sendOutgoingIq') {
211 if (typeof message.data['iq'] != 'string') {
212 console.error('Received invalid sendOutgoingIq message: ' + messageStr);
213 return;
214 }
215 this.onOutgoingIqHandler(message.data['iq']);
216 } else if (message.method == 'logDebugMessage') {
217 if (typeof message.data['message'] != 'string') {
218 console.error('Received invalid logDebugMessage message: ' + messageStr);
219 return;
220 }
221 this.onDebugMessageHandler(message.data['message']);
222 } else if (message.method == 'onConnectionStatus') {
223 if (typeof message.data['state'] != 'string' ||
224 !remoting.ClientSession.State.hasOwnProperty(message.data['state']) ||
225 typeof message.data['error'] != 'string') {
226 console.error('Received invalid onConnectionState message: ' +
227 messageStr);
228 return;
229 }
230
231 /** @type {remoting.ClientSession.State} */
232 var state = remoting.ClientSession.State[message.data['state']];
233 var error;
234 if (remoting.ClientSession.ConnectionError.hasOwnProperty(
235 message.data['error'])) {
236 error = /** @type {remoting.ClientSession.ConnectionError} */
237 remoting.ClientSession.ConnectionError[message.data['error']];
238 } else {
239 error = remoting.ClientSession.ConnectionError.UNKNOWN;
240 }
241
242 this.onConnectionStatusUpdateHandler(state, error);
243 } else if (message.method == 'onDesktopSize') {
244 if (typeof message.data['width'] != 'number' ||
245 typeof message.data['height'] != 'number') {
246 console.error('Received invalid onDesktopSize message: ' + messageStr);
247 return;
248 }
249 this.desktopWidth = /** @type {number} */ message.data['width'];
250 this.desktopHeight = /** @type {number} */ message.data['height'];
251 this.desktopXDpi = (typeof message.data['x_dpi'] == 'number') ?
252 /** @type {number} */ (message.data['x_dpi']) : 96;
253 this.desktopYDpi = (typeof message.data['y_dpi'] == 'number') ?
254 /** @type {number} */ (message.data['y_dpi']) : 96;
255 this.onDesktopSizeUpdateHandler();
256 } else if (message.method == 'onPerfStats') {
257 if (typeof message.data['videoBandwidth'] != 'number' ||
258 typeof message.data['videoFrameRate'] != 'number' ||
259 typeof message.data['captureLatency'] != 'number' ||
260 typeof message.data['encodeLatency'] != 'number' ||
261 typeof message.data['decodeLatency'] != 'number' ||
262 typeof message.data['renderLatency'] != 'number' ||
263 typeof message.data['roundtripLatency'] != 'number') {
264 console.error('Received incorrect onPerfStats message: ' + messageStr);
265 return;
266 }
267 this.perfStats_ =
268 /** @type {remoting.ClientSession.PerfStats} */ message.data;
269 } else if (message.method == 'injectClipboardItem') {
270 if (typeof message.data['mimeType'] != 'string' ||
271 typeof message.data['item'] != 'string') {
272 console.error('Received incorrect injectClipboardItem message.');
273 return;
274 }
275 if (remoting.clipboard) {
276 remoting.clipboard.fromHost(message.data['mimeType'],
277 message.data['item']);
278 }
279 } else if (message.method == 'onFirstFrameReceived') {
280 if (remoting.clientSession) {
281 remoting.clientSession.onFirstFrameReceived();
282 }
283 } else if (message.method == 'onConnectionReady') {
284 if (typeof message.data['ready'] != 'boolean') {
285 console.error('Received incorrect onConnectionReady message.');
286 return;
287 }
288 var ready = /** @type {boolean} */ message.data['ready'];
289 this.onConnectionReadyHandler(ready);
290 } else if (message.method == 'fetchPin') {
291 // The pairingSupported value in the dictionary indicates whether both
292 // client and host support pairing. If the client doesn't support pairing,
293 // then the value won't be there at all, so give it a default of false.
294 /** @type {boolean} */
295 var pairingSupported = false;
296 if ('pairingSupported' in message.data) {
297 pairingSupported =
298 /** @type {boolean} */ message.data['pairingSupported'];
299 if (typeof pairingSupported != 'boolean') {
300 console.error('Received incorrect fetchPin message.');
301 return;
302 }
303 }
304 this.fetchPinHandler(pairingSupported);
305 } else if (message.method == 'setCapabilities') {
306 if (typeof message.data['capabilities'] != 'string') {
307 console.error('Received incorrect setCapabilities message.');
308 return;
309 }
310
311 /** @type {!Array.<string>} */
312 var capabilities = tokenize(message.data['capabilities']);
313 this.onSetCapabilitiesHandler(capabilities);
314 } else if (message.method == 'fetchThirdPartyToken') {
315 if (typeof message.data['tokenUrl'] != 'string' ||
316 typeof message.data['hostPublicKey'] != 'string' ||
317 typeof message.data['scope'] != 'string') {
318 console.error('Received incorrect fetchThirdPartyToken message.');
319 return;
320 }
321 var tokenUrl = /** @type {string} */ message.data['tokenUrl'];
322 var hostPublicKey =
323 /** @type {string} */ message.data['hostPublicKey'];
324 var scope = /** @type {string} */ message.data['scope'];
325 this.fetchThirdPartyTokenHandler(tokenUrl, hostPublicKey, scope);
326 } else if (message.method == 'pairingResponse') {
327 var clientId = /** @type {string} */ message.data['clientId'];
328 var sharedSecret = /** @type {string} */ message.data['sharedSecret'];
329 if (typeof clientId != 'string' || typeof sharedSecret != 'string') {
330 console.error('Received incorrect pairingResponse message.');
331 return;
332 }
333 this.onPairingComplete_(clientId, sharedSecret);
334 } else if (message.method == 'extensionMessage') {
335 if (typeof(message.data['type']) != 'string' ||
336 typeof(message.data['data']) != 'string') {
337 console.error('Invalid extension message:', message.data);
338 return;
339 }
340 switch (message.data['type']) {
341 case 'test-echo-reply':
342 console.log('Got echo reply: ' + message.data['data']);
343 break;
344 default:
345 console.log('Unexpected message received: ' +
346 message.data['type'] + ': ' + message.data['data']);
347 }
348 }
349 };
350
351 /**
352 * Deletes the plugin.
353 */
354 remoting.ClientPlugin.prototype.cleanup = function() {
355 this.plugin.parentNode.removeChild(this.plugin);
356 };
357
358 /**
359 * @return {HTMLEmbedElement} HTML element that correspods to the plugin.
360 */
361 remoting.ClientPlugin.prototype.element = function() {
362 return this.plugin;
363 };
364
365 /**
366 * @param {function(boolean): void} onDone
367 */
368 remoting.ClientPlugin.prototype.initialize = function(onDone) {
369 if (this.helloReceived_) {
370 onDone(true);
371 } else {
372 this.onInitializedCallback_ = onDone;
373 }
374 };
375
376 /**
377 * @return {boolean} True if the plugin and web-app versions are compatible.
378 */
379 remoting.ClientPlugin.prototype.isSupportedVersion = function() {
380 if (!this.helloReceived_) {
381 console.error(
382 "isSupportedVersion() is called before the plugin is initialized.");
383 return false;
384 }
385 return this.API_VERSION_ >= this.pluginApiMinVersion_ &&
386 this.pluginApiVersion_ >= this.API_MIN_VERSION_;
387 };
388
389 /**
74 * @param {remoting.ClientPlugin.Feature} feature The feature to test for. 390 * @param {remoting.ClientPlugin.Feature} feature The feature to test for.
75 * @return {boolean} True if the plugin supports the named feature. 391 * @return {boolean} True if the plugin supports the named feature.
76 */ 392 */
77 remoting.ClientPlugin.prototype.hasFeature = function(feature) {}; 393 remoting.ClientPlugin.prototype.hasFeature = function(feature) {
78 394 if (!this.helloReceived_) {
79 /** 395 console.error(
80 * @return {HTMLEmbedElement} HTML element that corresponds to the plugin. 396 "hasFeature() is called before the plugin is initialized.");
81 */ 397 return false;
82 remoting.ClientPlugin.prototype.element = function() {}; 398 }
83 399 return this.pluginApiFeatures_.indexOf(feature) > -1;
84 /** 400 };
85 * Deletes the plugin. 401
86 */ 402 /**
87 remoting.ClientPlugin.prototype.cleanup = function() {}; 403 * @return {boolean} True if the plugin supports the injectKeyEvent API.
88 404 */
89 /** 405 remoting.ClientPlugin.prototype.isInjectKeyEventSupported = function() {
90 * Must be called for each incoming stanza received from the host. 406 return this.pluginApiVersion_ >= 6;
407 };
408
409 /**
91 * @param {string} iq Incoming IQ stanza. 410 * @param {string} iq Incoming IQ stanza.
92 */ 411 */
93 remoting.ClientPlugin.prototype.onIncomingIq = function(iq) {}; 412 remoting.ClientPlugin.prototype.onIncomingIq = function(iq) {
413 if (this.plugin && this.plugin.postMessage) {
414 this.plugin.postMessage(JSON.stringify(
415 { method: 'incomingIq', data: { iq: iq } }));
416 } else {
417 // plugin.onIq may not be set after the plugin has been shut
418 // down. Particularly this happens when we receive response to
419 // session-terminate stanza.
420 console.warn('plugin.onIq is not set so dropping incoming message.');
421 }
422 };
94 423
95 /** 424 /**
96 * @param {string} hostJid The jid of the host to connect to. 425 * @param {string} hostJid The jid of the host to connect to.
97 * @param {string} hostPublicKey The base64 encoded version of the host's 426 * @param {string} hostPublicKey The base64 encoded version of the host's
98 * public key. 427 * public key.
99 * @param {string} localJid Local jid. 428 * @param {string} localJid Local jid.
100 * @param {string} sharedSecret The access code for IT2Me or the PIN 429 * @param {string} sharedSecret The access code for IT2Me or the PIN
101 * for Me2Me. 430 * for Me2Me.
102 * @param {string} authenticationMethods Comma-separated list of 431 * @param {string} authenticationMethods Comma-separated list of
103 * authentication methods the client should attempt to use. 432 * authentication methods the client should attempt to use.
104 * @param {string} authenticationTag A host-specific tag to mix into 433 * @param {string} authenticationTag A host-specific tag to mix into
105 * authentication hashes. 434 * authentication hashes.
106 * @param {string} clientPairingId For paired Me2Me connections, the 435 * @param {string} clientPairingId For paired Me2Me connections, the
107 * pairing id for this client, as issued by the host. 436 * pairing id for this client, as issued by the host.
108 * @param {string} clientPairedSecret For paired Me2Me connections, the 437 * @param {string} clientPairedSecret For paired Me2Me connections, the
109 * paired secret for this client, as issued by the host. 438 * paired secret for this client, as issued by the host.
110 */ 439 */
111 remoting.ClientPlugin.prototype.connect = function( 440 remoting.ClientPlugin.prototype.connect = function(
112 hostJid, hostPublicKey, localJid, sharedSecret, 441 hostJid, hostPublicKey, localJid, sharedSecret,
113 authenticationMethods, authenticationTag, 442 authenticationMethods, authenticationTag,
114 clientPairingId, clientPairedSecret) {}; 443 clientPairingId, clientPairedSecret) {
444 this.plugin.postMessage(JSON.stringify(
445 { method: 'connect', data: {
446 hostJid: hostJid,
447 hostPublicKey: hostPublicKey,
448 localJid: localJid,
449 sharedSecret: sharedSecret,
450 authenticationMethods: authenticationMethods,
451 authenticationTag: authenticationTag,
452 capabilities: this.capabilities_.join(" "),
453 clientPairingId: clientPairingId,
454 clientPairedSecret: clientPairedSecret
455 }
456 }));
457 };
115 458
116 /** 459 /**
117 * Release all currently pressed keys. 460 * Release all currently pressed keys.
118 */ 461 */
119 remoting.ClientPlugin.prototype.releaseAllKeys = function() {}; 462 remoting.ClientPlugin.prototype.releaseAllKeys = function() {
463 this.plugin.postMessage(JSON.stringify(
464 { method: 'releaseAllKeys', data: {} }));
465 };
120 466
121 /** 467 /**
122 * Send a key event to the host. 468 * Send a key event to the host.
123 * 469 *
124 * @param {number} usbKeycode The USB-style code of the key to inject. 470 * @param {number} usbKeycode The USB-style code of the key to inject.
125 * @param {boolean} pressed True to inject a key press, False for a release. 471 * @param {boolean} pressed True to inject a key press, False for a release.
126 */ 472 */
127 remoting.ClientPlugin.prototype.injectKeyEvent = 473 remoting.ClientPlugin.prototype.injectKeyEvent =
128 function(usbKeycode, pressed) {}; 474 function(usbKeycode, pressed) {
475 this.plugin.postMessage(JSON.stringify(
476 { method: 'injectKeyEvent', data: {
477 'usbKeycode': usbKeycode,
478 'pressed': pressed}
479 }));
480 };
129 481
130 /** 482 /**
131 * Remap one USB keycode to another in all subsequent key events. 483 * Remap one USB keycode to another in all subsequent key events.
132 * 484 *
133 * @param {number} fromKeycode The USB-style code of the key to remap. 485 * @param {number} fromKeycode The USB-style code of the key to remap.
134 * @param {number} toKeycode The USB-style code to remap the key to. 486 * @param {number} toKeycode The USB-style code to remap the key to.
135 */ 487 */
136 remoting.ClientPlugin.prototype.remapKey = 488 remoting.ClientPlugin.prototype.remapKey =
137 function(fromKeycode, toKeycode) {}; 489 function(fromKeycode, toKeycode) {
490 this.plugin.postMessage(JSON.stringify(
491 { method: 'remapKey', data: {
492 'fromKeycode': fromKeycode,
493 'toKeycode': toKeycode}
494 }));
495 };
138 496
139 /** 497 /**
140 * Enable/disable redirection of the specified key to the web-app. 498 * Enable/disable redirection of the specified key to the web-app.
141 * 499 *
142 * @param {number} keycode The USB-style code of the key. 500 * @param {number} keycode The USB-style code of the key.
143 * @param {Boolean} trap True to enable trapping, False to disable. 501 * @param {Boolean} trap True to enable trapping, False to disable.
144 */ 502 */
145 remoting.ClientPlugin.prototype.trapKey = function(keycode, trap) {}; 503 remoting.ClientPlugin.prototype.trapKey = function(keycode, trap) {
504 this.plugin.postMessage(JSON.stringify(
505 { method: 'trapKey', data: {
506 'keycode': keycode,
507 'trap': trap}
508 }));
509 };
146 510
147 /** 511 /**
148 * Returns an associative array with a set of stats for this connection. 512 * Returns an associative array with a set of stats for this connecton.
149 * 513 *
150 * @return {remoting.ClientSession.PerfStats} The connection statistics. 514 * @return {remoting.ClientSession.PerfStats} The connection statistics.
151 */ 515 */
152 remoting.ClientPlugin.prototype.getPerfStats = function() {}; 516 remoting.ClientPlugin.prototype.getPerfStats = function() {
517 return this.perfStats_;
518 };
153 519
154 /** 520 /**
155 * Sends a clipboard item to the host. 521 * Sends a clipboard item to the host.
156 * 522 *
157 * @param {string} mimeType The MIME type of the clipboard item. 523 * @param {string} mimeType The MIME type of the clipboard item.
158 * @param {string} item The clipboard item. 524 * @param {string} item The clipboard item.
159 */ 525 */
160 remoting.ClientPlugin.prototype.sendClipboardItem = function(mimeType, item) {}; 526 remoting.ClientPlugin.prototype.sendClipboardItem =
527 function(mimeType, item) {
528 if (!this.hasFeature(remoting.ClientPlugin.Feature.SEND_CLIPBOARD_ITEM))
529 return;
530 this.plugin.postMessage(JSON.stringify(
531 { method: 'sendClipboardItem',
532 data: { mimeType: mimeType, item: item }}));
533 };
161 534
162 /** 535 /**
163 * Notifies the host that the client has the specified size and pixel density. 536 * Notifies the host that the client has the specified size and pixel density.
164 * 537 *
165 * @param {number} width The available client width in DIPs. 538 * @param {number} width The available client width in DIPs.
166 * @param {number} height The available client height in DIPs. 539 * @param {number} height The available client height in DIPs.
167 * @param {number} device_scale The number of device pixels per DIP. 540 * @param {number} device_scale The number of device pixels per DIP.
168 */ 541 */
169 remoting.ClientPlugin.prototype.notifyClientResolution = 542 remoting.ClientPlugin.prototype.notifyClientResolution =
170 function(width, height, device_scale) {}; 543 function(width, height, device_scale) {
544 if (this.hasFeature(remoting.ClientPlugin.Feature.NOTIFY_CLIENT_RESOLUTION)) {
545 var dpi = Math.floor(device_scale * 96);
546 this.plugin.postMessage(JSON.stringify(
547 { method: 'notifyClientResolution',
548 data: { width: Math.floor(width * device_scale),
549 height: Math.floor(height * device_scale),
550 x_dpi: dpi, y_dpi: dpi }}));
551 }
552 };
171 553
172 /** 554 /**
173 * Requests that the host pause or resume sending video updates. 555 * Requests that the host pause or resume sending video updates.
174 * 556 *
175 * @param {boolean} pause True to suspend video updates, false otherwise. 557 * @param {boolean} pause True to suspend video updates, false otherwise.
176 */ 558 */
177 remoting.ClientPlugin.prototype.pauseVideo = 559 remoting.ClientPlugin.prototype.pauseVideo =
178 function(pause) {}; 560 function(pause) {
561 if (!this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_VIDEO))
562 return;
563 this.plugin.postMessage(JSON.stringify(
564 { method: 'pauseVideo', data: { pause: pause }}));
565 };
179 566
180 /** 567 /**
181 * Requests that the host pause or resume sending audio updates. 568 * Requests that the host pause or resume sending audio updates.
182 * 569 *
183 * @param {boolean} pause True to suspend audio updates, false otherwise. 570 * @param {boolean} pause True to suspend audio updates, false otherwise.
184 */ 571 */
185 remoting.ClientPlugin.prototype.pauseAudio = 572 remoting.ClientPlugin.prototype.pauseAudio =
186 function(pause) {}; 573 function(pause) {
574 if (!this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_AUDIO))
575 return;
576 this.plugin.postMessage(JSON.stringify(
577 { method: 'pauseAudio', data: { pause: pause }}));
578 };
187 579
188 /** 580 /**
189 * Gives the client authenticator the PIN. 581 * Called when a PIN is obtained from the user.
190 * 582 *
191 * @param {string} pin The PIN. 583 * @param {string} pin The PIN.
192 */ 584 */
193 remoting.ClientPlugin.prototype.onPinFetched = function(pin) {}; 585 remoting.ClientPlugin.prototype.onPinFetched =
586 function(pin) {
587 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) {
588 return;
589 }
590 this.plugin.postMessage(JSON.stringify(
591 { method: 'onPinFetched', data: { pin: pin }}));
592 };
194 593
195 /** 594 /**
196 * Tells the plugin to ask for the PIN asynchronously. 595 * Tells the plugin to ask for the PIN asynchronously.
197 */ 596 */
198 remoting.ClientPlugin.prototype.useAsyncPinDialog = function() {}; 597 remoting.ClientPlugin.prototype.useAsyncPinDialog =
598 function() {
599 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) {
600 return;
601 }
602 this.plugin.postMessage(JSON.stringify(
603 { method: 'useAsyncPinDialog', data: {} }));
604 };
199 605
200 /** 606 /**
201 * Sets the third party authentication token and shared secret. 607 * Sets the third party authentication token and shared secret.
202 * 608 *
203 * @param {string} token The token received from the token URL. 609 * @param {string} token The token received from the token URL.
204 * @param {string} sharedSecret Shared secret received from the token URL. 610 * @param {string} sharedSecret Shared secret received from the token URL.
205 */ 611 */
206 remoting.ClientPlugin.prototype.onThirdPartyTokenFetched = 612 remoting.ClientPlugin.prototype.onThirdPartyTokenFetched = function(
207 function(token, sharedSecret) {}; 613 token, sharedSecret) {
614 this.plugin.postMessage(JSON.stringify(
615 { method: 'onThirdPartyTokenFetched',
616 data: { token: token, sharedSecret: sharedSecret}}));
617 };
208 618
209 /** 619 /**
210 * Request pairing with the host for PIN-less authentication. 620 * Request pairing with the host for PIN-less authentication.
211 * 621 *
212 * @param {string} clientName The human-readable name of the client. 622 * @param {string} clientName The human-readable name of the client.
213 * @param {function(string, string):void} onDone, Callback to receive the 623 * @param {function(string, string):void} onDone, Callback to receive the
214 * client id and shared secret when they are available. 624 * client id and shared secret when they are available.
215 */ 625 */
216 remoting.ClientPlugin.prototype.requestPairing = function( 626 remoting.ClientPlugin.prototype.requestPairing =
217 clientName, onDone) {}; 627 function(clientName, onDone) {
628 if (!this.hasFeature(remoting.ClientPlugin.Feature.PINLESS_AUTH)) {
629 return;
630 }
631 this.onPairingComplete_ = onDone;
632 this.plugin.postMessage(JSON.stringify(
633 { method: 'requestPairing', data: { clientName: clientName } }));
634 };
635
636 /**
637 * Send an extension message to the host.
638 *
639 * @param {string} type The message type.
640 * @param {Object} message The message payload.
641 */
642 remoting.ClientPlugin.prototype.sendClientMessage =
643 function(type, message) {
644 if (!this.hasFeature(remoting.ClientPlugin.Feature.EXTENSION_MESSAGE)) {
645 return;
646 }
647 this.plugin.postMessage(JSON.stringify(
648 { method: 'extensionMessage',
649 data: { type: type, data: JSON.stringify(message) } }));
650
651 };
652
653 /**
654 * If we haven't yet received a "hello" message from the plugin, change its
655 * size so that the user can confirm it if click-to-play is enabled, or can
656 * see the "this plugin is disabled" message if it is actually disabled.
657 * @private
658 */
659 remoting.ClientPlugin.prototype.showPluginForClickToPlay_ = function() {
660 if (!this.helloReceived_) {
661 var width = 200;
662 var height = 200;
663 this.plugin.width = width;
664 this.plugin.height = height;
665 // Center the plugin just underneath the "Connnecting..." dialog.
666 var parentNode = this.plugin.parentNode;
667 var dialog = document.getElementById('client-dialog');
668 var dialogRect = dialog.getBoundingClientRect();
669 parentNode.style.top = (dialogRect.bottom + 16) + 'px';
670 parentNode.style.left = (window.innerWidth - width) / 2 + 'px';
671 }
672 };
OLDNEW
« no previous file with comments | « remoting/webapp/all_js_load.gtestjs ('k') | remoting/webapp/client_plugin_async.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698