Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / remoting / webapp / host_dispatcher.js
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
3 // found in the LICENSE file.
4
5 /**
6  * @fileoverview
7  * This class provides an interface between the HostController and either the
8  * NativeMessaging Host.
9  */
10
11 'use strict';
12
13 /** @suppress {duplicate} */
14 var remoting = remoting || {};
15
16 /**
17  * @constructor
18  */
19 remoting.HostDispatcher = function() {
20   /** @type {remoting.HostNativeMessaging} @private */
21   this.nativeMessagingHost_ = new remoting.HostNativeMessaging();
22
23   /** @type {remoting.HostDispatcher.State} @private */
24   this.state_ = remoting.HostDispatcher.State.UNKNOWN;
25
26   /** @type {Array.<function()>} @private */
27   this.pendingRequests_ = [];
28
29   this.tryToInitialize_();
30 }
31
32 /** @enum {number} */
33 remoting.HostDispatcher.State = {
34   UNKNOWN: 0,
35   NATIVE_MESSAGING: 1,
36   NOT_INSTALLED: 2
37 };
38
39 remoting.HostDispatcher.prototype.tryToInitialize_ = function() {
40   /** @type {remoting.HostDispatcher} */
41   var that = this;
42
43   if (this.state_ != remoting.HostDispatcher.State.UNKNOWN)
44     return;
45
46   function sendPendingRequests() {
47     var pendingRequests = that.pendingRequests_;
48     that.pendingRequests_ = [];
49     for (var i = 0; i < pendingRequests.length; i++) {
50       pendingRequests[i]();
51     }
52   }
53
54   function onNativeMessagingInit() {
55     that.state_ = remoting.HostDispatcher.State.NATIVE_MESSAGING;
56     sendPendingRequests();
57   }
58
59   function onNativeMessagingFailed(error) {
60     that.state_ = remoting.HostDispatcher.State.NOT_INSTALLED;
61     sendPendingRequests();
62   }
63
64   this.nativeMessagingHost_.initialize(onNativeMessagingInit,
65                                        onNativeMessagingFailed);
66 };
67
68 /**
69  * @param {remoting.HostController.Feature} feature The feature to test for.
70  * @param {function(boolean):void} onDone
71  * @return {void}
72  */
73 remoting.HostDispatcher.prototype.hasFeature = function(
74     feature, onDone) {
75   switch (this.state_) {
76     case remoting.HostDispatcher.State.UNKNOWN:
77       this.pendingRequests_.push(
78           this.hasFeature.bind(this, feature, onDone));
79       break;
80     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
81       onDone(this.nativeMessagingHost_.hasFeature(feature));
82       break;
83     case remoting.HostDispatcher.State.NOT_INSTALLED:
84       onDone(false);
85       break;
86   }
87 };
88
89 /**
90  * @param {function(string):void} onDone
91  * @param {function(remoting.Error):void} onError
92  * @return {void}
93  */
94 remoting.HostDispatcher.prototype.getHostName = function(onDone, onError) {
95   switch (this.state_) {
96     case remoting.HostDispatcher.State.UNKNOWN:
97       this.pendingRequests_.push(
98           this.getHostName.bind(this, onDone, onError));
99       break;
100     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
101       this.nativeMessagingHost_.getHostName(onDone, onError);
102       break;
103     case remoting.HostDispatcher.State.NOT_INSTALLED:
104       onError(remoting.Error.MISSING_PLUGIN);
105       break;
106   }
107 };
108
109 /**
110  * @param {string} hostId
111  * @param {string} pin
112  * @param {function(string):void} onDone
113  * @param {function(remoting.Error):void} onError
114  * @return {void}
115  */
116 remoting.HostDispatcher.prototype.getPinHash =
117     function(hostId, pin, onDone, onError) {
118   switch (this.state_) {
119     case remoting.HostDispatcher.State.UNKNOWN:
120       this.pendingRequests_.push(
121           this.getPinHash.bind(this, hostId, pin, onDone, onError));
122       break;
123     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
124       this.nativeMessagingHost_.getPinHash(hostId, pin, onDone, onError);
125       break;
126     case remoting.HostDispatcher.State.NOT_INSTALLED:
127       onError(remoting.Error.MISSING_PLUGIN);
128       break;
129   }
130 };
131
132 /**
133  * @param {function(string, string):void} onDone
134  * @param {function(remoting.Error):void} onError
135  * @return {void}
136  */
137 remoting.HostDispatcher.prototype.generateKeyPair = function(onDone, onError) {
138   switch (this.state_) {
139     case remoting.HostDispatcher.State.UNKNOWN:
140       this.pendingRequests_.push(
141           this.generateKeyPair.bind(this, onDone, onError));
142       break;
143     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
144       this.nativeMessagingHost_.generateKeyPair(onDone, onError);
145       break;
146     case remoting.HostDispatcher.State.NOT_INSTALLED:
147       onError(remoting.Error.MISSING_PLUGIN);
148       break;
149   }
150 };
151
152 /**
153  * @param {Object} config
154  * @param {function(remoting.HostController.AsyncResult):void} onDone
155  * @param {function(remoting.Error):void} onError
156  * @return {void}
157  */
158 remoting.HostDispatcher.prototype.updateDaemonConfig =
159     function(config, onDone, onError) {
160   switch (this.state_) {
161     case remoting.HostDispatcher.State.UNKNOWN:
162       this.pendingRequests_.push(
163           this.updateDaemonConfig.bind(this, config, onDone, onError));
164       break;
165     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
166       this.nativeMessagingHost_.updateDaemonConfig(config, onDone, onError);
167       break;
168     case remoting.HostDispatcher.State.NOT_INSTALLED:
169       onError(remoting.Error.MISSING_PLUGIN);
170       break;
171   }
172 };
173
174 /**
175  * @param {function(Object):void} onDone
176  * @param {function(remoting.Error):void} onError
177  * @return {void}
178  */
179 remoting.HostDispatcher.prototype.getDaemonConfig = function(onDone, onError) {
180   switch (this.state_) {
181     case remoting.HostDispatcher.State.UNKNOWN:
182       this.pendingRequests_.push(
183           this.getDaemonConfig.bind(this, onDone, onError));
184       break;
185     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
186       this.nativeMessagingHost_.getDaemonConfig(onDone, onError);
187       break;
188     case remoting.HostDispatcher.State.NOT_INSTALLED:
189       onDone({});
190       break;
191   }
192 };
193
194 /**
195  * @param {function(string):void} onDone
196  * @param {function(remoting.Error):void} onError
197  * @return {void}
198  */
199 remoting.HostDispatcher.prototype.getDaemonVersion = function(onDone, onError) {
200   switch (this.state_) {
201     case remoting.HostDispatcher.State.UNKNOWN:
202       this.pendingRequests_.push(
203           this.getDaemonVersion.bind(this, onDone, onError));
204       break;
205     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
206       onDone(this.nativeMessagingHost_.getDaemonVersion());
207       break;
208     case remoting.HostDispatcher.State.NOT_INSTALLED:
209       onError(remoting.Error.MISSING_PLUGIN);
210       break;
211   }
212 };
213
214 /**
215  * @param {function(boolean, boolean, boolean):void} onDone
216  * @param {function(remoting.Error):void} onError
217  * @return {void}
218  */
219 remoting.HostDispatcher.prototype.getUsageStatsConsent =
220     function(onDone, onError) {
221   switch (this.state_) {
222     case remoting.HostDispatcher.State.UNKNOWN:
223       this.pendingRequests_.push(
224           this.getUsageStatsConsent.bind(this, onDone, onError));
225       break;
226     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
227       this.nativeMessagingHost_.getUsageStatsConsent(onDone, onError);
228       break;
229     case remoting.HostDispatcher.State.NOT_INSTALLED:
230       onError(remoting.Error.MISSING_PLUGIN);
231       break;
232   }
233 };
234
235 /**
236  * @param {Object} config
237  * @param {boolean} consent
238  * @param {function(remoting.HostController.AsyncResult):void} onDone
239  * @param {function(remoting.Error):void} onError
240  * @return {void}
241  */
242 remoting.HostDispatcher.prototype.startDaemon =
243     function(config, consent, onDone, onError) {
244   switch (this.state_) {
245     case remoting.HostDispatcher.State.UNKNOWN:
246       this.pendingRequests_.push(
247           this.startDaemon.bind(this, config, consent, onDone, onError));
248       break;
249     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
250       this.nativeMessagingHost_.startDaemon(config, consent, onDone, onError);
251       break;
252     case remoting.HostDispatcher.State.NOT_INSTALLED:
253       onError(remoting.Error.MISSING_PLUGIN);
254       break;
255   }
256 };
257
258 /**
259  * @param {function(remoting.HostController.AsyncResult):void} onDone
260  * @param {function(remoting.Error):void} onError
261  * @return {void}
262  */
263 remoting.HostDispatcher.prototype.stopDaemon = function(onDone, onError) {
264   switch (this.state_) {
265     case remoting.HostDispatcher.State.UNKNOWN:
266       this.pendingRequests_.push(this.stopDaemon.bind(this, onDone, onError));
267       break;
268     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
269       this.nativeMessagingHost_.stopDaemon(onDone, onError);
270       break;
271     case remoting.HostDispatcher.State.NOT_INSTALLED:
272       onError(remoting.Error.MISSING_PLUGIN);
273       break;
274   }
275 };
276
277 /**
278  * @param {function(remoting.HostController.State):void} onDone
279  * @param {function(remoting.Error):void} onError
280  * @return {void}
281  */
282 remoting.HostDispatcher.prototype.getDaemonState = function(onDone, onError) {
283   // If the host was in not-initialized state try initializing it again in case
284   // it was installed.
285   if (this.state_ == remoting.HostDispatcher.State.NOT_INSTALLED) {
286     this.state_ = remoting.HostDispatcher.State.UNKNOWN;
287     this.tryToInitialize_();
288   }
289
290   this.getDaemonStateInternal_(onDone, onError);
291 }
292
293 /**
294  * @param {function(remoting.HostController.State):void} onDone
295  * @param {function(remoting.Error):void} onError
296  * @return {void}
297  */
298 remoting.HostDispatcher.prototype.getDaemonStateInternal_ =
299     function(onDone, onError) {
300   switch (this.state_) {
301     case remoting.HostDispatcher.State.UNKNOWN:
302       this.pendingRequests_.push(
303           this.getDaemonStateInternal_.bind(this, onDone, onError));
304       break;
305     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
306       this.nativeMessagingHost_.getDaemonState(onDone, onError);
307       break;
308     case remoting.HostDispatcher.State.NOT_INSTALLED:
309       onDone(remoting.HostController.State.NOT_INSTALLED);
310       break;
311   }
312 };
313
314 /**
315  * @param {function(Array.<remoting.PairedClient>):void} onDone
316  * @param {function(remoting.Error):void} onError
317  * @return {void}
318  */
319 remoting.HostDispatcher.prototype.getPairedClients = function(onDone, onError) {
320   switch (this.state_) {
321     case remoting.HostDispatcher.State.UNKNOWN:
322       this.pendingRequests_.push(
323           this.getPairedClients.bind(this, onDone, onError));
324       break;
325     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
326       this.nativeMessagingHost_.getPairedClients(onDone, onError);
327       break;
328     case remoting.HostDispatcher.State.NOT_INSTALLED:
329       onError(remoting.Error.MISSING_PLUGIN);
330       break;
331   }
332 };
333
334 /**
335  * 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
337  * function converts one to the other.
338  *
339  * @param {function():void} onDone Success callback.
340  * @param {function(remoting.Error):void} onError Error callback.
341  * @param {boolean} success True if the operation succeeded; false otherwise.
342  * @private
343  */
344 remoting.HostDispatcher.runCallback_ = function(onDone, onError, success) {
345   if (success) {
346     onDone();
347   } else {
348     onError(remoting.Error.UNEXPECTED);
349   }
350 };
351
352 /**
353  * @param {function():void} onDone
354  * @param {function(remoting.Error):void} onError
355  * @return {void}
356  */
357 remoting.HostDispatcher.prototype.clearPairedClients =
358     function(onDone, onError) {
359   var callback =
360       remoting.HostDispatcher.runCallback_.bind(null, onDone, onError);
361   switch (this.state_) {
362     case remoting.HostDispatcher.State.UNKNOWN:
363       this.pendingRequests_.push(
364         this.clearPairedClients.bind(this, onDone, onError));
365       break;
366     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
367       this.nativeMessagingHost_.clearPairedClients(callback, onError);
368       break;
369     case remoting.HostDispatcher.State.NOT_INSTALLED:
370       onError(remoting.Error.MISSING_PLUGIN);
371       break;
372   }
373 };
374
375 /**
376  * @param {string} client
377  * @param {function():void} onDone
378  * @param {function(remoting.Error):void} onError
379  * @return {void}
380  */
381 remoting.HostDispatcher.prototype.deletePairedClient =
382     function(client, onDone, onError) {
383   var callback =
384       remoting.HostDispatcher.runCallback_.bind(null, onDone, onError);
385   switch (this.state_) {
386     case remoting.HostDispatcher.State.UNKNOWN:
387       this.pendingRequests_.push(
388         this.deletePairedClient.bind(this, client, onDone, onError));
389       break;
390     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
391       this.nativeMessagingHost_.deletePairedClient(client, callback, onError);
392       break;
393     case remoting.HostDispatcher.State.NOT_INSTALLED:
394       onError(remoting.Error.MISSING_PLUGIN);
395       break;
396   }
397 };
398
399 /**
400  * @param {function(string):void} onDone
401  * @param {function(remoting.Error):void} onError
402  * @return {void}
403  */
404 remoting.HostDispatcher.prototype.getHostClientId =
405     function(onDone, onError) {
406   switch (this.state_) {
407     case remoting.HostDispatcher.State.UNKNOWN:
408       this.pendingRequests_.push(
409           this.getHostClientId.bind(this, onDone, onError));
410       break;
411     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
412       this.nativeMessagingHost_.getHostClientId(onDone, onError);
413       break;
414     case remoting.HostDispatcher.State.NOT_INSTALLED:
415       onError(remoting.Error.MISSING_PLUGIN);
416       break;
417   }
418 };
419
420 /**
421  * @param {string} authorizationCode
422  * @param {function(string, string):void} onDone
423  * @param {function(remoting.Error):void} onError
424  * @return {void}
425  */
426 remoting.HostDispatcher.prototype.getCredentialsFromAuthCode =
427     function(authorizationCode, onDone, onError) {
428   switch (this.state_) {
429     case remoting.HostDispatcher.State.UNKNOWN:
430       this.pendingRequests_.push(
431           this.getCredentialsFromAuthCode.bind(
432               this, authorizationCode, onDone, onError));
433       break;
434     case remoting.HostDispatcher.State.NATIVE_MESSAGING:
435       this.nativeMessagingHost_.getCredentialsFromAuthCode(
436           authorizationCode, onDone, onError);
437       break;
438     case remoting.HostDispatcher.State.NOT_INSTALLED:
439       onError(remoting.Error.MISSING_PLUGIN);
440       break;
441   }
442 };