diff options
author | garykac@chromium.org <garykac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-08 19:46:14 +0000 |
---|---|---|
committer | garykac@chromium.org <garykac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-08 19:46:14 +0000 |
commit | cc1a4ca35f3095776c98f84f476b098037967c6d (patch) | |
tree | fc5200df1ba83530973a23ec988beba3173bdb15 /remoting | |
parent | 63f01e39ac59725da8d30fa7570f6d85b6ed1f67 (diff) | |
download | chromium_src-cc1a4ca35f3095776c98f84f476b098037967c6d.zip chromium_src-cc1a4ca35f3095776c98f84f476b098037967c6d.tar.gz chromium_src-cc1a4ca35f3095776c98f84f476b098037967c6d.tar.bz2 |
Improve UI of Chromoting client UI to select available hosts.
BUG=53988
TEST=none
Review URL: http://codereview.chromium.org/3338014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@58862 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/client/extension/chromoticon.png | bin | 0 -> 332 bytes | |||
-rw-r--r-- | remoting/client/extension/client.js | 308 | ||||
-rw-r--r-- | remoting/client/extension/icon.png | bin | 3789 -> 0 bytes | |||
-rw-r--r-- | remoting/client/extension/login.html | 41 | ||||
-rw-r--r-- | remoting/client/extension/machine.png | bin | 0 -> 4992 bytes | |||
-rw-r--r-- | remoting/client/extension/main.css | 98 | ||||
-rw-r--r-- | remoting/client/extension/manifest.json | 2 | ||||
-rw-r--r-- | remoting/client/extension/popup.html | 38 | ||||
-rwxr-xr-x | remoting/tools/gethosts.sh | 7 |
9 files changed, 355 insertions, 139 deletions
diff --git a/remoting/client/extension/chromoticon.png b/remoting/client/extension/chromoticon.png Binary files differnew file mode 100644 index 0000000..a5cb2b2 --- /dev/null +++ b/remoting/client/extension/chromoticon.png diff --git a/remoting/client/extension/client.js b/remoting/client/extension/client.js index dd53cf3..138d014 100644 --- a/remoting/client/extension/client.js +++ b/remoting/client/extension/client.js @@ -2,65 +2,100 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -function initParams() { - var hash; - var hashes = window.location.href.slice( - window.location.href.indexOf('?') + 1).split('&'); - - // Prepopulate via cookies first. - document.getElementById('xmpp_auth').value = getCookie('xmpp_auth'); - document.getElementById('chromoting_auth').value = - getCookie('chromoting_auth'); - document.getElementById('username').value = getCookie('username'); - - for(var i = 0; i < hashes.length; i++) - { - hash = hashes[i].split('='); - if (hash[0] == 'xmpp_auth') { - document.getElementById('xmpp_auth').value = hash[1]; - setCookie('xmpp_auth', hash[1]); - - } else if (hash[0] == "chromoting_auth") { - document.getElementById('chromoting_auth').value = hash[1]; - setCookie('chromoting_auth', hash[1]); - - } else if (hash[0] == 'username') { - document.getElementById('username').value = hash[1]; - setCookie('username', hash[1]); - - } else if (hash[0] == 'password') { - document.getElementById('password').value = hash[1]; - - } else if (hash[0] == 'host_jid') { - document.getElementById('host_jid').value = hash[1]; - } - } +var BAD_AUTH_TOKEN = 'bad_token'; + +function init() { + updateLoginStatus(); + + // Defer getting the host list for a little bit so that we don't + // block the display of the extension popup. + window.setTimeout(listHosts, 100); } -function findHosts(form) { - // If either cookie is missing, login first. - if (getCookie('chromoting_auth') == null || - getCookie('xmpp_auth') == null) { - doLogin(form.username.value, form.username.password, doListHosts); +// Update the login status region (at the bottom of the popup) with the +// current account and links to sign in/out. +function updateLoginStatus() { + var username = getCookie('username'); + + var loginDiv = document.getElementById('login_div'); + clear(loginDiv); + + if (!username) { + var signinLink = document.createElement('a'); + signinLink.setAttribute('href', + "javascript:window.open('login.html', 'Sign In', " + + "'width=400,height=200,scrollbars=no'); return false;"); + signinLink.appendChild(document.createTextNode('Sign In')); + loginDiv.appendChild(signinLink); } else { - doListHosts(); + var email = document.createElement('span'); + email.setAttribute('class', 'login_email'); + email.appendChild(document.createTextNode(username)); + loginDiv.appendChild(email); + + loginDiv.appendChild(document.createTextNode(' | ')); + + var signoutLink = document.createElement('a'); + signoutLink.setAttribute('href', 'javascript:logout(this.form);'); + signoutLink.appendChild(document.createTextNode('Sign Out')); + loginDiv.appendChild(signoutLink); } } +// Sign out the current user by erasing the auth cookies. +function logout(form) { + setCookie('username', '', 100); + setCookie('chromoting_auth', '', 100); + setCookie('xmpp_auth', '', 100); + + updateLoginStatus(); + listHosts(); +} + function login(form) { - doLogin(form.username.value, form.password.value); + var status = document.getElementById('login_status'); + clear(status); + doLogin(form.username.value, form.password.value, checkLogin); } -function extractAuthToken(message) { - var lines = message.split('\n'); - for (var i = 0; i < lines.length; i++) { - if (lines[i].match('^Auth=.*')) { - return lines[i].split('=')[1]; +// Check to see if the login was successful. +function checkLogin() { + var username = getCookie('username'); + var cauth = getCookie('chromoting_auth'); + var xauth = getCookie('xmpp_auth'); + + // Verify login and show login status. + var status = document.getElementById('login_status'); + if (cauth == BAD_AUTH_TOKEN || xauth == BAD_AUTH_TOKEN) { + appendMessage(status, '', 'Sign in failed!'); + if (username) { + setCookie('username', '', 100); } + } else { + appendMessage(status, '', 'Successfully signed in as ' + username); } +} - console.log('Could not parse auth token in : "' + message + '"'); - return 'bad_token'; +function doLogin(username, password, done) { + // Don't call |done| callback until both login requests have completed. + var count = 2; + var barrier = function() { + count--; + if (done && count == 0) { + done(); + } + } + setCookie('username', username, 100); + doGaiaLogin(username, password, 'chromoting', + function(cAuthToken) { + setCookie('chromoting_auth', cAuthToken, 100); + barrier(); + }); + doGaiaLogin(username, password, 'chromiumsync', + function(xAuthToken) { + setCookie('xmpp_auth', xAuthToken, 100); + barrier(); + }); } function doGaiaLogin(username, password, service, done) { @@ -82,54 +117,90 @@ function doGaiaLogin(username, password, service, done) { password + '&service=' + service + '&source=chromoclient'); } -function doLogin(username, password, done) { - var count = 2; - var barrier = function() { - count--; - if (done && count == 0) { - done(); +function extractAuthToken(message) { + var lines = message.split('\n'); + for (var i = 0; i < lines.length; i++) { + if (lines[i].match('^Auth=.*')) { + return lines[i].split('=')[1]; } } - setCookie('username', username, 100); - doGaiaLogin(username, password, 'chromoting', - function(token1) { - setCookie('chromoting_auth', token1, 100); - document.getElementById('chromoting_auth').value = token1; - barrier(); - }); - doGaiaLogin(username, password, 'chromiumsync', - function(token) { - setCookie('xmpp_auth', token, 100); - document.getElementById('xmpp_auth').value = token; - barrier(); - }); + + console.log('Could not parse auth token in : "' + message + '"'); + return BAD_AUTH_TOKEN; +} + +// Open a chromoting connection in a new tab. +function openChromotingTab(host_jid) { + var background = chrome.extension.getBackgroundPage(); + background.openChromotingTab(host_jid); +} + +// Erase the content of the specified element. +function clear(e) { + e.innerHTML = ''; +} + +// Clear out the specified element and show the message to the user. +function displayMessage(e, classname, message) { + clear(e); + appendMessage(e, classname, message); } -function doListHosts() { +// Append the message text to the specified element. +function appendMessage(e, classname, message) { + var p = document.createElement('p'); + if (classname.length != 0) { + p.setAttribute('class', classname); + } + + p.appendChild(document.createTextNode(message)); + + e.appendChild(p); +} + +function listHosts() { + var username = getCookie('username'); + + var hostlistDiv = document.getElementById('hostlist_div'); + if (!username) { + displayMessage(hostlistDiv, 'message', + 'Please sign in to see a list of available hosts.'); + return; + } + var xhr = new XMLHttpRequest(); var token = getCookie('chromoting_auth'); // Unhide host list. - var hostlist_div = document.getElementById('hostlist_div'); - hostlist_div.style.display = "block"; + hostlistDiv.style.display = "block"; xhr.onreadystatechange = function() { if (xhr.readyState == 1) { - hostlist_div.appendChild(document.createTextNode('Finding..')); - hostlist_div.appendChild(document.createElement('br')); + displayMessage(hostlistDiv, 'message', 'Loading host list for ' + + username); } if (xhr.readyState != 4) { return; } if (xhr.status == 200) { - parsed_response = JSON.parse(xhr.responseText); - hostlist_div.appendChild(document.createTextNode('--Found Hosts--')); - hostlist_div.appendChild(document.createElement('br')); + var parsed_response = JSON.parse(xhr.responseText); appendHostLinks(parsed_response.data.items); } else { - console.log('bad status on host list query: "' + xhr.status + ' ' + - xhr.statusText); - hostlist_div.appendChild(document.createTextNode('!! Failed !!. :\'(')); + var errorResponse = JSON.parse(xhr.responseText); + + console.log('Error: Bad status on host list query: "' + + xhr.status + ' ' + xhr.statusText); + console.log('Error code ' + errorResponse.error.code); + console.log('Error message ' + errorResponse.error.message); + + clear(hostlistDiv); + appendMessage(hostlistDiv, 'message', + 'Unable to load host list for ' + username + '. ' + + 'Please try again later.'); + appendMessage(hostlistDiv, 'message', + 'Error code: ' + errorResponse.error.code); + appendMessage(hostlistDiv, 'message', + 'Message: ' + errorResponse.error.message); } }; @@ -139,47 +210,64 @@ function doListHosts() { xhr.send(null); } +// Populate the 'hostlist_div' element with the list of hosts for this user. function appendHostLinks(hostlist) { - // A host link entry should look like: - // - Host: <a onclick="openChromotingTab(host_jid); return false;"> - // NAME (JID) </a> <br /> - var host; - var host_link; - var hostlist_div = document.getElementById('hostlist_div'); + var hostlistDiv = document.getElementById('hostlist_div'); - // Cleanup the div - hostlist_div.innerHTML = ""; + // Clear the div before adding the host info. + clear(hostlistDiv); // Add the hosts. - for(var i = 0; i < hostlist.length; ++i) { - hostlist_div.appendChild(document.createTextNode('-*- Host: ')); - host = hostlist[i]; - host_link = document.createElement('a'); - // TODO(ajwong): Reenable once we figure out how to control a new tab. - host_link.setAttribute('onclick', 'openChromotingTab(\'' + host.jabberId + - '\'); return false;'); - host_link.setAttribute('href', 'javascript:void(0)'); - host_link.appendChild( - document.createTextNode(host.hostName + ' (' + host.hostId + ', ' + - host.jabberId + ')')); - hostlist_div.appendChild(host_link); - hostlist_div.appendChild(document.createElement('br')); + // TODO(garykac): We should have some sort of MRU list here. + // First, add all of the connected hosts. + for (var i = 0; i < hostlist.length; ++i) { + if (hostlist[i].status == "ONLINE") { + hostlistDiv.appendChild(addHostInfo(hostlist[i])); + } + } + // Add non-online hosts at the end. + for (var i = 0; i < hostlist.length; ++i) { + if (hostlist[i].status != "ONLINE") { + hostlistDiv.appendChild(addHostInfo(hostlist[i])); + } } } -function connect(form) { - openChromotingTab(form.host_jid); -} +// Create a single host description element. +function addHostInfo(host) { + var hostEntry = document.createElement('div'); + hostEntry.setAttribute('class', 'hostentry'); -function openChromotingTab(host_jid) { - var background = chrome.extension.getBackgroundPage(); - background.openChromotingTab(host_jid); -} + var hostIcon = document.createElement('img'); + hostIcon.setAttribute('src', 'machine.png'); + hostIcon.setAttribute('class', 'hosticon'); + hostEntry.appendChild(hostIcon); + + var span = document.createElement('span'); + span.setAttribute('class', 'connect'); + var connect = document.createElement('input'); + connect.setAttribute('type', 'button'); + connect.setAttribute('value', 'Connect'); + connect.setAttribute('onclick', 'openChromotingTab(\'' + host.jabberId + + '\'); return false;'); + span.appendChild(connect); + hostEntry.appendChild(span); + + var hostName = document.createElement('p'); + hostName.setAttribute('class', 'hostname'); + hostName.appendChild(document.createTextNode(host.hostName)); + hostEntry.appendChild(hostName); + + var hostStatus = document.createElement('p'); + hostStatus.setAttribute('class', 'hostinfo hoststatus_' + + ((host.status == 'ONLINE') ? 'good' : 'bad')); + hostStatus.appendChild(document.createTextNode(host.status)); + hostEntry.appendChild(hostStatus); -function setAuthCookies(form) { - var now = new Date(); - now.setTime(now.getTime() + 1000 * 60 * 60 * 24 * 365) + var hostInfo = document.createElement('p'); + hostInfo.setAttribute('class', 'hostinfo'); + hostInfo.appendChild(document.createTextNode(host.jabberId)); + hostEntry.appendChild(hostInfo); - setCookie('xmpp_auth', form.xmpp_auth.value, 100); - setCookie('chromoting_auth', form.chromoting_auth.value, 100); + return hostEntry; } diff --git a/remoting/client/extension/icon.png b/remoting/client/extension/icon.png Binary files differdeleted file mode 100644 index 103ff36..0000000 --- a/remoting/client/extension/icon.png +++ /dev/null diff --git a/remoting/client/extension/login.html b/remoting/client/extension/login.html new file mode 100644 index 0000000..23998ac --- /dev/null +++ b/remoting/client/extension/login.html @@ -0,0 +1,41 @@ +<!-- +Copyright (c) 2010 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<html> + <head> + <script type="text/javascript" src="base.js"></script> + <script type="text/javascript" src="client.js"></script> + <link rel="stylesheet" type="text/css" href="main.css" /> + <title>Sign in</title> + </head> + <body> + + <form name="loginform" action="" method="GET"> + <table> + <tr> + <td align="right">Email:</td> + <td align="left"> + <input type="text" name="username" id="username" value="" /> + </td> + </tr><tr> + <td align="right">Password:</td> + <td align="left"> + <input type="password" name="password" id="password" value="" /> + </td> + </tr><tr> + <td></td> + <td> + <input type="button" name="login_button" value="Log In" + onclick="login(this.form)" /> + <td> + </table> + </form> + + <div id="login_status"> + </div> + + </body> +</html> diff --git a/remoting/client/extension/machine.png b/remoting/client/extension/machine.png Binary files differnew file mode 100644 index 0000000..635a9bb --- /dev/null +++ b/remoting/client/extension/machine.png diff --git a/remoting/client/extension/main.css b/remoting/client/extension/main.css new file mode 100644 index 0000000..d375107 --- /dev/null +++ b/remoting/client/extension/main.css @@ -0,0 +1,98 @@ +body { + width: 500px; + overflow: hidden; + scrollbars: no; +} + +p { + color: black; +} + +h1 { + font-family: sans-serif; + font-size: 2em; + font-weight: bold; + margin: 2px 5px 5px 5px +} + +.message { + font-family: sans-serif; + font-size: 1.2em; + padding: 0px 4px 0px 4px; +} + +.hostlist { + width: 100%; + height: 400px; + margin: 0px; + overflow: auto; + border: black 1px solid; +} + +.hostentry { + margin: 0; + padding: 3px; + border-top: blue 1px solid; + min-height: 70px; +} + +.hostentry:first-child { + border-top-style: none; +} + +a.hostentry { text-decoration: none; } + +.hosticon { + float: left; + margin: 2px; +} + +.hostname { + font-family: sans-serif; + font-size: 1.2em; + font-weight: bold; + line-height: 1.2em; + margin: 2px 4px 2px 75px; +} + +.hoststatus_good { + font-weight: bold; + color: green; +} + +.hoststatus_bad { + font-weight: bold; + color: red; +} + +.hostinfo { + font-family: sans-serif; + font-size: 0.8em; + line-height: 1em; + margin: 2px 4px 2px 75px; +} + +.connect { + float: right; +} + +.reload { + font-family: sans-serif; + font-size: 0.8em; + font-style: italic; + text-align: right; + margin: 0.25em 0 0.5em 0; + line-height: 1em; +} + +.login { + font-family: sans-serif; + font-size: 0.9em; + position: absolute; + bottom: 0; + margin-bottom: 3px; +} + +.login_email { + font-weight: bold; +} diff --git a/remoting/client/extension/manifest.json b/remoting/client/extension/manifest.json index 15f22a5..6d5f0d6 100644 --- a/remoting/client/extension/manifest.json +++ b/remoting/client/extension/manifest.json @@ -3,7 +3,7 @@ "version": "1.0", "description": "Lists the hosts that the user can access.", "browser_action": { - "default_icon": "icon.png", + "default_icon": "chromoticon.png", "popup": "popup.html" }, "background_page": "background.html", diff --git a/remoting/client/extension/popup.html b/remoting/client/extension/popup.html index a4162c5..d582cba 100644 --- a/remoting/client/extension/popup.html +++ b/remoting/client/extension/popup.html @@ -8,40 +8,22 @@ found in the LICENSE file. <head> <script type="text/javascript" src="base.js"></script> <script type="text/javascript" src="client.js"></script> - <title>Get hosts</title> + <link rel="stylesheet" type="text/css" href="main.css" /> + <title>Remote Access</title> </head> - <body onload="initParams();" style="width:250;"> + <body onload="init();"> - <div style="border: blue 1px dotted;"> - <form name="hostqueryform" action="" method="GET"> - Fill-in to reauthenticate. <br /> - U: <input type="text" name="username" id="username" value="" /> <br /> - P: <input type="password" name="password" id="password" value="" /> <br /> - <input type="button" name="login_button" value="Log In" onclick="login(this.form)" /> - </form> - </div> - - <div style="border: blue 1px dotted;"> - Use to manually override the cookies. <br /> - <form name="connectparamsform" action="" method="GET"> - chromoting: <input type="text" name="chromoting_auth" id="chromoting_auth" value="" /> <br /> - xmpp: <input type="text" name="xmpp_auth" id="xmpp_auth" value="" /> - <input type="button" name="set_cookie_button" value="Set Auth Cookies" onclick="setAuthCookies(this.form)" /> - </form> - </div> + <h1>Remote Access</h1> - <div style="border: blue 1px dotted;"> - <form name="connectform" action="" method="GET"> - Conenct directly to host using auth cookies. Find Hosts doesn't require the host_jid to be filled out. <br /> - host_jid: <input type="text" name="host_jid" id="host_jid" value="" /> <br /> - <input type="button" name="connect_button" value="Connect" onclick="connect(this.form)" /> - <input type="button" name="find_host_button" value="Find Hosts" onclick="findHosts(this.form)" /> - </form> + <div id="hostlist_div" class="hostlist"> + <p class='message'>Initializing...</p> </div> - <br /> + <p class="reload"> + <a href="javascript:listHosts()">Reload host list</a> + </p> - <div id="hostlist_div" style="border: blue 1px solid; display: none;"> + <div id="login_div" class="login"> </div> <br /> diff --git a/remoting/tools/gethosts.sh b/remoting/tools/gethosts.sh new file mode 100755 index 0000000..dc31202 --- /dev/null +++ b/remoting/tools/gethosts.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Simple shell script to get list of available hosts from the Chromoting +# Directory API using the saved AuthToken. +authToken=`sed -n 2p ~/.chromotingDirectoryAuthToken` +url="https://www.googleapis.com/chromoting/v1/@me/hosts" +curl --header "Content-Type: application/json" --header "Authorization: GoogleLogin Auth=$authToken" -L "$url" +echo |