OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
Sergey Ulanov
2014/09/20 00:35:25
2014 - this is a new file
| |
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 /** | 5 /** |
6 * @fileoverview | 6 * @fileoverview |
7 * Class that wraps low-level details of interacting with the client plugin. | 7 * Class that wraps low-level details of interacting with the client plugin. |
8 * | 8 * |
9 * This abstracts a <embed> element and controls the plugin which does | 9 * This abstracts a <embed> element and controls the plugin which does |
10 * the actual remoting work. It also handles differences between | 10 * the actual remoting work. It also handles differences between |
11 * client plugins versions when it is necessary. | 11 * client plugins versions when it is necessary. |
12 */ | 12 */ |
13 | 13 |
14 'use strict'; | 14 'use strict'; |
15 | 15 |
16 /** @suppress {duplicate} */ | 16 /** @suppress {duplicate} */ |
17 var remoting = remoting || {}; | 17 var remoting = remoting || {}; |
18 | 18 |
19 /** | 19 /** |
20 * @param {Element} container The container for the embed element. | 20 * @param {Element} container The container for the embed element. |
21 * @param {function(string, string):boolean} onExtensionMessage The handler for | 21 * @param {function(string, string):boolean} onExtensionMessage The handler for |
22 * protocol extension messages. Returns true if a message is recognized; | 22 * protocol extension messages. Returns true if a message is recognized; |
23 * false otherwise. | 23 * false otherwise. |
24 * @constructor | 24 * @constructor |
25 * @implements {remoting.ClientPlugin} | |
25 */ | 26 */ |
26 remoting.ClientPlugin = function(container, onExtensionMessage) { | 27 remoting.ClientPluginImpl = function(container, onExtensionMessage) { |
27 this.plugin_ = remoting.ClientPlugin.createPluginElement_(); | 28 this.plugin_ = remoting.ClientPluginImpl.createPluginElement_(); |
28 this.plugin_.id = 'session-client-plugin'; | 29 this.plugin_.id = 'session-client-plugin'; |
29 container.appendChild(this.plugin_); | 30 container.appendChild(this.plugin_); |
30 | 31 |
31 this.onExtensionMessage_ = onExtensionMessage; | 32 this.onExtensionMessage_ = onExtensionMessage; |
32 | 33 |
33 this.desktopWidth = 0; | 34 /** @private */ |
34 this.desktopHeight = 0; | 35 this.desktopWidth_ = 0; |
35 this.desktopXDpi = 96; | 36 /** @private */ |
36 this.desktopYDpi = 96; | 37 this.desktopHeight_ = 0; |
38 /** @private */ | |
39 this.desktopXDpi_ = 96; | |
40 /** @private */ | |
41 this.desktopYDpi_ = 96; | |
37 | 42 |
38 /** @param {string} iq The Iq stanza received from the host. */ | 43 /** |
39 this.onOutgoingIqHandler = function (iq) {}; | 44 * @param {string} iq The Iq stanza received from the host. |
40 /** @param {string} message Log message. */ | 45 * @private |
41 this.onDebugMessageHandler = function (message) {}; | 46 */ |
47 this.onOutgoingIqHandler_ = function (iq) {}; | |
48 /** | |
49 * @param {string} message Log message. | |
50 * @private | |
51 */ | |
52 this.onDebugMessageHandler_ = function (message) {}; | |
42 /** | 53 /** |
43 * @param {number} state The connection state. | 54 * @param {number} state The connection state. |
44 * @param {number} error The error code, if any. | 55 * @param {number} error The error code, if any. |
56 * @private | |
45 */ | 57 */ |
46 this.onConnectionStatusUpdateHandler = function(state, error) {}; | 58 this.onConnectionStatusUpdateHandler_ = function(state, error) {}; |
47 /** @param {boolean} ready Connection ready state. */ | 59 /** |
48 this.onConnectionReadyHandler = function(ready) {}; | 60 * @param {boolean} ready Connection ready state. |
61 * @private | |
62 */ | |
63 this.onConnectionReadyHandler_ = function(ready) {}; | |
49 | 64 |
50 /** | 65 /** |
51 * @param {string} tokenUrl Token-request URL, received from the host. | 66 * @param {string} tokenUrl Token-request URL, received from the host. |
52 * @param {string} hostPublicKey Public key for the host. | 67 * @param {string} hostPublicKey Public key for the host. |
53 * @param {string} scope OAuth scope to request the token for. | 68 * @param {string} scope OAuth scope to request the token for. |
69 * @private | |
54 */ | 70 */ |
55 this.fetchThirdPartyTokenHandler = function( | 71 this.fetchThirdPartyTokenHandler_ = function( |
56 tokenUrl, hostPublicKey, scope) {}; | 72 tokenUrl, hostPublicKey, scope) {}; |
57 this.onDesktopSizeUpdateHandler = function () {}; | 73 /** @private */ |
58 /** @param {!Array.<string>} capabilities The negotiated capabilities. */ | 74 this.onDesktopSizeUpdateHandler_ = function () {}; |
59 this.onSetCapabilitiesHandler = function (capabilities) {}; | 75 /** |
60 this.fetchPinHandler = function (supportsPairing) {}; | 76 * @param {!Array.<string>} capabilities The negotiated capabilities. |
61 /** @param {string} data Remote gnubbyd data. */ | 77 * @private |
62 this.onGnubbyAuthHandler = function(data) {}; | 78 */ |
79 this.onSetCapabilitiesHandler_ = function (capabilities) {}; | |
80 /** @private */ | |
81 this.fetchPinHandler_ = function (supportsPairing) {}; | |
82 /** | |
83 * @param {string} data Remote gnubbyd data. | |
84 * @private | |
85 */ | |
86 this.onGnubbyAuthHandler_ = function(data) {}; | |
63 /** | 87 /** |
64 * @param {string} url | 88 * @param {string} url |
65 * @param {number} hotspotX | 89 * @param {number} hotspotX |
66 * @param {number} hotspotY | 90 * @param {number} hotspotY |
91 * @private | |
67 */ | 92 */ |
68 this.updateMouseCursorImage = function(url, hotspotX, hotspotY) {}; | 93 this.updateMouseCursorImage_ = function(url, hotspotX, hotspotY) {}; |
69 | 94 |
70 /** @param {string} data Remote cast extension message. */ | 95 /** |
71 this.onCastExtensionHandler = function(data) {}; | 96 * @param {string} data Remote cast extension message. |
97 * @private | |
98 */ | |
99 this.onCastExtensionHandler_ = function(data) {}; | |
72 | 100 |
73 /** @type {remoting.MediaSourceRenderer} */ | 101 /** |
102 * @type {remoting.MediaSourceRenderer} | |
103 * @private | |
104 */ | |
74 this.mediaSourceRenderer_ = null; | 105 this.mediaSourceRenderer_ = null; |
75 | 106 |
76 /** @type {number} */ | 107 /** |
108 * @type {number} | |
109 * @private | |
110 */ | |
77 this.pluginApiVersion_ = -1; | 111 this.pluginApiVersion_ = -1; |
78 /** @type {Array.<string>} */ | 112 /** |
113 * @type {Array.<string>} | |
114 * @private | |
115 */ | |
79 this.pluginApiFeatures_ = []; | 116 this.pluginApiFeatures_ = []; |
80 /** @type {number} */ | 117 /** |
118 * @type {number} | |
119 * @private | |
120 */ | |
81 this.pluginApiMinVersion_ = -1; | 121 this.pluginApiMinVersion_ = -1; |
82 /** @type {!Array.<string>} */ | 122 /** |
123 * @type {!Array.<string>} | |
124 * @private | |
125 */ | |
83 this.capabilities_ = []; | 126 this.capabilities_ = []; |
84 /** @type {boolean} */ | 127 /** |
128 * @type {boolean} | |
129 * @private | |
130 */ | |
85 this.helloReceived_ = false; | 131 this.helloReceived_ = false; |
86 /** @type {function(boolean)|null} */ | 132 /** |
133 * @type {function(boolean)|null} | |
134 * @private | |
135 */ | |
87 this.onInitializedCallback_ = null; | 136 this.onInitializedCallback_ = null; |
88 /** @type {function(string, string):void} */ | 137 /** |
138 * @type {function(string, string):void} | |
139 * @private | |
140 */ | |
89 this.onPairingComplete_ = function(clientId, sharedSecret) {}; | 141 this.onPairingComplete_ = function(clientId, sharedSecret) {}; |
90 /** @type {remoting.ClientSession.PerfStats} */ | 142 /** |
143 * @type {remoting.ClientSession.PerfStats} | |
144 * @private | |
145 */ | |
91 this.perfStats_ = new remoting.ClientSession.PerfStats(); | 146 this.perfStats_ = new remoting.ClientSession.PerfStats(); |
92 | 147 |
93 /** @type {remoting.ClientPlugin} */ | 148 /** @type {remoting.ClientPluginImpl} */ |
94 var that = this; | 149 var that = this; |
95 /** @param {Event} event Message event from the plugin. */ | 150 /** @param {Event} event Message event from the plugin. */ |
96 this.plugin_.addEventListener('message', function(event) { | 151 this.plugin_.addEventListener('message', function(event) { |
97 that.handleMessage_(event.data); | 152 that.handleMessage_(event.data); |
98 }, false); | 153 }, false); |
99 | 154 |
100 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'native') { | 155 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'native') { |
101 window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500); | 156 window.setTimeout(this.showPluginForClickToPlay_.bind(this), 500); |
102 } | 157 } |
103 }; | 158 }; |
104 | 159 |
105 /** | 160 /** |
106 * Creates plugin element without adding it to a container. | 161 * Creates plugin element without adding it to a container. |
107 * | 162 * |
108 * @return {remoting.ViewerPlugin} Plugin element | 163 * @return {remoting.ViewerPlugin} Plugin element |
109 */ | 164 */ |
110 remoting.ClientPlugin.createPluginElement_ = function() { | 165 remoting.ClientPluginImpl.createPluginElement_ = function() { |
111 var plugin = /** @type {remoting.ViewerPlugin} */ | 166 var plugin = /** @type {remoting.ViewerPlugin} */ |
112 document.createElement('embed'); | 167 document.createElement('embed'); |
113 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'pnacl') { | 168 if (remoting.settings.CLIENT_PLUGIN_TYPE == 'pnacl') { |
114 plugin.src = 'remoting_client_pnacl.nmf'; | 169 plugin.src = 'remoting_client_pnacl.nmf'; |
115 plugin.type = 'application/x-pnacl'; | 170 plugin.type = 'application/x-pnacl'; |
116 } else if (remoting.settings.CLIENT_PLUGIN_TYPE == 'nacl') { | 171 } else if (remoting.settings.CLIENT_PLUGIN_TYPE == 'nacl') { |
117 plugin.src = 'remoting_client_nacl.nmf'; | 172 plugin.src = 'remoting_client_nacl.nmf'; |
118 plugin.type = 'application/x-nacl'; | 173 plugin.type = 'application/x-nacl'; |
119 } else { | 174 } else { |
120 plugin.src = 'about://none'; | 175 plugin.src = 'about://none'; |
121 plugin.type = 'application/vnd.chromium.remoting-viewer'; | 176 plugin.type = 'application/vnd.chromium.remoting-viewer'; |
122 } | 177 } |
123 plugin.width = 0; | 178 plugin.width = 0; |
124 plugin.height = 0; | 179 plugin.height = 0; |
125 plugin.tabIndex = 0; // Required, otherwise focus() doesn't work. | 180 plugin.tabIndex = 0; // Required, otherwise focus() doesn't work. |
126 return plugin; | 181 return plugin; |
127 } | 182 } |
128 | 183 |
129 /** | 184 /** |
130 * Preloads the plugin to make instantiation faster when the user tries | |
131 * to connect. | |
132 */ | |
133 remoting.ClientPlugin.preload = function() { | |
134 if (remoting.settings.CLIENT_PLUGIN_TYPE != 'pnacl') { | |
135 return; | |
136 } | |
137 | |
138 var plugin = remoting.ClientPlugin.createPluginElement_(); | |
139 plugin.addEventListener( | |
140 'loadend', function() { document.body.removeChild(plugin); }, false); | |
141 document.body.appendChild(plugin); | |
142 } | |
143 | |
144 /** | |
145 * Set of features for which hasFeature() can be used to test. | |
146 * | |
147 * @enum {string} | |
148 */ | |
149 remoting.ClientPlugin.Feature = { | |
150 INJECT_KEY_EVENT: 'injectKeyEvent', | |
151 NOTIFY_CLIENT_RESOLUTION: 'notifyClientResolution', | |
152 ASYNC_PIN: 'asyncPin', | |
153 PAUSE_VIDEO: 'pauseVideo', | |
154 PAUSE_AUDIO: 'pauseAudio', | |
155 REMAP_KEY: 'remapKey', | |
156 SEND_CLIPBOARD_ITEM: 'sendClipboardItem', | |
157 THIRD_PARTY_AUTH: 'thirdPartyAuth', | |
158 TRAP_KEY: 'trapKey', | |
159 PINLESS_AUTH: 'pinlessAuth', | |
160 EXTENSION_MESSAGE: 'extensionMessage', | |
161 MEDIA_SOURCE_RENDERING: 'mediaSourceRendering', | |
162 VIDEO_CONTROL: 'videoControl' | |
163 }; | |
164 | |
165 /** | |
166 * Chromoting session API version (for this javascript). | 185 * Chromoting session API version (for this javascript). |
167 * This is compared with the plugin API version to verify that they are | 186 * This is compared with the plugin API version to verify that they are |
168 * compatible. | 187 * compatible. |
169 * | 188 * |
170 * @const | 189 * @const |
171 * @private | 190 * @private |
172 */ | 191 */ |
173 remoting.ClientPlugin.prototype.API_VERSION_ = 6; | 192 remoting.ClientPluginImpl.prototype.API_VERSION_ = 6; |
174 | 193 |
175 /** | 194 /** |
176 * The oldest API version that we support. | 195 * The oldest API version that we support. |
177 * This will differ from the |API_VERSION_| if we maintain backward | 196 * This will differ from the |API_VERSION_| if we maintain backward |
178 * compatibility with older API versions. | 197 * compatibility with older API versions. |
179 * | 198 * |
180 * @const | 199 * @const |
181 * @private | 200 * @private |
182 */ | 201 */ |
183 remoting.ClientPlugin.prototype.API_MIN_VERSION_ = 5; | 202 remoting.ClientPluginImpl.prototype.API_MIN_VERSION_ = 5; |
203 | |
204 /** | |
205 * @param {function(string):void} handler | |
206 */ | |
207 remoting.ClientPluginImpl.prototype.setOnOutgoingIqHandler = function(handler) { | |
208 this.onOutgoingIqHandler_ = handler; | |
209 }; | |
210 | |
211 /** | |
212 * @param {function(string):void} handler | |
213 */ | |
214 remoting.ClientPluginImpl.prototype.setOnDebugMessageHandler = | |
215 function(handler) { | |
216 this.onDebugMessageHandler_ = handler; | |
217 }; | |
218 | |
219 /** | |
220 * @param {function(number, number):void} handler | |
221 */ | |
222 remoting.ClientPluginImpl.prototype.setConnectionStatusUpdateHandler = | |
223 function(handler) { | |
224 this.onConnectionStatusUpdateHandler_ = handler; | |
225 }; | |
226 | |
227 /** | |
228 * @param {function(boolean):void} handler | |
229 */ | |
230 remoting.ClientPluginImpl.prototype.setConnectionReadyHandler = | |
231 function(handler) { | |
232 this.onConnectionReadyHandler_ = handler; | |
233 }; | |
234 | |
235 /** | |
236 * @param {function():void} handler | |
237 */ | |
238 remoting.ClientPluginImpl.prototype.setDesktopSizeUpdateHandler = | |
239 function(handler) { | |
240 this.onDesktopSizeUpdateHandler_ = handler; | |
241 }; | |
242 | |
243 /** | |
244 * @param {function(!Array.<string>):void} handler | |
245 */ | |
246 remoting.ClientPluginImpl.prototype.setCapabilitiesHandler = function(handler) { | |
247 this.onSetCapabilitiesHandler_ = handler; | |
248 }; | |
249 | |
250 /** | |
251 * @param {function(string):void} handler | |
252 */ | |
253 remoting.ClientPluginImpl.prototype.setGnubbyAuthHandler = function(handler) { | |
254 this.onGnubbyAuthHandler_ = handler; | |
255 }; | |
256 | |
257 /** | |
258 * @param {function(string):void} handler | |
259 */ | |
260 remoting.ClientPluginImpl.prototype.setCastExtensionHandler = | |
261 function(handler) { | |
262 this.onCastExtensionHandler_ = handler; | |
263 }; | |
264 | |
265 /** | |
266 * @param {function(string, number, number):void} handler | |
267 */ | |
268 remoting.ClientPluginImpl.prototype.setMouseCursorHandler = function(handler) { | |
269 this.updateMouseCursorImage_ = handler; | |
270 }; | |
271 | |
272 /** | |
273 * @param {function(string, string, string):void} handler | |
274 */ | |
275 remoting.ClientPluginImpl.prototype.setFetchThirdPartyTokenHandler = | |
276 function(handler) { | |
277 this.fetchThirdPartyTokenHandler_ = handler; | |
278 }; | |
279 | |
280 /** | |
281 * @param {function(boolean):void} handler | |
282 */ | |
283 remoting.ClientPluginImpl.prototype.setFetchPinHandler = function(handler) { | |
284 this.fetchPinHandler_ = handler; | |
285 }; | |
184 | 286 |
185 /** | 287 /** |
186 * @param {string|{method:string, data:Object.<string,*>}} | 288 * @param {string|{method:string, data:Object.<string,*>}} |
187 * rawMessage Message from the plugin. | 289 * rawMessage Message from the plugin. |
188 * @private | 290 * @private |
189 */ | 291 */ |
190 remoting.ClientPlugin.prototype.handleMessage_ = function(rawMessage) { | 292 remoting.ClientPluginImpl.prototype.handleMessage_ = function(rawMessage) { |
191 var message = | 293 var message = |
192 /** @type {{method:string, data:Object.<string,*>}} */ | 294 /** @type {{method:string, data:Object.<string,*>}} */ |
193 ((typeof(rawMessage) == 'string') ? jsonParseSafe(rawMessage) | 295 ((typeof(rawMessage) == 'string') ? jsonParseSafe(rawMessage) |
194 : rawMessage); | 296 : rawMessage); |
195 if (!message || !('method' in message) || !('data' in message)) { | 297 if (!message || !('method' in message) || !('data' in message)) { |
196 console.error('Received invalid message from the plugin:', rawMessage); | 298 console.error('Received invalid message from the plugin:', rawMessage); |
197 return; | 299 return; |
198 } | 300 } |
199 | 301 |
200 try { | 302 try { |
201 this.handleMessageMethod_(message); | 303 this.handleMessageMethod_(message); |
202 } catch(e) { | 304 } catch(e) { |
203 console.error(/** @type {*} */ (e)); | 305 console.error(/** @type {*} */ (e)); |
204 } | 306 } |
205 } | 307 } |
206 | 308 |
207 /** | 309 /** |
208 * @param {{method:string, data:Object.<string,*>}} | 310 * @param {{method:string, data:Object.<string,*>}} |
209 * message Parsed message from the plugin. | 311 * message Parsed message from the plugin. |
210 * @private | 312 * @private |
211 */ | 313 */ |
212 remoting.ClientPlugin.prototype.handleMessageMethod_ = function(message) { | 314 remoting.ClientPluginImpl.prototype.handleMessageMethod_ = function(message) { |
213 /** | 315 /** |
214 * Splits a string into a list of words delimited by spaces. | 316 * Splits a string into a list of words delimited by spaces. |
215 * @param {string} str String that should be split. | 317 * @param {string} str String that should be split. |
216 * @return {!Array.<string>} List of words. | 318 * @return {!Array.<string>} List of words. |
217 */ | 319 */ |
218 var tokenize = function(str) { | 320 var tokenize = function(str) { |
219 /** @type {Array.<string>} */ | 321 /** @type {Array.<string>} */ |
220 var tokens = str.match(/\S+/g); | 322 var tokens = str.match(/\S+/g); |
221 return tokens ? tokens : []; | 323 return tokens ? tokens : []; |
222 }; | 324 }; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
278 } else { | 380 } else { |
279 this.pluginApiFeatures_ = ['highQualityScaling']; | 381 this.pluginApiFeatures_ = ['highQualityScaling']; |
280 } | 382 } |
281 this.helloReceived_ = true; | 383 this.helloReceived_ = true; |
282 if (this.onInitializedCallback_ != null) { | 384 if (this.onInitializedCallback_ != null) { |
283 this.onInitializedCallback_(true); | 385 this.onInitializedCallback_(true); |
284 this.onInitializedCallback_ = null; | 386 this.onInitializedCallback_ = null; |
285 } | 387 } |
286 | 388 |
287 } else if (message.method == 'sendOutgoingIq') { | 389 } else if (message.method == 'sendOutgoingIq') { |
288 this.onOutgoingIqHandler(getStringAttr(message.data, 'iq')); | 390 this.onOutgoingIqHandler_(getStringAttr(message.data, 'iq')); |
289 | 391 |
290 } else if (message.method == 'logDebugMessage') { | 392 } else if (message.method == 'logDebugMessage') { |
291 this.onDebugMessageHandler(getStringAttr(message.data, 'message')); | 393 this.onDebugMessageHandler_(getStringAttr(message.data, 'message')); |
292 | 394 |
293 } else if (message.method == 'onConnectionStatus') { | 395 } else if (message.method == 'onConnectionStatus') { |
294 var state = remoting.ClientSession.State.fromString( | 396 var state = remoting.ClientSession.State.fromString( |
295 getStringAttr(message.data, 'state')) | 397 getStringAttr(message.data, 'state')) |
296 var error = remoting.ClientSession.ConnectionError.fromString( | 398 var error = remoting.ClientSession.ConnectionError.fromString( |
297 getStringAttr(message.data, 'error')); | 399 getStringAttr(message.data, 'error')); |
298 this.onConnectionStatusUpdateHandler(state, error); | 400 this.onConnectionStatusUpdateHandler_(state, error); |
299 | 401 |
300 } else if (message.method == 'onDesktopSize') { | 402 } else if (message.method == 'onDesktopSize') { |
301 this.desktopWidth = getNumberAttr(message.data, 'width'); | 403 this.desktopWidth_ = getNumberAttr(message.data, 'width'); |
302 this.desktopHeight = getNumberAttr(message.data, 'height'); | 404 this.desktopHeight_ = getNumberAttr(message.data, 'height'); |
303 this.desktopXDpi = getNumberAttr(message.data, 'x_dpi', 96); | 405 this.desktopXDpi_ = getNumberAttr(message.data, 'x_dpi', 96); |
304 this.desktopYDpi = getNumberAttr(message.data, 'y_dpi', 96); | 406 this.desktopYDpi_ = getNumberAttr(message.data, 'y_dpi', 96); |
305 this.onDesktopSizeUpdateHandler(); | 407 this.onDesktopSizeUpdateHandler_(); |
306 | 408 |
307 } else if (message.method == 'onPerfStats') { | 409 } else if (message.method == 'onPerfStats') { |
308 // Return value is ignored. These calls will throw an error if the value | 410 // Return value is ignored. These calls will throw an error if the value |
309 // is not a number. | 411 // is not a number. |
310 getNumberAttr(message.data, 'videoBandwidth'); | 412 getNumberAttr(message.data, 'videoBandwidth'); |
311 getNumberAttr(message.data, 'videoFrameRate'); | 413 getNumberAttr(message.data, 'videoFrameRate'); |
312 getNumberAttr(message.data, 'captureLatency'); | 414 getNumberAttr(message.data, 'captureLatency'); |
313 getNumberAttr(message.data, 'encodeLatency'); | 415 getNumberAttr(message.data, 'encodeLatency'); |
314 getNumberAttr(message.data, 'decodeLatency'); | 416 getNumberAttr(message.data, 'decodeLatency'); |
315 getNumberAttr(message.data, 'renderLatency'); | 417 getNumberAttr(message.data, 'renderLatency'); |
316 getNumberAttr(message.data, 'roundtripLatency'); | 418 getNumberAttr(message.data, 'roundtripLatency'); |
317 this.perfStats_ = | 419 this.perfStats_ = |
318 /** @type {remoting.ClientSession.PerfStats} */ message.data; | 420 /** @type {remoting.ClientSession.PerfStats} */ message.data; |
319 | 421 |
320 } else if (message.method == 'injectClipboardItem') { | 422 } else if (message.method == 'injectClipboardItem') { |
321 var mimetype = getStringAttr(message.data, 'mimeType'); | 423 var mimetype = getStringAttr(message.data, 'mimeType'); |
322 var item = getStringAttr(message.data, 'item'); | 424 var item = getStringAttr(message.data, 'item'); |
323 if (remoting.clipboard) { | 425 if (remoting.clipboard) { |
324 remoting.clipboard.fromHost(mimetype, item); | 426 remoting.clipboard.fromHost(mimetype, item); |
325 } | 427 } |
326 | 428 |
327 } else if (message.method == 'onFirstFrameReceived') { | 429 } else if (message.method == 'onFirstFrameReceived') { |
328 if (remoting.clientSession) { | 430 if (remoting.clientSession) { |
329 remoting.clientSession.onFirstFrameReceived(); | 431 remoting.clientSession.onFirstFrameReceived(); |
330 } | 432 } |
331 | 433 |
332 } else if (message.method == 'onConnectionReady') { | 434 } else if (message.method == 'onConnectionReady') { |
333 var ready = getBooleanAttr(message.data, 'ready'); | 435 var ready = getBooleanAttr(message.data, 'ready'); |
334 this.onConnectionReadyHandler(ready); | 436 this.onConnectionReadyHandler_(ready); |
335 | 437 |
336 } else if (message.method == 'fetchPin') { | 438 } else if (message.method == 'fetchPin') { |
337 // The pairingSupported value in the dictionary indicates whether both | 439 // The pairingSupported value in the dictionary indicates whether both |
338 // client and host support pairing. If the client doesn't support pairing, | 440 // client and host support pairing. If the client doesn't support pairing, |
339 // then the value won't be there at all, so give it a default of false. | 441 // then the value won't be there at all, so give it a default of false. |
340 var pairingSupported = getBooleanAttr(message.data, 'pairingSupported', | 442 var pairingSupported = getBooleanAttr(message.data, 'pairingSupported', |
341 false) | 443 false) |
342 this.fetchPinHandler(pairingSupported); | 444 this.fetchPinHandler_(pairingSupported); |
343 | 445 |
344 } else if (message.method == 'setCapabilities') { | 446 } else if (message.method == 'setCapabilities') { |
345 /** @type {!Array.<string>} */ | 447 /** @type {!Array.<string>} */ |
346 var capabilities = tokenize(getStringAttr(message.data, 'capabilities')); | 448 var capabilities = tokenize(getStringAttr(message.data, 'capabilities')); |
347 this.onSetCapabilitiesHandler(capabilities); | 449 this.onSetCapabilitiesHandler_(capabilities); |
348 | 450 |
349 } else if (message.method == 'fetchThirdPartyToken') { | 451 } else if (message.method == 'fetchThirdPartyToken') { |
350 var tokenUrl = getStringAttr(message.data, 'tokenUrl'); | 452 var tokenUrl = getStringAttr(message.data, 'tokenUrl'); |
351 var hostPublicKey = getStringAttr(message.data, 'hostPublicKey'); | 453 var hostPublicKey = getStringAttr(message.data, 'hostPublicKey'); |
352 var scope = getStringAttr(message.data, 'scope'); | 454 var scope = getStringAttr(message.data, 'scope'); |
353 this.fetchThirdPartyTokenHandler(tokenUrl, hostPublicKey, scope); | 455 this.fetchThirdPartyTokenHandler_(tokenUrl, hostPublicKey, scope); |
354 | 456 |
355 } else if (message.method == 'pairingResponse') { | 457 } else if (message.method == 'pairingResponse') { |
356 var clientId = getStringAttr(message.data, 'clientId'); | 458 var clientId = getStringAttr(message.data, 'clientId'); |
357 var sharedSecret = getStringAttr(message.data, 'sharedSecret'); | 459 var sharedSecret = getStringAttr(message.data, 'sharedSecret'); |
358 this.onPairingComplete_(clientId, sharedSecret); | 460 this.onPairingComplete_(clientId, sharedSecret); |
359 | 461 |
360 } else if (message.method == 'extensionMessage') { | 462 } else if (message.method == 'extensionMessage') { |
361 var extMsgType = getStringAttr(message.data, 'type'); | 463 var extMsgType = getStringAttr(message.data, 'type'); |
362 var extMsgData = getStringAttr(message.data, 'data'); | 464 var extMsgData = getStringAttr(message.data, 'data'); |
363 switch (extMsgType) { | 465 switch (extMsgType) { |
364 case 'gnubby-auth': | 466 case 'gnubby-auth': |
365 this.onGnubbyAuthHandler(extMsgData); | 467 this.onGnubbyAuthHandler_(extMsgData); |
366 break; | 468 break; |
367 case 'test-echo-reply': | 469 case 'test-echo-reply': |
368 console.log('Got echo reply: ' + extMsgData); | 470 console.log('Got echo reply: ' + extMsgData); |
369 break; | 471 break; |
370 case 'cast_message': | 472 case 'cast_message': |
371 this.onCastExtensionHandler(extMsgData); | 473 this.onCastExtensionHandler_(extMsgData); |
372 break; | 474 break; |
373 default: | 475 default: |
374 this.onExtensionMessage_(extMsgType, extMsgData); | 476 this.onExtensionMessage_(extMsgType, extMsgData); |
375 break; | 477 break; |
376 } | 478 } |
377 | 479 |
378 } else if (message.method == 'mediaSourceReset') { | 480 } else if (message.method == 'mediaSourceReset') { |
379 if (!this.mediaSourceRenderer_) { | 481 if (!this.mediaSourceRenderer_) { |
380 console.error('Unexpected mediaSourceReset.'); | 482 console.error('Unexpected mediaSourceReset.'); |
381 return; | 483 return; |
382 } | 484 } |
383 this.mediaSourceRenderer_.reset(getStringAttr(message.data, 'format')) | 485 this.mediaSourceRenderer_.reset(getStringAttr(message.data, 'format')) |
384 | 486 |
385 } else if (message.method == 'mediaSourceData') { | 487 } else if (message.method == 'mediaSourceData') { |
386 if (!(message.data['buffer'] instanceof ArrayBuffer)) { | 488 if (!(message.data['buffer'] instanceof ArrayBuffer)) { |
387 console.error('Invalid mediaSourceData message:', message.data); | 489 console.error('Invalid mediaSourceData message:', message.data); |
388 return; | 490 return; |
389 } | 491 } |
390 if (!this.mediaSourceRenderer_) { | 492 if (!this.mediaSourceRenderer_) { |
391 console.error('Unexpected mediaSourceData.'); | 493 console.error('Unexpected mediaSourceData.'); |
392 return; | 494 return; |
393 } | 495 } |
394 // keyframe flag may be absent from the message. | 496 // keyframe flag may be absent from the message. |
395 var keyframe = !!message.data['keyframe']; | 497 var keyframe = !!message.data['keyframe']; |
396 this.mediaSourceRenderer_.onIncomingData( | 498 this.mediaSourceRenderer_.onIncomingData( |
397 (/** @type {ArrayBuffer} */ message.data['buffer']), keyframe); | 499 (/** @type {ArrayBuffer} */ message.data['buffer']), keyframe); |
398 | 500 |
399 } else if (message.method == 'unsetCursorShape') { | 501 } else if (message.method == 'unsetCursorShape') { |
400 this.updateMouseCursorImage('', 0, 0); | 502 this.updateMouseCursorImage_('', 0, 0); |
401 | 503 |
402 } else if (message.method == 'setCursorShape') { | 504 } else if (message.method == 'setCursorShape') { |
403 var width = getNumberAttr(message.data, 'width'); | 505 var width = getNumberAttr(message.data, 'width'); |
404 var height = getNumberAttr(message.data, 'height'); | 506 var height = getNumberAttr(message.data, 'height'); |
405 var hotspotX = getNumberAttr(message.data, 'hotspotX'); | 507 var hotspotX = getNumberAttr(message.data, 'hotspotX'); |
406 var hotspotY = getNumberAttr(message.data, 'hotspotY'); | 508 var hotspotY = getNumberAttr(message.data, 'hotspotY'); |
407 var srcArrayBuffer = getObjectAttr(message.data, 'data'); | 509 var srcArrayBuffer = getObjectAttr(message.data, 'data'); |
408 | 510 |
409 var canvas = | 511 var canvas = |
410 /** @type {HTMLCanvasElement} */ (document.createElement('canvas')); | 512 /** @type {HTMLCanvasElement} */ (document.createElement('canvas')); |
411 canvas.width = width; | 513 canvas.width = width; |
412 canvas.height = height; | 514 canvas.height = height; |
413 | 515 |
414 var context = | 516 var context = |
415 /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); | 517 /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); |
416 var imageData = context.getImageData(0, 0, width, height); | 518 var imageData = context.getImageData(0, 0, width, height); |
417 base.debug.assert(srcArrayBuffer instanceof ArrayBuffer); | 519 base.debug.assert(srcArrayBuffer instanceof ArrayBuffer); |
418 var src = new Uint8Array(/** @type {ArrayBuffer} */(srcArrayBuffer)); | 520 var src = new Uint8Array(/** @type {ArrayBuffer} */(srcArrayBuffer)); |
419 var dest = imageData.data; | 521 var dest = imageData.data; |
420 for (var i = 0; i < /** @type {number} */(dest.length); i += 4) { | 522 for (var i = 0; i < /** @type {number} */(dest.length); i += 4) { |
421 dest[i] = src[i + 2]; | 523 dest[i] = src[i + 2]; |
422 dest[i + 1] = src[i + 1]; | 524 dest[i + 1] = src[i + 1]; |
423 dest[i + 2] = src[i]; | 525 dest[i + 2] = src[i]; |
424 dest[i + 3] = src[i + 3]; | 526 dest[i + 3] = src[i + 3]; |
425 } | 527 } |
426 | 528 |
427 context.putImageData(imageData, 0, 0); | 529 context.putImageData(imageData, 0, 0); |
428 this.updateMouseCursorImage(canvas.toDataURL(), hotspotX, hotspotY); | 530 this.updateMouseCursorImage_(canvas.toDataURL(), hotspotX, hotspotY); |
429 } | 531 } |
430 }; | 532 }; |
431 | 533 |
432 /** | 534 /** |
433 * Deletes the plugin. | 535 * Deletes the plugin. |
434 */ | 536 */ |
435 remoting.ClientPlugin.prototype.cleanup = function() { | 537 remoting.ClientPluginImpl.prototype.dispose = function() { |
436 if (this.plugin_) { | 538 if (this.plugin_) { |
437 this.plugin_.parentNode.removeChild(this.plugin_); | 539 this.plugin_.parentNode.removeChild(this.plugin_); |
438 this.plugin_ = null; | 540 this.plugin_ = null; |
439 } | 541 } |
440 }; | 542 }; |
441 | 543 |
442 /** | 544 /** |
443 * @return {HTMLEmbedElement} HTML element that corresponds to the plugin. | 545 * @return {HTMLEmbedElement} HTML element that corresponds to the plugin. |
444 */ | 546 */ |
445 remoting.ClientPlugin.prototype.element = function() { | 547 remoting.ClientPluginImpl.prototype.element = function() { |
446 return this.plugin_; | 548 return this.plugin_; |
447 }; | 549 }; |
448 | 550 |
449 /** | 551 /** |
450 * @param {function(boolean): void} onDone | 552 * @param {function(boolean): void} onDone |
451 */ | 553 */ |
452 remoting.ClientPlugin.prototype.initialize = function(onDone) { | 554 remoting.ClientPluginImpl.prototype.initialize = function(onDone) { |
453 if (this.helloReceived_) { | 555 if (this.helloReceived_) { |
454 onDone(true); | 556 onDone(true); |
455 } else { | 557 } else { |
456 this.onInitializedCallback_ = onDone; | 558 this.onInitializedCallback_ = onDone; |
457 } | 559 } |
458 }; | 560 }; |
459 | 561 |
460 /** | 562 /** |
461 * @return {boolean} True if the plugin and web-app versions are compatible. | 563 * @return {boolean} True if the plugin and web-app versions are compatible. |
462 */ | 564 */ |
463 remoting.ClientPlugin.prototype.isSupportedVersion = function() { | 565 remoting.ClientPluginImpl.prototype.isSupportedVersion = function() { |
464 if (!this.helloReceived_) { | 566 if (!this.helloReceived_) { |
465 console.error( | 567 console.error( |
466 "isSupportedVersion() is called before the plugin is initialized."); | 568 "isSupportedVersion() is called before the plugin is initialized."); |
467 return false; | 569 return false; |
468 } | 570 } |
469 return this.API_VERSION_ >= this.pluginApiMinVersion_ && | 571 return this.API_VERSION_ >= this.pluginApiMinVersion_ && |
470 this.pluginApiVersion_ >= this.API_MIN_VERSION_; | 572 this.pluginApiVersion_ >= this.API_MIN_VERSION_; |
471 }; | 573 }; |
472 | 574 |
473 /** | 575 /** |
474 * @param {remoting.ClientPlugin.Feature} feature The feature to test for. | 576 * @param {remoting.ClientPlugin.Feature} feature The feature to test for. |
475 * @return {boolean} True if the plugin supports the named feature. | 577 * @return {boolean} True if the plugin supports the named feature. |
476 */ | 578 */ |
477 remoting.ClientPlugin.prototype.hasFeature = function(feature) { | 579 remoting.ClientPluginImpl.prototype.hasFeature = function(feature) { |
478 if (!this.helloReceived_) { | 580 if (!this.helloReceived_) { |
479 console.error( | 581 console.error( |
480 "hasFeature() is called before the plugin is initialized."); | 582 "hasFeature() is called before the plugin is initialized."); |
481 return false; | 583 return false; |
482 } | 584 } |
483 return this.pluginApiFeatures_.indexOf(feature) > -1; | 585 return this.pluginApiFeatures_.indexOf(feature) > -1; |
484 }; | 586 }; |
485 | 587 |
486 /** | 588 /** |
487 * @return {boolean} True if the plugin supports the injectKeyEvent API. | 589 * @return {boolean} True if the plugin supports the injectKeyEvent API. |
488 */ | 590 */ |
489 remoting.ClientPlugin.prototype.isInjectKeyEventSupported = function() { | 591 remoting.ClientPluginImpl.prototype.isInjectKeyEventSupported = function() { |
490 return this.pluginApiVersion_ >= 6; | 592 return this.pluginApiVersion_ >= 6; |
491 }; | 593 }; |
492 | 594 |
493 /** | 595 /** |
494 * @param {string} iq Incoming IQ stanza. | 596 * @param {string} iq Incoming IQ stanza. |
495 */ | 597 */ |
496 remoting.ClientPlugin.prototype.onIncomingIq = function(iq) { | 598 remoting.ClientPluginImpl.prototype.onIncomingIq = function(iq) { |
497 if (this.plugin_ && this.plugin_.postMessage) { | 599 if (this.plugin_ && this.plugin_.postMessage) { |
498 this.plugin_.postMessage(JSON.stringify( | 600 this.plugin_.postMessage(JSON.stringify( |
499 { method: 'incomingIq', data: { iq: iq } })); | 601 { method: 'incomingIq', data: { iq: iq } })); |
500 } else { | 602 } else { |
501 // plugin.onIq may not be set after the plugin has been shut | 603 // plugin.onIq may not be set after the plugin has been shut |
502 // down. Particularly this happens when we receive response to | 604 // down. Particularly this happens when we receive response to |
503 // session-terminate stanza. | 605 // session-terminate stanza. |
504 console.warn('plugin.onIq is not set so dropping incoming message.'); | 606 console.warn('plugin.onIq is not set so dropping incoming message.'); |
505 } | 607 } |
506 }; | 608 }; |
507 | 609 |
508 /** | 610 /** |
509 * @param {string} hostJid The jid of the host to connect to. | 611 * @param {string} hostJid The jid of the host to connect to. |
510 * @param {string} hostPublicKey The base64 encoded version of the host's | 612 * @param {string} hostPublicKey The base64 encoded version of the host's |
511 * public key. | 613 * public key. |
512 * @param {string} localJid Local jid. | 614 * @param {string} localJid Local jid. |
513 * @param {string} sharedSecret The access code for IT2Me or the PIN | 615 * @param {string} sharedSecret The access code for IT2Me or the PIN |
514 * for Me2Me. | 616 * for Me2Me. |
515 * @param {string} authenticationMethods Comma-separated list of | 617 * @param {string} authenticationMethods Comma-separated list of |
516 * authentication methods the client should attempt to use. | 618 * authentication methods the client should attempt to use. |
517 * @param {string} authenticationTag A host-specific tag to mix into | 619 * @param {string} authenticationTag A host-specific tag to mix into |
518 * authentication hashes. | 620 * authentication hashes. |
519 * @param {string} clientPairingId For paired Me2Me connections, the | 621 * @param {string} clientPairingId For paired Me2Me connections, the |
520 * pairing id for this client, as issued by the host. | 622 * pairing id for this client, as issued by the host. |
521 * @param {string} clientPairedSecret For paired Me2Me connections, the | 623 * @param {string} clientPairedSecret For paired Me2Me connections, the |
522 * paired secret for this client, as issued by the host. | 624 * paired secret for this client, as issued by the host. |
523 */ | 625 */ |
524 remoting.ClientPlugin.prototype.connect = function( | 626 remoting.ClientPluginImpl.prototype.connect = function( |
525 hostJid, hostPublicKey, localJid, sharedSecret, | 627 hostJid, hostPublicKey, localJid, sharedSecret, |
526 authenticationMethods, authenticationTag, | 628 authenticationMethods, authenticationTag, |
527 clientPairingId, clientPairedSecret) { | 629 clientPairingId, clientPairedSecret) { |
528 var keyFilter = ''; | 630 var keyFilter = ''; |
529 if (remoting.platformIsMac()) { | 631 if (remoting.platformIsMac()) { |
530 keyFilter = 'mac'; | 632 keyFilter = 'mac'; |
531 } else if (remoting.platformIsChromeOS()) { | 633 } else if (remoting.platformIsChromeOS()) { |
532 keyFilter = 'cros'; | 634 keyFilter = 'cros'; |
533 } | 635 } |
534 this.plugin_.postMessage(JSON.stringify( | 636 this.plugin_.postMessage(JSON.stringify( |
(...skipping 10 matching lines...) Expand all Loading... | |
545 clientPairingId: clientPairingId, | 647 clientPairingId: clientPairingId, |
546 clientPairedSecret: clientPairedSecret, | 648 clientPairedSecret: clientPairedSecret, |
547 keyFilter: keyFilter | 649 keyFilter: keyFilter |
548 } | 650 } |
549 })); | 651 })); |
550 }; | 652 }; |
551 | 653 |
552 /** | 654 /** |
553 * Release all currently pressed keys. | 655 * Release all currently pressed keys. |
554 */ | 656 */ |
555 remoting.ClientPlugin.prototype.releaseAllKeys = function() { | 657 remoting.ClientPluginImpl.prototype.releaseAllKeys = function() { |
556 this.plugin_.postMessage(JSON.stringify( | 658 this.plugin_.postMessage(JSON.stringify( |
557 { method: 'releaseAllKeys', data: {} })); | 659 { method: 'releaseAllKeys', data: {} })); |
558 }; | 660 }; |
559 | 661 |
560 /** | 662 /** |
561 * Send a key event to the host. | 663 * Send a key event to the host. |
562 * | 664 * |
563 * @param {number} usbKeycode The USB-style code of the key to inject. | 665 * @param {number} usbKeycode The USB-style code of the key to inject. |
564 * @param {boolean} pressed True to inject a key press, False for a release. | 666 * @param {boolean} pressed True to inject a key press, False for a release. |
565 */ | 667 */ |
566 remoting.ClientPlugin.prototype.injectKeyEvent = | 668 remoting.ClientPluginImpl.prototype.injectKeyEvent = |
567 function(usbKeycode, pressed) { | 669 function(usbKeycode, pressed) { |
568 this.plugin_.postMessage(JSON.stringify( | 670 this.plugin_.postMessage(JSON.stringify( |
569 { method: 'injectKeyEvent', data: { | 671 { method: 'injectKeyEvent', data: { |
570 'usbKeycode': usbKeycode, | 672 'usbKeycode': usbKeycode, |
571 'pressed': pressed} | 673 'pressed': pressed} |
572 })); | 674 })); |
573 }; | 675 }; |
574 | 676 |
575 /** | 677 /** |
576 * Remap one USB keycode to another in all subsequent key events. | 678 * Remap one USB keycode to another in all subsequent key events. |
577 * | 679 * |
578 * @param {number} fromKeycode The USB-style code of the key to remap. | 680 * @param {number} fromKeycode The USB-style code of the key to remap. |
579 * @param {number} toKeycode The USB-style code to remap the key to. | 681 * @param {number} toKeycode The USB-style code to remap the key to. |
580 */ | 682 */ |
581 remoting.ClientPlugin.prototype.remapKey = | 683 remoting.ClientPluginImpl.prototype.remapKey = |
582 function(fromKeycode, toKeycode) { | 684 function(fromKeycode, toKeycode) { |
583 this.plugin_.postMessage(JSON.stringify( | 685 this.plugin_.postMessage(JSON.stringify( |
584 { method: 'remapKey', data: { | 686 { method: 'remapKey', data: { |
585 'fromKeycode': fromKeycode, | 687 'fromKeycode': fromKeycode, |
586 'toKeycode': toKeycode} | 688 'toKeycode': toKeycode} |
587 })); | 689 })); |
588 }; | 690 }; |
589 | 691 |
590 /** | 692 /** |
591 * Enable/disable redirection of the specified key to the web-app. | 693 * Enable/disable redirection of the specified key to the web-app. |
592 * | 694 * |
593 * @param {number} keycode The USB-style code of the key. | 695 * @param {number} keycode The USB-style code of the key. |
594 * @param {Boolean} trap True to enable trapping, False to disable. | 696 * @param {Boolean} trap True to enable trapping, False to disable. |
595 */ | 697 */ |
596 remoting.ClientPlugin.prototype.trapKey = function(keycode, trap) { | 698 remoting.ClientPluginImpl.prototype.trapKey = function(keycode, trap) { |
597 this.plugin_.postMessage(JSON.stringify( | 699 this.plugin_.postMessage(JSON.stringify( |
598 { method: 'trapKey', data: { | 700 { method: 'trapKey', data: { |
599 'keycode': keycode, | 701 'keycode': keycode, |
600 'trap': trap} | 702 'trap': trap} |
601 })); | 703 })); |
602 }; | 704 }; |
603 | 705 |
604 /** | 706 /** |
605 * Returns an associative array with a set of stats for this connecton. | 707 * Returns an associative array with a set of stats for this connecton. |
606 * | 708 * |
607 * @return {remoting.ClientSession.PerfStats} The connection statistics. | 709 * @return {remoting.ClientSession.PerfStats} The connection statistics. |
608 */ | 710 */ |
609 remoting.ClientPlugin.prototype.getPerfStats = function() { | 711 remoting.ClientPluginImpl.prototype.getPerfStats = function() { |
610 return this.perfStats_; | 712 return this.perfStats_; |
611 }; | 713 }; |
612 | 714 |
613 /** | 715 /** |
614 * Sends a clipboard item to the host. | 716 * Sends a clipboard item to the host. |
615 * | 717 * |
616 * @param {string} mimeType The MIME type of the clipboard item. | 718 * @param {string} mimeType The MIME type of the clipboard item. |
617 * @param {string} item The clipboard item. | 719 * @param {string} item The clipboard item. |
618 */ | 720 */ |
619 remoting.ClientPlugin.prototype.sendClipboardItem = | 721 remoting.ClientPluginImpl.prototype.sendClipboardItem = |
620 function(mimeType, item) { | 722 function(mimeType, item) { |
621 if (!this.hasFeature(remoting.ClientPlugin.Feature.SEND_CLIPBOARD_ITEM)) | 723 if (!this.hasFeature(remoting.ClientPlugin.Feature.SEND_CLIPBOARD_ITEM)) |
622 return; | 724 return; |
623 this.plugin_.postMessage(JSON.stringify( | 725 this.plugin_.postMessage(JSON.stringify( |
624 { method: 'sendClipboardItem', | 726 { method: 'sendClipboardItem', |
625 data: { mimeType: mimeType, item: item }})); | 727 data: { mimeType: mimeType, item: item }})); |
626 }; | 728 }; |
627 | 729 |
628 /** | 730 /** |
629 * Notifies the host that the client has the specified size and pixel density. | 731 * Notifies the host that the client has the specified size and pixel density. |
630 * | 732 * |
631 * @param {number} width The available client width in DIPs. | 733 * @param {number} width The available client width in DIPs. |
632 * @param {number} height The available client height in DIPs. | 734 * @param {number} height The available client height in DIPs. |
633 * @param {number} device_scale The number of device pixels per DIP. | 735 * @param {number} device_scale The number of device pixels per DIP. |
634 */ | 736 */ |
635 remoting.ClientPlugin.prototype.notifyClientResolution = | 737 remoting.ClientPluginImpl.prototype.notifyClientResolution = |
636 function(width, height, device_scale) { | 738 function(width, height, device_scale) { |
637 if (this.hasFeature(remoting.ClientPlugin.Feature.NOTIFY_CLIENT_RESOLUTION)) { | 739 if (this.hasFeature(remoting.ClientPlugin.Feature.NOTIFY_CLIENT_RESOLUTION)) { |
638 var dpi = Math.floor(device_scale * 96); | 740 var dpi = Math.floor(device_scale * 96); |
639 this.plugin_.postMessage(JSON.stringify( | 741 this.plugin_.postMessage(JSON.stringify( |
640 { method: 'notifyClientResolution', | 742 { method: 'notifyClientResolution', |
641 data: { width: Math.floor(width * device_scale), | 743 data: { width: Math.floor(width * device_scale), |
642 height: Math.floor(height * device_scale), | 744 height: Math.floor(height * device_scale), |
643 x_dpi: dpi, y_dpi: dpi }})); | 745 x_dpi: dpi, y_dpi: dpi }})); |
644 } | 746 } |
645 }; | 747 }; |
646 | 748 |
647 /** | 749 /** |
648 * Requests that the host pause or resume sending video updates. | 750 * Requests that the host pause or resume sending video updates. |
649 * | 751 * |
650 * @param {boolean} pause True to suspend video updates, false otherwise. | 752 * @param {boolean} pause True to suspend video updates, false otherwise. |
651 */ | 753 */ |
652 remoting.ClientPlugin.prototype.pauseVideo = | 754 remoting.ClientPluginImpl.prototype.pauseVideo = |
653 function(pause) { | 755 function(pause) { |
654 if (this.hasFeature(remoting.ClientPlugin.Feature.VIDEO_CONTROL)) { | 756 if (this.hasFeature(remoting.ClientPlugin.Feature.VIDEO_CONTROL)) { |
655 this.plugin_.postMessage(JSON.stringify( | 757 this.plugin_.postMessage(JSON.stringify( |
656 { method: 'videoControl', data: { pause: pause }})); | 758 { method: 'videoControl', data: { pause: pause }})); |
657 } else if (this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_VIDEO)) { | 759 } else if (this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_VIDEO)) { |
658 this.plugin_.postMessage(JSON.stringify( | 760 this.plugin_.postMessage(JSON.stringify( |
659 { method: 'pauseVideo', data: { pause: pause }})); | 761 { method: 'pauseVideo', data: { pause: pause }})); |
660 } | 762 } |
661 }; | 763 }; |
662 | 764 |
663 /** | 765 /** |
664 * Requests that the host pause or resume sending audio updates. | 766 * Requests that the host pause or resume sending audio updates. |
665 * | 767 * |
666 * @param {boolean} pause True to suspend audio updates, false otherwise. | 768 * @param {boolean} pause True to suspend audio updates, false otherwise. |
667 */ | 769 */ |
668 remoting.ClientPlugin.prototype.pauseAudio = | 770 remoting.ClientPluginImpl.prototype.pauseAudio = |
669 function(pause) { | 771 function(pause) { |
670 if (!this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_AUDIO)) { | 772 if (!this.hasFeature(remoting.ClientPlugin.Feature.PAUSE_AUDIO)) { |
671 return; | 773 return; |
672 } | 774 } |
673 this.plugin_.postMessage(JSON.stringify( | 775 this.plugin_.postMessage(JSON.stringify( |
674 { method: 'pauseAudio', data: { pause: pause }})); | 776 { method: 'pauseAudio', data: { pause: pause }})); |
675 }; | 777 }; |
676 | 778 |
677 /** | 779 /** |
678 * Requests that the host configure the video codec for lossless encode. | 780 * Requests that the host configure the video codec for lossless encode. |
679 * | 781 * |
680 * @param {boolean} wantLossless True to request lossless encoding. | 782 * @param {boolean} wantLossless True to request lossless encoding. |
681 */ | 783 */ |
682 remoting.ClientPlugin.prototype.setLosslessEncode = | 784 remoting.ClientPluginImpl.prototype.setLosslessEncode = |
683 function(wantLossless) { | 785 function(wantLossless) { |
684 if (!this.hasFeature(remoting.ClientPlugin.Feature.VIDEO_CONTROL)) { | 786 if (!this.hasFeature(remoting.ClientPlugin.Feature.VIDEO_CONTROL)) { |
685 return; | 787 return; |
686 } | 788 } |
687 this.plugin_.postMessage(JSON.stringify( | 789 this.plugin_.postMessage(JSON.stringify( |
688 { method: 'videoControl', data: { losslessEncode: wantLossless }})); | 790 { method: 'videoControl', data: { losslessEncode: wantLossless }})); |
689 }; | 791 }; |
690 | 792 |
691 /** | 793 /** |
692 * Requests that the host configure the video codec for lossless color. | 794 * Requests that the host configure the video codec for lossless color. |
693 * | 795 * |
694 * @param {boolean} wantLossless True to request lossless color. | 796 * @param {boolean} wantLossless True to request lossless color. |
695 */ | 797 */ |
696 remoting.ClientPlugin.prototype.setLosslessColor = | 798 remoting.ClientPluginImpl.prototype.setLosslessColor = |
697 function(wantLossless) { | 799 function(wantLossless) { |
698 if (!this.hasFeature(remoting.ClientPlugin.Feature.VIDEO_CONTROL)) { | 800 if (!this.hasFeature(remoting.ClientPlugin.Feature.VIDEO_CONTROL)) { |
699 return; | 801 return; |
700 } | 802 } |
701 this.plugin_.postMessage(JSON.stringify( | 803 this.plugin_.postMessage(JSON.stringify( |
702 { method: 'videoControl', data: { losslessColor: wantLossless }})); | 804 { method: 'videoControl', data: { losslessColor: wantLossless }})); |
703 }; | 805 }; |
704 | 806 |
705 /** | 807 /** |
706 * Called when a PIN is obtained from the user. | 808 * Called when a PIN is obtained from the user. |
707 * | 809 * |
708 * @param {string} pin The PIN. | 810 * @param {string} pin The PIN. |
709 */ | 811 */ |
710 remoting.ClientPlugin.prototype.onPinFetched = | 812 remoting.ClientPluginImpl.prototype.onPinFetched = |
711 function(pin) { | 813 function(pin) { |
712 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) { | 814 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) { |
713 return; | 815 return; |
714 } | 816 } |
715 this.plugin_.postMessage(JSON.stringify( | 817 this.plugin_.postMessage(JSON.stringify( |
716 { method: 'onPinFetched', data: { pin: pin }})); | 818 { method: 'onPinFetched', data: { pin: pin }})); |
717 }; | 819 }; |
718 | 820 |
719 /** | 821 /** |
720 * Tells the plugin to ask for the PIN asynchronously. | 822 * Tells the plugin to ask for the PIN asynchronously. |
721 */ | 823 */ |
722 remoting.ClientPlugin.prototype.useAsyncPinDialog = | 824 remoting.ClientPluginImpl.prototype.useAsyncPinDialog = |
723 function() { | 825 function() { |
724 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) { | 826 if (!this.hasFeature(remoting.ClientPlugin.Feature.ASYNC_PIN)) { |
725 return; | 827 return; |
726 } | 828 } |
727 this.plugin_.postMessage(JSON.stringify( | 829 this.plugin_.postMessage(JSON.stringify( |
728 { method: 'useAsyncPinDialog', data: {} })); | 830 { method: 'useAsyncPinDialog', data: {} })); |
729 }; | 831 }; |
730 | 832 |
731 /** | 833 /** |
732 * Sets the third party authentication token and shared secret. | 834 * Sets the third party authentication token and shared secret. |
733 * | 835 * |
734 * @param {string} token The token received from the token URL. | 836 * @param {string} token The token received from the token URL. |
735 * @param {string} sharedSecret Shared secret received from the token URL. | 837 * @param {string} sharedSecret Shared secret received from the token URL. |
736 */ | 838 */ |
737 remoting.ClientPlugin.prototype.onThirdPartyTokenFetched = function( | 839 remoting.ClientPluginImpl.prototype.onThirdPartyTokenFetched = function( |
738 token, sharedSecret) { | 840 token, sharedSecret) { |
739 this.plugin_.postMessage(JSON.stringify( | 841 this.plugin_.postMessage(JSON.stringify( |
740 { method: 'onThirdPartyTokenFetched', | 842 { method: 'onThirdPartyTokenFetched', |
741 data: { token: token, sharedSecret: sharedSecret}})); | 843 data: { token: token, sharedSecret: sharedSecret}})); |
742 }; | 844 }; |
743 | 845 |
744 /** | 846 /** |
745 * Request pairing with the host for PIN-less authentication. | 847 * Request pairing with the host for PIN-less authentication. |
746 * | 848 * |
747 * @param {string} clientName The human-readable name of the client. | 849 * @param {string} clientName The human-readable name of the client. |
748 * @param {function(string, string):void} onDone, Callback to receive the | 850 * @param {function(string, string):void} onDone, Callback to receive the |
749 * client id and shared secret when they are available. | 851 * client id and shared secret when they are available. |
750 */ | 852 */ |
751 remoting.ClientPlugin.prototype.requestPairing = | 853 remoting.ClientPluginImpl.prototype.requestPairing = |
752 function(clientName, onDone) { | 854 function(clientName, onDone) { |
753 if (!this.hasFeature(remoting.ClientPlugin.Feature.PINLESS_AUTH)) { | 855 if (!this.hasFeature(remoting.ClientPlugin.Feature.PINLESS_AUTH)) { |
754 return; | 856 return; |
755 } | 857 } |
756 this.onPairingComplete_ = onDone; | 858 this.onPairingComplete_ = onDone; |
757 this.plugin_.postMessage(JSON.stringify( | 859 this.plugin_.postMessage(JSON.stringify( |
758 { method: 'requestPairing', data: { clientName: clientName } })); | 860 { method: 'requestPairing', data: { clientName: clientName } })); |
759 }; | 861 }; |
760 | 862 |
761 /** | 863 /** |
762 * Send an extension message to the host. | 864 * Send an extension message to the host. |
763 * | 865 * |
764 * @param {string} type The message type. | 866 * @param {string} type The message type. |
765 * @param {string} message The message payload. | 867 * @param {string} message The message payload. |
766 */ | 868 */ |
767 remoting.ClientPlugin.prototype.sendClientMessage = | 869 remoting.ClientPluginImpl.prototype.sendClientMessage = |
768 function(type, message) { | 870 function(type, message) { |
769 if (!this.hasFeature(remoting.ClientPlugin.Feature.EXTENSION_MESSAGE)) { | 871 if (!this.hasFeature(remoting.ClientPlugin.Feature.EXTENSION_MESSAGE)) { |
770 return; | 872 return; |
771 } | 873 } |
772 this.plugin_.postMessage(JSON.stringify( | 874 this.plugin_.postMessage(JSON.stringify( |
773 { method: 'extensionMessage', | 875 { method: 'extensionMessage', |
774 data: { type: type, data: message } })); | 876 data: { type: type, data: message } })); |
775 | 877 |
776 }; | 878 }; |
777 | 879 |
778 /** | 880 /** |
779 * Request MediaStream-based rendering. | 881 * Request MediaStream-based rendering. |
780 * | 882 * |
781 * @param {remoting.MediaSourceRenderer} mediaSourceRenderer | 883 * @param {remoting.MediaSourceRenderer} mediaSourceRenderer |
782 */ | 884 */ |
783 remoting.ClientPlugin.prototype.enableMediaSourceRendering = | 885 remoting.ClientPluginImpl.prototype.enableMediaSourceRendering = |
784 function(mediaSourceRenderer) { | 886 function(mediaSourceRenderer) { |
785 if (!this.hasFeature(remoting.ClientPlugin.Feature.MEDIA_SOURCE_RENDERING)) { | 887 if (!this.hasFeature(remoting.ClientPlugin.Feature.MEDIA_SOURCE_RENDERING)) { |
786 return; | 888 return; |
787 } | 889 } |
788 this.mediaSourceRenderer_ = mediaSourceRenderer; | 890 this.mediaSourceRenderer_ = mediaSourceRenderer; |
789 this.plugin_.postMessage(JSON.stringify( | 891 this.plugin_.postMessage(JSON.stringify( |
790 { method: 'enableMediaSourceRendering', data: {} })); | 892 { method: 'enableMediaSourceRendering', data: {} })); |
791 }; | 893 }; |
792 | 894 |
895 remoting.ClientPluginImpl.prototype.getDesktopWidth = function() { | |
896 return this.desktopWidth_; | |
897 } | |
898 | |
899 remoting.ClientPluginImpl.prototype.getDesktopHeight = function() { | |
900 return this.desktopHeight_; | |
901 } | |
902 | |
903 remoting.ClientPluginImpl.prototype.getDesktopXDpi = function() { | |
904 return this.desktopXDpi_; | |
905 } | |
906 | |
907 remoting.ClientPluginImpl.prototype.getDesktopYDpi = function() { | |
908 return this.desktopYDpi_; | |
909 } | |
910 | |
793 /** | 911 /** |
794 * If we haven't yet received a "hello" message from the plugin, change its | 912 * If we haven't yet received a "hello" message from the plugin, change its |
795 * size so that the user can confirm it if click-to-play is enabled, or can | 913 * size so that the user can confirm it if click-to-play is enabled, or can |
796 * see the "this plugin is disabled" message if it is actually disabled. | 914 * see the "this plugin is disabled" message if it is actually disabled. |
797 * @private | 915 * @private |
798 */ | 916 */ |
799 remoting.ClientPlugin.prototype.showPluginForClickToPlay_ = function() { | 917 remoting.ClientPluginImpl.prototype.showPluginForClickToPlay_ = function() { |
800 if (!this.helloReceived_) { | 918 if (!this.helloReceived_) { |
801 var width = 200; | 919 var width = 200; |
802 var height = 200; | 920 var height = 200; |
803 this.plugin_.style.width = width + 'px'; | 921 this.plugin_.style.width = width + 'px'; |
804 this.plugin_.style.height = height + 'px'; | 922 this.plugin_.style.height = height + 'px'; |
805 // Center the plugin just underneath the "Connnecting..." dialog. | 923 // Center the plugin just underneath the "Connnecting..." dialog. |
806 var dialog = document.getElementById('client-dialog'); | 924 var dialog = document.getElementById('client-dialog'); |
807 var dialogRect = dialog.getBoundingClientRect(); | 925 var dialogRect = dialog.getBoundingClientRect(); |
808 this.plugin_.style.top = (dialogRect.bottom + 16) + 'px'; | 926 this.plugin_.style.top = (dialogRect.bottom + 16) + 'px'; |
809 this.plugin_.style.left = (window.innerWidth - width) / 2 + 'px'; | 927 this.plugin_.style.left = (window.innerWidth - width) / 2 + 'px'; |
810 this.plugin_.style.position = 'fixed'; | 928 this.plugin_.style.position = 'fixed'; |
811 } | 929 } |
812 }; | 930 }; |
813 | 931 |
814 /** | 932 /** |
815 * Undo the CSS rules needed to make the plugin clickable for click-to-play. | 933 * Undo the CSS rules needed to make the plugin clickable for click-to-play. |
816 * @private | 934 * @private |
817 */ | 935 */ |
818 remoting.ClientPlugin.prototype.hidePluginForClickToPlay_ = function() { | 936 remoting.ClientPluginImpl.prototype.hidePluginForClickToPlay_ = function() { |
819 this.plugin_.style.width = ''; | 937 this.plugin_.style.width = ''; |
820 this.plugin_.style.height = ''; | 938 this.plugin_.style.height = ''; |
821 this.plugin_.style.top = ''; | 939 this.plugin_.style.top = ''; |
822 this.plugin_.style.left = ''; | 940 this.plugin_.style.left = ''; |
823 this.plugin_.style.position = ''; | 941 this.plugin_.style.position = ''; |
824 }; | 942 }; |
943 | |
944 | |
945 /** | |
946 * @constructor | |
947 * @implements {remoting.ClientPluginFactory} | |
948 */ | |
949 remoting.DefaultClientPluginFactory = function() {}; | |
950 | |
951 /** | |
952 * @param {Element} container | |
953 * @param {function(string, string):boolean} onExtensionMessage | |
954 * @return {remoting.ClientPlugin} | |
955 */ | |
956 remoting.DefaultClientPluginFactory.prototype.createPlugin = | |
957 function(container, onExtensionMessage) { | |
958 return new remoting.ClientPluginImpl(container, onExtensionMessage); | |
959 }; | |
960 | |
961 remoting.DefaultClientPluginFactory.prototype.preloadPlugin = function() { | |
962 if (remoting.settings.CLIENT_PLUGIN_TYPE != 'pnacl') { | |
963 return; | |
964 } | |
965 | |
966 var plugin = remoting.ClientPluginImpl.createPluginElement_(); | |
967 plugin.addEventListener( | |
968 'loadend', function() { document.body.removeChild(plugin); }, false); | |
969 document.body.appendChild(plugin); | |
970 }; | |
OLD | NEW |