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 * This class implements the functionality that is specific to desktop
8 * remoting ("Chromoting" or CRD).
13 /** @suppress {duplicate} */
14 var remoting = remoting || {};
18 * @implements {remoting.ApplicationInterface}
19 * @extends {remoting.Application}
21 remoting.DesktopRemoting = function() {
22 base.inherits(this, remoting.Application);
24 // Save recent errors for inclusion in user feedback.
25 remoting.ConsoleWrapper.getInstance().activate(
27 remoting.ConsoleWrapper.LogType.ERROR,
28 remoting.ConsoleWrapper.LogType.ASSERT);
30 /** @protected {remoting.DesktopRemoting.Mode} */
31 this.connectionMode_ = remoting.DesktopRemoting.Mode.ME2ME;
33 /** @private {remoting.Activity} */
34 this.activity_ = null;
38 * The current desktop remoting mode (IT2Me or Me2Me).
42 remoting.DesktopRemoting.Mode = {
48 * Get the connection mode (Me2Me or IT2Me).
50 * @return {remoting.DesktopRemoting.Mode}
52 remoting.DesktopRemoting.prototype.getConnectionMode = function() {
53 return this.connectionMode_;
57 * @return {string} Application Id.
58 * @override {remoting.ApplicationInterface}
60 remoting.DesktopRemoting.prototype.getApplicationId = function() {
61 // Application IDs are not used in desktop remoting.
66 * @return {string} Application product name to be used in UI.
67 * @override {remoting.ApplicationInterface}
69 remoting.DesktopRemoting.prototype.getApplicationName = function() {
70 return chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME');
74 * @param {!remoting.Error} error The failure reason.
75 * @override {remoting.ApplicationInterface}
77 remoting.DesktopRemoting.prototype.signInFailed_ = function(error) {
78 remoting.showErrorMessage(error);
82 * @override {remoting.ApplicationInterface}
84 remoting.DesktopRemoting.prototype.initApplication_ = function() {
85 remoting.initElementEventHandlers();
87 if (remoting.platformIsWindows()) {
88 document.body.classList.add('os-windows');
89 } else if (remoting.platformIsMac()) {
90 document.body.classList.add('os-mac');
91 } else if (remoting.platformIsChromeOS()) {
92 document.body.classList.add('os-chromeos');
93 } else if (remoting.platformIsLinux()) {
94 document.body.classList.add('os-linux');
97 if (base.isAppsV2()) {
98 remoting.windowFrame = new remoting.WindowFrame(
99 document.getElementById('title-bar'), this.disconnect_.bind(this));
100 remoting.optionsMenu = remoting.windowFrame.createOptionsMenu();
102 var START_FULLSCREEN = 'start-fullscreen';
103 remoting.fullscreen = new remoting.FullscreenAppsV2();
104 remoting.fullscreen.addListener(function(isFullscreen) {
105 chrome.storage.local.set({START_FULLSCREEN: isFullscreen});
107 // TODO(jamiewalch): This should be handled by the background page when the
108 // window is created, but due to crbug.com/51587 it needs to be done here.
109 // Remove this hack once that bug is fixed.
110 chrome.storage.local.get(
112 /** @param {Object} values */
114 if (values[START_FULLSCREEN]) {
115 remoting.fullscreen.activate(true);
121 remoting.fullscreen = new remoting.FullscreenAppsV1();
122 remoting.toolbar = new remoting.Toolbar(
123 document.getElementById('session-toolbar'),
124 this.disconnect_.bind(this));
125 remoting.optionsMenu = remoting.toolbar.createOptionsMenu();
127 window.addEventListener('beforeunload',
128 this.promptClose_.bind(this), false);
129 window.addEventListener('unload', this.disconnect_.bind(this), false);
132 remoting.initHostlist_(this.connectMe2Me_.bind(this));
133 document.getElementById('access-mode-button').addEventListener(
134 'click', this.connectIt2Me_.bind(this), false);
136 remoting.manageHelpAndFeedback(
137 document.getElementById('title-bar'));
139 remoting.showOrHideIT2MeUi();
140 remoting.showOrHideMe2MeUi();
142 // For Apps v1, check the tab type to warn the user if they are not getting
143 // the best keyboard experience.
144 if (!base.isAppsV2() && !remoting.platformIsMac()) {
145 /** @param {boolean} isWindowed */
146 var onIsWindowed = function(isWindowed) {
148 document.getElementById('startup-mode-box-me2me').hidden = false;
149 document.getElementById('startup-mode-box-it2me').hidden = false;
152 this.isWindowed_(onIsWindowed);
155 remoting.ClientPlugin.factory.preloadPlugin();
159 * @param {string} token An OAuth access token.
160 * @override {remoting.ApplicationInterface}
162 remoting.DesktopRemoting.prototype.startApplication_ = function(token) {
163 remoting.identity.getEmail().then(
164 function(/** string */ email) {
165 document.getElementById('current-email').innerText = email;
166 document.getElementById('get-started-it2me').disabled = false;
167 document.getElementById('get-started-me2me').disabled = false;
171 /** @override {remoting.ApplicationInterface} */
172 remoting.DesktopRemoting.prototype.exitApplication_ = function() {
174 this.closeMainWindow_();
178 * Determine whether or not the app is running in a window.
179 * @param {function(boolean):void} callback Callback to receive whether or not
180 * the current tab is running in windowed mode.
183 remoting.DesktopRemoting.prototype.isWindowed_ = function(callback) {
184 var windowCallback = function(/** ChromeWindow */ win) {
185 callback(win.type == 'popup');
187 /** @param {Tab=} tab */
188 var tabCallback = function(tab) {
192 chrome.windows.get(tab.windowId, null, windowCallback);
196 chrome.tabs.getCurrent(tabCallback);
198 console.error('chome.tabs is not available.');
203 * If an IT2Me client or host is active then prompt the user before closing.
204 * If a Me2Me client is active then don't bother, since closing the window is
205 * the more intuitive way to end a Me2Me session, and re-connecting is easy.
208 remoting.DesktopRemoting.prototype.promptClose_ = function() {
209 if (this.getConnectionMode() === remoting.DesktopRemoting.Mode.IT2ME) {
210 switch (remoting.currentMode) {
211 case remoting.AppMode.CLIENT_CONNECTING:
212 case remoting.AppMode.HOST_WAITING_FOR_CODE:
213 case remoting.AppMode.HOST_WAITING_FOR_CONNECTION:
214 case remoting.AppMode.HOST_SHARED:
215 case remoting.AppMode.IN_SESSION:
216 return chrome.i18n.getMessage(/*i18n-content*/'CLOSE_PROMPT');
223 /** @returns {remoting.DesktopConnectedView} */
224 remoting.DesktopRemoting.prototype.getConnectedViewForTesting = function() {
225 var activity = /** @type {remoting.Me2MeActivity} */ (this.activity_);
226 return activity.getDesktopActivity().getConnectedView();
229 remoting.DesktopRemoting.prototype.getActivity = function() {
230 return this.activity_;
233 remoting.DesktopRemoting.prototype.disconnect_ = function() {
234 if (this.activity_) {
235 this.activity_.stop();
240 * Entry-point for Me2Me connections.
242 * @param {string} hostId The unique id of the host.
243 * @return {void} Nothing.
246 remoting.DesktopRemoting.prototype.connectMe2Me_ = function(hostId) {
247 var host = remoting.hostList.getHostForId(hostId);
248 base.dispose(this.activity_);
249 this.activity_ = new remoting.Me2MeActivity(host, remoting.hostList);
250 this.activity_.start();
251 this.connectionMode_ = remoting.DesktopRemoting.Mode.ME2ME;
255 * Entry-point for It2Me connections.
259 remoting.DesktopRemoting.prototype.connectIt2Me_ = function() {
260 base.dispose(this.activity_);
261 this.activity_ = new remoting.It2MeActivity();
262 this.activity_.start();
263 this.connectionMode_ = remoting.DesktopRemoting.Mode.IT2ME;