Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: remoting/webapp/crd/js/host_screen.js

Issue 895723006: Fix It2Me Host doesn't kill the native process after canceling a share (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reviewer's feedback Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | remoting/webapp/crd/js/host_session.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview 6 * @fileoverview
7 * Functions related to the 'host screen' for Chromoting. 7 * Functions related to the 'host screen' for Chromoting.
8 */ 8 */
9 9
10 'use strict';
11
12 /** @suppress {duplicate} */ 10 /** @suppress {duplicate} */
13 var remoting = remoting || {}; 11 var remoting = remoting || {};
14 12
13 (function(){
14
15 'use strict';
16
15 /** @type {remoting.HostSession} */ 17 /** @type {remoting.HostSession} */
16 remoting.hostSession = null; 18 var hostSession_ = null;
17 19
18 /** 20 /**
19 * @type {boolean} Whether or not the last share was cancelled by the user. 21 * @type {boolean} Whether or not the last share was cancelled by the user.
20 * This controls what screen is shown when the host signals completion. 22 * This controls what screen is shown when the host signals completion.
21 * @private
22 */ 23 */
23 var lastShareWasCancelled_ = false; 24 var lastShareWasCancelled_ = false;
24 25
25 /** 26 /**
26 * Start a host session. This is the main entry point for the host screen, 27 * Start a host session. This is the main entry point for the host screen,
27 * called directly from the onclick action of a button on the home screen. 28 * called directly from the onclick action of a button on the home screen.
28 * It first verifies that the native host components are installed and asks 29 * It first verifies that the native host components are installed and asks
29 * to install them if necessary. 30 * to install them if necessary.
30 */ 31 */
31 remoting.tryShare = function() { 32 remoting.tryShare = function() {
32 /** @type {remoting.It2MeHostFacade} */ 33 /** @type {remoting.It2MeHostFacade} */
33 var hostFacade = new remoting.It2MeHostFacade(); 34 var hostFacade = new remoting.It2MeHostFacade();
34 35
35 /** @type {remoting.HostInstallDialog} */ 36 /** @type {remoting.HostInstallDialog} */
36 var hostInstallDialog = null; 37 var hostInstallDialog = null;
37 38
38 var tryInitializeFacade = function() { 39 var tryInitializeFacade = function() {
39 hostFacade.initialize(onFacadeInitialized, onFacadeInitializationFailed); 40 hostFacade.initialize(onFacadeInitialized, onFacadeInitializationFailed);
40 } 41 };
41 42
42 var onFacadeInitialized = function () { 43 var onFacadeInitialized = function () {
43 // Host already installed. 44 // Host already installed.
44 remoting.startHostUsingFacade_(hostFacade); 45 remoting.startHostUsingFacade_(hostFacade);
45 }; 46 };
46 47
47 var onFacadeInitializationFailed = function() { 48 var onFacadeInitializationFailed = function() {
48 // If we failed to initialize the dispatcher then prompt the user to install 49 // If we failed to initialize the dispatcher then prompt the user to install
49 // the host manually. 50 // the host manually.
50 var hasHostDialog = (hostInstallDialog != null); /** jscompile hack */ 51 var hasHostDialog = (hostInstallDialog !== null); /** jscompile hack */
51 if (!hasHostDialog) { 52 if (!hasHostDialog) {
52 hostInstallDialog = new remoting.HostInstallDialog(); 53 hostInstallDialog = new remoting.HostInstallDialog();
53 hostInstallDialog.show(tryInitializeFacade, onInstallError); 54 hostInstallDialog.show(tryInitializeFacade, onInstallError);
54 } else { 55 } else {
55 hostInstallDialog.tryAgain(); 56 hostInstallDialog.tryAgain();
56 } 57 }
57 }; 58 };
58 59
59 /** @param {remoting.Error} error */ 60 /** @param {remoting.Error} error */
60 var onInstallError = function(error) { 61 var onInstallError = function(error) {
61 if (error == remoting.Error.CANCELLED) { 62 if (error == remoting.Error.CANCELLED) {
62 remoting.setMode(remoting.AppMode.HOME); 63 remoting.setMode(remoting.AppMode.HOME);
63 } else { 64 } else {
64 showShareError_(error); 65 showShareError_(error);
65 } 66 }
66 } 67 };
67 68
68 tryInitializeFacade(); 69 tryInitializeFacade();
69 }; 70 };
70 71
71 /** 72 /**
72 * @param {remoting.It2MeHostFacade} hostFacade An initialized It2MeHostFacade. 73 * @param {remoting.It2MeHostFacade} hostFacade An initialized It2MeHostFacade.
73 */ 74 */
74 remoting.startHostUsingFacade_ = function(hostFacade) { 75 remoting.startHostUsingFacade_ = function(hostFacade) {
75 console.log('Attempting to share...'); 76 console.log('Attempting to share...');
76 remoting.identity.callWithToken( 77 remoting.identity.callWithToken(
77 remoting.tryShareWithToken_.bind(null, hostFacade), 78 remoting.tryShareWithToken_.bind(null, hostFacade),
78 remoting.showErrorMessage); 79 remoting.showErrorMessage);
79 } 80 }
80 81
81 /** 82 /**
82 * @param {remoting.It2MeHostFacade} hostFacade An initialized 83 * @param {remoting.It2MeHostFacade} hostFacade An initialized
83 * It2MeHostFacade. 84 * It2MeHostFacade.
84 * @param {string} token The OAuth access token. 85 * @param {string} token The OAuth access token.
85 * @private 86 * @private
86 */ 87 */
87 remoting.tryShareWithToken_ = function(hostFacade, token) { 88 remoting.tryShareWithToken_ = function(hostFacade, token) {
88 lastShareWasCancelled_ = false; 89 lastShareWasCancelled_ = false;
89 onNatTraversalPolicyChanged_(true); // Hide warning by default. 90 onNatTraversalPolicyChanged_(true); // Hide warning by default.
90 remoting.setMode(remoting.AppMode.HOST_WAITING_FOR_CODE); 91 remoting.setMode(remoting.AppMode.HOST_WAITING_FOR_CODE);
91 document.getElementById('cancel-share-button').disabled = false; 92 document.getElementById('cancel-share-button').disabled = false;
92 disableTimeoutCountdown_(); 93 disableTimeoutCountdown_();
93 94
94 remoting.hostSession = new remoting.HostSession(); 95 base.debug.assert(hostSession_ === null);
96 hostSession_ = new remoting.HostSession();
95 var email = /** @type {string} */ (remoting.identity.getCachedEmail()); 97 var email = /** @type {string} */ (remoting.identity.getCachedEmail());
96 remoting.hostSession.connect( 98 hostSession_.connect(
97 hostFacade, email, token, onHostStateChanged_, 99 hostFacade, email, token, onHostStateChanged_,
98 onNatTraversalPolicyChanged_, logDebugInfo_, it2meConnectFailed_); 100 onNatTraversalPolicyChanged_, logDebugInfo_, it2meConnectFailed_);
99 }; 101 };
100 102
101 /** 103 /**
102 * Callback for the host plugin to notify the web app of state changes. 104 * Callback for the host plugin to notify the web app of state changes.
103 * @param {remoting.HostSession.State} state The new state of the plugin. 105 * @param {remoting.HostSession.State} state The new state of the plugin.
104 * @return {void} Nothing. 106 * @return {void} Nothing.
105 * @private
106 */ 107 */
107 function onHostStateChanged_(state) { 108 function onHostStateChanged_(state) {
108 if (state == remoting.HostSession.State.STARTING) { 109 if (state == remoting.HostSession.State.STARTING) {
109 // Nothing to do here. 110 // Nothing to do here.
110 console.log('Host state: STARTING'); 111 console.log('Host state: STARTING');
111 112
112 } else if (state == remoting.HostSession.State.REQUESTED_ACCESS_CODE) { 113 } else if (state == remoting.HostSession.State.REQUESTED_ACCESS_CODE) {
113 // Nothing to do here. 114 // Nothing to do here.
114 console.log('Host state: REQUESTED_ACCESS_CODE'); 115 console.log('Host state: REQUESTED_ACCESS_CODE');
115 116
116 } else if (state == remoting.HostSession.State.RECEIVED_ACCESS_CODE) { 117 } else if (state == remoting.HostSession.State.RECEIVED_ACCESS_CODE) {
117 console.log('Host state: RECEIVED_ACCESS_CODE'); 118 console.log('Host state: RECEIVED_ACCESS_CODE');
118 var accessCode = remoting.hostSession.getAccessCode(); 119 var accessCode = hostSession_.getAccessCode();
119 var accessCodeDisplay = document.getElementById('access-code-display'); 120 var accessCodeDisplay = document.getElementById('access-code-display');
120 accessCodeDisplay.innerText = ''; 121 accessCodeDisplay.innerText = '';
121 // Display the access code in groups of four digits for readability. 122 // Display the access code in groups of four digits for readability.
122 var kDigitsPerGroup = 4; 123 var kDigitsPerGroup = 4;
123 for (var i = 0; i < accessCode.length; i += kDigitsPerGroup) { 124 for (var i = 0; i < accessCode.length; i += kDigitsPerGroup) {
124 var nextFourDigits = document.createElement('span'); 125 var nextFourDigits = document.createElement('span');
125 nextFourDigits.className = 'access-code-digit-group'; 126 nextFourDigits.className = 'access-code-digit-group';
126 nextFourDigits.innerText = accessCode.substring(i, i + kDigitsPerGroup); 127 nextFourDigits.innerText = accessCode.substring(i, i + kDigitsPerGroup);
127 accessCodeDisplay.appendChild(nextFourDigits); 128 accessCodeDisplay.appendChild(nextFourDigits);
128 } 129 }
129 accessCodeExpiresIn_ = remoting.hostSession.getAccessCodeLifetime(); 130 accessCodeExpiresIn_ = hostSession_.getAccessCodeLifetime();
130 if (accessCodeExpiresIn_ > 0) { // Check it hasn't expired. 131 if (accessCodeExpiresIn_ > 0) { // Check it hasn't expired.
131 accessCodeTimerId_ = setInterval(decrementAccessCodeTimeout_, 1000); 132 accessCodeTimerId_ = setInterval(decrementAccessCodeTimeout_, 1000);
132 timerRunning_ = true; 133 timerRunning_ = true;
133 updateAccessCodeTimeoutElement_(); 134 updateAccessCodeTimeoutElement_();
134 updateTimeoutStyles_(); 135 updateTimeoutStyles_();
135 remoting.setMode(remoting.AppMode.HOST_WAITING_FOR_CONNECTION); 136 remoting.setMode(remoting.AppMode.HOST_WAITING_FOR_CONNECTION);
136 } else { 137 } else {
137 // This can only happen if the cloud tells us that the code lifetime is 138 // This can only happen if the cloud tells us that the code lifetime is
138 // <= 0s, which shouldn't happen so we don't care how clean this UX is. 139 // <= 0s, which shouldn't happen so we don't care how clean this UX is.
139 console.error('Access code already invalid on receipt!'); 140 console.error('Access code already invalid on receipt!');
140 remoting.cancelShare(); 141 remoting.cancelShare();
141 } 142 }
142 143
143 } else if (state == remoting.HostSession.State.CONNECTED) { 144 } else if (state == remoting.HostSession.State.CONNECTED) {
144 console.log('Host state: CONNECTED'); 145 console.log('Host state: CONNECTED');
145 var element = document.getElementById('host-shared-message'); 146 var element = document.getElementById('host-shared-message');
146 var client = remoting.hostSession.getClient(); 147 var client = hostSession_.getClient();
147 l10n.localizeElement(element, client); 148 l10n.localizeElement(element, client);
148 remoting.setMode(remoting.AppMode.HOST_SHARED); 149 remoting.setMode(remoting.AppMode.HOST_SHARED);
149 disableTimeoutCountdown_(); 150 disableTimeoutCountdown_();
150 151
151 } else if (state == remoting.HostSession.State.DISCONNECTING) { 152 } else if (state == remoting.HostSession.State.DISCONNECTING) {
152 console.log('Host state: DISCONNECTING'); 153 console.log('Host state: DISCONNECTING');
153 154
154 } else if (state == remoting.HostSession.State.DISCONNECTED) { 155 } else if (state == remoting.HostSession.State.DISCONNECTED) {
155 console.log('Host state: DISCONNECTED'); 156 console.log('Host state: DISCONNECTED');
156 if (remoting.currentMode != remoting.AppMode.HOST_SHARE_FAILED) { 157 if (remoting.currentMode != remoting.AppMode.HOST_SHARE_FAILED) {
157 // If an error is being displayed, then the plugin should not be able to 158 // If an error is being displayed, then the plugin should not be able to
158 // hide it by setting the state. Errors must be dismissed by the user 159 // hide it by setting the state. Errors must be dismissed by the user
159 // clicking OK, which puts the app into mode HOME. 160 // clicking OK, which puts the app into mode HOME.
160 if (lastShareWasCancelled_) { 161 if (lastShareWasCancelled_) {
161 remoting.setMode(remoting.AppMode.HOME); 162 remoting.setMode(remoting.AppMode.HOME);
162 } else { 163 } else {
163 remoting.setMode(remoting.AppMode.HOST_SHARE_FINISHED); 164 remoting.setMode(remoting.AppMode.HOST_SHARE_FINISHED);
164 } 165 }
165 } 166 }
167 cleanUp();
166 } else if (state == remoting.HostSession.State.ERROR) { 168 } else if (state == remoting.HostSession.State.ERROR) {
167 console.error('Host state: ERROR'); 169 console.error('Host state: ERROR');
168 showShareError_(remoting.Error.UNEXPECTED); 170 showShareError_(remoting.Error.UNEXPECTED);
169 } else if (state == remoting.HostSession.State.INVALID_DOMAIN_ERROR) { 171 } else if (state == remoting.HostSession.State.INVALID_DOMAIN_ERROR) {
170 console.error('Host state: INVALID_DOMAIN_ERROR'); 172 console.error('Host state: INVALID_DOMAIN_ERROR');
171 showShareError_(remoting.Error.INVALID_HOST_DOMAIN); 173 showShareError_(remoting.Error.INVALID_HOST_DOMAIN);
172 } else { 174 } else {
173 console.error('Unknown state -> ' + state); 175 console.error('Unknown state -> ' + state);
174 } 176 }
175 } 177 }
176 178
177 /** 179 /**
178 * This is the callback that the host plugin invokes to indicate that there 180 * This is the callback that the host plugin invokes to indicate that there
179 * is additional debug log info to display. 181 * is additional debug log info to display.
180 * @param {string} msg The message (which will not be localized) to be logged. 182 * @param {string} msg The message (which will not be localized) to be logged.
181 * @private
182 */ 183 */
183 function logDebugInfo_(msg) { 184 function logDebugInfo_(msg) {
184 console.log('plugin: ' + msg); 185 console.log('plugin: ' + msg);
185 } 186 }
186 187
187 /** 188 /**
188 * Show a host-side error message. 189 * Show a host-side error message.
189 * 190 *
190 * @param {string} errorTag The error message to be localized and displayed. 191 * @param {string} errorTag The error message to be localized and displayed.
191 * @return {void} Nothing. 192 * @return {void} Nothing.
192 * @private
193 */ 193 */
194 function showShareError_(errorTag) { 194 function showShareError_(errorTag) {
195 var errorDiv = document.getElementById('host-plugin-error'); 195 var errorDiv = document.getElementById('host-plugin-error');
196 l10n.localizeElementFromTag(errorDiv, errorTag); 196 l10n.localizeElementFromTag(errorDiv, errorTag);
197 console.error('Sharing error: ' + errorTag); 197 console.error('Sharing error: ' + errorTag);
198 remoting.setMode(remoting.AppMode.HOST_SHARE_FAILED); 198 remoting.setMode(remoting.AppMode.HOST_SHARE_FAILED);
199 cleanUp();
199 } 200 }
200 201
201 /** 202 /**
202 * Show a sharing error with error code UNEXPECTED . 203 * Show a sharing error with error code UNEXPECTED .
203 * 204 *
204 * @return {void} Nothing. 205 * @return {void} Nothing.
205 * @private
206 */ 206 */
207 function it2meConnectFailed_() { 207 function it2meConnectFailed_() {
208 // TODO (weitaosu): Instruct the user to install the native messaging host. 208 // TODO (weitaosu): Instruct the user to install the native messaging host.
209 // We probably want to add a new error code (with the corresponding error 209 // We probably want to add a new error code (with the corresponding error
210 // message for sharing error. 210 // message for sharing error.
211 console.error('Cannot share desktop.'); 211 console.error('Cannot share desktop.');
212 showShareError_(remoting.Error.UNEXPECTED); 212 showShareError_(remoting.Error.UNEXPECTED);
213 } 213 }
214 214
215 function cleanUp() {
216 base.dispose(hostSession_);
217 hostSession_ = null;
218 }
219
215 /** 220 /**
216 * Cancel an active or pending it2me share operation. 221 * Cancel an active or pending it2me share operation.
217 * 222 *
218 * @return {void} Nothing. 223 * @return {void} Nothing.
219 */ 224 */
220 remoting.cancelShare = function() { 225 remoting.cancelShare = function() {
221 document.getElementById('cancel-share-button').disabled = true; 226 document.getElementById('cancel-share-button').disabled = true;
222 console.log('Canceling share...'); 227 console.log('Canceling share...');
223 remoting.lastShareWasCancelled = true; 228 remoting.lastShareWasCancelled = true;
224 try { 229 try {
225 remoting.hostSession.disconnect(); 230 hostSession_.disconnect();
226 } catch (/** @type {*} */ error) { 231 } catch (/** @type {*} */ error) {
227 console.error('Error disconnecting: ' + error + 232 console.error('Error disconnecting: ' + error +
228 '. The host probably crashed.'); 233 '. The host probably crashed.');
229 // TODO(jamiewalch): Clean this up. We should have a class representing 234 // TODO(jamiewalch): Clean this up. We should have a class representing
230 // the host plugin, like we do for the client, which should handle crash 235 // the host plugin, like we do for the client, which should handle crash
231 // reporting and it should use a more detailed error message than the 236 // reporting and it should use a more detailed error message than the
232 // default 'generic' one. See crbug.com/94624 237 // default 'generic' one. See crbug.com/94624
233 showShareError_(remoting.Error.UNEXPECTED); 238 showShareError_(remoting.Error.UNEXPECTED);
234 } 239 }
235 disableTimeoutCountdown_(); 240 disableTimeoutCountdown_();
236 }; 241 };
237 242
238 /** 243 /**
239 * @type {boolean} Whether or not the access code timeout countdown is running. 244 * @type {boolean} Whether or not the access code timeout countdown is running.
240 * @private
241 */ 245 */
242 var timerRunning_ = false; 246 var timerRunning_ = false;
243 247
244 /** 248 /**
245 * @type {number} The id of the access code expiry countdown timer. 249 * @type {number} The id of the access code expiry countdown timer.
246 * @private
247 */ 250 */
248 var accessCodeTimerId_ = 0; 251 var accessCodeTimerId_ = 0;
249 252
250 /** 253 /**
251 * @type {number} The number of seconds until the access code expires. 254 * @type {number} The number of seconds until the access code expires.
252 * @private
253 */ 255 */
254 var accessCodeExpiresIn_ = 0; 256 var accessCodeExpiresIn_ = 0;
255 257
256 /** 258 /**
257 * The timer callback function 259 * The timer callback function
258 * @return {void} Nothing. 260 * @return {void} Nothing.
259 * @private
260 */ 261 */
261 function decrementAccessCodeTimeout_() { 262 function decrementAccessCodeTimeout_() {
262 --accessCodeExpiresIn_; 263 --accessCodeExpiresIn_;
263 updateAccessCodeTimeoutElement_(); 264 updateAccessCodeTimeoutElement_();
264 }; 265 }
265 266
266 /** 267 /**
267 * Stop the access code timeout countdown if it is running. 268 * Stop the access code timeout countdown if it is running.
268 * @return {void} Nothing. 269 * @return {void} Nothing.
269 * @private
270 */ 270 */
271 function disableTimeoutCountdown_() { 271 function disableTimeoutCountdown_() {
272 if (timerRunning_) { 272 if (timerRunning_) {
273 clearInterval(accessCodeTimerId_); 273 clearInterval(accessCodeTimerId_);
274 timerRunning_ = false; 274 timerRunning_ = false;
275 updateTimeoutStyles_(); 275 updateTimeoutStyles_();
276 } 276 }
277 } 277 }
278 278
279 /** 279 /**
280 * Constants controlling the access code timer countdown display. 280 * Constants controlling the access code timer countdown display.
281 * @private
282 */ 281 */
283 var ACCESS_CODE_TIMER_DISPLAY_THRESHOLD_ = 30; 282 var ACCESS_CODE_TIMER_DISPLAY_THRESHOLD_ = 30;
284 var ACCESS_CODE_RED_THRESHOLD_ = 10; 283 var ACCESS_CODE_RED_THRESHOLD_ = 10;
285 284
286 /** 285 /**
287 * Show/hide or restyle various elements, depending on the remaining countdown 286 * Show/hide or restyle various elements, depending on the remaining countdown
288 * and timer state. 287 * and timer state.
289 * 288 *
290 * @return {boolean} True if the timeout is in progress, false if it has 289 * @return {boolean} True if the timeout is in progress, false if it has
291 * expired. 290 * expired.
292 * @private
293 */ 291 */
294 function updateTimeoutStyles_() { 292 function updateTimeoutStyles_() {
295 if (timerRunning_) { 293 if (timerRunning_) {
296 if (accessCodeExpiresIn_ <= 0) { 294 if (accessCodeExpiresIn_ <= 0) {
297 remoting.cancelShare(); 295 remoting.cancelShare();
298 return false; 296 return false;
299 } 297 }
300 var accessCode = document.getElementById('access-code-display'); 298 var accessCode = document.getElementById('access-code-display');
301 if (accessCodeExpiresIn_ <= ACCESS_CODE_RED_THRESHOLD_) { 299 if (accessCodeExpiresIn_ <= ACCESS_CODE_RED_THRESHOLD_) {
302 accessCode.classList.add('expiring'); 300 accessCode.classList.add('expiring');
303 } else { 301 } else {
304 accessCode.classList.remove('expiring'); 302 accessCode.classList.remove('expiring');
305 } 303 }
306 } 304 }
307 document.getElementById('access-code-countdown').hidden = 305 document.getElementById('access-code-countdown').hidden =
308 (accessCodeExpiresIn_ > ACCESS_CODE_TIMER_DISPLAY_THRESHOLD_) || 306 (accessCodeExpiresIn_ > ACCESS_CODE_TIMER_DISPLAY_THRESHOLD_) ||
309 !timerRunning_; 307 !timerRunning_;
310 return true; 308 return true;
311 } 309 }
312 310
313 /** 311 /**
314 * Update the text and appearance of the access code timeout element to 312 * Update the text and appearance of the access code timeout element to
315 * reflect the time remaining. 313 * reflect the time remaining.
316 * @return {void} Nothing. 314 * @return {void} Nothing.
317 * @private
318 */ 315 */
319 function updateAccessCodeTimeoutElement_() { 316 function updateAccessCodeTimeoutElement_() {
320 var pad = (accessCodeExpiresIn_ < 10) ? '0:0' : '0:'; 317 var pad = (accessCodeExpiresIn_ < 10) ? '0:0' : '0:';
321 l10n.localizeElement(document.getElementById('seconds-remaining'), 318 l10n.localizeElement(document.getElementById('seconds-remaining'),
322 pad + accessCodeExpiresIn_); 319 pad + accessCodeExpiresIn_);
323 if (!updateTimeoutStyles_()) { 320 if (!updateTimeoutStyles_()) {
324 disableTimeoutCountdown_(); 321 disableTimeoutCountdown_();
325 } 322 }
326 } 323 }
327 324
328 /** 325 /**
329 * Callback to show or hide the NAT traversal warning when the policy changes. 326 * Callback to show or hide the NAT traversal warning when the policy changes.
330 * @param {boolean} enabled True if NAT traversal is enabled. 327 * @param {boolean} enabled True if NAT traversal is enabled.
331 * @return {void} Nothing. 328 * @return {void} Nothing.
332 * @private
333 */ 329 */
334 function onNatTraversalPolicyChanged_(enabled) { 330 function onNatTraversalPolicyChanged_(enabled) {
335 var natBox = document.getElementById('nat-box'); 331 var natBox = document.getElementById('nat-box');
336 if (enabled) { 332 if (enabled) {
337 natBox.classList.add('traversal-enabled'); 333 natBox.classList.add('traversal-enabled');
338 } else { 334 } else {
339 natBox.classList.remove('traversal-enabled'); 335 natBox.classList.remove('traversal-enabled');
340 } 336 }
341 } 337 }
338
339 })();
OLDNEW
« no previous file with comments | « no previous file | remoting/webapp/crd/js/host_session.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698