Chromium Code Reviews| Index: remoting/webapp/background/it2me_service.js |
| diff --git a/remoting/webapp/background/it2me_service.js b/remoting/webapp/background/it2me_service.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..db5c2a06bd9b7ded7c990989b39b692b5983762f |
| --- /dev/null |
| +++ b/remoting/webapp/background/it2me_service.js |
| @@ -0,0 +1,177 @@ |
| +// Copyright 2014 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 |
| + * It2MeService listens to incoming connections requests from Hangouts |
| + * and the webapp and creates a It2MeHelperChannel between them. |
| + * It supports multiple concurrent helper sessions. |
|
Jamie
2014/08/13 01:44:53
Add ", but only a single helpee."
|
| + */ |
| + |
| +'use strict'; |
| + |
| +/** @suppress {duplicate} */ |
| +var remoting = remoting || {}; |
| + |
| +/** |
| + * @param {remoting.AppLauncher} appLauncher |
| + * @constructor |
| + */ |
| +remoting.It2MeService = function(appLauncher) { |
| + /** |
| + * @type {remoting.AppLauncher} |
| + * @private |
| + */ |
| + this.appLauncher_ = appLauncher; |
| + |
| + /** |
| + * @type {Array.<remoting.It2MeHelperChannel>} |
| + * @private |
| + */ |
| + this.helpers_ = []; |
| + |
| + /** @private */ |
|
Jamie
2014/08/13 01:44:53
Type?
kelvinp
2014/08/13 23:44:10
Will be filled on the next CL
|
| + this.helpee_ = null; |
| + |
| + this.onWebappConnectRef_ = this.onWebappConnect_.bind(this); |
| + this.onMessageExternalRef_ = this.onMessageExternal_.bind(this); |
| + this.onConnectExternalRef_ = this.onConnectExternal_.bind(this); |
| +}; |
| + |
| +/** @enum {string} */ |
| +remoting.It2MeService.ConnectionTypes = { |
|
kelvinp
2014/08/13 00:08:48
These names are not global. They only needs to be
Jamie
2014/08/13 01:44:53
Acknowledged.
|
| + HELPER_HANGOUT: 'it2me.helper.hangout', |
| + HELPEE_HANGOUT: 'it2me.helpee.hangout', |
| + HELPER_WEBAPP: 'it2me.helper.webapp' |
| +}; |
| + |
| +/** |
| + * Starts listening to external connection from Hangouts and the webapp. |
| + */ |
| +remoting.It2MeService.prototype.init = function() { |
| + chrome.runtime.onConnect.addListener(this.onWebappConnectRef_); |
| + chrome.runtime.onMessageExternal.addListener(this.onMessageExternalRef_); |
| + chrome.runtime.onConnectExternal.addListener(this.onConnectExternalRef_); |
| +}; |
| + |
| +remoting.It2MeService.prototype.dispose = function() { |
| + chrome.runtime.onConnect.removeListener(this.onWebappConnectRef_); |
| + chrome.runtime.onMessageExternal.removeListener( |
| + this.onMessageExternalRef_); |
| + chrome.runtime.onConnectExternal.removeListener( |
| + this.onConnectExternalRef_); |
| +}; |
| + |
| +/** |
| + * This function is called when a runtime message is received from an external |
| + * web page (hangout) or extension. |
| + * |
| + * @param {{method:string, data:Object.<string,*>}} message |
| + * @param {chrome.runtime.MessageSender} sender |
| + * @param {Function} sendResponse |
|
Jamie
2014/08/13 01:44:53
s/Function/function/
Ideally, it should have a pr
kelvinp
2014/08/13 23:44:10
Acknowledged.
|
| + */ |
| +remoting.It2MeService.prototype.onMessageExternal_ = |
| + function(message, sender, sendResponse) { |
| + try { |
| + var method = message.method; |
| + var isHandled = false; |
|
Jamie
2014/08/13 01:44:53
You're not using this.
kelvinp
2014/08/13 23:44:10
Done.
|
| + |
| + if (method == 'hello') { |
| + // The hello message is used by hangouts to detect whether the app is |
| + // installed and what features are supported. |
| + sendResponse({ |
| + method: 'helloResponse', |
| + supportedFeatures: ['it2me'] |
| + }); |
| + return true; |
| + } |
| + throw new Error('Unknown method: ' + method); |
| + } catch (e) { |
| + var error = /** @type {Error} */ e; |
|
Jamie
2014/08/13 01:44:53
I think you should log this error.
|
| + sendResponse({ |
| + method: message.method + 'Response', |
|
Jamie
2014/08/13 01:44:53
Does the API guarantee that message is an object?
kelvinp
2014/08/13 23:44:10
Yes, the messaging API requires the message object
|
| + error: error.message |
|
Jamie
2014/08/13 01:44:53
Are you guaranteed that error will be an object wi
kelvinp
2014/08/13 23:44:10
Errors thrown by sendResponse will still have a me
|
| + }); |
| + } |
|
Jamie
2014/08/13 01:44:53
return false
kelvinp
2014/08/13 23:44:10
Done.
|
| +}; |
| + |
| +/** |
| + * This function is called when Hangouts connects via chrome.runtime.connect. |
| + * Only web pages that are white-listed in the manifest are allowed to connect. |
| + * |
| + * @param {chrome.runtime.Port} port |
| + */ |
| +remoting.It2MeService.prototype.onConnectExternal_ = function(port) { |
| + var ConnectionTypes = remoting.It2MeService.ConnectionTypes; |
| + try { |
| + switch (port.name) { |
|
kelvinp
2014/08/13 00:08:48
Only are web-pages that are white-listed in the ma
Jamie
2014/08/13 01:44:53
Acknowledged.
|
| + case ConnectionTypes.HELPER_HANGOUT: |
| + this.handleExternalHelperConnection_(port); |
| + return true; |
| + default: |
| + throw new Error('Unsupported port - ' + port.name); |
| + } |
| + } catch (e) { |
| + port.disconnect(); |
|
Jamie
2014/08/13 01:44:53
Log the error?
kelvinp
2014/08/13 23:44:10
Done.
|
| + } |
|
Jamie
2014/08/13 01:44:53
return false
kelvinp
2014/08/13 23:44:10
Done.
|
| +}; |
| + |
| +/** |
| + * @param {chrome.runtime.Port} port |
| + */ |
| +remoting.It2MeService.prototype.onWebappConnect_ = function(port) { |
| + try { |
| + console.log('Incoming helper connection from webapp.'); |
| + |
| + // The senderId (tabId or windowId) of the webapp is embedded in the port |
| + // name with the format port_name@senderId. |
| + var parts = port.name.split('@'); |
| + var portName = parts[0]; |
| + var senderId = parts[1]; |
| + var ConnectionTypes = remoting.It2MeService.ConnectionTypes; |
| + if (portName === ConnectionTypes.HELPER_WEBAPP && senderId !== undefined) { |
| + for (var i = 0; i < this.helpers_.length; i++) { |
| + var helper = this.helpers_[i]; |
| + if (helper.instanceId() === senderId) { |
| + helper.onWebappConnect(port, senderId); |
| + return; |
| + } |
| + } |
| + } |
| + throw new Error('No matching hangout connection found for ' + port.name); |
| + } catch (e) { |
| + var error = /** @type {Error} */ e; |
| + console.error(error); |
| + port.disconnect(); |
| + } |
| +}; |
| + |
| +/** |
| + * @param {remoting.It2MeHelperChannel} helper |
| + */ |
| +remoting.It2MeService.prototype.onHelperChannelDisconnected = function(helper) { |
| + for (var i = 0; i < this.helpers_.length; i++) { |
| + if (helper === this.helpers_[i]) { |
| + this.helpers_.splice(i, 1); |
| + } |
| + } |
| +}; |
| + |
| +/** |
| + * @param {chrome.runtime.Port} port |
| + */ |
| +remoting.It2MeService.prototype.handleExternalHelperConnection_ = |
| + function(port) { |
| + if (this.helpee_) { |
| + console.error( |
| + 'Cannot start a helper session while a helpee session is in process.'); |
|
kelvinp
2014/08/13 00:08:48
Not sure what do you mean by making this error pro
Jamie
2014/08/13 01:44:53
I think I meant it should be surfaced in the UI so
kelvinp
2014/08/13 23:44:10
Since this is called by external code, I think it
|
| + port.disconnect(); |
| + } |
| + |
| + console.log('Incoming helper connection from Hangouts'); |
| + var helper = new remoting.It2MeHelperChannel( |
| + this.appLauncher_, port, this.onHelperChannelDisconnected.bind(this)); |
| + helper.init(); |
| + this.helpers_.push(helper); |
| +}; |