Make power API generic

Decouple it from XVP and make it a generic API.
This commit is contained in:
Pierre Ossman 2017-10-13 14:25:26 +02:00
parent 85b35fc0cc
commit cd523e8f28
7 changed files with 101 additions and 101 deletions

View File

@ -591,17 +591,17 @@ select:active {
padding: 0 10px;
}
/* XVP Shutdown/Reboot */
:root:not(.noVNC_connected) #noVNC_xvp_button {
/* Shutdown/Reboot */
:root:not(.noVNC_connected) #noVNC_power_button {
display: none;
}
#noVNC_xvp {
#noVNC_power {
}
#noVNC_xvp_buttons {
#noVNC_power_buttons {
display: none;
}
#noVNC_xvp input[type=button] {
#noVNC_power input[type=button] {
width: 100%;
}

View File

@ -91,7 +91,7 @@ var UI = {
UI.addControlbarHandlers();
UI.addTouchSpecificHandlers();
UI.addExtraKeysHandlers();
UI.addXvpHandlers();
UI.addMachineHandlers();
UI.addConnectionControlHandlers();
UI.addClipboardHandlers();
UI.addSettingsHandlers();
@ -207,7 +207,7 @@ var UI = {
'onUpdateState': UI.updateState,
'onDisconnected': UI.disconnectFinished,
'onCredentialsRequired': UI.credentials,
'onXvpInit': UI.updateXvpButton,
'onCapabilities': UI.updatePowerButton,
'onClipboard': UI.clipboardReceive,
'onBell': UI.bell,
'onFBUComplete': UI.initialResize,
@ -332,15 +332,15 @@ var UI = {
.addEventListener('click', UI.sendCtrlAltDel);
},
addXvpHandlers: function() {
document.getElementById("noVNC_xvp_shutdown_button")
.addEventListener('click', function() { UI.rfb.xvpShutdown(); });
document.getElementById("noVNC_xvp_reboot_button")
.addEventListener('click', function() { UI.rfb.xvpReboot(); });
document.getElementById("noVNC_xvp_reset_button")
.addEventListener('click', function() { UI.rfb.xvpReset(); });
document.getElementById("noVNC_xvp_button")
.addEventListener('click', UI.toggleXvpPanel);
addMachineHandlers: function() {
document.getElementById("noVNC_shutdown_button")
.addEventListener('click', function() { UI.rfb.machineShutdown(); });
document.getElementById("noVNC_reboot_button")
.addEventListener('click', function() { UI.rfb.machineReboot(); });
document.getElementById("noVNC_reset_button")
.addEventListener('click', function() { UI.rfb.machineReset(); });
document.getElementById("noVNC_power_button")
.addEventListener('click', UI.togglePowerPanel);
},
addConnectionControlHandlers: function() {
@ -489,7 +489,7 @@ var UI = {
UI.enableSetting('port');
UI.enableSetting('path');
UI.enableSetting('repeaterID');
UI.updateXvpButton(0);
UI.updatePowerButton();
UI.keepControlbar();
}
@ -868,7 +868,7 @@ var UI = {
closeAllPanels: function() {
UI.closeSettingsPanel();
UI.closeXvpPanel();
UI.closePowerPanel();
UI.closeClipboardPanel();
UI.closeExtraKeys();
},
@ -926,50 +926,52 @@ var UI = {
/* ------^-------
* /SETTINGS
* ==============
* XVP
* POWER
* ------v------*/
openXvpPanel: function() {
openPowerPanel: function() {
UI.closeAllPanels();
UI.openControlbar();
document.getElementById('noVNC_xvp')
document.getElementById('noVNC_power')
.classList.add("noVNC_open");
document.getElementById('noVNC_xvp_button')
document.getElementById('noVNC_power_button')
.classList.add("noVNC_selected");
},
closeXvpPanel: function() {
document.getElementById('noVNC_xvp')
closePowerPanel: function() {
document.getElementById('noVNC_power')
.classList.remove("noVNC_open");
document.getElementById('noVNC_xvp_button')
document.getElementById('noVNC_power_button')
.classList.remove("noVNC_selected");
},
toggleXvpPanel: function() {
if (document.getElementById('noVNC_xvp')
togglePowerPanel: function() {
if (document.getElementById('noVNC_power')
.classList.contains("noVNC_open")) {
UI.closeXvpPanel();
UI.closePowerPanel();
} else {
UI.openXvpPanel();
UI.openPowerPanel();
}
},
// Disable/enable XVP button
updateXvpButton: function(ver) {
if (ver >= 1 && !UI.rfb.get_view_only()) {
document.getElementById('noVNC_xvp_button')
// Disable/enable power button
updatePowerButton: function() {
if (UI.connected &&
UI.rfb.get_capabilities().power &&
!UI.rfb.get_view_only()) {
document.getElementById('noVNC_power_button')
.classList.remove("noVNC_hidden");
} else {
document.getElementById('noVNC_xvp_button')
document.getElementById('noVNC_power_button')
.classList.add("noVNC_hidden");
// Close XVP panel if open
UI.closeXvpPanel();
// Close power panel if open
UI.closePowerPanel();
}
},
/* ------^-------
* /XVP
* /POWER
* ==============
* CLIPBOARD
* ------v------*/

View File

@ -49,6 +49,8 @@ export default function RFB(defaults) {
this._rfb_tightvnc = false;
this._rfb_xvp_ver = 0;
this._capabilities = { power: false };
this._encHandlers = {};
this._encStats = {};
@ -140,7 +142,7 @@ export default function RFB(defaults) {
'onFBUComplete': function () { }, // onFBUComplete(rfb): RFB FBU received and processed
'onFBResize': function () { }, // onFBResize(rfb, width, height): frame buffer resized
'onDesktopName': function () { }, // onDesktopName(rfb, name): desktop name received
'onXvpInit': function () { } // onXvpInit(version): XVP extensions active for this connection
'onCapabilities': function () { } // onCapabilities(rfb, caps): the supported capabilities has changed
});
// main setup
@ -282,23 +284,16 @@ RFB.prototype = {
return true;
},
xvpOp: function (ver, op) {
if (this._rfb_xvp_ver < ver) { return false; }
Log.Info("Sending XVP operation " + op + " (version " + ver + ")");
RFB.messages.xvpOp(this._sock, ver, op);
return true;
machineShutdown: function () {
this._xvpOp(1, 2);
},
xvpShutdown: function () {
return this.xvpOp(1, 2);
machineReboot: function () {
this._xvpOp(1, 3);
},
xvpReboot: function () {
return this.xvpOp(1, 3);
},
xvpReset: function () {
return this.xvpOp(1, 4);
machineReset: function () {
this._xvpOp(1, 4);
},
// Send a key press. If 'down' is not specified then send a down key
@ -1282,7 +1277,8 @@ RFB.prototype = {
case 1: // XVP_INIT
this._rfb_xvp_ver = xvp_ver;
Log.Info("XVP extensions enabled (version " + this._rfb_xvp_ver + ")");
this._onXvpInit(this._rfb_xvp_ver);
this._capabilities.power = true;
this._onCapabilities(this, this._capabilities)
break;
default:
this._fail("Unexpected server message",
@ -1480,7 +1476,13 @@ RFB.prototype = {
this._timing.fbu_rt_start = (new Date()).getTime();
this._updateContinuousUpdates();
}
},
_xvpOp: function (ver, op) {
if (this._rfb_xvp_ver < ver) { return; }
Log.Info("Sending XVP operation " + op + " (version " + ver + ")");
RFB.messages.xvpOp(this._sock, ver, op);
},
};
make_properties(RFB, [
@ -1496,6 +1498,7 @@ make_properties(RFB, [
['wsProtocols', 'rw', 'arr'], // Protocols to use in the WebSocket connection
['repeaterID', 'rw', 'str'], // [UltraVNC] RepeaterID to connect to
['viewportDrag', 'rw', 'bool'], // Move the viewport on mouse drags
['capabilities', 'ro', 'arr'], // Supported capabilities
// Callback functions
['onUpdateState', 'rw', 'func'], // onUpdateState(rfb, state, oldstate): connection state change
@ -1508,7 +1511,7 @@ make_properties(RFB, [
['onFBUComplete', 'rw', 'func'], // onFBUComplete(rfb, fbu): RFB FBU received and processed
['onFBResize', 'rw', 'func'], // onFBResize(rfb, width, height): frame buffer resized
['onDesktopName', 'rw', 'func'], // onDesktopName(rfb, name): desktop name received
['onXvpInit', 'rw', 'func'] // onXvpInit(version): XVP extensions active for this connection
['onCapabilities', 'rw', 'func'] // onCapabilities(rfb, caps): the supported capabilities has changed
]);
RFB.prototype.set_local_cursor = function (cursor) {

View File

@ -41,6 +41,7 @@ attribute mode is one of the following:
| wsProtocols | arr | RW | ['binary'] | Protocols to use in the WebSocket connection
| repeaterID | str | RW | '' | UltraVNC RepeaterID to connect to
| viewportDrag | bool | RW | false | Move the viewport on mouse drags
| capabilities | arr | RO | [] | Supported capabilities (can include: 'power')
## 2 Methods
@ -55,10 +56,9 @@ object instance.
| disconnect | () | Disconnect
| sendCredentials | (credentials) | Send credentials after onCredentialsRequired callback
| sendCtrlAltDel | () | Send Ctrl-Alt-Del key sequence
| xvpOp | (ver, op) | Send a XVP operation (2=shutdown, 3=reboot, 4=reset)
| xvpShutdown | () | Send XVP shutdown.
| xvpReboot | () | Send XVP reboot.
| xvpReset | () | Send XVP reset.
| machineShutdown | () | Request a shutdown of the remote machine.
| machineReboot | () | Request a reboot of the remote machine.
| machineReset | () | Request a reset of the remote machine.
| sendKey | (keysym, code, down) | Send a key press event. If down not specified, send a down and up event.
| clipboardPasteFrom | (text) | Send a clipboard paste event
| autoscale | (width, height, downscaleOnly) | Scale the display
@ -84,7 +84,7 @@ functions.
| onFBUComplete | (rfb, fbu) | RFB FBU received and processed (see details below)
| onFBResize | (rfb, width, height) | Frame buffer (remote desktop) size changed
| onDesktopName | (rfb, name) | VNC desktop name recieved
| onXvpInit | (version) | XVP extensions active for this connection.
| onCapabilities | (rfb, capabilities) | The supported capabilities has changed
__RFB onUpdateState callback details__

View File

@ -300,28 +300,23 @@ describe('Remote Frame Buffer Protocol Client', function() {
client._rfb_xvp_ver = 1;
});
it('should send the shutdown signal on #xvpShutdown', function () {
client.xvpShutdown();
it('should send the shutdown signal on #machineShutdown', function () {
client.machineShutdown();
expect(client._sock).to.have.sent(new Uint8Array([0xFA, 0x00, 0x01, 0x02]));
});
it('should send the reboot signal on #xvpReboot', function () {
client.xvpReboot();
it('should send the reboot signal on #machineReboot', function () {
client.machineReboot();
expect(client._sock).to.have.sent(new Uint8Array([0xFA, 0x00, 0x01, 0x03]));
});
it('should send the reset signal on #xvpReset', function () {
client.xvpReset();
it('should send the reset signal on #machineReset', function () {
client.machineReset();
expect(client._sock).to.have.sent(new Uint8Array([0xFA, 0x00, 0x01, 0x04]));
});
it('should support sending arbitrary XVP operations via #xvpOp', function () {
client.xvpOp(1, 7);
expect(client._sock).to.have.sent(new Uint8Array([0xFA, 0x00, 0x01, 0x07]));
});
it('should not send XVP operations with higher versions than we support', function () {
expect(client.xvpOp(2, 7)).to.be.false;
client._xvpOp(2, 7);
expect(client._sock.flush).to.not.have.been.called;
});
});
@ -1800,11 +1795,11 @@ describe('Remote Frame Buffer Protocol Client', function() {
});
it('should set the XVP version and fire the callback with the version on XVP_INIT', function () {
client.set_onXvpInit(sinon.spy());
client.set_onCapabilities(sinon.spy());
client._sock._websocket._receive_data(new Uint8Array([250, 0, 10, 1]));
expect(client._rfb_xvp_ver).to.equal(10);
expect(client.get_onXvpInit()).to.have.been.calledOnce;
expect(client.get_onXvpInit()).to.have.been.calledWith(10);
expect(client.get_onCapabilities()).to.have.been.calledOnce;
expect(client.get_onCapabilities()).to.have.been.calledWith(client, { power: true });
});
it('should fail on unknown XVP message types', function () {

View File

@ -152,18 +152,18 @@
</div>
</div>
<!-- XVP Shutdown/Reboot -->
<!-- Shutdown/Reboot -->
<input type="image" alt="Shutdown/Reboot" src="app/images/power.svg"
id="noVNC_xvp_button" class="noVNC_button"
id="noVNC_power_button" class="noVNC_button"
title="Shutdown/Reboot..." />
<div class="noVNC_vcenter">
<div id="noVNC_xvp" class="noVNC_panel">
<div id="noVNC_power" class="noVNC_panel">
<div class="noVNC_heading">
<img src="app/images/power.svg"> Power
</div>
<input type="button" id="noVNC_xvp_shutdown_button" value="Shutdown" />
<input type="button" id="noVNC_xvp_reboot_button" value="Reboot" />
<input type="button" id="noVNC_xvp_reset_button" value="Reset" />
<input type="button" id="noVNC_shutdown_button" value="Shutdown" />
<input type="button" id="noVNC_reboot_button" value="Reboot" />
<input type="button" id="noVNC_reset_button" value="Reset" />
</div>
</div>

View File

@ -122,16 +122,16 @@
rfb.sendCtrlAltDel();
return false;
}
function xvpShutdown() {
rfb.xvpShutdown();
function machineShutdown() {
rfb.machineShutdown();
return false;
}
function xvpReboot() {
rfb.xvpReboot();
function machineReboot() {
rfb.machineReboot();
return false;
}
function xvpReset() {
rfb.xvpReset();
function machineReset() {
rfb.machineReset();
return false;
}
function status(text, level) {
@ -176,7 +176,7 @@
cad.disabled = false;
} else {
cad.disabled = true;
xvpInit(0);
updatePowerButtons();
}
}
@ -199,21 +199,21 @@
}, 500);
};
function xvpInit(ver) {
var xvpbuttons;
xvpbuttons = document.getElementById('noVNC_xvp_buttons');
if (ver >= 1) {
xvpbuttons.style.display = 'inline';
function updatePowerButtons() {
var powerbuttons;
powerbuttons = document.getElementById('noVNC_power_buttons');
if (rfb.get_capabilities().power) {
powerbuttons.style.display = 'inline';
} else {
xvpbuttons.style.display = 'none';
powerbuttons.style.display = 'none';
}
}
document.getElementById('sendCtrlAltDelButton').style.display = "inline";
document.getElementById('sendCtrlAltDelButton').onclick = sendCtrlAltDel;
document.getElementById('xvpShutdownButton').onclick = xvpShutdown;
document.getElementById('xvpRebootButton').onclick = xvpReboot;
document.getElementById('xvpResetButton').onclick = xvpReset;
document.getElementById('machineShutdownButton').onclick = machineShutdown;
document.getElementById('machineRebootButton').onclick = machineReboot;
document.getElementById('machineResetButton').onclick = machineReset;
WebUtil.init_logging(WebUtil.getConfigVar('logging', 'warn'));
document.title = WebUtil.getConfigVar('title', 'noVNC');
@ -262,7 +262,7 @@
'onNotification': notification,
'onUpdateState': updateState,
'onDisconnected': disconnected,
'onXvpInit': xvpInit,
'onCapabilities': updatePowerButtons,
'onCredentialsRequired': credentials,
'onFBUComplete': FBUComplete,
'onDesktopName': updateDesktopName});
@ -286,13 +286,13 @@
<td width="1%"><div id="noVNC_buttons">
<input type=button value="Send CtrlAltDel"
id="sendCtrlAltDelButton">
<span id="noVNC_xvp_buttons">
<span id="noVNC_power_buttons">
<input type=button value="Shutdown"
id="xvpShutdownButton">
id="machineShutdownButton">
<input type=button value="Reboot"
id="xvpRebootButton">
id="machineRebootButton">
<input type=button value="Reset"
id="xvpResetButton">
id="machineResetButton">
</span>
</div></td>
</tr></table>