OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 /** |
| 6 * @fileoverview |
| 7 * It2MeService listens to incoming connections requests from Hangouts |
| 8 * and the webapp and creates a It2MeHelperChannel between them. |
| 9 * It supports multiple helper sessions, but only a single helpee. |
| 10 */ |
| 11 |
| 12 'use strict'; |
| 13 |
| 14 /** @suppress {duplicate} */ |
| 15 var remoting = remoting || {}; |
| 16 |
| 17 /** |
| 18 * @param {remoting.AppLauncher} appLauncher |
| 19 * @constructor |
| 20 */ |
| 21 remoting.It2MeService = function(appLauncher) { |
| 22 /** |
| 23 * @type {remoting.AppLauncher} |
| 24 * @private |
| 25 */ |
| 26 this.appLauncher_ = appLauncher; |
| 27 |
| 28 /** |
| 29 * @type {Array.<remoting.It2MeHelperChannel>} |
| 30 * @private |
| 31 */ |
| 32 this.helpers_ = []; |
| 33 |
| 34 /** @private */ |
| 35 this.helpee_ = null; |
| 36 |
| 37 this.onWebappConnectRef_ = this.onWebappConnect_.bind(this); |
| 38 this.onMessageExternalRef_ = this.onMessageExternal_.bind(this); |
| 39 this.onConnectExternalRef_ = this.onConnectExternal_.bind(this); |
| 40 }; |
| 41 |
| 42 /** @enum {string} */ |
| 43 remoting.It2MeService.ConnectionTypes = { |
| 44 HELPER_HANGOUT: 'it2me.helper.hangout', |
| 45 HELPEE_HANGOUT: 'it2me.helpee.hangout', |
| 46 HELPER_WEBAPP: 'it2me.helper.webapp' |
| 47 }; |
| 48 |
| 49 /** |
| 50 * Starts listening to external connection from Hangouts and the webapp. |
| 51 */ |
| 52 remoting.It2MeService.prototype.init = function() { |
| 53 chrome.runtime.onConnect.addListener(this.onWebappConnectRef_); |
| 54 chrome.runtime.onMessageExternal.addListener(this.onMessageExternalRef_); |
| 55 chrome.runtime.onConnectExternal.addListener(this.onConnectExternalRef_); |
| 56 }; |
| 57 |
| 58 remoting.It2MeService.prototype.dispose = function() { |
| 59 chrome.runtime.onConnect.removeListener(this.onWebappConnectRef_); |
| 60 chrome.runtime.onMessageExternal.removeListener( |
| 61 this.onMessageExternalRef_); |
| 62 chrome.runtime.onConnectExternal.removeListener( |
| 63 this.onConnectExternalRef_); |
| 64 }; |
| 65 |
| 66 /** |
| 67 * This function is called when a runtime message is received from an external |
| 68 * web page (hangout) or extension. |
| 69 * |
| 70 * @param {{method:string, data:Object.<string,*>}} message |
| 71 * @param {chrome.runtime.MessageSender} sender |
| 72 * @param {function(*):void} sendResponse |
| 73 * @private |
| 74 */ |
| 75 remoting.It2MeService.prototype.onMessageExternal_ = |
| 76 function(message, sender, sendResponse) { |
| 77 try { |
| 78 var method = message.method; |
| 79 if (method == 'hello') { |
| 80 // The hello message is used by hangouts to detect whether the app is |
| 81 // installed and what features are supported. |
| 82 sendResponse({ |
| 83 method: 'helloResponse', |
| 84 supportedFeatures: ['it2me'] |
| 85 }); |
| 86 return true; |
| 87 } |
| 88 throw new Error('Unknown method: ' + method); |
| 89 } catch (e) { |
| 90 var error = /** @type {Error} */ e; |
| 91 console.error(error); |
| 92 sendResponse({ |
| 93 method: message.method + 'Response', |
| 94 error: error.message |
| 95 }); |
| 96 } |
| 97 return false; |
| 98 }; |
| 99 |
| 100 /** |
| 101 * This function is called when Hangouts connects via chrome.runtime.connect. |
| 102 * Only web pages that are white-listed in the manifest are allowed to connect. |
| 103 * |
| 104 * @param {chrome.runtime.Port} port |
| 105 * @private |
| 106 */ |
| 107 remoting.It2MeService.prototype.onConnectExternal_ = function(port) { |
| 108 var ConnectionTypes = remoting.It2MeService.ConnectionTypes; |
| 109 try { |
| 110 switch (port.name) { |
| 111 case ConnectionTypes.HELPER_HANGOUT: |
| 112 this.handleExternalHelperConnection_(port); |
| 113 return true; |
| 114 default: |
| 115 throw new Error('Unsupported port - ' + port.name); |
| 116 } |
| 117 } catch (e) { |
| 118 var error = /**@type {Error} */ e; |
| 119 console.error(error); |
| 120 port.disconnect(); |
| 121 } |
| 122 return false; |
| 123 }; |
| 124 |
| 125 /** |
| 126 * @param {chrome.runtime.Port} port |
| 127 * @private |
| 128 */ |
| 129 remoting.It2MeService.prototype.onWebappConnect_ = function(port) { |
| 130 try { |
| 131 console.log('Incoming helper connection from webapp.'); |
| 132 |
| 133 // The senderId (tabId or windowId) of the webapp is embedded in the port |
| 134 // name with the format port_name@senderId. |
| 135 var parts = port.name.split('@'); |
| 136 var portName = parts[0]; |
| 137 var senderId = parts[1]; |
| 138 var ConnectionTypes = remoting.It2MeService.ConnectionTypes; |
| 139 if (portName === ConnectionTypes.HELPER_WEBAPP && senderId !== undefined) { |
| 140 for (var i = 0; i < this.helpers_.length; i++) { |
| 141 var helper = this.helpers_[i]; |
| 142 if (helper.instanceId() === senderId) { |
| 143 helper.onWebappConnect(port, senderId); |
| 144 return; |
| 145 } |
| 146 } |
| 147 } |
| 148 throw new Error('No matching hangout connection found for ' + port.name); |
| 149 } catch (e) { |
| 150 var error = /** @type {Error} */ e; |
| 151 console.error(error); |
| 152 port.disconnect(); |
| 153 } |
| 154 }; |
| 155 |
| 156 /** |
| 157 * @param {remoting.It2MeHelperChannel} helper |
| 158 */ |
| 159 remoting.It2MeService.prototype.onHelperChannelDisconnected = function(helper) { |
| 160 for (var i = 0; i < this.helpers_.length; i++) { |
| 161 if (helper === this.helpers_[i]) { |
| 162 this.helpers_.splice(i, 1); |
| 163 } |
| 164 } |
| 165 }; |
| 166 |
| 167 /** |
| 168 * @param {chrome.runtime.Port} port |
| 169 * @private |
| 170 */ |
| 171 remoting.It2MeService.prototype.handleExternalHelperConnection_ = |
| 172 function(port) { |
| 173 if (this.helpee_) { |
| 174 console.error( |
| 175 'Cannot start a helper session while a helpee session is in process.'); |
| 176 port.disconnect(); |
| 177 } |
| 178 |
| 179 console.log('Incoming helper connection from Hangouts'); |
| 180 var helper = new remoting.It2MeHelperChannel( |
| 181 this.appLauncher_, port, this.onHelperChannelDisconnected.bind(this)); |
| 182 helper.init(); |
| 183 this.helpers_.push(helper); |
| 184 }; |
OLD | NEW |