diff options
author | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-30 20:02:23 +0000 |
---|---|---|
committer | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-30 20:02:23 +0000 |
commit | 63157e7efd57c3b7bd89af64607eea1a8f460bb6 (patch) | |
tree | 6dffd9eeee4d2a09d91cab086e03f40981fd2cc9 /remoting/webapp | |
parent | 2a5c8be4bd97e396000cfe767820c31da6ebbd84 (diff) | |
download | chromium_src-63157e7efd57c3b7bd89af64607eea1a8f460bb6.zip chromium_src-63157e7efd57c3b7bd89af64607eea1a8f460bb6.tar.gz chromium_src-63157e7efd57c3b7bd89af64607eea1a8f460bb6.tar.bz2 |
Implement hello exchange with Chromoting Native Messaging host
The webapp initializes Native Messaging, sends a 'hello'
message to the host and waits for a response. If this fails,
the webapp gets a disconnect notification on the port (if it
was successfully created) and falls back to using the NPAPI
plugin.
BUG=173509
TEST=manual
Review URL: https://chromiumcodereview.appspot.com/13284002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191544 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/webapp')
-rw-r--r-- | remoting/webapp/host_controller.js | 58 | ||||
-rw-r--r-- | remoting/webapp/host_native_messaging.js | 92 |
2 files changed, 104 insertions, 46 deletions
diff --git a/remoting/webapp/host_controller.js b/remoting/webapp/host_controller.js index c35d63c..fd54442 100644 --- a/remoting/webapp/host_controller.js +++ b/remoting/webapp/host_controller.js @@ -9,34 +9,46 @@ var remoting = remoting || {}; /** @constructor */ remoting.HostController = function() { + /** @type {remoting.HostController} */ + var that = this; + + /** @type {boolean} @private */ + this.pluginSupported_ = true; + /** @type {remoting.HostPlugin} @private */ - this.plugin_ = null; - if (remoting.HostNativeMessaging.isSupported()) { - this.plugin_ = new remoting.HostNativeMessaging(); - } else { - this.plugin_ = remoting.HostSession.createPlugin(); - /** @type {HTMLElement} @private */ - var container = document.getElementById('daemon-plugin-container'); - container.appendChild(this.plugin_); - } + this.plugin_ = new remoting.HostNativeMessaging(); - /** @param {string} version */ - var printVersion = function(version) { - if (version == '') { - console.log('Host not installed.'); + /** @param {boolean} success */ + var onNativeMessagingInit = function(success) { + if (success) { + console.log('Native Messaging supported.'); } else { - console.log('Host version: ' + version); + console.log('Native Messaging unsupported, falling back to NPAPI.'); + that.plugin_ = remoting.HostSession.createPlugin(); + /** @type {HTMLElement} @private */ + var container = document.getElementById('daemon-plugin-container'); + container.appendChild(that.plugin_); + } + + /** @param {string} version */ + var printVersion = function(version) { + if (version == '') { + console.log('Host not installed.'); + } else { + console.log('Host version: ' + version); + } + }; + that.pluginSupported_ = true; + try { + that.plugin_.getDaemonVersion(printVersion); + } catch (err) { + console.log('Host version not available.'); + that.pluginSupported_ = false; } - }; - /** @type {boolean} @private */ - this.pluginSupported_ = true; - try { - this.plugin_.getDaemonVersion(printVersion); - } catch (err) { - console.log('Host version not available.'); - this.pluginSupported_ = false; } -}; + + this.plugin_.initialize(onNativeMessagingInit); +} // Note that the values in the enums below are copied from // daemon_controller.h and must be kept in sync. diff --git a/remoting/webapp/host_native_messaging.js b/remoting/webapp/host_native_messaging.js index 64576a5..b1e58f0 100644 --- a/remoting/webapp/host_native_messaging.js +++ b/remoting/webapp/host_native_messaging.js @@ -24,26 +24,51 @@ remoting.HostNativeMessaging = function() { this.nextId_ = 0; /** - * @type {Object.<number, {callback:function(...):void, type:string}>} + * @type {Object.<number, {callback:?function(...):void, type:string}>} * @private */ this.pendingReplies_ = {}; - /** @private */ - this.port_ = chrome.runtime.connectNative( - 'chrome-remote-desktop-native-host'); - this.port_.onMessage.addListener(this.onIncomingMessage_.bind(this)); + /** @type {?chrome.extension.Port} @private */ + this.port_ = null; + + /** @type {?function(boolean):void} @private */ + this.onInitializedCallback_ = null; + + /** @type {string} @private */ + this.version_ = '' }; /** - * @return {boolean} True if native messaging is supported. + * Sets up connection to the Native Messaging host process and exchanges + * 'hello' messages. If Native Messaging is not available or the host + * process is not installed, this returns false to the callback. + * + * @param {function(boolean): void} onDone Called with the result of + * initialization. + * @return {void} Nothing. */ -remoting.HostNativeMessaging.isSupported = function() { - // TODO(lambroslambrou): This needs to perform an asynchronous "hello" - // exchange with the native host component (possibly getting its version - // number at the same time), and report the result via a regular callback or - // an error callback. For now, simply return false here. - return false; +remoting.HostNativeMessaging.prototype.initialize = function(onDone) { + if (!chrome.runtime.connectNative) { + console.log('Native Messaging API not available'); + onDone(false); + return; + } + + try { + this.port_ = chrome.runtime.connectNative( + 'com.google.chrome.remote_desktop'); + this.port_.onMessage.addListener(this.onIncomingMessage_.bind(this)); + this.port_.onDisconnect.addListener(this.onDisconnect_.bind(this)); + this.postMessage_({type: 'hello'}, null); + } catch (err) { + console.log('Native Messaging initialization failed: ', + /** @type {*} */ (err)); + onDone(false); + return; + } + + this.onInitializedCallback_ = onDone; }; /** @@ -90,8 +115,8 @@ function asAsyncResult_(result) { * depending on the message type. * * @param {{type: string}} message The message to post. - * @param {function(...):void} callback The callback to be triggered on - * response. + * @param {?function(...):void} callback The callback, if any, to be triggered + * on response. * @return {void} Nothing. * @private */ @@ -143,6 +168,20 @@ remoting.HostNativeMessaging.prototype.onIncomingMessage_ = function(message) { // TODO(lambroslambrou): Errors here should be passed to an error-callback // supplied by the caller of this interface. switch (type) { + case 'helloResponse': + /** @type {string} */ + var version = message['version']; + if (checkType_('version', version, 'string')) { + this.version_ = version; + if (this.onInitializedCallback_) { + this.onInitializedCallback_(true); + this.onInitializedCallback_ = null; + } else { + console.error('Unexpected helloResponse received.'); + } + } + break; + case 'getHostNameResponse': /** @type {*} */ var hostname = message['hostname']; @@ -185,14 +224,6 @@ remoting.HostNativeMessaging.prototype.onIncomingMessage_ = function(message) { } break; - case 'getDaemonVersionResponse': - /** @type {*} */ - var version = message['version']; - if (checkType_('version', version, 'string')) { - callback(version); - } - break; - case 'getUsageStatsConsentResponse': /** @type {*} */ var supported = message['supported']; @@ -221,6 +252,18 @@ remoting.HostNativeMessaging.prototype.onIncomingMessage_ = function(message) { }; /** + * @return {void} Nothing. + * @private + */ +remoting.HostNativeMessaging.prototype.onDisconnect_ = function() { + console.log('Native Message port disconnected'); + if (this.onInitializedCallback_) { + this.onInitializedCallback_(false); + this.onInitializedCallback_ = null; + } +} + +/** * @param {string} email The email address of the connector. * @param {string} token The access token for the connector. * @return {void} Nothing. @@ -321,7 +364,10 @@ remoting.HostNativeMessaging.prototype.getDaemonConfig = function(callback) { * @return {void} Nothing. */ remoting.HostNativeMessaging.prototype.getDaemonVersion = function(callback) { - this.postMessage_({type: 'getDaemonVersion'}, callback); + // Return the cached version from the 'hello' exchange. This interface needs + // to be asynchronous because the NPAPI version is, and this implements the + // same interface. + callback(this.version_); }; /** |