1 // Copyright 2014 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.
7 * Class to communicate with the It2me Host component via Native Messaging.
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
18 remoting.It2MeHostFacade = function() {
26 * @type {?chrome.extension.Port}
35 this.accessCode_ = '';
41 this.accessCodeLifetime_ = 0;
53 this.initialized_ = false;
56 * @type {function():void}
59 this.onInitialized_ = function() {};
62 * Called if Native Messaging host has failed to start.
65 this.onInitializationFailed_ = function() {};
68 * Called if the It2Me Native Messaging host sends a malformed message:
69 * missing required attributes, attributes with incorrect types, etc.
70 * @param {remoting.Error} error
73 this.onError_ = function(error) {};
76 * @type {function(remoting.HostSession.State):void}
79 this.onStateChanged_ = function() {};
82 * @type {function(boolean):void}
85 this.onNatPolicyChanged_ = function() {};
89 * Sets up connection to the Native Messaging host process and exchanges
90 * 'hello' messages. If Native Messaging is not supported or if the it2me
91 * native messaging host is not installed, onInitializationFailed is invoked.
92 * Otherwise, onInitialized is invoked.
94 * @param {function():void} onInitialized Called after successful
96 * @param {function():void} onInitializationFailed Called if cannot connect to
97 * the native messaging host.
100 remoting.It2MeHostFacade.prototype.initialize =
101 function(onInitialized, onInitializationFailed) {
102 this.onInitialized_ = onInitialized;
103 this.onInitializationFailed_ = onInitializationFailed;
106 this.port_ = chrome.runtime.connectNative(
107 'com.google.chrome.remote_assistance');
108 this.port_.onMessage.addListener(this.onIncomingMessage_.bind(this));
109 this.port_.onDisconnect.addListener(this.onHostDisconnect_.bind(this));
110 this.port_.postMessage({type: 'hello'});
112 console.log('Native Messaging initialization failed: ',
113 /** @type {*} */ (err));
114 onInitializationFailed();
120 * @param {string} email The user's email address.
121 * @param {string} authServiceWithToken Concatenation of the auth service
122 * (e.g. oauth2) and the access token.
123 * @param {function(remoting.HostSession.State):void} onStateChanged Callback to
124 * invoke when the host state changes.
125 * @param {function(boolean):void} onNatPolicyChanged Callback to invoke when
126 * the nat traversal policy changes.
127 * @param {function(string):void} logDebugInfo Callback allowing the plugin
128 * to log messages to the debug log.
129 * @param {string} xmppServerAddress XMPP server host name (or IP address) and
131 * @param {boolean} xmppServerUseTls Whether to use TLS on connections to the
133 * @param {string} directoryBotJid XMPP JID for the remoting directory server
135 * @param {function(remoting.Error):void} onError Callback to invoke in case of
139 remoting.It2MeHostFacade.prototype.connect =
140 function(email, authServiceWithToken, onStateChanged, onNatPolicyChanged,
141 logDebugInfo, xmppServerAddress, xmppServerUseTls, directoryBotJid,
145 'remoting.It2MeHostFacade.connect() without initialization.');
146 onError(remoting.Error.UNEXPECTED);
150 this.onStateChanged_ = onStateChanged;
151 this.onNatPolicyChanged_ = onNatPolicyChanged;
152 this.onErrorHandler_ = onError;
153 this.port_.postMessage({
156 authServiceWithToken: authServiceWithToken,
157 xmppServerAddress: xmppServerAddress,
158 xmppServerUseTls: xmppServerUseTls,
159 directoryBotJid: directoryBotJid
166 remoting.It2MeHostFacade.prototype.disconnect = function() {
168 this.port_.postMessage({type: 'disconnect'});
174 remoting.It2MeHostFacade.prototype.getAccessCode = function() {
175 return this.accessCode_
181 remoting.It2MeHostFacade.prototype.getAccessCodeLifetime = function() {
182 return this.accessCodeLifetime_
188 remoting.It2MeHostFacade.prototype.getClient = function() {
189 return this.clientId_;
193 * Handler for incoming messages.
195 * @param {Object} message The received message.
199 remoting.It2MeHostFacade.prototype.onIncomingMessage_ =
201 var type = getStringAttr(message, 'type');
204 case 'helloResponse':
205 var version = getStringAttr(message, 'version');
206 console.log('Host version: ', version);
207 this.initialized_ = true;
208 // A "hello" request is sent immediately after the native messaging host
209 // is started. We can proceed to the next task once we receive the
211 this.onInitialized_();
214 case 'connectResponse':
215 console.log('connectResponse received');
216 // Response to the "connect" request. No action is needed until we
217 // receive the corresponding "hostStateChanged" message.
220 case 'disconnectResponse':
221 console.log('disconnectResponse received');
222 // Response to the "disconnect" request. No action is needed until we
223 // receive the corresponding "hostStateChanged" message.
226 case 'hostStateChanged':
227 var stateString = getStringAttr(message, 'state');
228 console.log('hostStateChanged received: ', stateString);
229 var state = remoting.HostSession.State.fromString(stateString);
232 case remoting.HostSession.State.RECEIVED_ACCESS_CODE:
233 var accessCode = getStringAttr(message, 'accessCode');
234 var accessCodeLifetime = getNumberAttr(message, 'accessCodeLifetime');
235 this.onReceivedAccessCode_(accessCode, accessCodeLifetime);
238 case remoting.HostSession.State.CONNECTED:
239 var client = getStringAttr(message, 'client');
240 this.onConnected_(client);
243 this.onStateChanged_(state);
246 case 'natPolicyChanged':
247 var natTraversalEnabled = getBooleanAttr(message, 'natTraversalEnabled');
248 this.onNatPolicyChanged_(natTraversalEnabled);
252 console.error(getStringAttr(message, 'description'));
253 this.onError_(remoting.Error.UNEXPECTED);
257 throw 'Unexpected native message: ' + message;
262 * @param {string} accessCode
263 * @param {number} accessCodeLifetime
267 remoting.It2MeHostFacade.prototype.onReceivedAccessCode_ =
268 function(accessCode, accessCodeLifetime) {
269 this.accessCode_ = accessCode;
270 this.accessCodeLifetime_ = accessCodeLifetime;
274 * @param {string} clientId
278 remoting.It2MeHostFacade.prototype.onConnected_ = function(clientId) {
279 this.clientId_ = clientId;
286 remoting.It2MeHostFacade.prototype.onHostDisconnect_ = function() {
287 if (!this.initialized_) {
288 // If the host is disconnected before it is initialized, it probably means
289 // the host is not propertly installed (or not installed at all).
290 // E.g., if the host manifest is not present we get "Specified native
291 // messaging host not found" error. If the host manifest is present but
292 // the host binary cannot be found we get the "Native host has exited"
294 console.log('Native Messaging initialization failed: ' +
295 chrome.runtime.lastError.message);
296 this.onInitializationFailed_();
298 console.error('Native Messaging port disconnected.');
300 this.onError_(remoting.Error.UNEXPECTED);