diff options
author | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-08 22:56:37 +0000 |
---|---|---|
committer | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-08 22:56:37 +0000 |
commit | 0398c320ae167c350ee3fc8d79e6a4ecf94f25df (patch) | |
tree | 12711b2dfb5e8198c90080b39facee05080acaca /remoting/webapp | |
parent | a0ee86c8d352a4768ee9f7532b14c53274225cf3 (diff) | |
download | chromium_src-0398c320ae167c350ee3fc8d79e6a4ecf94f25df.zip chromium_src-0398c320ae167c350ee3fc8d79e6a4ecf94f25df.tar.gz chromium_src-0398c320ae167c350ee3fc8d79e6a4ecf94f25df.tar.bz2 |
Dispatch HostController requests to NativeMessaging host or NPAPI plugin.
Add HostDispatcher class which tries to initialize
NativeMessaging, falling back to the NPAPI plugin if
NativeMessaging is unsupported. The HostController makes
all Me2Me requests via this new class, which dispatches
them to the NativeMessaging host or the NPAPI plugin. If
support status is not yet known (the test is asynchronous),
the request is added to a pending queue, and is dispatched
when the status has been determined.
BUG=173509
Review URL: https://chromiumcodereview.appspot.com/14780005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199035 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/webapp')
-rw-r--r-- | remoting/webapp/all_js_load.gtestjs | 2 | ||||
-rw-r--r-- | remoting/webapp/host_controller.js | 75 | ||||
-rw-r--r-- | remoting/webapp/host_dispatcher.js | 270 | ||||
-rw-r--r-- | remoting/webapp/host_plugin_wrapper.js | 117 | ||||
-rw-r--r-- | remoting/webapp/main.html | 2 |
5 files changed, 303 insertions, 163 deletions
diff --git a/remoting/webapp/all_js_load.gtestjs b/remoting/webapp/all_js_load.gtestjs index 6ec116c..f1716c4 100644 --- a/remoting/webapp/all_js_load.gtestjs +++ b/remoting/webapp/all_js_load.gtestjs @@ -35,10 +35,10 @@ AllJsLoadTest.prototype = { //'format_iq.js', // Already covered by format_iq.gtestjs 'host.js', 'host_controller.js', + 'host_dispatcher.js', 'host_list.js', 'host_native_messaging.js', //'host_plugin_proto.js', // Only used by jscompiler - 'host_plugin_wrapper.js', 'host_screen.js', 'host_session.js', 'host_setup_dialog.js', diff --git a/remoting/webapp/host_controller.js b/remoting/webapp/host_controller.js index adc3b1a..40486d8 100644 --- a/remoting/webapp/host_controller.js +++ b/remoting/webapp/host_controller.js @@ -9,41 +9,28 @@ var remoting = remoting || {}; /** @constructor */ remoting.HostController = function() { - /** @type {remoting.HostController} */ - var that = this; + /** @return {remoting.HostPlugin} */ + var createNpapiPlugin = function() { + var plugin = remoting.HostSession.createPlugin(); + /** @type {HTMLElement} @private */ + var container = document.getElementById('daemon-plugin-container'); + container.appendChild(plugin); + return plugin; + } - /** @type {remoting.HostNativeMessaging} @private */ - this.plugin_ = new remoting.HostNativeMessaging(); + /** @type {remoting.HostDispatcher} @private */ + this.hostDispatcher_ = new remoting.HostDispatcher(createNpapiPlugin); - /** @param {boolean} success */ - var onNativeMessagingInit = function(success) { - if (success) { - console.log('Native Messaging supported.'); + /** @param {string} version */ + var printVersion = function(version) { + if (version == '') { + console.log('Host not installed.'); } else { - console.log('Native Messaging unsupported, falling back to NPAPI.'); - var plugin = remoting.HostSession.createPlugin(); - that.plugin_ = new remoting.HostPluginWrapper(plugin); - /** @type {HTMLElement} @private */ - var container = document.getElementById('daemon-plugin-container'); - container.appendChild(plugin); - } - - /** @param {string} version */ - var printVersion = function(version) { - if (version == '') { - console.log('Host not installed.'); - } else { - console.log('Host version: ' + version); - } - }; - try { - that.plugin_.getDaemonVersion(printVersion); - } catch (err) { - console.log('Host version not available.'); + console.log('Host version: ' + version); } - } + }; - this.plugin_.initialize(onNativeMessagingInit); + this.hostDispatcher_.getDaemonVersion(printVersion); } // Note that the values in the enums below are copied from @@ -73,7 +60,7 @@ remoting.HostController.AsyncResult = { * called when done. */ remoting.HostController.prototype.getConsent = function(callback) { - this.plugin_.getUsageStatsConsent(callback); + this.hostDispatcher_.getUsageStatsConsent(callback); }; /** @@ -129,8 +116,8 @@ remoting.HostController.prototype.start = function(hostPin, consent, callback) { var success = (xhr.status == 200); if (success) { - that.plugin_.getPinHash(newHostId, hostPin, startHostWithHash.bind( - null, hostName, publicKey, privateKey, xhr)); + that.hostDispatcher_.getPinHash(newHostId, hostPin, + startHostWithHash.bind(null, hostName, publicKey, privateKey, xhr)); } else { console.log('Failed to register the host. Status: ' + xhr.status + ' response: ' + xhr.responseText); @@ -159,7 +146,7 @@ remoting.HostController.prototype.start = function(hostPin, consent, callback) { var onStartDaemon = function(result) { onStarted(callback, result, hostName, publicKey); }; - that.plugin_.startDaemon(hostConfig, consent, onStartDaemon); + that.hostDispatcher_.startDaemon(hostConfig, consent, onStartDaemon); } /** @@ -210,10 +197,10 @@ remoting.HostController.prototype.start = function(hostPin, consent, callback) { * @return {void} Nothing. */ function startWithHostname(hostName) { - that.plugin_.generateKeyPair(onKeyGenerated.bind(null, hostName)); + that.hostDispatcher_.generateKeyPair(onKeyGenerated.bind(null, hostName)); } - this.plugin_.getHostName(startWithHostname); + this.hostDispatcher_.getHostName(startWithHostname); }; /** @@ -250,7 +237,7 @@ remoting.HostController.prototype.stop = function(callback) { that.getLocalHostId(unregisterHost.bind(null, result)); }; - this.plugin_.stopDaemon(onStopped); + this.hostDispatcher_.stopDaemon(onStopped); }; /** @@ -297,20 +284,20 @@ remoting.HostController.prototype.updatePin = function(newPin, callback) { return; } var hostId = config['host_id']; - that.plugin_.getPinHash(hostId, newPin, updateDaemonConfigWithHash); - }; + that.hostDispatcher_.getPinHash(hostId, newPin, updateDaemonConfigWithHash); + } /** @param {string} pinHash */ function updateDaemonConfigWithHash(pinHash) { var newConfig = JSON.stringify({ host_secret_hash: pinHash }); - that.plugin_.updateDaemonConfig(newConfig, callback); - }; + that.hostDispatcher_.updateDaemonConfig(newConfig, callback); + } // TODO(sergeyu): When crbug.com/121518 is fixed: replace this call // with an upriveleged version if that is necessary. - this.plugin_.getDaemonConfig(onConfig); + this.hostDispatcher_.getDaemonConfig(onConfig); }; /** @@ -320,7 +307,7 @@ remoting.HostController.prototype.updatePin = function(newPin, callback) { * Completion callback. */ remoting.HostController.prototype.getLocalHostState = function(onDone) { - this.plugin_.getDaemonState(onDone); + this.hostDispatcher_.getDaemonState(onDone); }; /** @@ -341,7 +328,7 @@ remoting.HostController.prototype.getLocalHostId = function(onDone) { onDone(hostId); }; try { - this.plugin_.getDaemonConfig(onConfig); + this.hostDispatcher_.getDaemonConfig(onConfig); } catch (err) { onDone(null); } diff --git a/remoting/webapp/host_dispatcher.js b/remoting/webapp/host_dispatcher.js new file mode 100644 index 0000000..fe0ba38 --- /dev/null +++ b/remoting/webapp/host_dispatcher.js @@ -0,0 +1,270 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview + * This class provides an interface between the HostController and either the + * NativeMessaging Host or the Host NPAPI plugin, depending on whether + * NativeMessaging is supported. Since the test for NativeMessaging support is + * asynchronous, this class stores any requests on a queue, pending the result + * of the test. + * Once the test is complete, the pending requests are performed on either the + * NativeMessaging host, or the NPAPI plugin. + * + * If necessary, the HostController is instructed (via a callback) to + * instantiate the NPAPI plugin, and return a reference to it here. + */ + +'use strict'; + +/** @suppress {duplicate} */ +var remoting = remoting || {}; + +/** + * @constructor + * @param {function():remoting.HostPlugin} createPluginCallback Callback to + * instantiate the NPAPI plugin when NativeMessaging is determined to be + * unsupported. + */ +remoting.HostDispatcher = function(createPluginCallback) { + /** @type {remoting.HostDispatcher} */ + var that = this; + + /** @type {remoting.HostNativeMessaging} @private */ + this.nativeMessagingHost_ = new remoting.HostNativeMessaging(); + + /** @type {remoting.HostPlugin} @private */ + this.npapiHost_ = null; + + /** @type {remoting.HostDispatcher.State} */ + this.state_ = remoting.HostDispatcher.State.UNKNOWN; + + /** @type {Array.<function()>} */ + this.pendingRequests_ = []; + + /** @param {boolean} success */ + var onNativeMessagingInit = function(success) { + if (success) { + console.log('Native Messaging supported.'); + that.state_ = remoting.HostDispatcher.State.NATIVE_MESSAGING; + } else { + console.log('Native Messaging unsupported, falling back to NPAPI.'); + that.npapiHost_ = createPluginCallback(); + that.state_ = remoting.HostDispatcher.State.NPAPI; + } + // Send pending requests. + for (var i = 0; i < that.pendingRequests_.length; i++) { + that.pendingRequests_[i](); + } + that.pendingRequests_ = null; + }; + + this.nativeMessagingHost_.initialize(onNativeMessagingInit); +}; + +/** @enum {number} */ +remoting.HostDispatcher.State = { + UNKNOWN: 0, + NATIVE_MESSAGING: 1, + NPAPI: 2 +}; + +/** + * @param {function(string):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.getHostName = function(callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.getHostName.bind(this, callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.getHostName(callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.getHostName(callback); + break; + } +}; + +/** + * @param {string} hostId + * @param {string} pin + * @param {function(string):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.getPinHash = function(hostId, pin, callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.getPinHash.bind(this, hostId, pin, + callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.getPinHash(hostId, pin, callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.getPinHash(hostId, pin, callback); + break; + } +}; + +/** + * @param {function(string, string):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.generateKeyPair = function(callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.generateKeyPair.bind(this, callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.generateKeyPair(callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.generateKeyPair(callback); + break; + } +}; + +/** + * @param {string} config + * @param {function(remoting.HostController.AsyncResult):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.updateDaemonConfig = function(config, + callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.updateDaemonConfig.bind(this, callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.updateDaemonConfig(config, callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.updateDaemonConfig(config, callback); + break; + } + +}; + +/** + * @param {function(string):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.getDaemonConfig = function(callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.getDaemonConfig.bind(this, callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.getDaemonConfig(callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.getDaemonConfig(callback); + break; + } +}; + +/** + * @param {function(string):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.getDaemonVersion = function(callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.getDaemonVersion.bind(this, callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.getDaemonVersion(callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.getDaemonVersion(callback); + break; + } +}; + +/** + * @param {function(boolean, boolean, boolean):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.getUsageStatsConsent = function(callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.getUsageStatsConsent.bind(this, + callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.getUsageStatsConsent(callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.getUsageStatsConsent(callback); + break; + } +}; + +/** + * @param {string} config + * @param {boolean} consent + * @param {function(remoting.HostController.AsyncResult):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.startDaemon = function(config, consent, + callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.startDaemon.bind(this, config, consent, + callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.startDaemon(config, consent, callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.startDaemon(config, consent, callback); + break; + } +}; + +/** + * @param {function(remoting.HostController.AsyncResult):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.stopDaemon = function(callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.stopDaemon.bind(this, callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.stopDaemon(callback); + break; + case remoting.HostDispatcher.State.NPAPI: + this.npapiHost_.stopDaemon(callback); + break; + } +}; + +/** + * @param {function(remoting.HostController.State):void} callback + * @return {void} + */ +remoting.HostDispatcher.prototype.getDaemonState = function(callback) { + switch (this.state_) { + case remoting.HostDispatcher.State.UNKNOWN: + this.pendingRequests_.push(this.getDaemonState.bind(this, callback)); + break; + case remoting.HostDispatcher.State.NATIVE_MESSAGING: + this.nativeMessagingHost_.getDaemonState(callback); + break; + case remoting.HostDispatcher.State.NPAPI: + // Call the callback directly, since NPAPI exposes the state directly as + // a field member, rather than an asynchronous method. + var state = this.npapiHost_.daemonState; + if (state === undefined) { + // If the plug-in can't be instantiated, for example on ChromeOS, then + // return something sensible. + state = remoting.HostController.State.NOT_IMPLEMENTED; + } + callback(state); + break; + } +} diff --git a/remoting/webapp/host_plugin_wrapper.js b/remoting/webapp/host_plugin_wrapper.js deleted file mode 100644 index 870eec3..0000000 --- a/remoting/webapp/host_plugin_wrapper.js +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file provides a compatibility wrapper around the NPAPI plugin object, -// exposing an interface that matches the Native Messaging interface. - -// TODO(lambroslambrou): Add error callback parameters here, and in Native -// Messaging. The extra callback parameters will be ignored here. - -/** @suppress {duplicate} */ -var remoting = remoting || {}; - -/** - * @constructor - * @param {remoting.HostPlugin} plugin Wrapped NPAPI plugin object. - * @extends remoting.HostNativeMessaging - */ -remoting.HostPluginWrapper = function(plugin) { - /** @type {remoting.HostPlugin} @private */ - this.plugin_ = plugin; -}; - -/** - * @param {function(string):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.getHostName = function(callback) { - this.plugin_.getHostName(callback); -}; - -/** - * @param {string} hostId - * @param {string} pin - * @param {function(string):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.getPinHash = function(hostId, pin, - callback) { - this.plugin_.getPinHash(hostId, pin, callback); -}; - -/** - * @param {function(string, string):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.generateKeyPair = function(callback) { - this.plugin_.generateKeyPair(callback); -}; - -/** - * @param {string} config - * @param {function(remoting.HostController.AsyncResult):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.updateDaemonConfig = function(config, - callback) { - this.plugin_.updateDaemonConfig(config, callback); -}; - -/** - * @param {function(string):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.getDaemonConfig = function(callback) { - this.plugin_.getDaemonConfig(callback); -}; - -/** - * @param {function(string):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.getDaemonVersion = function(callback) { - this.plugin_.getDaemonVersion(callback); -}; - -/** - * @param {function(boolean, boolean, boolean):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.getUsageStatsConsent = function(callback) { - this.plugin_.getUsageStatsConsent(callback); -}; - -/** - * @param {string} config - * @param {function(remoting.HostController.AsyncResult):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.startDaemon = function( - config, consent, callback) { - this.plugin_.startDaemon(config, consent, callback); -}; - -/** - * @param {function(remoting.HostController.AsyncResult):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.stopDaemon = function(callback) { - this.plugin_.stopDaemon(callback); -}; - -/** - * @param {function(remoting.HostController.State):void} callback - * @return {void} - */ -remoting.HostPluginWrapper.prototype.getDaemonState = function(callback) { - // Call the callback directly, since NPAPI exposes the state directly as a - // field member, rather than an asynchronous method. - var state = this.plugin_.daemonState; - if (state === undefined) { - // If the plug-in can't be instantiated, for example on ChromeOS, then - // return something sensible. - state = remoting.HostController.State.NOT_IMPLEMENTED; - } - callback(state); -} diff --git a/remoting/webapp/main.html b/remoting/webapp/main.html index a186e3941..341aa5d 100644 --- a/remoting/webapp/main.html +++ b/remoting/webapp/main.html @@ -27,9 +27,9 @@ found in the LICENSE file. <script src="format_iq.js"></script> <script src="host.js"></script> <script src="host_controller.js"></script> + <script src="host_dispatcher.js"></script> <script src="host_list.js"></script> <script src="host_native_messaging.js"></script> - <script src="host_plugin_wrapper.js"></script> <script src="host_screen.js"></script> <script src="host_session.js"></script> <script src="host_settings.js"></script> |