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
;