• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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} */
15var remoting = remoting || {};
16
17/**
18 * @param {remoting.AppLauncher} appLauncher
19 * @constructor
20 */
21remoting.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.onConnectExternalRef_ = this.onConnectExternal_.bind(this);
39};
40
41/** @enum {string} */
42remoting.It2MeService.ConnectionTypes = {
43  HELPER_HANGOUT: 'it2me.helper.hangout',
44  HELPEE_HANGOUT: 'it2me.helpee.hangout',
45  HELPER_WEBAPP: 'it2me.helper.webapp'
46};
47
48/**
49 * Starts listening to external connection from Hangouts and the webapp.
50 */
51remoting.It2MeService.prototype.init = function() {
52  chrome.runtime.onConnect.addListener(this.onWebappConnectRef_);
53  chrome.runtime.onConnectExternal.addListener(this.onConnectExternalRef_);
54};
55
56remoting.It2MeService.prototype.dispose = function() {
57  chrome.runtime.onConnect.removeListener(this.onWebappConnectRef_);
58  chrome.runtime.onConnectExternal.removeListener(
59      this.onConnectExternalRef_);
60};
61
62/**
63 * This function is called when Hangouts connects via chrome.runtime.connect.
64 * Only web pages that are white-listed in the manifest are allowed to connect.
65 *
66 * @param {chrome.runtime.Port} port
67 * @private
68 */
69remoting.It2MeService.prototype.onConnectExternal_ = function(port) {
70  var ConnectionTypes = remoting.It2MeService.ConnectionTypes;
71  try {
72    switch (port.name) {
73      case ConnectionTypes.HELPER_HANGOUT:
74        this.handleExternalHelperConnection_(port);
75        return true;
76      case ConnectionTypes.HELPEE_HANGOUT:
77        this.handleExternalHelpeeConnection_(port);
78        return true;
79      default:
80        throw new Error('Unsupported port - ' + port.name);
81    }
82  } catch (e) {
83    var error = /**@type {Error} */ e;
84    console.error(error);
85    port.disconnect();
86  }
87  return false;
88};
89
90/**
91 * @param {chrome.runtime.Port} port
92 * @private
93 */
94remoting.It2MeService.prototype.onWebappConnect_ = function(port) {
95  try {
96    console.log('Incoming helper connection from webapp.');
97
98    // The senderId (tabId or windowId) of the webapp is embedded in the port
99    // name with the format port_name@senderId.
100    var parts = port.name.split('@');
101    var portName = parts[0];
102    var senderId = parts[1];
103    var ConnectionTypes = remoting.It2MeService.ConnectionTypes;
104    if (portName === ConnectionTypes.HELPER_WEBAPP && senderId !== undefined) {
105      for (var i = 0; i < this.helpers_.length; i++) {
106        var helper = this.helpers_[i];
107        if (helper.instanceId() === senderId) {
108          helper.onWebappConnect(port, senderId);
109          return;
110        }
111      }
112    }
113    throw new Error('No matching hangout connection found for ' + port.name);
114  } catch (e) {
115    var error = /** @type {Error} */ e;
116    console.error(error);
117    port.disconnect();
118  }
119};
120
121/**
122 * @param {remoting.It2MeHelperChannel} helper
123 */
124remoting.It2MeService.prototype.onHelperChannelDisconnected = function(helper) {
125  for (var i = 0; i < this.helpers_.length; i++) {
126    if (helper === this.helpers_[i]) {
127      this.helpers_.splice(i, 1);
128    }
129  }
130};
131
132remoting.It2MeService.prototype.onHelpeeChannelDisconnected = function() {
133  base.debug.assert(this.helpee_ !== null);
134  this.helpee_ = null;
135};
136
137/**
138 * @param {chrome.runtime.Port} port
139 * @private
140 */
141remoting.It2MeService.prototype.handleExternalHelperConnection_ =
142    function(port) {
143  if (this.helpee_) {
144    console.error(
145        'Cannot start a helper session while a helpee session is in process.');
146    port.disconnect();
147    return;
148  }
149
150  console.log('Incoming helper connection from Hangouts');
151  var helper = new remoting.It2MeHelperChannel(
152      this.appLauncher_, port, this.onHelperChannelDisconnected.bind(this));
153  helper.init();
154  this.helpers_.push(helper);
155};
156
157/**
158 * @param {chrome.runtime.Port} hangoutPort Represents a connection to Hangouts.
159 * @private
160 */
161remoting.It2MeService.prototype.handleExternalHelpeeConnection_ =
162    function(hangoutPort) {
163  if (this.helpee_) {
164    console.error('An existing helpee session is in process.');
165    hangoutPort.disconnect();
166    return;
167  }
168
169  console.log('Incoming helpee connection from Hangouts');
170  this.helpee_ = new remoting.It2MeHelpeeChannel(
171      hangoutPort,
172      new remoting.It2MeHostFacade(),
173      new remoting.HostInstaller(),
174      this.onHelpeeChannelDisconnected.bind(this));
175  this.helpee_.init();
176};