WIP, firefox support

This commit is contained in:
matt 2021-10-01 19:02:51 +00:00
parent c533d18ac7
commit 8842f372b8
2 changed files with 71 additions and 61 deletions

View File

@ -1134,32 +1134,15 @@ const UI = {
return; return;
} }
if (UI.rfb && UI.rfb.clipboardUp && UI.rfb.clipboardSeamless) { if (UI.rfb && UI.rfb.clipboardUp && UI.rfb.clipboardSeamless) {
navigator.clipboard.read().then((data) => {
UI.rfb.clipboardPasteDataFrom(data);
UI.needToCheckClipboardChange = false;
});
/*UI.readClipboard(function (text) { if (UI.rfb.clipboardBinary) {
console.log("clipboard read"); navigator.clipboard.read().then((data) => {
var maximumBufferSize = 10000; UI.rfb.clipboardPasteDataFrom(data);
var clipVal = document.getElementById('noVNC_clipboard_text').value; UI.needToCheckClipboardChange = false;
}, (err) => {
if (clipVal != text) { console.log("No data in clipboard");
console.log("clipboard sent") });
document.getElementById('noVNC_clipboard_text').value = text; // The websocket has a maximum buffer array size }
if (text.length > maximumBufferSize) {
UI.popupMessage("Clipboard contents too large. Data truncated", 2000);
UI.rfb.clipboardPasteFrom(text.slice(0, maximumBufferSize));
} else {
//UI.popupMessage("Copied from Local Clipboard");
UI.rfb.clipboardPasteFrom(text);
}
} // Reset flag to prevent checking too often
UI.needToCheckClipboardChange = false;
}); */
} }
}, },
@ -1300,15 +1283,13 @@ const UI = {
UI.rfb.antiAliasing = UI.getSetting('anti_aliasing'); UI.rfb.antiAliasing = UI.getSetting('anti_aliasing');
UI.rfb.clipboardUp = UI.getSetting('clipboard_up'); UI.rfb.clipboardUp = UI.getSetting('clipboard_up');
UI.rfb.clipboardDown = UI.getSetting('clipboard_down'); UI.rfb.clipboardDown = UI.getSetting('clipboard_down');
UI.rfb.clipboardBinary = supportsBinaryClipboard();
UI.rfb.clipboardSeamless = UI.getSetting('clipboard_seamless'); UI.rfb.clipboardSeamless = UI.getSetting('clipboard_seamless');
if (UI.rfb.clipboardSeamless) { UI.rfb.clipboardBinary = supportsBinaryClipboard() && UI.rfb.clipboardSeamless;
//Only explicitly request permission to clipboard on browsers that support binary clipboard access
if (supportsBinaryClipboard()) {
// explicitly request permission to the clipboard // explicitly request permission to the clipboard
if (UI.rfb.clipboardBinary) { navigator.permissions.query({ name: "clipboard-read" }).then((result) => { console.log('binary clipboard enabled') });
navigator.permissions.query({ name: "clipboard-read" }).then((result) => { console.log('binary clipboard enabled') });
} else {
navigator.permissions.query({ name: "clipboardRead" }).then((result) => { console.log('binary clipboard enabled') });
}
} }
// KASM-960 workaround, disable seamless on Safari // KASM-960 workaround, disable seamless on Safari
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent))

View File

@ -783,21 +783,28 @@ export default class RFB extends EventTargetMixin {
clipboardPasteFrom(text) { clipboardPasteFrom(text) {
if (this._rfbConnectionState !== 'connected' || this._viewOnly) { return; } if (this._rfbConnectionState !== 'connected' || this._viewOnly) { return; }
if (!(typeof text === 'string' && text.length > 0)) { return; }
this.sentEventsCounter+=1; this.sentEventsCounter+=1;
if (this._clipboardServerCapabilitiesFormats[extendedClipboardFormatText] &&
this._clipboardServerCapabilitiesActions[extendedClipboardActionNotify]) {
this._clipboardText = text; let data = new Uint8Array(text.length);
RFB.messages.extendedClipboardNotify(this._sock, [extendedClipboardFormatText]); for (let i = 0; i < text.length; i++) {
} else { data[i] = text.charCodeAt(i);
let data = new Uint8Array(text.length);
for (let i = 0; i < text.length; i++) {
// FIXME: text can have values outside of Latin1/Uint8
data[i] = text.charCodeAt(i);
}
RFB.messages.clientCutText(this._sock, data);
} }
let h = hashUInt8Array(data);
if (h === this._clipHash) {
console.log('No clipboard changes');
return;
} else {
this._clipHash = h;
}
let dataset = [];
let mimes = [ 'text/plain' ];
dataset.push(data);
RFB.messages.sendBinaryClipboard(this._sock, dataset, mimes);
} }
async clipboardPasteDataFrom(clipdata) { async clipboardPasteDataFrom(clipdata) {
@ -816,6 +823,9 @@ export default class RFB extends EventTargetMixin {
case 'text/plain': case 'text/plain':
case 'text/html': case 'text/html':
let blob = await clipdata[i].getType(mime); let blob = await clipdata[i].getType(mime);
if (!blob) {
continue;
}
let buff = await blob.arrayBuffer(); let buff = await blob.arrayBuffer();
let data = new Uint8Array(buff); let data = new Uint8Array(buff);
@ -2465,31 +2475,48 @@ export default class RFB extends EventTargetMixin {
Log.Debug("HandleBinaryClipboard"); Log.Debug("HandleBinaryClipboard");
let num = this._sock.rQshift8(); // how many different mime types let num = this._sock.rQshift8(); // how many different mime types
let blobs = [];
let clipdata = [];
let mimes = []; let mimes = [];
let clipItemData = {};
console.log('Clipboard items recieved.'); console.log('Clipboard items recieved.');
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
let mimelen = this._sock.rQshift8(); let mimelen = this._sock.rQshift8();
const mime = this._sock.rQshiftStr(mimelen); let mime = this._sock.rQshiftStr(mimelen);
let len = this._sock.rQshift32(); let len = this._sock.rQshift32();
let data = this._sock.rQshiftBytes(len);
const data = this._sock.rQshiftBytes(len);
switch(mime) { switch(mime) {
case "image/png": case "image/png":
case "text/html": case "text/html":
case "text/plain": case "text/plain":
if (mimes.includes(mime)){ //if (mimes.includes(mime)){
// continue;
//}
mimes.push(mime);
if (!this.clipboardBinary) {
if (mime == "text/plain") {
let textdata = new TextDecoder().decode(data);
if ((textdata.length > 0) && "\0" === textdata.charAt(textdata.length - 1)) {
textdata = textdata.slice(0, -1);
}
console.log('Clipboard item raw: ' + data);
console.log('Clipboard item decoded: ' + textdata);
this.dispatchEvent(new CustomEvent(
"clipboard",
{ detail: { text: textdata } })
);
continue;
}
continue; continue;
} }
mimes.push(mime);
console.log("Mime " + mime + ", len ", len); console.log("Mime " + mime + ", len ", len);
console.log(data); console.log(data);
let blob = new Blob([data], { type: mime }); clipItemData[mime] = new Blob([data], { type: mime });
clipdata.push(new ClipboardItem({ [mime]: blob }));
break; break;
default: default:
console.log('Mime type skipped: ' + mime); console.log('Mime type skipped: ' + mime);
@ -2497,13 +2524,15 @@ export default class RFB extends EventTargetMixin {
} }
} }
if (clipdata.length > 0) { if (Object.keys(clipItemData).length > 0) {
this._clipHash = 0; if (this.clipboardBinary) {
navigator.clipboard.write(clipdata).then( this._clipHash = 0;
function() {}, navigator.clipboard.write([new ClipboardItem(clipItemData)]).then(
function(err) { function() {},
console.log("Error writing to client clipboard: " + err); function(err) {
}); console.log("Error writing to client clipboard: " + err);
});
}
} }
return true; return true;