1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-04-02 10:50:07 +03:00

feature #3748: Add spice and vnc standalone windows

This commit is contained in:
Daniel Molina 2015-06-26 17:44:50 +02:00
parent 2e67d8d4ce
commit 24ba82f32b
12 changed files with 862 additions and 341 deletions

View File

@ -304,6 +304,7 @@ SUNSTONE_DIRS="$SUNSTONE_LOCATION/routes \
$SUNSTONE_LOCATION/models/OpenNebulaJSON \
$SUNSTONE_LOCATION/public \
$SUNSTONE_LOCATION/public/dist \
$SUNSTONE_LOCATION/public/dist/console \
$SUNSTONE_LOCATION/public/css \
$SUNSTONE_LOCATION/public/bower_components/fontawesome/fonts \
$SUNSTONE_LOCATION/public/locale/languages \
@ -471,6 +472,7 @@ INSTALL_SUNSTONE_FILES=(
SUNSTONE_MODELS_JSON_FILES:$SUNSTONE_LOCATION/models/OpenNebulaJSON
SUNSTONE_VIEWS_FILES:$SUNSTONE_LOCATION/views
SUNSTONE_PUBLIC_JS_FILES:$SUNSTONE_LOCATION/public/dist
SUNSTONE_PUBLIC_JS_CONSOLE_FILES:$SUNSTONE_LOCATION/public/dist/console
SUNSTONE_PUBLIC_FONT_AWSOME:$SUNSTONE_LOCATION/public/bower_components/fontawesome/fonts
SUNSTONE_ROUTES_FILES:$SUNSTONE_LOCATION/routes
SUNSTONE_PUBLIC_CSS_FILES:$SUNSTONE_LOCATION/public/css
@ -1570,6 +1572,11 @@ SUNSTONE_PUBLIC_JS_FILES="src/sunstone/public/dist/login.js \
src/sunstone/public/dist/main.js \
src/sunstone/public/dist/main.js.map"
SUNSTONE_PUBLIC_JS_CONSOLE_FILES="src/sunstone/public/dist/console/vnc.js \
src/sunstone/public/dist/console/vnc.js.map \
src/sunstone/public/dist/console/spice.js \
src/sunstone/public/dist/console/spice.js.map"
SUNSTONE_ROUTES_FILES="src/sunstone/routes/oneflow.rb \
src/sunstone/routes/vcenter.rb \

View File

@ -50,8 +50,9 @@ module.exports = function(grunt) {
preserveLicenseComments: false,
optimize: 'uglify2',
generateSourceMaps: true,
removeCombined: false,
findNestedDependencies: true,
removeCombined: true,
//skipDirOptimize: false,
//findNestedDependencies: true,
modules: [
{
name: 'main',
@ -61,6 +62,16 @@ module.exports = function(grunt) {
name: 'login',
include: ['almond'],
insertRequire: ['login']
},
{
name: 'console/vnc',
include: ['almond'],
insertRequire: ['console/vnc']
},
{
name: 'console/spice',
include: ['almond'],
insertRequire: ['console/spice']
}
/*{
name: 'main'

View File

@ -0,0 +1,112 @@
define(function(require) {
require('spice-main');
var host = null, port = null;
var sc;
function spice_set_cookie(name, value, days) {
var date, expires;
date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
document.cookie = name + "=" + value + expires + "; path=/";
};
function spice_query_var(name, defvalue) {
var match = RegExp('[?&]' + name + '=([^&]*)')
.exec(window.location.search);
return match ?
decodeURIComponent(match[1].replace(/\+/g, ' '))
: defvalue;
}
function spice_error(e) {
disconnect();
}
function connect() {
var host, port, password, scheme = "ws://", uri;
// By default, use the host and port of server that served this file
host = spice_query_var('host', window.location.hostname);
// Note that using the web server port only makes sense
// if your web server has a reverse proxy to relay the WebSocket
// traffic to the correct destination port.
var default_port = window.location.port;
if (!default_port) {
if (window.location.protocol == 'http:') {
default_port = 80;
} else if (window.location.protocol == 'https:') {
default_port = 443;
}
}
port = spice_query_var('port', default_port);
if (window.location.protocol == 'https:') {
scheme = "wss://";
}
// If a token variable is passed in, set the parameter in a cookie.
// This is used by nova-spiceproxy.
token = spice_query_var('token', null);
if (token) {
spice_set_cookie('token', token, 1)
}
password = spice_query_var('password', '');
path = spice_query_var('path', 'websockify');
if ((!host) || (!port)) {
console.log("must specify host and port in URL");
return;
}
if (sc) {
sc.stop();
}
uri = scheme + host + ":" + port + "?token=" + token;
try {
sc = new SpiceMainConn({uri: uri, screen_id: "spice-screen", dump_id: "debug-div",
message_id: "message-div", password: password, onerror: spice_error, onagent: agent_connected});
}
catch (e) {
alert(e.toString());
disconnect();
}
}
function disconnect() {
console.log(">> disconnect");
if (sc) {
sc.stop();
}
if (window.File && window.FileReader && window.FileList && window.Blob) {
var spice_xfer_area = document.getElementById('spice-xfer-area');
document.getElementById('spice-area').removeChild(spice_xfer_area);
document.getElementById('spice-area').removeEventListener('dragover', handle_file_dragover, false);
document.getElementById('spice-area').removeEventListener('drop', handle_file_drop, false);
}
console.log("<< disconnect");
}
function agent_connected(sc) {
window.addEventListener('resize', handle_resize);
window.spice_connection = this;
resize_helper(this);
if (window.File && window.FileReader && window.FileList && window.Blob) {
var spice_xfer_area = document.createElement("div");
spice_xfer_area.setAttribute('id', 'spice-xfer-area');
document.getElementById('spice-area').addEventListener('dragover', handle_file_dragover, false);
document.getElementById('spice-area').addEventListener('drop', handle_file_drop, false);
} else {
console.log("File API is not supported");
}
}
connect();
});

View File

@ -0,0 +1,137 @@
define(function(require) {
require('vnc-util');
require('vnc-webutil');
require('vnc-base64');
require('vnc-websock');
require('vnc-des');
require('vnc-keysymdef');
require('vnc-keyboard');
require('vnc-input');
require('vnc-display');
require('vnc-jsunzip');
require('vnc-rfb');
require('vnc-keysym');
var rfb;
function passwordRequired(rfb) {
var msg;
msg = '<form onsubmit="return setPassword();"';
msg += ' style="margin-bottom: 0px">';
msg += 'Password Required: ';
msg += '<input type=password size=10 id="password_input" class="noVNC_status">';
msg += '<\/form>';
$D('noVNC_status_bar').setAttribute("class", "noVNC_status_warn");
$D('noVNC_status').innerHTML = msg;
}
function setPassword() {
rfb.sendPassword($D('password_input').value);
return false;
}
function sendCtrlAltDel() {
rfb.sendCtrlAltDel();
return false;
}
function xvpShutdown() {
rfb.xvpShutdown();
return false;
}
function xvpReboot() {
rfb.xvpReboot();
return false;
}
function xvpReset() {
rfb.xvpReset();
return false;
}
function updateState(rfb, state, oldstate, msg) {
var s, sb, cad, level;
s = $D('noVNC_status');
sb = $D('noVNC_status_bar');
cad = $D('sendCtrlAltDelButton');
switch (state) {
case 'failed': level = "error"; break;
case 'fatal': level = "error"; break;
case 'normal': level = "normal"; break;
case 'disconnected': level = "normal"; break;
case 'loaded': level = "normal"; break;
default: level = "warn"; break;
}
if (state === "normal") {
cad.disabled = false;
} else {
cad.disabled = true;
xvpInit(0);
}
if (typeof(msg) !== 'undefined') {
sb.setAttribute("class", "noVNC_status_" + level);
s.innerHTML = msg;
}
}
function xvpInit(ver) {
var xvpbuttons;
xvpbuttons = $D('noVNC_xvp_buttons');
if (ver >= 1) {
xvpbuttons.style.display = 'inline';
} else {
xvpbuttons.style.display = 'none';
}
}
var host, port, password, path, token;
$D('sendCtrlAltDelButton').style.display = "inline";
$D('sendCtrlAltDelButton').onclick = sendCtrlAltDel;
$D('xvpShutdownButton').onclick = xvpShutdown;
$D('xvpRebootButton').onclick = xvpReboot;
$D('xvpResetButton').onclick = xvpReset;
WebUtil.init_logging(WebUtil.getQueryVar('logging', 'warn'));
document.title = unescape(WebUtil.getQueryVar('title', 'noVNC'));
// By default, use the host and port of server that served this file
host = WebUtil.getQueryVar('host', window.location.hostname);
port = WebUtil.getQueryVar('port', window.location.port);
// if port == 80 (or 443) then it won't be present and should be
// set manually
if (!port) {
if (window.location.protocol.substring(0, 4) == 'http') {
port = 80;
} else if (window.location.protocol.substring(0, 5) == 'https') {
port = 443;
}
}
// If a token variable is passed in, set the parameter in a cookie.
// This is used by nova-novncproxy.
token = WebUtil.getQueryVar('token', null);
if (token) {
WebUtil.createCookie('token', token, 1)
}
password = WebUtil.getQueryVar('password', '');
path = WebUtil.getQueryVar('path', 'websockify');
if ((!host) || (!port)) {
updateState('failed',
"Must specify host and port in URL");
return;
}
rfb = new RFB({'target': $D('noVNC_canvas'),
'encrypt': WebUtil.getQueryVar('encrypt',
(window.location.protocol === "https:")),
'repeaterID': WebUtil.getQueryVar('repeaterID', ''),
'true_color': WebUtil.getQueryVar('true_color', true),
'local_cursor': WebUtil.getQueryVar('cursor', true),
'shared': WebUtil.getQueryVar('shared', true),
'view_only': WebUtil.getQueryVar('view_only', false),
'onUpdateState': updateState,
'onXvpInit': xvpInit,
'onPasswordRequired': passwordRequired});
rfb.connect(host, port, password, path + "?token=" + token);
})

View File

@ -0,0 +1,483 @@
/*
* Based on the noVNC base CSS
* Copyright (C) 2012 Joel Martin
* Copyright (C) 2013 Samuel Mannehed for Cendio AB
* noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
* This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
*/
body {
margin:0;
padding:0;
font-family: Helvetica;
/*Background image with light grey curve.*/
height:100%;
}
html {
height:100%;
}
#noVNC_controls ul {
list-style: none;
margin: 0px;
padding: 0px;
}
#noVNC_controls li {
padding-bottom:8px;
}
#noVNC_host {
width:150px;
}
#noVNC_port {
width: 80px;
}
#noVNC_password {
width: 150px;
}
#noVNC_encrypt {
}
#noVNC_path {
width: 100px;
}
#noVNC_connect_button {
width: 110px;
float:right;
}
#noVNC_buttons {
white-space: nowrap;
}
#noVNC_view_drag_button {
display: none;
}
#sendCtrlAltDelButton {
display: none;
}
#noVNC_xvp_buttons {
display: none;
}
#noVNC_mobile_buttons {
display: none;
}
#noVNC_extra_keys {
display: inline;
list-style-type: none;
padding: 0px;
margin: 0px;
position: relative;
}
.noVNC-buttons-left {
float: left;
z-index: 1;
position: relative;
}
.noVNC-buttons-right {
float:right;
right: 0px;
z-index: 2;
position: absolute;
}
#noVNC_status {
font-size: 12px;
padding-top: 4px;
height:32px;
text-align: center;
font-weight: bold;
}
#noVNC_settings_menu {
margin: 3px;
text-align: left;
}
#noVNC_settings_menu ul {
list-style: none;
margin: 0px;
padding: 0px;
}
#noVNC_apply {
float:right;
}
/* Do not set width/height for VNC_screen or VNC_canvas or incorrect
* scaling will occur. Canvas resizes to remote VNC settings */
#noVNC_screen_pad {
margin: 0px;
padding: 0px;
height: 36px;
}
#noVNC_screen {
text-align: center;
display: table;
width:100%;
height:100%;
/*border-top-left-radius: 800px 600px;*/
}
#noVNC_container, #noVNC_canvas {
margin: 0px;
padding: 0px;
}
#noVNC_canvas {
left: 0px;
}
#VNC_clipboard_clear_button {
float:right;
}
#VNC_clipboard_text {
font-size: 11px;
}
#noVNC_clipboard_clear_button {
float:right;
}
/*Bubble contents divs*/
#noVNC_settings {
display:none;
margin-top:73px;
right:20px;
position:fixed;
}
#noVNC_controls {
display:none;
margin-top:73px;
right:12px;
position:fixed;
}
#noVNC_controls.top:after {
right:15px;
}
#noVNC_description {
display:none;
position:fixed;
margin-top:73px;
right:20px;
left:20px;
padding:15px;
color:#000;
border:2px solid #E0E0E0;
}
#noVNC_popup_status_panel {
display:none;
position: fixed;
z-index: 1;
margin:15px;
margin-top:60px;
padding:15px;
width:auto;
text-align:center;
font-weight:bold;
word-wrap:break-word;
background:rgba(0,0,0,0.65);
-webkit-border-radius:10px;
-moz-border-radius:10px;
border-radius:10px;
}
#noVNC_xvp {
display:none;
margin-top:73px;
right:30px;
position:fixed;
}
#noVNC_xvp.top:after {
right:125px;
}
#noVNC_clipboard {
display:none;
margin-top:73px;
right:30px;
position:fixed;
}
#noVNC_clipboard.top:after {
right:85px;
}
#keyboardinput {
width:1px;
height:1px;
background-color:#fff;
color:#fff;
border:0;
position: relative;
left: -40px;
z-index: -1;
}
/*
* Advanced Styling
*/
.noVNC_status_normal {
color: #b2bdcd; /* Old browsers */
}
.noVNC_status_error {
color: #f04040; /* Old browsers */
}
.noVNC_status_warn {
color: #f0f040; /* Old browsers */
}
/* Control bar */
#noVNC-control-bar {
position:fixed;
display:block;
height:36px;
left:0;
top:0;
width:100%;
z-index:200;
}
.noVNC_status_button {
padding: 4px 4px;
vertical-align: middle;
border:1px solid #869dbc;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
background: #b2bdcd; /* Old browsers */
background: -moz-linear-gradient(top, #b2bdcd 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2bdcd), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#b2bdcd', endColorstr='#6e84a3',GradientType=0 ); /* IE6-9 */
background: linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */
/*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/
}
.noVNC_status_button_selected {
padding: 4px 4px;
vertical-align: middle;
border:1px solid #4366a9;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
background: #779ced; /* Old browsers */
background: -moz-linear-gradient(top, #779ced 0%, #3970e0 49%, #2160dd 51%, #2463df 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#779ced), color-stop(49%,#3970e0), color-stop(51%,#2160dd), color-stop(100%,#2463df)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* IE10+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#779ced', endColorstr='#2463df',GradientType=0 ); /* IE6-9 */
background: linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* W3C */
/*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/
}
/*Settings Bubble*/
.triangle-right {
position:relative;
padding:15px;
margin:1em 0 3em;
color:#fff;
background:#fff; /* default background for browsers without gradient support */
/* css3 */
/*background:-webkit-gradient(linear, 0 0, 0 100%, from(#2e88c4), to(#075698));
background:-moz-linear-gradient(#2e88c4, #075698);
background:-o-linear-gradient(#2e88c4, #075698);
background:linear-gradient(#2e88c4, #075698);*/
-webkit-border-radius:10px;
-moz-border-radius:10px;
border-radius:10px;
color:#000;
border:2px solid #E0E0E0;
}
.triangle-right.top:after {
border-color: transparent #E0E0E0;
border-width: 20px 20px 0 0;
bottom: auto;
left: auto;
right: 50px;
top: -20px;
}
.triangle-right:after {
content:"";
position:absolute;
bottom:-20px; /* value = - border-top-width - border-bottom-width */
left:50px; /* controls horizontal position */
border-width:20px 0 0 20px; /* vary these values to change the angle of the vertex */
border-style:solid;
border-color:#E0E0E0 transparent;
/* reduce the damage in FF3.0 */
display:block;
width:0;
}
.triangle-right.top:after {
top:-40px; /* value = - border-top-width - border-bottom-width */
right:50px; /* controls horizontal position */
bottom:auto;
left:auto;
border-width:40px 40px 0 0; /* vary these values to change the angle of the vertex */
border-color:transparent #E0E0E0;
}
/*Default noVNC logo.*/
/* From: http://fonts.googleapis.com/css?family=Orbitron:700 */
@font-face {
font-family: 'Orbitron';
font-style: normal;
font-weight: 700;
src: local('?'), url('Orbitron700.woff') format('woff'),
url('Orbitron700.ttf') format('truetype');
}
#noVNC_logo {
margin-top: 170px;
margin-left: 10px;
color:yellow;
text-align:left;
font-family: 'Orbitron', 'OrbitronTTF', sans-serif;
line-height:90%;
text-shadow:
5px 5px 0 #000,
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
}
#noVNC_logo span{
color:green;
}
/* ----------------------------------------
* Media sizing
* ----------------------------------------
*/
.noVNC_status_button {
font-size: 12px;
}
#noVNC_clipboard_text {
width: 500px;
}
#noVNC_logo {
font-size: 180px;
}
.noVNC-buttons-left {
padding-left: 10px;
}
.noVNC-buttons-right {
padding-right: 10px;
}
#noVNC_status {
z-index: 0;
position: absolute;
width: 100%;
margin-left: 0px;
}
#showExtraKeysButton { display: none; }
#toggleCtrlButton { display: inline; }
#toggleAltButton { display: inline; }
#sendTabButton { display: inline; }
#sendEscButton { display: inline; }
/* left-align the status text on lower resolutions */
@media screen and (max-width: 800px){
#noVNC_status {
z-index: 1;
position: relative;
width: auto;
float: left;
margin-left: 4px;
}
}
@media screen and (max-width: 640px){
#noVNC_clipboard_text {
width: 410px;
}
#noVNC_logo {
font-size: 150px;
}
.noVNC_status_button {
font-size: 10px;
}
.noVNC-buttons-left {
padding-left: 0px;
}
.noVNC-buttons-right {
padding-right: 0px;
}
/* collapse the extra keys on lower resolutions */
#showExtraKeysButton {
display: inline;
}
#toggleCtrlButton {
display: none;
position: absolute;
top: 30px;
left: 0px;
}
#toggleAltButton {
display: none;
position: absolute;
top: 65px;
left: 0px;
}
#sendTabButton {
display: none;
position: absolute;
top: 100px;
left: 0px;
}
#sendEscButton {
display: none;
position: absolute;
top: 135px;
left: 0px;
}
}
@media screen and (min-width: 321px) and (max-width: 480px) {
#noVNC_clipboard_text {
width: 250px;
}
#noVNC_logo {
font-size: 110px;
}
}
@media screen and (max-width: 320px) {
.noVNC_status_button {
font-size: 9px;
}
#noVNC_clipboard_text {
width: 220px;
}
#noVNC_logo {
font-size: 90px;
}
}

View File

@ -0,0 +1,48 @@
body
{
margin: 0; padding: 0;
font-family: "Lucida Grande", "Lucida Sans Unicode", "Helvetica Neue", Helvetica, Arial, Verdana, sans-serif;
font-size: 12pt;
line-height: 1.5em;
}
* { margin: 0; }
#spice-area
{
height: 100%;
padding: 0;
margin-left: auto;
margin-right: auto;
}
.spice-screen
{
min-height: 600px;
height: 100%;
margin-left: auto;
margin-right: auto;
padding: 0;
text-align: center;
}
.spice-message {
width: 700px;
height: 50px;
overflow: auto;
background-color: #efefef;
border: solid #c3c3c3 1px;
font-size: 8pt;
float: right;
margin-right: 30px;
line-height: 1.1em;
font-family: 'Andale Mono', monospace;
}
.spice-message p {
margin-bottom: 0em;
margin-top: 0em;
}
.spice-message-warning {
color: orange;
}
.spice-message-error {
color: red;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,5 @@
<!--
Based on the original:
Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
This file is part of spice-html5.
@ -28,158 +29,8 @@
<head>
<title><%= params['title']%></title>
<script src="vendor/spice/spicearraybuffer.js"></script>
<script src="vendor/spice/enums.js"></script>
<script src="vendor/spice/atKeynames.js"></script>
<script src="vendor/spice/utils.js"></script>
<script src="vendor/spice/png.js"></script>
<script src="vendor/spice/lz.js"></script>
<script src="vendor/spice/quic.js"></script>
<script src="vendor/spice/bitmap.js"></script>
<script src="vendor/spice/spicedataview.js"></script>
<script src="vendor/spice/spicetype.js"></script>
<script src="vendor/spice/spicemsg.js"></script>
<script src="vendor/spice/wire.js"></script>
<script src="vendor/spice/spiceconn.js"></script>
<script src="vendor/spice/display.js"></script>
<script src="vendor/spice/main.js"></script>
<script src="vendor/spice/inputs.js"></script>
<script src="vendor/spice/webm.js"></script>
<script src="vendor/spice/playback.js"></script>
<script src="vendor/spice/simulatecursor.js"></script>
<script src="vendor/spice/cursor.js"></script>
<script src="vendor/spice/jsbn.js"></script>
<script src="vendor/spice/rsa.js"></script>
<script src="vendor/spice/prng4.js"></script>
<script src="vendor/spice/rng.js"></script>
<script src="vendor/spice/sha1.js"></script>
<script src="vendor/spice/ticket.js"></script>
<script src="vendor/spice/resize.js"></script>
<script src="vendor/spice/filexfer.js"></script>
<link rel="stylesheet" type="text/css" href="vendor/spice/spice-custom.css" />
<script>
var host = null, port = null;
var sc;
function spice_set_cookie(name, value, days) {
var date, expires;
date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toGMTString();
document.cookie = name + "=" + value + expires + "; path=/";
};
function spice_query_var(name, defvalue) {
var match = RegExp('[?&]' + name + '=([^&]*)')
.exec(window.location.search);
return match ?
decodeURIComponent(match[1].replace(/\+/g, ' '))
: defvalue;
}
function spice_error(e)
{
disconnect();
}
function connect()
{
var host, port, password, scheme = "ws://", uri;
// By default, use the host and port of server that served this file
host = spice_query_var('host', window.location.hostname);
// Note that using the web server port only makes sense
// if your web server has a reverse proxy to relay the WebSocket
// traffic to the correct destination port.
var default_port = window.location.port;
if (!default_port) {
if (window.location.protocol == 'http:') {
default_port = 80;
}
else if (window.location.protocol == 'https:') {
default_port = 443;
}
}
port = spice_query_var('port', default_port);
if (window.location.protocol == 'https:') {
scheme = "wss://";
}
// If a token variable is passed in, set the parameter in a cookie.
// This is used by nova-spiceproxy.
token = spice_query_var('token', null);
if (token) {
spice_set_cookie('token', token, 1)
}
password = spice_query_var('password', '');
path = spice_query_var('path', 'websockify');
if ((!host) || (!port)) {
console.log("must specify host and port in URL");
return;
}
if (sc) {
sc.stop();
}
uri = scheme + host + ":" + port + "?token=" + token;
try
{
sc = new SpiceMainConn({uri: uri, screen_id: "spice-screen", dump_id: "debug-div",
message_id: "message-div", password: password, onerror: spice_error, onagent: agent_connected });
}
catch (e)
{
alert(e.toString());
disconnect();
}
}
function disconnect()
{
console.log(">> disconnect");
if (sc) {
sc.stop();
}
if (window.File && window.FileReader && window.FileList && window.Blob)
{
var spice_xfer_area = document.getElementById('spice-xfer-area');
document.getElementById('spice-area').removeChild(spice_xfer_area);
document.getElementById('spice-area').removeEventListener('dragover', handle_file_dragover, false);
document.getElementById('spice-area').removeEventListener('drop', handle_file_drop, false);
}
console.log("<< disconnect");
}
function agent_connected(sc)
{
window.addEventListener('resize', handle_resize);
window.spice_connection = this;
resize_helper(this);
if (window.File && window.FileReader && window.FileList && window.Blob)
{
var spice_xfer_area = document.createElement("div");
spice_xfer_area.setAttribute('id', 'spice-xfer-area');
document.getElementById('spice-area').addEventListener('dragover', handle_file_dragover, false);
document.getElementById('spice-area').addEventListener('drop', handle_file_drop, false);
}
else
{
console.log("File API is not supported");
}
}
connect();
</script>
<link rel="stylesheet" type="text/css" href="css/spice-custom.css" />
<script src="dist/console/spice.js"></script>
</head>
<body>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<!--
<!--
Based on the original:
noVNC example: simple example using default UI
Copyright (C) 2012 Joel Martin
@ -13,202 +13,59 @@
http://example.com/?host=HOST&port=PORT&encrypt=1&true_color=1
-->
<title><%= params['vm_name']%></title>
<title><%= params['vm_name']%></title>
<meta charset="utf-8">
<meta charset="utf-8">
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
Remove this if you use the .htaccess -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!-- Apple iOS Safari settings -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<!-- App Start Icon -->
<link rel="apple-touch-startup-image" href="images/screen_320x460.png" />
<!-- For iOS devices set the icon to use if user bookmarks app on their homescreen -->
<link rel="apple-touch-icon" href="images/screen_57x57.png">
<!--
<!-- Apple iOS Safari settings -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<!-- App Start Icon -->
<link rel="apple-touch-startup-image" href="images/screen_320x460.png" />
<!-- For iOS devices set the icon to use if user bookmarks app on their homescreen -->
<link rel="apple-touch-icon" href="images/screen_57x57.png">
<!--
<link rel="apple-touch-icon-precomposed" href="images/screen_57x57.png" />
-->
<!-- Stylesheets -->
<link rel="stylesheet" href="vendor/noVNC/novnc-custom.css" title="plain">
<script>
var INCLUDE_URI = "vendor/noVNC/";
</script>
<script src="vendor/noVNC/util.js"></script>
-->
<!-- Stylesheets -->
<link rel="stylesheet" type="text/css" href="css/novnc-custom.css" title="plain">
<script src="dist/console/vnc.js"></script>
</head>
<body style="margin: 0px;">
<div id="noVNC_screen">
<div id="noVNC_screen">
<div style="background: #f7f7f7; border-bottom: 1px solid #dfdfdf; padding: 10px 0px 15px 0px">
<div id="noVNC_status_bar" class="noVNC_status_bar" style="margin-top: 0px;">
<table border=0 width="100%"><tr>
<td width="1%" ><img src="images/one_small_logo.png" style="height:40px; vertical-align:top; margin-left: 30px"></td>
<td><div id="noVNC_status" style="position: relative; height: auto;">
Loading
</div></td>
<td width="1%" ><div id="noVNC_buttons" style="margin-right: 30px">
<input type=button value="Send CtrlAltDel"
<div id="noVNC_status_bar" class="noVNC_status_bar" style="margin-top: 0px;">
<table border=0 width="100%">
<tr>
<td width="1%" >
<img src="images/one_small_logo.png" style="height:40px; vertical-align:top; margin-left: 30px"></td>
<td>
<div id="noVNC_status" style="position: relative; height: auto;">Loading</div>
</td>
<td width="1%" >
<div id="noVNC_buttons" style="margin-right: 30px">
<input type=button value="Send CtrlAltDel"
id="sendCtrlAltDelButton">
<span id="noVNC_xvp_buttons">
<input type=button value="Shutdown"
<span id="noVNC_xvp_buttons">
<input type=button value="Shutdown"
id="xvpShutdownButton">
<input type=button value="Reboot"
<input type=button value="Reboot"
id="xvpRebootButton">
<input type=button value="Reset"
id="xvpResetButton">
</span>
</div></td>
</tr></table>
</div>
<input type=button value="Reset"
id="xvpResetButton"></span>
</div>
</td>
</tr>
</table>
</div>
</div>
<canvas id="noVNC_canvas" width="640px" height="20px">
Canvas not supported.
</canvas>
</div>
<script>
/*jslint white: false */
/*global window, $, Util, RFB, */
"use strict";
// Load supporting scripts
Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
"keysymdef.js", "keyboard.js", "input.js", "display.js",
"jsunzip.js", "rfb.js", "keysym.js"]);
var rfb;
function passwordRequired(rfb) {
var msg;
msg = '<form onsubmit="return setPassword();"';
msg += ' style="margin-bottom: 0px">';
msg += 'Password Required: ';
msg += '<input type=password size=10 id="password_input" class="noVNC_status">';
msg += '<\/form>';
$D('noVNC_status_bar').setAttribute("class", "noVNC_status_warn");
$D('noVNC_status').innerHTML = msg;
}
function setPassword() {
rfb.sendPassword($D('password_input').value);
return false;
}
function sendCtrlAltDel() {
rfb.sendCtrlAltDel();
return false;
}
function xvpShutdown() {
rfb.xvpShutdown();
return false;
}
function xvpReboot() {
rfb.xvpReboot();
return false;
}
function xvpReset() {
rfb.xvpReset();
return false;
}
function updateState(rfb, state, oldstate, msg) {
var s, sb, cad, level;
s = $D('noVNC_status');
sb = $D('noVNC_status_bar');
cad = $D('sendCtrlAltDelButton');
switch (state) {
case 'failed': level = "error"; break;
case 'fatal': level = "error"; break;
case 'normal': level = "normal"; break;
case 'disconnected': level = "normal"; break;
case 'loaded': level = "normal"; break;
default: level = "warn"; break;
}
if (state === "normal") {
cad.disabled = false;
} else {
cad.disabled = true;
xvpInit(0);
}
if (typeof(msg) !== 'undefined') {
sb.setAttribute("class", "noVNC_status_" + level);
s.innerHTML = msg;
}
}
function xvpInit(ver) {
var xvpbuttons;
xvpbuttons = $D('noVNC_xvp_buttons');
if (ver >= 1) {
xvpbuttons.style.display = 'inline';
} else {
xvpbuttons.style.display = 'none';
}
}
window.onscriptsload = function () {
var host, port, password, path, token;
$D('sendCtrlAltDelButton').style.display = "inline";
$D('sendCtrlAltDelButton').onclick = sendCtrlAltDel;
$D('xvpShutdownButton').onclick = xvpShutdown;
$D('xvpRebootButton').onclick = xvpReboot;
$D('xvpResetButton').onclick = xvpReset;
WebUtil.init_logging(WebUtil.getQueryVar('logging', 'warn'));
document.title = unescape(WebUtil.getQueryVar('title', 'noVNC'));
// By default, use the host and port of server that served this file
host = WebUtil.getQueryVar('host', window.location.hostname);
port = WebUtil.getQueryVar('port', window.location.port);
// if port == 80 (or 443) then it won't be present and should be
// set manually
if (!port) {
if (window.location.protocol.substring(0,4) == 'http') {
port = 80;
}
else if (window.location.protocol.substring(0,5) == 'https') {
port = 443;
}
}
// If a token variable is passed in, set the parameter in a cookie.
// This is used by nova-novncproxy.
token = WebUtil.getQueryVar('token', null);
if (token) {
WebUtil.createCookie('token', token, 1)
}
password = WebUtil.getQueryVar('password', '');
path = WebUtil.getQueryVar('path', 'websockify');
if ((!host) || (!port)) {
updateState('failed',
"Must specify host and port in URL");
return;
}
rfb = new RFB({'target': $D('noVNC_canvas'),
'encrypt': WebUtil.getQueryVar('encrypt',
(window.location.protocol === "https:")),
'repeaterID': WebUtil.getQueryVar('repeaterID', ''),
'true_color': WebUtil.getQueryVar('true_color', true),
'local_cursor': WebUtil.getQueryVar('cursor', true),
'shared': WebUtil.getQueryVar('shared', true),
'view_only': WebUtil.getQueryVar('view_only', false),
'onUpdateState': updateState,
'onXvpInit': xvpInit,
'onPasswordRequired': passwordRequired});
rfb.connect("<%= params['host']%>", "<%= params['port']%>", "<%= params['password']%>", path+"?token=<%= params['token']%>");
};
</script>
</body>
</html>
<canvas id="noVNC_canvas" width="640px" height="20px">Canvas not supported.</canvas>
</div>
</body>
</html>