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
.HostIt2MeNativeMessaging = function() {
26 * @type {?chrome.extension.Port}
35 this.accessCode_
= '';
41 this.accessCodeLifetime_
= 0;
53 this.initialized_
= false;
56 * @type {function():void}
59 this.onHostStarted_ = function() {};
62 * Called if Native Messaging host has failed to start.
65 this.onHostInitFailed_ = 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, onHostInitFailed is invoked.
92 * Otherwise, onHostStarted is invoked.
94 * @param {function():void} onHostStarted Called after successful
96 * @param {function():void} onHostInitFailed Called if cannot connect to host.
97 * @param {function(remoting.Error):void} onError Called on host error after
98 * successfully connecting to the host.
101 remoting
.HostIt2MeNativeMessaging
.prototype.initialize
=
102 function(onHostStarted
, onHostInitFailed
, onError
) {
103 this.onHostStarted_
= onHostStarted
;
104 this.onHostInitFailed_
= onHostInitFailed
;
105 this.onError_
= onError
;
108 this.port_
= chrome
.runtime
.connectNative(
109 'com.google.chrome.remote_assistance');
110 this.port_
.onMessage
.addListener(this.onIncomingMessage_
.bind(this));
111 this.port_
.onDisconnect
.addListener(this.onHostDisconnect_
.bind(this));
112 this.postMessage_({type
: 'hello'});
114 console
.log('Native Messaging initialization failed: ',
115 /** @type {*} */ (err
));
122 * Attaches a new ID to the supplied message, and posts it to the Native
124 * |message| should have its 'type' field set, and any other fields set
125 * depending on the message type.
127 * @param {{type: string}} message The message to post.
131 remoting
.HostIt2MeNativeMessaging
.prototype.postMessage_
=
133 var id
= this.nextId_
++;
135 this.port_
.postMessage(message
);
139 * Handler for incoming Native Messages.
141 * @param {Object} message The received message.
145 remoting
.HostIt2MeNativeMessaging
.prototype.onIncomingMessage_
=
148 this.handleIncomingMessage_(message
);
150 console
.error(/** @type {*} */ (e
));
151 this.onError_(remoting
.Error
.UNEXPECTED
);
156 * Handler for incoming Native Messages.
158 * @param {Object} message The received message.
162 remoting
.HostIt2MeNativeMessaging
.prototype.handleIncomingMessage_
=
164 var type
= getStringAttr(message
, 'type');
167 case 'helloResponse':
168 var version
= getStringAttr(message
, 'version');
169 console
.log('Host version: ', version
);
170 this.initialized_
= true;
171 // A "hello" request is sent immediately after the native messaging host
172 // is started. We can proceed to the next task once we receive the
174 this.onHostStarted_();
177 case 'connectResponse':
178 console
.log('connectResponse received');
179 // Response to the "connect" request. No action is needed until we
180 // receive the corresponding "hostStateChanged" message.
183 case 'disconnectResponse':
184 console
.log('disconnectResponse received');
185 // Response to the "disconnect" request. No action is needed until we
186 // receive the corresponding "hostStateChanged" message.
189 case 'hostStateChanged':
190 var stateString
= getStringAttr(message
, 'state');
191 console
.log('hostStateChanged received: ', stateString
);
192 var state
= remoting
.HostSession
.State
.fromString(stateString
);
195 case remoting
.HostSession
.State
.RECEIVED_ACCESS_CODE
:
196 var accessCode
= getStringAttr(message
, 'accessCode');
197 var accessCodeLifetime
= getNumberAttr(message
, 'accessCodeLifetime');
198 this.onReceivedAccessCode_(accessCode
, accessCodeLifetime
);
201 case remoting
.HostSession
.State
.CONNECTED
:
202 var client
= getStringAttr(message
, 'client');
203 this.onConnected_(client
);
206 this.onStateChanged_(state
);
209 case 'natPolicyChanged':
210 var natTraversalEnabled
= getBooleanAttr(message
, 'natTraversalEnabled');
211 this.onNatPolicyChanged_(natTraversalEnabled
);
215 console
.error(getStringAttr(message
, 'description'));
216 this.onError_(remoting
.Error
.UNEXPECTED
);
220 throw 'Unexpected native message: ' + message
;
225 * @param {string} email The user's email address.
226 * @param {string} authServiceWithToken Concatenation of the auth service
227 * (e.g. oauth2) and the access token.
228 * @param {function(remoting.HostSession.State):void} onStateChanged Callback to
229 * invoke when the host state changes.
230 * @param {function(boolean):void} onNatPolicyChanged Callback to invoke when
231 * the nat traversal policy changes.
232 * @param {string} xmppServerAddress XMPP server host name (or IP address) and
234 * @param {boolean} xmppServerUseTls Whether to use TLS on connections to the
236 * @param {string} directoryBotJid XMPP JID for the remoting directory server
240 remoting
.HostIt2MeNativeMessaging
.prototype.connect
=
241 function(email
, authServiceWithToken
, onStateChanged
, onNatPolicyChanged
,
242 xmppServerAddress
, xmppServerUseTls
, directoryBotJid
) {
243 this.onStateChanged_
= onStateChanged
;
244 this.onNatPolicyChanged_
= onNatPolicyChanged
;
248 authServiceWithToken
: authServiceWithToken
,
249 xmppServerAddress
: xmppServerAddress
,
250 xmppServerUseTls
: xmppServerUseTls
,
251 directoryBotJid
: directoryBotJid
});
257 remoting
.HostIt2MeNativeMessaging
.prototype.disconnect
=
260 type
: 'disconnect'});
264 * @param {string} accessCode
265 * @param {number} accessCodeLifetime
269 remoting
.HostIt2MeNativeMessaging
.prototype.onReceivedAccessCode_
=
270 function(accessCode
, accessCodeLifetime
) {
271 this.accessCode_
= accessCode
;
272 this.accessCodeLifetime_
= accessCodeLifetime
;
276 * @param {string} clientId
280 remoting
.HostIt2MeNativeMessaging
.prototype.onConnected_
=
282 this.clientId_
= clientId
;
289 remoting
.HostIt2MeNativeMessaging
.prototype.onHostDisconnect_ = function() {
290 if (!this.initialized_
) {
291 // If the host is disconnected before it is initialized, it probably means
292 // the host is not propertly installed (or not installed at all).
293 // E.g., if the host manifest is not present we get "Specified native
294 // messaging host not found" error. If the host manifest is present but
295 // the host binary cannot be found we get the "Native host has exited"
297 console
.log('Native Messaging initialization failed: ' +
298 chrome
.runtime
.lastError
.message
);
299 this.onHostInitFailed_();
301 console
.error('Native Messaging port disconnected.');
302 this.onError_(remoting
.Error
.UNEXPECTED
);
309 remoting
.HostIt2MeNativeMessaging
.prototype.getAccessCode = function() {
310 return this.accessCode_
316 remoting
.HostIt2MeNativeMessaging
.prototype.getAccessCodeLifetime = function() {
317 return this.accessCodeLifetime_
323 remoting
.HostIt2MeNativeMessaging
.prototype.getClient = function() {
324 return this.clientId_
;