OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 /** | 5 /** |
6 * @fileoverview | 6 * @fileoverview |
7 * This class provides an interface between the HostController and either the | 7 * This class provides an interface between the HostController and either the |
8 * NativeMessaging Host. | 8 * NativeMessaging Host or the Host NPAPI plugin, depending on whether or not |
| 9 * NativeMessaging is supported. Since the test for NativeMessaging support is |
| 10 * asynchronous, this class stores any requests on a queue, pending the result |
| 11 * of the test. |
| 12 * Once the test is complete, the pending requests are performed on either the |
| 13 * NativeMessaging host, or the NPAPI plugin. |
| 14 * |
| 15 * If necessary, the HostController is instructed (via a callback) to |
| 16 * instantiate the NPAPI plugin, and return a reference to it here. |
9 */ | 17 */ |
10 | 18 |
11 'use strict'; | 19 'use strict'; |
12 | 20 |
13 /** @suppress {duplicate} */ | 21 /** @suppress {duplicate} */ |
14 var remoting = remoting || {}; | 22 var remoting = remoting || {}; |
15 | 23 |
16 /** | 24 /** |
17 * @constructor | 25 * @constructor |
| 26 * @param {function():remoting.HostPlugin} createPluginCallback Callback to |
| 27 * instantiate the NPAPI plugin when NativeMessaging is determined to be |
| 28 * unsupported. |
18 */ | 29 */ |
19 remoting.HostDispatcher = function() { | 30 remoting.HostDispatcher = function(createPluginCallback) { |
20 /** @type {remoting.HostNativeMessaging} @private */ | 31 /** @type {remoting.HostNativeMessaging} @private */ |
21 this.nativeMessagingHost_ = new remoting.HostNativeMessaging(); | 32 this.nativeMessagingHost_ = new remoting.HostNativeMessaging(); |
22 | 33 |
| 34 /** @type {remoting.HostPlugin} @private */ |
| 35 this.npapiHost_ = null; |
| 36 |
23 /** @type {remoting.HostDispatcher.State} @private */ | 37 /** @type {remoting.HostDispatcher.State} @private */ |
24 this.state_ = remoting.HostDispatcher.State.UNKNOWN; | 38 this.state_ = remoting.HostDispatcher.State.UNKNOWN; |
25 | 39 |
26 /** @type {Array.<function()>} @private */ | 40 /** @type {Array.<function()>} @private */ |
27 this.pendingRequests_ = []; | 41 this.pendingRequests_ = []; |
28 | 42 |
| 43 /** @type {function():remoting.HostPlugin} @private */ |
| 44 this.createPluginCallback_ = createPluginCallback; |
| 45 |
29 this.tryToInitialize_(); | 46 this.tryToInitialize_(); |
30 } | 47 } |
31 | 48 |
32 /** @enum {number} */ | 49 /** @enum {number} */ |
33 remoting.HostDispatcher.State = { | 50 remoting.HostDispatcher.State = { |
34 UNKNOWN: 0, | 51 UNKNOWN: 0, |
35 NATIVE_MESSAGING: 1, | 52 NATIVE_MESSAGING: 1, |
36 NOT_INSTALLED: 2 | 53 NPAPI: 2, |
| 54 NOT_INSTALLED: 3 |
37 }; | 55 }; |
38 | 56 |
39 remoting.HostDispatcher.prototype.tryToInitialize_ = function() { | 57 remoting.HostDispatcher.prototype.tryToInitialize_ = function() { |
40 /** @type {remoting.HostDispatcher} */ | 58 /** @type {remoting.HostDispatcher} */ |
41 var that = this; | 59 var that = this; |
42 | 60 |
43 if (this.state_ != remoting.HostDispatcher.State.UNKNOWN) | 61 if (this.state_ != remoting.HostDispatcher.State.UNKNOWN) |
44 return; | 62 return; |
45 | 63 |
46 function sendPendingRequests() { | 64 function sendPendingRequests() { |
47 var pendingRequests = that.pendingRequests_; | 65 var pendingRequests = that.pendingRequests_; |
48 that.pendingRequests_ = []; | 66 that.pendingRequests_ = []; |
49 for (var i = 0; i < pendingRequests.length; i++) { | 67 for (var i = 0; i < pendingRequests.length; i++) { |
50 pendingRequests[i](); | 68 pendingRequests[i](); |
51 } | 69 } |
52 } | 70 } |
53 | 71 |
54 function onNativeMessagingInit() { | 72 function onNativeMessagingInit() { |
55 that.state_ = remoting.HostDispatcher.State.NATIVE_MESSAGING; | 73 that.state_ = remoting.HostDispatcher.State.NATIVE_MESSAGING; |
56 sendPendingRequests(); | 74 sendPendingRequests(); |
57 } | 75 } |
58 | 76 |
59 function onNativeMessagingFailed(error) { | 77 function onNativeMessagingFailed(error) { |
60 that.state_ = remoting.HostDispatcher.State.NOT_INSTALLED; | 78 that.npapiHost_ = that.createPluginCallback_(); |
| 79 |
| 80 that.state_ = that.npapiHost_ ? remoting.HostDispatcher.State.NPAPI |
| 81 : remoting.HostDispatcher.State.NOT_INSTALLED; |
61 sendPendingRequests(); | 82 sendPendingRequests(); |
62 } | 83 } |
63 | 84 |
64 this.nativeMessagingHost_.initialize(onNativeMessagingInit, | 85 this.nativeMessagingHost_.initialize(onNativeMessagingInit, |
65 onNativeMessagingFailed); | 86 onNativeMessagingFailed); |
66 }; | 87 }; |
67 | 88 |
68 /** | 89 /** |
| 90 * @return {remoting.HostPlugin} |
| 91 */ |
| 92 remoting.HostDispatcher.prototype.getNpapiHost = function() { |
| 93 return this.npapiHost_; |
| 94 } |
| 95 |
| 96 /** |
69 * @param {remoting.HostController.Feature} feature The feature to test for. | 97 * @param {remoting.HostController.Feature} feature The feature to test for. |
70 * @param {function(boolean):void} onDone | 98 * @param {function(boolean):void} onDone |
71 * @return {void} | 99 * @return {void} |
72 */ | 100 */ |
73 remoting.HostDispatcher.prototype.hasFeature = function( | 101 remoting.HostDispatcher.prototype.hasFeature = function( |
74 feature, onDone) { | 102 feature, onDone) { |
75 switch (this.state_) { | 103 switch (this.state_) { |
76 case remoting.HostDispatcher.State.UNKNOWN: | 104 case remoting.HostDispatcher.State.UNKNOWN: |
77 this.pendingRequests_.push( | 105 this.pendingRequests_.push( |
78 this.hasFeature.bind(this, feature, onDone)); | 106 this.hasFeature.bind(this, feature, onDone)); |
79 break; | 107 break; |
80 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 108 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
81 onDone(this.nativeMessagingHost_.hasFeature(feature)); | 109 onDone(this.nativeMessagingHost_.hasFeature(feature)); |
82 break; | 110 break; |
| 111 case remoting.HostDispatcher.State.NPAPI: |
| 112 // If this is an old NPAPI plugin that doesn't list supportedFeatures, |
| 113 // assume it is an old plugin that doesn't support any new feature. |
| 114 var supportedFeatures = []; |
| 115 if (typeof(this.npapiHost_.supportedFeatures) == 'string') { |
| 116 supportedFeatures = this.npapiHost_.supportedFeatures.split(' '); |
| 117 } |
| 118 onDone(supportedFeatures.indexOf(feature) >= 0); |
| 119 break; |
83 case remoting.HostDispatcher.State.NOT_INSTALLED: | 120 case remoting.HostDispatcher.State.NOT_INSTALLED: |
84 onDone(false); | 121 onDone(false); |
85 break; | 122 break; |
86 } | 123 } |
87 }; | 124 }; |
88 | 125 |
89 /** | 126 /** |
90 * @param {function(string):void} onDone | 127 * @param {function(string):void} onDone |
91 * @param {function(remoting.Error):void} onError | 128 * @param {function(remoting.Error):void} onError |
92 * @return {void} | 129 * @return {void} |
93 */ | 130 */ |
94 remoting.HostDispatcher.prototype.getHostName = function(onDone, onError) { | 131 remoting.HostDispatcher.prototype.getHostName = function(onDone, onError) { |
95 switch (this.state_) { | 132 switch (this.state_) { |
96 case remoting.HostDispatcher.State.UNKNOWN: | 133 case remoting.HostDispatcher.State.UNKNOWN: |
97 this.pendingRequests_.push( | 134 this.pendingRequests_.push( |
98 this.getHostName.bind(this, onDone, onError)); | 135 this.getHostName.bind(this, onDone, onError)); |
99 break; | 136 break; |
100 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 137 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
101 this.nativeMessagingHost_.getHostName(onDone, onError); | 138 this.nativeMessagingHost_.getHostName(onDone, onError); |
102 break; | 139 break; |
| 140 case remoting.HostDispatcher.State.NPAPI: |
| 141 try { |
| 142 this.npapiHost_.getHostName(onDone); |
| 143 } catch (err) { |
| 144 onError(remoting.Error.MISSING_PLUGIN); |
| 145 } |
| 146 break; |
103 case remoting.HostDispatcher.State.NOT_INSTALLED: | 147 case remoting.HostDispatcher.State.NOT_INSTALLED: |
104 onError(remoting.Error.MISSING_PLUGIN); | 148 onError(remoting.Error.MISSING_PLUGIN); |
105 break; | 149 break; |
106 } | 150 } |
107 }; | 151 }; |
108 | 152 |
109 /** | 153 /** |
110 * @param {string} hostId | 154 * @param {string} hostId |
111 * @param {string} pin | 155 * @param {string} pin |
112 * @param {function(string):void} onDone | 156 * @param {function(string):void} onDone |
113 * @param {function(remoting.Error):void} onError | 157 * @param {function(remoting.Error):void} onError |
114 * @return {void} | 158 * @return {void} |
115 */ | 159 */ |
116 remoting.HostDispatcher.prototype.getPinHash = | 160 remoting.HostDispatcher.prototype.getPinHash = |
117 function(hostId, pin, onDone, onError) { | 161 function(hostId, pin, onDone, onError) { |
118 switch (this.state_) { | 162 switch (this.state_) { |
119 case remoting.HostDispatcher.State.UNKNOWN: | 163 case remoting.HostDispatcher.State.UNKNOWN: |
120 this.pendingRequests_.push( | 164 this.pendingRequests_.push( |
121 this.getPinHash.bind(this, hostId, pin, onDone, onError)); | 165 this.getPinHash.bind(this, hostId, pin, onDone, onError)); |
122 break; | 166 break; |
123 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 167 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
124 this.nativeMessagingHost_.getPinHash(hostId, pin, onDone, onError); | 168 this.nativeMessagingHost_.getPinHash(hostId, pin, onDone, onError); |
125 break; | 169 break; |
| 170 case remoting.HostDispatcher.State.NPAPI: |
| 171 try { |
| 172 this.npapiHost_.getPinHash(hostId, pin, onDone); |
| 173 } catch (err) { |
| 174 onError(remoting.Error.MISSING_PLUGIN); |
| 175 } |
| 176 break; |
126 case remoting.HostDispatcher.State.NOT_INSTALLED: | 177 case remoting.HostDispatcher.State.NOT_INSTALLED: |
127 onError(remoting.Error.MISSING_PLUGIN); | 178 onError(remoting.Error.MISSING_PLUGIN); |
128 break; | 179 break; |
129 } | 180 } |
130 }; | 181 }; |
131 | 182 |
132 /** | 183 /** |
133 * @param {function(string, string):void} onDone | 184 * @param {function(string, string):void} onDone |
134 * @param {function(remoting.Error):void} onError | 185 * @param {function(remoting.Error):void} onError |
135 * @return {void} | 186 * @return {void} |
136 */ | 187 */ |
137 remoting.HostDispatcher.prototype.generateKeyPair = function(onDone, onError) { | 188 remoting.HostDispatcher.prototype.generateKeyPair = function(onDone, onError) { |
138 switch (this.state_) { | 189 switch (this.state_) { |
139 case remoting.HostDispatcher.State.UNKNOWN: | 190 case remoting.HostDispatcher.State.UNKNOWN: |
140 this.pendingRequests_.push( | 191 this.pendingRequests_.push( |
141 this.generateKeyPair.bind(this, onDone, onError)); | 192 this.generateKeyPair.bind(this, onDone, onError)); |
142 break; | 193 break; |
143 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 194 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
144 this.nativeMessagingHost_.generateKeyPair(onDone, onError); | 195 this.nativeMessagingHost_.generateKeyPair(onDone, onError); |
145 break; | 196 break; |
| 197 case remoting.HostDispatcher.State.NPAPI: |
| 198 try { |
| 199 this.npapiHost_.generateKeyPair(onDone); |
| 200 } catch (err) { |
| 201 onError(remoting.Error.MISSING_PLUGIN); |
| 202 } |
| 203 break; |
146 case remoting.HostDispatcher.State.NOT_INSTALLED: | 204 case remoting.HostDispatcher.State.NOT_INSTALLED: |
147 onError(remoting.Error.MISSING_PLUGIN); | 205 onError(remoting.Error.MISSING_PLUGIN); |
148 break; | 206 break; |
149 } | 207 } |
150 }; | 208 }; |
151 | 209 |
152 /** | 210 /** |
153 * @param {Object} config | 211 * @param {Object} config |
154 * @param {function(remoting.HostController.AsyncResult):void} onDone | 212 * @param {function(remoting.HostController.AsyncResult):void} onDone |
155 * @param {function(remoting.Error):void} onError | 213 * @param {function(remoting.Error):void} onError |
156 * @return {void} | 214 * @return {void} |
157 */ | 215 */ |
158 remoting.HostDispatcher.prototype.updateDaemonConfig = | 216 remoting.HostDispatcher.prototype.updateDaemonConfig = |
159 function(config, onDone, onError) { | 217 function(config, onDone, onError) { |
160 switch (this.state_) { | 218 switch (this.state_) { |
161 case remoting.HostDispatcher.State.UNKNOWN: | 219 case remoting.HostDispatcher.State.UNKNOWN: |
162 this.pendingRequests_.push( | 220 this.pendingRequests_.push( |
163 this.updateDaemonConfig.bind(this, config, onDone, onError)); | 221 this.updateDaemonConfig.bind(this, config, onDone, onError)); |
164 break; | 222 break; |
165 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 223 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
166 this.nativeMessagingHost_.updateDaemonConfig(config, onDone, onError); | 224 this.nativeMessagingHost_.updateDaemonConfig(config, onDone, onError); |
167 break; | 225 break; |
| 226 case remoting.HostDispatcher.State.NPAPI: |
| 227 try { |
| 228 this.npapiHost_.updateDaemonConfig(JSON.stringify(config), onDone); |
| 229 } catch (err) { |
| 230 onError(remoting.Error.MISSING_PLUGIN); |
| 231 } |
| 232 break; |
168 case remoting.HostDispatcher.State.NOT_INSTALLED: | 233 case remoting.HostDispatcher.State.NOT_INSTALLED: |
169 onError(remoting.Error.MISSING_PLUGIN); | 234 onError(remoting.Error.MISSING_PLUGIN); |
170 break; | 235 break; |
171 } | 236 } |
172 }; | 237 }; |
173 | 238 |
174 /** | 239 /** |
175 * @param {function(Object):void} onDone | 240 * @param {function(Object):void} onDone |
176 * @param {function(remoting.Error):void} onError | 241 * @param {function(remoting.Error):void} onError |
177 * @return {void} | 242 * @return {void} |
178 */ | 243 */ |
179 remoting.HostDispatcher.prototype.getDaemonConfig = function(onDone, onError) { | 244 remoting.HostDispatcher.prototype.getDaemonConfig = function(onDone, onError) { |
| 245 /** |
| 246 * Converts the config string from the NPAPI plugin to an Object, to pass to |
| 247 * |onDone|. |
| 248 * @param {string} configStr |
| 249 * @return {void} |
| 250 */ |
| 251 function callbackForNpapi(configStr) { |
| 252 var config = jsonParseSafe(configStr); |
| 253 if (typeof(config) != 'object') { |
| 254 onError(remoting.Error.UNEXPECTED); |
| 255 } else { |
| 256 onDone(/** @type {Object} */ (config)); |
| 257 } |
| 258 } |
| 259 |
180 switch (this.state_) { | 260 switch (this.state_) { |
181 case remoting.HostDispatcher.State.UNKNOWN: | 261 case remoting.HostDispatcher.State.UNKNOWN: |
182 this.pendingRequests_.push( | 262 this.pendingRequests_.push( |
183 this.getDaemonConfig.bind(this, onDone, onError)); | 263 this.getDaemonConfig.bind(this, onDone, onError)); |
184 break; | 264 break; |
185 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 265 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
186 this.nativeMessagingHost_.getDaemonConfig(onDone, onError); | 266 this.nativeMessagingHost_.getDaemonConfig(onDone, onError); |
187 break; | 267 break; |
| 268 case remoting.HostDispatcher.State.NPAPI: |
| 269 try { |
| 270 this.npapiHost_.getDaemonConfig(callbackForNpapi); |
| 271 } catch (err) { |
| 272 onError(remoting.Error.MISSING_PLUGIN); |
| 273 } |
| 274 break; |
188 case remoting.HostDispatcher.State.NOT_INSTALLED: | 275 case remoting.HostDispatcher.State.NOT_INSTALLED: |
189 onDone({}); | 276 onDone({}); |
190 break; | 277 break; |
191 } | 278 } |
192 }; | 279 }; |
193 | 280 |
194 /** | 281 /** |
195 * @param {function(string):void} onDone | 282 * @param {function(string):void} onDone |
196 * @param {function(remoting.Error):void} onError | 283 * @param {function(remoting.Error):void} onError |
197 * @return {void} | 284 * @return {void} |
198 */ | 285 */ |
199 remoting.HostDispatcher.prototype.getDaemonVersion = function(onDone, onError) { | 286 remoting.HostDispatcher.prototype.getDaemonVersion = function(onDone, onError) { |
200 switch (this.state_) { | 287 switch (this.state_) { |
201 case remoting.HostDispatcher.State.UNKNOWN: | 288 case remoting.HostDispatcher.State.UNKNOWN: |
202 this.pendingRequests_.push( | 289 this.pendingRequests_.push( |
203 this.getDaemonVersion.bind(this, onDone, onError)); | 290 this.getDaemonVersion.bind(this, onDone, onError)); |
204 break; | 291 break; |
205 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 292 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
206 onDone(this.nativeMessagingHost_.getDaemonVersion()); | 293 onDone(this.nativeMessagingHost_.getDaemonVersion()); |
207 break; | 294 break; |
| 295 case remoting.HostDispatcher.State.NPAPI: |
| 296 try { |
| 297 this.npapiHost_.getDaemonVersion(onDone); |
| 298 } catch (err) { |
| 299 onError(remoting.Error.MISSING_PLUGIN); |
| 300 } |
| 301 break; |
208 case remoting.HostDispatcher.State.NOT_INSTALLED: | 302 case remoting.HostDispatcher.State.NOT_INSTALLED: |
209 onError(remoting.Error.MISSING_PLUGIN); | 303 onError(remoting.Error.MISSING_PLUGIN); |
210 break; | 304 break; |
211 } | 305 } |
212 }; | 306 }; |
213 | 307 |
214 /** | 308 /** |
215 * @param {function(boolean, boolean, boolean):void} onDone | 309 * @param {function(boolean, boolean, boolean):void} onDone |
216 * @param {function(remoting.Error):void} onError | 310 * @param {function(remoting.Error):void} onError |
217 * @return {void} | 311 * @return {void} |
218 */ | 312 */ |
219 remoting.HostDispatcher.prototype.getUsageStatsConsent = | 313 remoting.HostDispatcher.prototype.getUsageStatsConsent = |
220 function(onDone, onError) { | 314 function(onDone, onError) { |
221 switch (this.state_) { | 315 switch (this.state_) { |
222 case remoting.HostDispatcher.State.UNKNOWN: | 316 case remoting.HostDispatcher.State.UNKNOWN: |
223 this.pendingRequests_.push( | 317 this.pendingRequests_.push( |
224 this.getUsageStatsConsent.bind(this, onDone, onError)); | 318 this.getUsageStatsConsent.bind(this, onDone, onError)); |
225 break; | 319 break; |
226 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 320 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
227 this.nativeMessagingHost_.getUsageStatsConsent(onDone, onError); | 321 this.nativeMessagingHost_.getUsageStatsConsent(onDone, onError); |
228 break; | 322 break; |
| 323 case remoting.HostDispatcher.State.NPAPI: |
| 324 try { |
| 325 this.npapiHost_.getUsageStatsConsent(onDone); |
| 326 } catch (err) { |
| 327 onError(remoting.Error.MISSING_PLUGIN); |
| 328 } |
| 329 break; |
229 case remoting.HostDispatcher.State.NOT_INSTALLED: | 330 case remoting.HostDispatcher.State.NOT_INSTALLED: |
230 onError(remoting.Error.MISSING_PLUGIN); | 331 onError(remoting.Error.MISSING_PLUGIN); |
| 332 break; |
| 333 } |
| 334 }; |
| 335 |
| 336 /** |
| 337 * This function installs the host using the NPAPI plugin and should only be |
| 338 * called on Windows. |
| 339 * |
| 340 * @param {function(remoting.HostController.AsyncResult):void} onDone |
| 341 * @param {function(remoting.Error):void} onError |
| 342 * @return {void} |
| 343 */ |
| 344 remoting.HostDispatcher.prototype.installHost = function(onDone, onError) { |
| 345 switch (this.state_) { |
| 346 case remoting.HostDispatcher.State.UNKNOWN: |
| 347 this.pendingRequests_.push(this.installHost.bind(this, onDone, onError)); |
| 348 break; |
| 349 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
| 350 // Host already installed, no action needed. |
| 351 onDone(remoting.HostController.AsyncResult.OK); |
| 352 break; |
| 353 case remoting.HostDispatcher.State.NPAPI: |
| 354 try { |
| 355 this.npapiHost_.installHost(onDone); |
| 356 } catch (err) { |
| 357 onError(remoting.Error.MISSING_PLUGIN); |
| 358 } |
| 359 break; |
| 360 case remoting.HostDispatcher.State.NOT_INSTALLED: |
| 361 onError(remoting.Error.MISSING_PLUGIN); |
231 break; | 362 break; |
232 } | 363 } |
233 }; | 364 }; |
234 | 365 |
235 /** | 366 /** |
236 * @param {Object} config | 367 * @param {Object} config |
237 * @param {boolean} consent | 368 * @param {boolean} consent |
238 * @param {function(remoting.HostController.AsyncResult):void} onDone | 369 * @param {function(remoting.HostController.AsyncResult):void} onDone |
239 * @param {function(remoting.Error):void} onError | 370 * @param {function(remoting.Error):void} onError |
240 * @return {void} | 371 * @return {void} |
241 */ | 372 */ |
242 remoting.HostDispatcher.prototype.startDaemon = | 373 remoting.HostDispatcher.prototype.startDaemon = |
243 function(config, consent, onDone, onError) { | 374 function(config, consent, onDone, onError) { |
244 switch (this.state_) { | 375 switch (this.state_) { |
245 case remoting.HostDispatcher.State.UNKNOWN: | 376 case remoting.HostDispatcher.State.UNKNOWN: |
246 this.pendingRequests_.push( | 377 this.pendingRequests_.push( |
247 this.startDaemon.bind(this, config, consent, onDone, onError)); | 378 this.startDaemon.bind(this, config, consent, onDone, onError)); |
248 break; | 379 break; |
249 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 380 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
250 this.nativeMessagingHost_.startDaemon(config, consent, onDone, onError); | 381 this.nativeMessagingHost_.startDaemon(config, consent, onDone, onError); |
251 break; | 382 break; |
| 383 case remoting.HostDispatcher.State.NPAPI: |
| 384 try { |
| 385 this.npapiHost_.startDaemon(JSON.stringify(config), consent, onDone); |
| 386 } catch (err) { |
| 387 onError(remoting.Error.MISSING_PLUGIN); |
| 388 } |
| 389 break; |
252 case remoting.HostDispatcher.State.NOT_INSTALLED: | 390 case remoting.HostDispatcher.State.NOT_INSTALLED: |
253 onError(remoting.Error.MISSING_PLUGIN); | 391 onError(remoting.Error.MISSING_PLUGIN); |
254 break; | 392 break; |
255 } | 393 } |
256 }; | 394 }; |
257 | 395 |
258 /** | 396 /** |
259 * @param {function(remoting.HostController.AsyncResult):void} onDone | 397 * @param {function(remoting.HostController.AsyncResult):void} onDone |
260 * @param {function(remoting.Error):void} onError | 398 * @param {function(remoting.Error):void} onError |
261 * @return {void} | 399 * @return {void} |
262 */ | 400 */ |
263 remoting.HostDispatcher.prototype.stopDaemon = function(onDone, onError) { | 401 remoting.HostDispatcher.prototype.stopDaemon = function(onDone, onError) { |
264 switch (this.state_) { | 402 switch (this.state_) { |
265 case remoting.HostDispatcher.State.UNKNOWN: | 403 case remoting.HostDispatcher.State.UNKNOWN: |
266 this.pendingRequests_.push(this.stopDaemon.bind(this, onDone, onError)); | 404 this.pendingRequests_.push(this.stopDaemon.bind(this, onDone, onError)); |
267 break; | 405 break; |
268 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 406 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
269 this.nativeMessagingHost_.stopDaemon(onDone, onError); | 407 this.nativeMessagingHost_.stopDaemon(onDone, onError); |
270 break; | 408 break; |
| 409 case remoting.HostDispatcher.State.NPAPI: |
| 410 try { |
| 411 this.npapiHost_.stopDaemon(onDone); |
| 412 } catch (err) { |
| 413 onError(remoting.Error.MISSING_PLUGIN); |
| 414 } |
| 415 break; |
271 case remoting.HostDispatcher.State.NOT_INSTALLED: | 416 case remoting.HostDispatcher.State.NOT_INSTALLED: |
272 onError(remoting.Error.MISSING_PLUGIN); | 417 onError(remoting.Error.MISSING_PLUGIN); |
273 break; | 418 break; |
274 } | 419 } |
275 }; | 420 }; |
276 | 421 |
277 /** | 422 /** |
278 * @param {function(remoting.HostController.State):void} onDone | 423 * @param {function(remoting.HostController.State):void} onDone |
279 * @param {function(remoting.Error):void} onError | 424 * @param {function(remoting.Error):void} onError |
280 * @return {void} | 425 * @return {void} |
(...skipping 17 matching lines...) Expand all Loading... |
298 remoting.HostDispatcher.prototype.getDaemonStateInternal_ = | 443 remoting.HostDispatcher.prototype.getDaemonStateInternal_ = |
299 function(onDone, onError) { | 444 function(onDone, onError) { |
300 switch (this.state_) { | 445 switch (this.state_) { |
301 case remoting.HostDispatcher.State.UNKNOWN: | 446 case remoting.HostDispatcher.State.UNKNOWN: |
302 this.pendingRequests_.push( | 447 this.pendingRequests_.push( |
303 this.getDaemonStateInternal_.bind(this, onDone, onError)); | 448 this.getDaemonStateInternal_.bind(this, onDone, onError)); |
304 break; | 449 break; |
305 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 450 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
306 this.nativeMessagingHost_.getDaemonState(onDone, onError); | 451 this.nativeMessagingHost_.getDaemonState(onDone, onError); |
307 break; | 452 break; |
| 453 case remoting.HostDispatcher.State.NPAPI: |
| 454 // Call the callback directly, since NPAPI exposes the state directly as |
| 455 // a field member, rather than an asynchronous method. |
| 456 var state = this.npapiHost_.daemonState; |
| 457 if (state === undefined) { |
| 458 onError(remoting.Error.MISSING_PLUGIN); |
| 459 } else { |
| 460 onDone(state); |
| 461 } |
| 462 break; |
308 case remoting.HostDispatcher.State.NOT_INSTALLED: | 463 case remoting.HostDispatcher.State.NOT_INSTALLED: |
309 onDone(remoting.HostController.State.NOT_INSTALLED); | 464 onDone(remoting.HostController.State.NOT_INSTALLED); |
310 break; | 465 break; |
311 } | 466 } |
312 }; | 467 }; |
313 | 468 |
314 /** | 469 /** |
315 * @param {function(Array.<remoting.PairedClient>):void} onDone | 470 * @param {function(Array.<remoting.PairedClient>):void} onDone |
316 * @param {function(remoting.Error):void} onError | 471 * @param {function(remoting.Error):void} onError |
317 * @return {void} | 472 * @return {void} |
318 */ | 473 */ |
319 remoting.HostDispatcher.prototype.getPairedClients = function(onDone, onError) { | 474 remoting.HostDispatcher.prototype.getPairedClients = function(onDone, onError) { |
| 475 /** |
| 476 * Converts the JSON string from the NPAPI plugin to Array.<PairedClient>, to |
| 477 * pass to |onDone|. |
| 478 * @param {string} pairedClientsJson |
| 479 * @return {void} |
| 480 */ |
| 481 function callbackForNpapi(pairedClientsJson) { |
| 482 var pairedClients = remoting.PairedClient.convertToPairedClientArray( |
| 483 jsonParseSafe(pairedClientsJson)); |
| 484 if (pairedClients != null) { |
| 485 onDone(pairedClients); |
| 486 } else { |
| 487 onError(remoting.Error.UNEXPECTED); |
| 488 } |
| 489 } |
| 490 |
320 switch (this.state_) { | 491 switch (this.state_) { |
321 case remoting.HostDispatcher.State.UNKNOWN: | 492 case remoting.HostDispatcher.State.UNKNOWN: |
322 this.pendingRequests_.push( | 493 this.pendingRequests_.push( |
323 this.getPairedClients.bind(this, onDone, onError)); | 494 this.getPairedClients.bind(this, onDone, onError)); |
324 break; | 495 break; |
325 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 496 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
326 this.nativeMessagingHost_.getPairedClients(onDone, onError); | 497 this.nativeMessagingHost_.getPairedClients(onDone, onError); |
327 break; | 498 break; |
| 499 case remoting.HostDispatcher.State.NPAPI: |
| 500 try { |
| 501 this.npapiHost_.getPairedClients(callbackForNpapi); |
| 502 } catch (err) { |
| 503 onError(remoting.Error.MISSING_PLUGIN); |
| 504 } |
| 505 break; |
328 case remoting.HostDispatcher.State.NOT_INSTALLED: | 506 case remoting.HostDispatcher.State.NOT_INSTALLED: |
329 onError(remoting.Error.MISSING_PLUGIN); | 507 onError(remoting.Error.MISSING_PLUGIN); |
330 break; | 508 break; |
331 } | 509 } |
332 }; | 510 }; |
333 | 511 |
334 /** | 512 /** |
335 * The pairing API returns a boolean to indicate success or failure, but | 513 * The pairing API returns a boolean to indicate success or failure, but |
336 * the JS API is defined in terms of onDone and onError callbacks. This | 514 * the JS API is defined in terms of onDone and onError callbacks. This |
337 * function converts one to the other. | 515 * function converts one to the other. |
(...skipping 21 matching lines...) Expand all Loading... |
359 var callback = | 537 var callback = |
360 remoting.HostDispatcher.runCallback_.bind(null, onDone, onError); | 538 remoting.HostDispatcher.runCallback_.bind(null, onDone, onError); |
361 switch (this.state_) { | 539 switch (this.state_) { |
362 case remoting.HostDispatcher.State.UNKNOWN: | 540 case remoting.HostDispatcher.State.UNKNOWN: |
363 this.pendingRequests_.push( | 541 this.pendingRequests_.push( |
364 this.clearPairedClients.bind(this, onDone, onError)); | 542 this.clearPairedClients.bind(this, onDone, onError)); |
365 break; | 543 break; |
366 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 544 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
367 this.nativeMessagingHost_.clearPairedClients(callback, onError); | 545 this.nativeMessagingHost_.clearPairedClients(callback, onError); |
368 break; | 546 break; |
| 547 case remoting.HostDispatcher.State.NPAPI: |
| 548 try { |
| 549 this.npapiHost_.clearPairedClients(callback); |
| 550 } catch (err) { |
| 551 onError(remoting.Error.MISSING_PLUGIN); |
| 552 } |
| 553 break; |
369 case remoting.HostDispatcher.State.NOT_INSTALLED: | 554 case remoting.HostDispatcher.State.NOT_INSTALLED: |
370 onError(remoting.Error.MISSING_PLUGIN); | 555 onError(remoting.Error.MISSING_PLUGIN); |
371 break; | 556 break; |
372 } | 557 } |
373 }; | 558 }; |
374 | 559 |
375 /** | 560 /** |
376 * @param {string} client | 561 * @param {string} client |
377 * @param {function():void} onDone | 562 * @param {function():void} onDone |
378 * @param {function(remoting.Error):void} onError | 563 * @param {function(remoting.Error):void} onError |
379 * @return {void} | 564 * @return {void} |
380 */ | 565 */ |
381 remoting.HostDispatcher.prototype.deletePairedClient = | 566 remoting.HostDispatcher.prototype.deletePairedClient = |
382 function(client, onDone, onError) { | 567 function(client, onDone, onError) { |
383 var callback = | 568 var callback = |
384 remoting.HostDispatcher.runCallback_.bind(null, onDone, onError); | 569 remoting.HostDispatcher.runCallback_.bind(null, onDone, onError); |
385 switch (this.state_) { | 570 switch (this.state_) { |
386 case remoting.HostDispatcher.State.UNKNOWN: | 571 case remoting.HostDispatcher.State.UNKNOWN: |
387 this.pendingRequests_.push( | 572 this.pendingRequests_.push( |
388 this.deletePairedClient.bind(this, client, onDone, onError)); | 573 this.deletePairedClient.bind(this, client, onDone, onError)); |
389 break; | 574 break; |
390 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 575 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
391 this.nativeMessagingHost_.deletePairedClient(client, callback, onError); | 576 this.nativeMessagingHost_.deletePairedClient(client, callback, onError); |
392 break; | 577 break; |
| 578 case remoting.HostDispatcher.State.NPAPI: |
| 579 try { |
| 580 this.npapiHost_.deletePairedClient(client, callback); |
| 581 } catch (err) { |
| 582 onError(remoting.Error.MISSING_PLUGIN); |
| 583 } |
| 584 break; |
393 case remoting.HostDispatcher.State.NOT_INSTALLED: | 585 case remoting.HostDispatcher.State.NOT_INSTALLED: |
394 onError(remoting.Error.MISSING_PLUGIN); | 586 onError(remoting.Error.MISSING_PLUGIN); |
395 break; | 587 break; |
396 } | 588 } |
397 }; | 589 }; |
398 | 590 |
399 /** | 591 /** |
400 * @param {function(string):void} onDone | 592 * @param {function(string):void} onDone |
401 * @param {function(remoting.Error):void} onError | 593 * @param {function(remoting.Error):void} onError |
402 * @return {void} | 594 * @return {void} |
403 */ | 595 */ |
404 remoting.HostDispatcher.prototype.getHostClientId = | 596 remoting.HostDispatcher.prototype.getHostClientId = |
405 function(onDone, onError) { | 597 function(onDone, onError) { |
406 switch (this.state_) { | 598 switch (this.state_) { |
407 case remoting.HostDispatcher.State.UNKNOWN: | 599 case remoting.HostDispatcher.State.UNKNOWN: |
408 this.pendingRequests_.push( | 600 this.pendingRequests_.push( |
409 this.getHostClientId.bind(this, onDone, onError)); | 601 this.getHostClientId.bind(this, onDone, onError)); |
410 break; | 602 break; |
411 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 603 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
412 this.nativeMessagingHost_.getHostClientId(onDone, onError); | 604 this.nativeMessagingHost_.getHostClientId(onDone, onError); |
413 break; | 605 break; |
| 606 case remoting.HostDispatcher.State.NPAPI: |
| 607 // The NPAPI plugin is packaged with the webapp, not the host, so it |
| 608 // doesn't have access to the API keys baked into the installed host. |
| 609 onError(remoting.Error.UNEXPECTED); |
| 610 break; |
414 case remoting.HostDispatcher.State.NOT_INSTALLED: | 611 case remoting.HostDispatcher.State.NOT_INSTALLED: |
415 onError(remoting.Error.MISSING_PLUGIN); | 612 onError(remoting.Error.MISSING_PLUGIN); |
416 break; | 613 break; |
417 } | 614 } |
418 }; | 615 }; |
419 | 616 |
420 /** | 617 /** |
421 * @param {string} authorizationCode | 618 * @param {string} authorizationCode |
422 * @param {function(string, string):void} onDone | 619 * @param {function(string, string):void} onDone |
423 * @param {function(remoting.Error):void} onError | 620 * @param {function(remoting.Error):void} onError |
424 * @return {void} | 621 * @return {void} |
425 */ | 622 */ |
426 remoting.HostDispatcher.prototype.getCredentialsFromAuthCode = | 623 remoting.HostDispatcher.prototype.getCredentialsFromAuthCode = |
427 function(authorizationCode, onDone, onError) { | 624 function(authorizationCode, onDone, onError) { |
428 switch (this.state_) { | 625 switch (this.state_) { |
429 case remoting.HostDispatcher.State.UNKNOWN: | 626 case remoting.HostDispatcher.State.UNKNOWN: |
430 this.pendingRequests_.push( | 627 this.pendingRequests_.push( |
431 this.getCredentialsFromAuthCode.bind( | 628 this.getCredentialsFromAuthCode.bind( |
432 this, authorizationCode, onDone, onError)); | 629 this, authorizationCode, onDone, onError)); |
433 break; | 630 break; |
434 case remoting.HostDispatcher.State.NATIVE_MESSAGING: | 631 case remoting.HostDispatcher.State.NATIVE_MESSAGING: |
435 this.nativeMessagingHost_.getCredentialsFromAuthCode( | 632 this.nativeMessagingHost_.getCredentialsFromAuthCode( |
436 authorizationCode, onDone, onError); | 633 authorizationCode, onDone, onError); |
437 break; | 634 break; |
| 635 case remoting.HostDispatcher.State.NPAPI: |
| 636 // The NPAPI plugin is packaged with the webapp, not the host, so it |
| 637 // doesn't have access to the API keys baked into the installed host. |
| 638 onError(remoting.Error.UNEXPECTED); |
| 639 break; |
438 case remoting.HostDispatcher.State.NOT_INSTALLED: | 640 case remoting.HostDispatcher.State.NOT_INSTALLED: |
439 onError(remoting.Error.MISSING_PLUGIN); | 641 onError(remoting.Error.MISSING_PLUGIN); |
440 break; | 642 break; |
441 } | 643 } |
442 }; | 644 }; |
| 645 |
| 646 /** |
| 647 * Returns true if the NPAPI plugin is being used. |
| 648 * @return {boolean} |
| 649 */ |
| 650 remoting.HostDispatcher.prototype.usingNpapiPlugin = function() { |
| 651 return this.state_ == remoting.HostDispatcher.State.NPAPI; |
| 652 } |
OLD | NEW |