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

Side by Side Diff: remoting/webapp/me2mom/remoting.js

Issue 7078022: Fix up remoting UI to make it closer to spec (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added comment about v8 bug Created 9 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "use strict";
6
5 // TODO(ajwong): This seems like a bad idea to share the exact same object 7 // TODO(ajwong): This seems like a bad idea to share the exact same object
6 // with the background page. Why are we doing it like this? 8 // with the background page. Why are we doing it like this?
7 var remoting = chrome.extension.getBackgroundPage().remoting; 9 var remoting = chrome.extension.getBackgroundPage().remoting;
10 remoting.CLIENT_MODE='client';
11 remoting.HOST_MODE='host';
12 remoting.PLUGIN_MIMETYPE='HOST_PLUGIN_MIMETYPE';
13 remoting.XMPP_LOGIN_NAME = 'xmpp_login';
14 remoting.HOST_PLUGIN_ID = 'host-plugin-id';
8 15
9 XMPP_LOGIN_NAME = 'xmpp_login'; 16 window.addEventListener("load", init_, false);
10 XMPP_TOKEN_NAME = 'xmpp_token';
11 HOST_PLUGIN_ID = 'host_plugin_id';
12 17
13 function updateAuthStatus_() { 18 function hasClass(element, cls) {
14 var oauth2_status = document.getElementById('oauth2_status'); 19 return element.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
15 if (remoting.oauth2.isAuthenticated()) { 20 }
16 oauth2_status.innerText = 'OK'; 21
17 oauth2_status.style.color = 'green'; 22 function showElement(element, visible) {
18 document.getElementById('oauth2_code_button').style.display = 'none'; 23 if (visible) {
19 document.getElementById('oauth2_clear_button').style.display = 'inline'; 24 if (hasClass(element, 'display-inline')) {
20 document.getElementById('oauth2_form').style.display = 'none'; 25 element.style.display = 'inline';
26 } else {
27 element.style.display = 'block';
28 }
21 } else { 29 } else {
22 oauth2_status.innerText = 'Unauthorized'; 30 element.style.display = 'none';
23 oauth2_status.style.color = 'red';
24 document.getElementById('oauth2_code_button').style.display = 'inline';
25 document.getElementById('oauth2_clear_button').style.display = 'none';
26 document.getElementById('oauth2_form').style.display = 'inline';
27 }
28 var xmpp_status = document.getElementById('xmpp_status');
29 if (remoting.getItem(XMPP_TOKEN_NAME) && remoting.getItem(XMPP_LOGIN_NAME)) {
30 document.getElementById('xmpp_clear').style.display = 'inline';
31 document.getElementById('xmpp_form').style.display = 'none';
32 xmpp_status.innerText = 'OK';
33 xmpp_status.style.color = 'green';
34 } else {
35 document.getElementById('xmpp_clear').style.display = 'none';
36 document.getElementById('xmpp_form').style.display = 'inline';
37 xmpp_status.innerText = 'Unauthorized';
38 xmpp_status.style.color = 'red';
39 }
40 var current_email = document.getElementById('current_email');
41 if (remoting.getItem(XMPP_LOGIN_NAME)) {
42 oauth2_status.style.color = 'green';
43 current_email.innerText = remoting.getItem(XMPP_LOGIN_NAME);
44 } else {
45 oauth2_status.style.color = 'red';
46 current_email.innerText = 'missing e-mail';
47 } 31 }
48 } 32 }
49 33
50 function clientLoginError_(xhr) { 34 function showElementById(id, visible) {
51 // If there's an error URL, load it into an iframe. 35 showElement(document.getElementById(id), visible);
52 var url_line = xhr.responseText.match('Url=.*');
53 if (url_line) {
54 url = url_line[0].substr(4);
55 var error_frame = document.getElementById('xmpp_error');
56 error_frame.src = url;
57 error_frame.style.display = 'block';
58 }
59
60 var log_msg = 'Client Login failed. Status: ' + xhr.status +
61 ' body: ' + xhr.responseText;
62 console.log(log_msg);
63 var last_error = document.getElementById('xmpp_last_error');
64 last_error.innerText = log_msg;
65 last_error.style.display = 'inline';
66 } 36 }
67 37
68 function resetXmppErrors_() { 38 // This code moved into this subroutine (instead of being inlined in
69 document.getElementById('xmpp_captcha').style.display = 'none'; 39 // updateAuthStatus_() because of bug in V8.
70 document.getElementById('xmpp_error').style.display = 'none'; 40 // http://code.google.com/p/v8/issues/detail?id=1423
71 document.getElementById('xmpp_last_error').style.display = 'none'; 41 function updateControls_(disable) {
42 var authStatusControls =
43 document.getElementsByClassName('auth-status-control');
44 for (var i = 0; i < authStatusControls.length; ++i) {
45 authStatusControls[i].disabled = disable;
46 }
72 } 47 }
73 48
74 function displayCaptcha_(form, url, token) { 49 function updateAuthStatus_() {
75 form['xmpp_captcha_token'].value = token; 50 var oauthValid = remoting.oauth2.isAuthenticated();
76 document.getElementById('xmpp_captcha_img').src = url; 51 if (!oauthValid) {
77 document.getElementById('xmpp_captcha').style.display = 'inline'; 52 document.getElementById('oauth2-code').value = "";
78 } 53 }
54 showElementById('oauth2-submit-button', false);
55 showElementById('oauth2-code', !oauthValid);
56 showElementById('oauth2-code-button', !oauthValid);
57 showElementById('oauth2-clear-button', oauthValid);
79 58
80 function readAndClearCaptcha_(form) { 59 var loginName = remoting.getItem(remoting.XMPP_LOGIN_NAME);
81 var captcha_token = form['xmpp_captcha_token'].value; 60 if (loginName) {
82 form['xmpp_captcha_token'].value = ''; 61 document.getElementById('current-email').innerText = loginName;
83 resetXmppErrors_(); 62 }
84 return [captcha_token, form['xmpp_captcha_result'].value]; 63 showElementById('current-email', loginName);
85 } 64 showElementById('change-email-button', loginName);
65 showElementById('new-email', !loginName);
66 showElementById('email-submit-button', !loginName);
86 67
87 function initAuthPanel_() { 68 var disableControls = !(loginName && oauthValid);
88 updateAuthStatus_(); 69 var authPanel = document.getElementById('auth-panel');
89 resetXmppErrors_(); 70 if (disableControls) {
71 authPanel.style.backgroundColor = 'rgba(204, 0, 0, 0.15)';
72 } else {
73 authPanel.style.backgroundColor = 'rgba(0, 204, 102, 0.15)';
74 }
75 updateControls_(disableControls);
90 } 76 }
91 77
92 function initBackgroundFuncs_() { 78 function initBackgroundFuncs_() {
93 remoting.getItem = chrome.extension.getBackgroundPage().getItem; 79 remoting.getItem = chrome.extension.getBackgroundPage().getItem;
94 remoting.setItem = chrome.extension.getBackgroundPage().setItem; 80 remoting.setItem = chrome.extension.getBackgroundPage().setItem;
95 remoting.removeItem = chrome.extension.getBackgroundPage().removeItem; 81 remoting.removeItem = chrome.extension.getBackgroundPage().removeItem;
96 remoting.oauth2 = new OAuth2(); 82 remoting.oauth2 = new OAuth2();
97 } 83 }
98 84
99 function authorizeXmpp(form) { 85 function setEmail(value) {
100 var xhr = new XMLHttpRequest(); 86 remoting.setItem(remoting.XMPP_LOGIN_NAME, value);
101 var captcha_result = readAndClearCaptcha_(form);
102
103 xhr.onreadystatechange = function() {
104 if (xhr.readyState != 4) {
105 return;
106 }
107
108 if (xhr.status == 200) {
109 var auth_line = xhr.responseText.match('Auth=.*');
110 if (!auth_line) {
111 clientLoginError_(xhr);
112 return;
113 }
114 remoting.setItem(XMPP_TOKEN_NAME, auth_line[0].substr(5));
115 remoting.setItem(XMPP_LOGIN_NAME, form['xmpp_username'].value);
116 updateAuthStatus_();
117 } else if (xhr.status == 403) {
118 var error_line = xhr.responseText.match('Error=.*');
119 if (error_line && error_line == 'Error=CaptchaRequired') {
120 var captcha_token = xhr.responseText.match('CaptchaToken=.*');
121 var captcha_url = xhr.responseText.match('CaptchaUrl=.*');
122 displayCaptcha_(
123 form,
124 'https://www.google.com/accounts/' + captcha_url[0].substr(11),
125 captcha_token[0].substr(13));
126 return;
127 }
128 clientLoginError_(xhr);
129 } else {
130 clientLoginError_(xhr);
131 }
132 };
133 xhr.open('POST', 'https://www.google.com/accounts/ClientLogin', true);
134 xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
135 var post_data =
136 'accountType=HOSTED_OR_GOOGLE' +
137 '&service=chromiumsync' +
138 '&source=remoting-webapp' +
139 '&Email=' + encodeURIComponent(form['xmpp_username'].value) +
140 '&Passwd=' + encodeURIComponent(form['xmpp_password'].value);
141
142 if (captcha_result[0]) {
143 post_data += '&logintoken=' + encodeURIComponent(captcha_result[0]) +
144 '&logincaptcha=' + encodeURIComponent(captcha_result[1]);
145 }
146 xhr.send(post_data);
147 }
148
149 function setEmail(form) {
150 remoting.setItem(XMPP_LOGIN_NAME, form['new_email'].value);
151 updateAuthStatus_(); 87 updateAuthStatus_();
152 } 88 }
153 89
154 function authorizeOAuth2(code) { 90 function exchangedCodeForToken_() {
155 remoting.oauth2.exchangeCodeForToken(code, updateAuthStatus_); 91 if (!remoting.oauth2.isAuthenticated()) {
92 alert("Your OAuth2 token was invalid. Please try again.");
93 }
94 updateAuthStatus_();
95 }
96
97 function authorizeOAuth2() {
98 remoting.oauth2.exchangeCodeForToken(
99 document.getElementById('oauth2-code').value, exchangedCodeForToken_);
156 } 100 }
157 101
158 function clearOAuth2() { 102 function clearOAuth2() {
159 remoting.oauth2.clear(); 103 remoting.oauth2.clear();
160 updateAuthStatus_(); 104 updateAuthStatus_();
161 } 105 }
162 106
163 function clearXmpp() { 107 function handleOAuth2CodeChange() {
164 remoting.removeItem(XMPP_TOKEN_NAME); 108 var hasCode = document.getElementById('oauth2-code').value.length > 0;
165 updateAuthStatus_(); 109
110 showElementById('oauth2-submit-button', hasCode);
111 showElementById('oauth2-code-button', !hasCode);
166 } 112 }
167 113
168 // Show the div with id |mode| and hide those with other ids in |modes|. 114 // Show the div with id |mode| and hide those with other ids in |modes|.
169 function setMode_(mode, modes) { 115 function setMode_(mode, modes) {
170 for (var i = 0; i < modes.length; ++i) { 116 for (var i = 0; i < modes.length; ++i) {
171 var div = document.getElementById(modes[i]); 117 showElement(modes[i], mode == modes[i].id);
172 if (mode == modes[i]) {
173 div.style.display = 'block';
174 } else {
175 div.style.display = 'none';
176 }
177 } 118 }
178 } 119 }
179 120
180 function init() { 121 function init_() {
181 initBackgroundFuncs_(); 122 initBackgroundFuncs_();
182 initAuthPanel_(); 123 updateAuthStatus_();
183 setHostMode('unshared'); 124 setHostMode('unshared');
184 setClientMode('unconnected'); 125 setClientMode('unconnected');
185 setGlobalMode(remoting.getItem('startup-mode', 'host')); 126 setGlobalMode(remoting.getItem('startup-mode', remoting.HOST_MODE));
186 } 127 }
187 128
188 function setGlobalMode(mode) { 129 function setGlobalMode(mode) {
189 setMode_(mode, ['host', 'client']); 130 var elementsToShow = [];
131 var elementsToHide = [];
132 var hostElements = document.getElementsByClassName('host-element');
133 var clientElements = document.getElementsByClassName('client-element');
134 if (mode == remoting.HOST_MODE) {
135 elementsToShow = hostElements;
136 elementsToHide = clientElements;
137 } else {
138 elementsToShow = clientElements;
139 elementsToHide = hostElements;
140 }
141 for (var i = 0; i < elementsToShow.length; ++i) {
142 showElement(elementsToShow[i], true);
143 }
144 for (var i = 0; i < elementsToHide.length; ++i) {
145 showElement(elementsToHide[i], false);
146 }
190 } 147 }
191 148
192 function setGlobalModePersistent(mode) { 149 function setGlobalModePersistent(mode) {
193 setGlobalMode(mode); 150 setGlobalMode(mode);
194 remoting.setItem('startup-mode', mode); 151 remoting.setItem('startup-mode', mode);
195 } 152 }
196 153
197 function setHostMode(mode) { 154 function setHostMode(mode) {
198 setMode_(mode, ['unshared', 155 var section = document.getElementById('host-section');
199 'preparing_to_share', 156 var modes = section.getElementsByClassName('mode');
200 'ready_to_share', 157 setMode_(mode, modes);
201 'shared']);
202 } 158 }
203 159
204 function setClientMode(mode) { 160 function setClientMode(mode) {
205 setMode_(mode, ['unconnected', 'connecting', 'connect_failed']); 161 var section = document.getElementById('client-section');
162 var modes = section.getElementsByClassName('mode');
163 setMode_(mode, modes);
206 } 164 }
207 165
208 function tryShare() { 166 function tryShare() {
209 if (remoting.oauth2.needsNewAccessToken()) { 167 if (remoting.oauth2.needsNewAccessToken()) {
210 remoting.oauth2.refreshAccessToken(function() { 168 remoting.oauth2.refreshAccessToken(function() {
211 if (remoting.oauth2.needsNewAccessToken()) { 169 if (remoting.oauth2.needsNewAccessToken()) {
212 // If we still need it, we're going to infinite loop. 170 // If we still need it, we're going to infinite loop.
213 throw "Unable to get access token"; 171 throw "Unable to get access token";
214 } 172 }
215 tryShare(); 173 tryShare();
216 }); 174 });
217 return; 175 return;
218 } 176 }
219 177
220 var div = document.getElementById('plugin_wrapper'); 178 var div = document.getElementById('plugin-wrapper');
221 var plugin = document.createElement('embed'); 179 var plugin = document.createElement('embed');
222 plugin.setAttribute('type', 'HOST_PLUGIN_MIMETYPE'); 180 plugin.setAttribute('type', remoting.PLUGIN_MIMETYPE);
223 plugin.setAttribute('hidden', 'true'); 181 plugin.setAttribute('hidden', 'true');
224 plugin.setAttribute('id', HOST_PLUGIN_ID); 182 plugin.setAttribute('id', remoting.HOST_PLUGIN_ID);
225 div.appendChild(plugin); 183 div.appendChild(plugin);
226 plugin.onStateChanged = onStateChanged_; 184 plugin.onStateChanged = onStateChanged_;
227 plugin.connect(remoting.getItem(XMPP_LOGIN_NAME), 185 plugin.connect(remoting.getItem(remoting.XMPP_LOGIN_NAME),
228 'oauth2:' + remoting.oauth2.getAccessToken()); 186 'oauth2:' + remoting.oauth2.getAccessToken());
229 } 187 }
230 188
231 function onStateChanged_() { 189 function onStateChanged_() {
232 var plugin = document.getElementById(HOST_PLUGIN_ID); 190 var plugin = document.getElementById(remoting.HOST_PLUGIN_ID);
233 var state = plugin.state; 191 var state = plugin.state;
234 if (state == plugin.REQUESTED_ACCESS_CODE) { 192 if (state == plugin.REQUESTED_ACCESS_CODE) {
235 setHostMode('preparing_to_share'); 193 setHostMode('preparing-to-share');
236 } else if (state == plugin.RECEIVED_ACCESS_CODE) { 194 } else if (state == plugin.RECEIVED_ACCESS_CODE) {
237 var access_code = plugin.accessCode; 195 var accessCode = plugin.accessCode;
238 var access_code_display = document.getElementById('access_code_display'); 196 var accessCodeDisplay = document.getElementById('access-code-display');
239 access_code_display.innerText = access_code; 197 accessCodeDisplay.innerText = accessCode;
240 setHostMode('ready_to_share'); 198 setHostMode('ready-to-share');
241 } else if (state == plugin.CONNECTED) { 199 } else if (state == plugin.CONNECTED) {
242 setHostMode('shared'); 200 setHostMode('shared');
243 } else if (state == plugin.DISCONNECTED) { 201 } else if (state == plugin.DISCONNECTED) {
244 setHostMode('unshared'); 202 setHostMode('unshared');
245 plugin.parentNode.removeChild(plugin); 203 plugin.parentNode.removeChild(plugin);
246 } else { 204 } else {
247 window.alert('Unknown state -> ' + state); 205 window.alert('Unknown state -> ' + state);
248 } 206 }
249 } 207 }
250 208
251 function cancelShare() { 209 function cancelShare() {
252 var plugin = document.getElementById(HOST_PLUGIN_ID); 210 var plugin = document.getElementById(remoting.HOST_PLUGIN_ID);
253 plugin.disconnect(); 211 plugin.disconnect();
254 } 212 }
255 213
256 function startSession_() { 214 function startSession_() {
257 remoting.username = remoting.getItem(XMPP_LOGIN_NAME); 215 remoting.username = remoting.getItem(remoting.XMPP_LOGIN_NAME);
258 document.location = 'remoting_session.html'; 216 document.location = 'remoting_session.html';
259 } 217 }
260 218
261 function showConnectError_(responseCode, responseString) { 219 function showConnectError_(responseCode, responseString) {
262 var invalid = document.getElementById('invalid_access_code'); 220 var invalid = document.getElementById('invalid-access-code');
263 var other = document.getElementById('other_connect_error'); 221 var other = document.getElementById('other-connect-error');
264 if (responseCode == 404) { 222 if (responseCode == 404) {
265 invalid.style.display = 'block'; 223 invalid.style.display = 'block';
266 other.style.display = 'none'; 224 other.style.display = 'none';
267 } else { 225 } else {
268 invalid.style.display = 'none'; 226 invalid.style.display = 'none';
269 other.style.display = 'block'; 227 other.style.display = 'block';
270 var responseNode = document.getElementById('server_response'); 228 var responseNode = document.getElementById('server-response');
271 responseNode.innerText = responseString + ' (' + responseCode + ')'; 229 responseNode.innerText = responseString + ' (' + responseCode + ')';
272 } 230 }
273 remoting.accessCode = ''; 231 remoting.accessCode = '';
274 setClientMode('connect_failed'); 232 setClientMode('connect-failed');
275 } 233 }
276 234
277 function parseServerResponse_(xhr) { 235 function parseServerResponse_(xhr) {
278 if (xhr.status == 200) { 236 if (xhr.status == 200) {
279 var host = JSON.parse(xhr.responseText); 237 var host = JSON.parse(xhr.responseText);
280 if (host.data && host.data.jabberId) { 238 if (host.data && host.data.jabberId) {
281 remoting.hostjid = host.data.jabberId; 239 remoting.hostjid = host.data.jabberId;
282 startSession_(); 240 startSession_();
283 return; 241 return;
284 } 242 }
285 } 243 }
286 showConnectError_(xhr.status, xhr.responseText); 244 showConnectError_(xhr.status, xhr.responseText);
287 } 245 }
288 246
289 function normalizeAccessCode(accessCode) { 247 function normalizeAccessCode(accessCode) {
290 // Trim whitespace from beginning and the end. 248 // Trim whitespace from beginning and the end.
291 // TODO(sergeyu): Do we need to do any other normalization here? 249 // TODO(sergeyu): Do we need to do any other normalization here?
292 return accessCode.replace(/^\s+|\s+$/, ''); 250 return accessCode.replace(/^\s+|\s+$/, '');
293 } 251 }
294 252
295 function resolveSupportId(support_id) { 253 function resolveSupportId(supportId) {
296 var xhr = new XMLHttpRequest(); 254 var xhr = new XMLHttpRequest();
297 xhr.onreadystatechange = function() { 255 xhr.onreadystatechange = function() {
298 if (xhr.readyState != 4) { 256 if (xhr.readyState != 4) {
299 return; 257 return;
300 } 258 }
301 parseServerResponse_(xhr); 259 parseServerResponse_(xhr);
302 }; 260 };
303 261
304 xhr.open('GET', 262 xhr.open('GET',
305 'https://www.googleapis.com/chromoting/v1/support-hosts/' + 263 'https://www.googleapis.com/chromoting/v1/support-hosts/' +
306 encodeURIComponent(support_id), 264 encodeURIComponent(supportId),
307 true); 265 true);
308 xhr.setRequestHeader('Authorization', 266 xhr.setRequestHeader('Authorization',
309 'OAuth ' + remoting.oauth2.getAccessToken()); 267 'OAuth ' + remoting.oauth2.getAccessToken());
310 xhr.send(null); 268 xhr.send(null);
311 } 269 }
312 270
313 function tryConnect(accessCode) { 271 function tryConnect() {
314 if (remoting.oauth2.needsNewAccessToken()) { 272 if (remoting.oauth2.needsNewAccessToken()) {
315 remoting.oauth2.refreshAccessToken(function() { 273 remoting.oauth2.refreshAccessToken(function() {
316 if (remoting.oauth2.needsNewAccessToken()) { 274 if (remoting.oauth2.needsNewAccessToken()) {
317 // If we still need it, we're going to infinite loop. 275 // If we still need it, we're going to infinite loop.
318 throw "Unable to get access token"; 276 throw "Unable to get access token";
319 } 277 }
320 tryConnect(accessCode); 278 tryConnect();
321 }); 279 });
322 return; 280 return;
323 } 281 }
324 282 var accessCode = document.getElementById('access-code-entry').value;
325 remoting.accessCode = accessCode; 283 remoting.accessCode = accessCode;
326 // TODO(jamiewalch): Since the mapping from (SupportId, HostSecret) to 284 // TODO(jamiewalch): Since the mapping from (SupportId, HostSecret) to
327 // AccessCode is not yet defined, assume it's hyphen-separated for now. 285 // AccessCode is not yet defined, assume it's hyphen-separated for now.
328 var parts = remoting.accessCode.split('-'); 286 var parts = remoting.accessCode.split('-');
329 if (parts.length != 2) { 287 if (parts.length != 2) {
330 showConnectError_(404); 288 showConnectError_(404);
331 } else { 289 } else {
332 setClientMode('connecting'); 290 setClientMode('connecting');
333 resolveSupportId(parts[0]); 291 resolveSupportId(parts[0]);
334 } 292 }
335 } 293 }
336 294
337 function cancelConnect() { 295 function cancelConnect() {
338 remoting.accessCode = ''; 296 remoting.accessCode = '';
339 setClientMode('unconnected'); 297 setClientMode('unconnected');
340 } 298 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698