514 lines
23 KiB
HTML
Executable File
514 lines
23 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
|
|
<!--
|
|
Copyright (c) 2024 lax1dude. All Rights Reserved.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
-->
|
|
|
|
<html style="width:100%;height:100%;">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Eaglercraft Desktop Runtime</title>
|
|
<link type="image/png" rel="shortcut icon" id="vigg" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAR/SURBVEhLtZXZK3ZRFMYPcqXc+gv413DHxVuGIpIhkciQWaRccCNjSCkligwXSOZ5nmfv9zvn2e8+58V753sudmuvvdZ61l5r7XOc8H+GS/D19aUNkPz5+aktQH5/f//4+LBKZKuRkpUtQjCUYG5gD2T38vLy/PwsDfL9/f3Dw8PT05M0b29vnKLhCKCBT4L4gvBLBIei4//4+Hh1dUVEQutUuLu7E83FxQUGnKLBWKfQaA3S+AREVxaEOD8/Pzk50XpzcyMDcH19zdZG3N3d3dzc3Nvb01aX5pQUpQGGQJxcQpfNysoKhUIdHR1o1tbWbInYAgxIPDMzMy8vLzc3FxqOdMoRqwJK8G8ALUYIhHMiSEhIwI6CyIb0qQzC4eGhsXCc1tZWnZIEKzdQJQSXgKxfX18RCM3Z5eWlcfVAxKOjo+Pj49PTU88lTOk2NjbMsePc3t6SAfcgFdszOyMuAdeBg0CQi2lhYUHOeOLDCisN8FzcPFZXV3t7ezHY3t5GQ+6it+2xMASsKhEEWKsmRLRBBUpPvpJ/TpFKFBwKYAiITmicsbYhdHfJAltqhUCVsCQhwslmeXmZxiBQT9c0Ar9E2O3v72sYSE0N1yQArkKy0kBMXLqlZqIZHR3t6empqqqSDcBdhXEJSJ/bUc3q6uq+vj629GB9fR1WsLW1NTs7u7S0RN2locMjIyOEm5ubQ7+4uJienk4/+vv77Y1hwhLBEKhwWHitdVFfX9/Y2Gg2HuLi4owUAysrK8yCG97rh0+ApP5Q2ZycHFlPTExUVFRIBvn5+WhKSkp2dnaMKhptbW2426GgQ/rwuAQCZ1hwFayLiork9hMFBQV1dXVmE0BLS4vqw3QFB8kn4IAxoGPkYpxi4FeDmpqas7Mz4pClAgqGwD48rjY2NmacYqC0tJQ1KSlJWyE5OZkpUKkBAxZVIntAoZh04+Q48fHxPNGBgYHExMT29naj9cBodnZ2mo3jlJWVMeW2OGQck4B1amqqoaGhqamJjx2lGxwcpL0mUgR8fJhsWqJtSkoKU2SbHHUDpkhPBujd8xuQG6PJRM/Pz09PT7O1NNnZ2Tw3fgZkXVhYKCUlUhBATP+hCVyKZGky17RV0g04laayslJ6hlVeFHB4eFhKaogGd0LxtmTgE+hbhKDnPjMzgw8E3qGL2tpaBWpubjYqj2BoaEj6rq4uNATRZ0ZwCbiL6gXEzINk5vCBQJ9rMD4+rkA8QNK036uDg4Py8vLu7m680KjIBNR3zBDoWQM1g98snyB+VSoRW8C/UwR81/SvhgNj9JOTkwwVERUdRBEI0BAdLRVERkhLS8vIyEDQlrsTPTU1lVFhKxARvZgUlFLbegCf4BvIsbi4mIg4E5EogIHhiKCMtU0WUFiVy06j5fAJIDdSBDQw+PegDfBRcbOPwH4F9LuFWIIQdQNKwWqzIE0aoFUaBsw+SQuFw0uNtC9A+F4i3QNrbg3IDn+SAsHh+wYiEpeyBEMLv/cAO6KzAijxxB+Y4wisBhssJUhjEbPJf4Nw+B+JXqLW3bw+wQAAAABJRU5ErkJggg==" />
|
|
<script type="text/javascript">
|
|
"use strict";
|
|
(function() {
|
|
var webSocketURI = "${client_websocket_uri}";
|
|
if(webSocketURI === ("$" + "{client_websocket_uri}")) {
|
|
alert("Don't open this file in your browser");
|
|
window.addEventListener("load", function() {
|
|
document.body.innerHTML = "<p style=\"text-align:center;\">cunt</p>";
|
|
});
|
|
return;
|
|
}
|
|
var eaglercraftXOpts = {eaglercraftXOpts};
|
|
var cspAttrSupport = false;
|
|
var checkSupport = function() {
|
|
if(eaglercraftXOpts.forceWebViewSupport) {
|
|
cspAttrSupport = true;
|
|
return true;
|
|
}else {
|
|
var tempIFrameElement = document.createElement("iframe");
|
|
cspAttrSupport = eaglercraftXOpts.enableWebViewCSP && (typeof tempIFrameElement.csp === "string");
|
|
return (typeof tempIFrameElement.allow === "string") && (typeof tempIFrameElement.sandbox === "object");
|
|
}
|
|
};
|
|
var supported = false;
|
|
try {
|
|
supported = checkSupport();
|
|
}catch(ex) {
|
|
supported = false;
|
|
}
|
|
console.log("CSP attribute support detected as " + cspAttrSupport);
|
|
if(!supported) {
|
|
console.error("Required IFrame safety features are not supported!");
|
|
window.addEventListener("load", function() {
|
|
document.getElementById("view_loading").style.display = "none";
|
|
document.getElementById("view_safety_error").style.display = "block";
|
|
});
|
|
return;
|
|
}
|
|
var websocketInstance = null;
|
|
var hasOpened = false;
|
|
var webviewOptions = null;
|
|
var webviewResetSerial = 0;
|
|
var hasErrored = false;
|
|
var hasRegisteredOnMsgHandler = false;
|
|
var currentMessageHandler = null;
|
|
var currentIFrame = null;
|
|
var currentMessageChannelName = null;
|
|
var elements = {};
|
|
var loadElements = function() {
|
|
var jsel = document.getElementsByClassName("__jsel");
|
|
for(var i = 0; i < jsel.length; ++i) {
|
|
var el = jsel[i];
|
|
if(el.id.length > 0) {
|
|
elements[el.id] = el;
|
|
}
|
|
}
|
|
};
|
|
function loadEagtekIcon() {
|
|
var faviconSrc = document.getElementById("vigg").href;
|
|
var imgElements = document.getElementsByClassName("eagtek_icon");
|
|
for(var i = 0; i < imgElements.length; ++i) {
|
|
imgElements[i].src = faviconSrc;
|
|
}
|
|
}
|
|
function setupElementListeners() {
|
|
elements.button_allow.addEventListener("click", function() {
|
|
if(websocketInstance !== null) {
|
|
if(elements.chkbox_remember.checked) {
|
|
websocketInstance.send(JSON.stringify({$:7,perm:"ALLOW"}));
|
|
}
|
|
beginShowingDirect();
|
|
}
|
|
});
|
|
elements.button_block.addEventListener("click", function() {
|
|
if(websocketInstance !== null) {
|
|
if(elements.chkbox_remember.checked) {
|
|
websocketInstance.send(JSON.stringify({$:7,perm:"BLOCK"}));
|
|
}
|
|
beginShowingContentBlocked();
|
|
}
|
|
});
|
|
elements.button_re_evaluate.addEventListener("click", function() {
|
|
if(websocketInstance !== null) {
|
|
websocketInstance.send(JSON.stringify({$:7,perm:"NOT_SET"}));
|
|
beginShowingEnableJavaScript();
|
|
}
|
|
});
|
|
}
|
|
window.specialHack = function() {
|
|
if(websocketInstance !== null) {
|
|
websocketInstance.send(JSON.stringify({$:7,perm:"NOT_SET"}));
|
|
}
|
|
};
|
|
var handleHandshake = function(pkt) {
|
|
webviewOptions = {};
|
|
webviewOptions.contentMode = pkt.contentMode || "BLOB_BASED";
|
|
webviewOptions.fallbackTitle = pkt.fallbackTitle || "Server Info";
|
|
document.title = webviewOptions.fallbackTitle + " - Eaglercraft Desktop Runtime";
|
|
webviewOptions.scriptEnabled = !!pkt.scriptEnabled;
|
|
webviewOptions.strictCSPEnable = !!pkt.strictCSPEnable || false;
|
|
webviewOptions.serverMessageAPIEnabled = !!pkt.serverMessageAPIEnabled;
|
|
webviewOptions.url = pkt.url;
|
|
webviewOptions.blob = pkt.blob;
|
|
webviewOptions.hasApprovedJS = pkt.hasApprovedJS || "NOT_SET";
|
|
if(webviewOptions.scriptEnabled) {
|
|
if(webviewOptions.hasApprovedJS === "NOT_SET") {
|
|
beginShowingEnableJavaScript();
|
|
}else if(webviewOptions.hasApprovedJS === "ALLOW") {
|
|
beginShowingDirect();
|
|
}else if(webviewOptions.hasApprovedJS === "BLOCK") {
|
|
beginShowingContentBlocked();
|
|
}else {
|
|
setErrored("Unknown JS permission state: " + webviewOptions.hasApprovedJS);
|
|
}
|
|
}else {
|
|
beginShowingDirect();
|
|
}
|
|
};
|
|
var handleServerError = function(pkt) {
|
|
console.error("Recieved error from server: " + pkt.msg);
|
|
setErrored(pkt.msg);
|
|
};
|
|
var handleServerWebViewStrMsg = function(pkt) {
|
|
var w;
|
|
if(currentMessageChannelName !== null && currentIFrame !== null && (w = currentIFrame.contentWindow) !== null) {
|
|
w.postMessage({ver:1,channel:currentMessageChannelName,type:"string",data:pkt.msg}, "*");
|
|
}else {
|
|
console.error("Server tried to send the WebView a message, but the message channel is not open!");
|
|
}
|
|
};
|
|
var handleServerWebViewBinMsg = function(arr) {
|
|
var w;
|
|
if(currentMessageChannelName !== null && currentIFrame !== null && (w = currentIFrame.contentWindow) !== null) {
|
|
w.postMessage({ver:1,channel:currentMessageChannelName,type:"binary",data:arr}, "*");
|
|
}else {
|
|
console.error("Server tried to send the WebView a message, but the message channel is not open!");
|
|
}
|
|
};
|
|
var hideAllViews = function() {
|
|
if(currentIFrame !== null) {
|
|
++webviewResetSerial;
|
|
if(currentIFrame.parentNode) currentIFrame.parentNode.removeChild(currentIFrame);
|
|
currentIFrame = null;
|
|
}
|
|
elements.view_loading.style.display = "none";
|
|
elements.view_iframe.style.display = "none";
|
|
elements.view_allow_javascript.style.display = "none";
|
|
elements.view_javascript_blocked.style.display = "none";
|
|
elements.view_safety_error.style.display = "none";
|
|
};
|
|
var setErrored = function(str) {
|
|
if(hasErrored) return;
|
|
hasErrored = true;
|
|
hideAllViews();
|
|
elements.loading_text.style.color = "#CC0000";
|
|
elements.loading_text.innerText = str;
|
|
elements.view_loading.style.display = "block";
|
|
if(websocketInstance !== null) {
|
|
websocketInstance.close();
|
|
websocketInstance = null;
|
|
}
|
|
};
|
|
var registerMessageHandler = function() {
|
|
if(!hasRegisteredOnMsgHandler) {
|
|
hasRegisteredOnMsgHandler = true;
|
|
window.addEventListener("message", function(evt) {
|
|
if(currentIFrame !== null && currentMessageHandler !== null && evt.source === currentIFrame.contentWindow) {
|
|
currentMessageHandler(evt);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
var beginShowingDirect = function() {
|
|
if(hasErrored) return;
|
|
hideAllViews();
|
|
if(!eaglercraftXOpts.forceWebViewSupport) {
|
|
try {
|
|
currentIFrame = document.createElement("iframe");
|
|
currentIFrame.allow = "";
|
|
if(currentIFrame.allow != "") throw "Failed to set allow to \"\"";
|
|
currentIFrame.referrerPolicy = "strict-origin";
|
|
var requiredSandboxTokens = [ "allow-downloads" ];
|
|
if(webviewOptions.scriptEnabled) {
|
|
requiredSandboxTokens.push("allow-scripts");
|
|
requiredSandboxTokens.push("allow-pointer-lock");
|
|
}
|
|
currentIFrame.sandbox = requiredSandboxTokens.join(" ");
|
|
for(var i = 0; i < requiredSandboxTokens.length; ++i) {
|
|
if(!currentIFrame.sandbox.contains(requiredSandboxTokens[i])) {
|
|
throw ("Failed to set sandbox attribute: " + requiredSandboxTokens[i]);
|
|
}
|
|
}
|
|
var sbox = currentIFrame.sandbox;
|
|
for(var i = 0; i < sbox.length; ++i) {
|
|
if(!requiredSandboxTokens.includes(sbox.item(i))) {
|
|
throw ("Unknown sandbox attribute detected: " + sbox.item(i));
|
|
}
|
|
}
|
|
}catch(ex) {
|
|
if(typeof ex === "string") {
|
|
console.error("Caught safety error: " + ex);
|
|
beginShowingSafetyError();
|
|
}else {webviewOptions
|
|
console.error("Fatal error while creating iframe!");
|
|
console.error(ex);
|
|
setErrored("Fatal error while creating iframe!");
|
|
}
|
|
return;
|
|
}
|
|
}else {
|
|
currentIFrame = document.createElement("iframe");
|
|
try {
|
|
currentIFrame.allow = "";
|
|
}catch(ex) {
|
|
}
|
|
try {
|
|
currentIFrame.referrerPolicy = "strict-origin";
|
|
}catch(ex) {
|
|
}
|
|
try {
|
|
var sandboxTokens = [ "allow-downloads", "allow-same-origin" ];
|
|
if(webviewOptions.scriptEnabled) {
|
|
sandboxTokens.push("allow-scripts");
|
|
sandboxTokens.push("allow-pointer-lock");
|
|
}
|
|
currentIFrame.sandbox = sandboxTokens.join(" ");
|
|
}catch(ex) {
|
|
}
|
|
}
|
|
currentIFrame.credentialless = true;
|
|
currentIFrame.loading = "lazy";
|
|
var cspWarn = false;
|
|
if(webviewOptions.contentMode === "BLOB_BASED") {
|
|
if(cspAttrSupport && eaglercraftXOpts.enableWebViewCSP) {
|
|
if(typeof currentIFrame.csp === "string") {
|
|
var csp = "default-src 'none';";
|
|
var protos = (webviewOptions.strictCSPEnable ? "" : " http: https:");
|
|
if(webviewOptions.scriptEnabled) {
|
|
csp += (" script-src 'unsafe-eval' 'unsafe-inline' data: blob:" + protos + ";");
|
|
csp += (" style-src 'unsafe-eval' 'unsafe-inline' data: blob:" + protos + ";");
|
|
csp += (" img-src data: blob:" + protos + ";");
|
|
csp += (" font-src data: blob:" + protos + ";");
|
|
csp += (" child-src data: blob:" + protos + ";");
|
|
csp += (" frame-src data: blob:;");
|
|
csp += (" media-src data: mediastream: blob:" + protos + ";");
|
|
csp += (" connect-src data: blob:" + protos + ";");
|
|
csp += (" worker-src data: blob:" + protos + ";");
|
|
}else {
|
|
csp += (" style-src data: 'unsafe-inline'" + protos + ";");
|
|
csp += (" img-src data:" + protos + ";");
|
|
csp += (" font-src data:" + protos + ";");
|
|
csp += (" media-src data:" + protos + ";");
|
|
}
|
|
currentIFrame.csp = csp;
|
|
}else {
|
|
console.error("This browser does not support CSP attribute on iframes! (try Chrome)");
|
|
cspWarn = true;
|
|
}
|
|
}else {
|
|
cspWarn = true;
|
|
}
|
|
if(cspWarn && webviewOptions.strictCSPEnable) {
|
|
console.error("Strict CSP was requested for this webview, but that feature is not available!");
|
|
}
|
|
}else {
|
|
cspWarn = true;
|
|
}
|
|
currentIFrame.style.border = "none";
|
|
currentIFrame.style.backgroundColor = "white";
|
|
currentIFrame.style.width = "100%";
|
|
currentIFrame.style.height = "100%";
|
|
elements.view_iframe.appendChild(currentIFrame);
|
|
elements.view_iframe.style.display = "block";
|
|
if(webviewOptions.contentMode === "BLOB_BASED") {
|
|
currentIFrame.srcdoc = webviewOptions.blob;
|
|
}else {
|
|
currentIFrame.src = webviewOptions.url;
|
|
}
|
|
currentIFrame.focus();
|
|
if(webviewOptions.scriptEnabled && webviewOptions.serverMessageAPIEnabled) {
|
|
var resetSer = webviewResetSerial;
|
|
var curIFrame = currentIFrame;
|
|
registerMessageHandler();
|
|
currentMessageHandler = function(evt) {
|
|
if(resetSer === webviewResetSerial && curIFrame === currentIFrame) {
|
|
handleMessageRawFromFrame(evt.data);
|
|
}
|
|
};
|
|
}
|
|
};
|
|
var handleMessageRawFromFrame = function(obj) {
|
|
if(hasErrored) return;
|
|
if((typeof obj === "object") && (obj.ver === 1) && ((typeof obj.channel === "string") && obj.channel.length > 0)) {
|
|
if(typeof obj.open === "boolean") {
|
|
sendMessageEnToServer(obj.open, obj.channel);
|
|
return;
|
|
}else if(typeof obj.data === "string") {
|
|
sendMessageToServerStr(obj.channel, obj.data);
|
|
return;
|
|
}else if(obj.data instanceof ArrayBuffer) {
|
|
sendMessageToServerBin(obj.channel, obj.data);
|
|
return;
|
|
}
|
|
}
|
|
console.error("WebView sent an invalid message!");
|
|
};
|
|
var sendMessageEnToServer = function(messageChannelOpen, channelName) {
|
|
if(channelName.length > 255) {
|
|
console.error("WebView tried to " + (messageChannelOpen ? "open" : "close") + " a channel, but channel name is too long, max is 255 characters!");
|
|
return;
|
|
}
|
|
if(messageChannelOpen && currentMessageChannelName !== null) {
|
|
console.error("WebView tried to open channel, but a channel is already open!");
|
|
sendMessageEnToServer(false, currentMessageChannelName);
|
|
}
|
|
if(!messageChannelOpen && currentMessageChannelName !== null && currentMessageChannelName === channelName) {
|
|
console.error("WebView tried to close the wrong channel!");
|
|
}
|
|
if(!messageChannelOpen && currentMessageChannelName === null) {
|
|
console.error("WebView tried to close channel, but the channel is not open!");
|
|
return;
|
|
}
|
|
if(websocketInstance !== null) {
|
|
if(messageChannelOpen) {
|
|
websocketInstance.send(JSON.stringify({$:3,channel:channelName}));
|
|
console.log("WebView opened message channel to server: \"" + channelName + "\"");
|
|
currentMessageChannelName = channelName;
|
|
}else {
|
|
websocketInstance.send(JSON.stringify({$:4}));
|
|
console.log("WebView closed message channel to server: \"" + currentMessageChannelName + "\"");
|
|
currentMessageChannelName = null;
|
|
}
|
|
}else {
|
|
console.error("WebView tried to send a message, but no websocket is open!");
|
|
}
|
|
};
|
|
var sendMessageToServerStr = function(channelName, msg) {
|
|
if(channelName.length > 255) {
|
|
console.error("WebView tried to send a message packet, but channel name is too long, max is 255 characters!");
|
|
return;
|
|
}
|
|
if(channelName !== currentMessageChannelName) {
|
|
console.error("WebView tried to send a message packet, but the channel is not open!");
|
|
return;
|
|
}
|
|
if(websocketInstance !== null) {
|
|
websocketInstance.send(JSON.stringify({$:5,msg:msg}));
|
|
}else {
|
|
console.error("WebView tried to send a message, but no callback for sending packets is set!");
|
|
}
|
|
};
|
|
var sendMessageToServerBin = function(channelName, msg) {
|
|
if(channelName.length > 255) {
|
|
console.error("WebView tried to send a message packet, but channel name is too long, max is 255 characters!");
|
|
return;
|
|
}
|
|
if(channelName !== currentMessageChannelName) {
|
|
console.error("WebView tried to send a message packet, but the channel is not open!");
|
|
return;
|
|
}
|
|
if(websocketInstance !== null) {
|
|
websocketInstance.send(msg);
|
|
}else {
|
|
console.error("WebView tried to send a message, but no callback for sending packets is set!");
|
|
}
|
|
};
|
|
var beginShowingEnableJavaScript = function() {
|
|
if(hasErrored) return;
|
|
hideAllViews();
|
|
if(webviewOptions.contentMode !== "BLOB_BASED") {
|
|
elements.strict_csp_value.innerText = "Impossible";
|
|
elements.strict_csp_value.style.color = "red";
|
|
}else if(!cspAttrSupport || !eaglercraftXOpts.enableWebViewCSP) {
|
|
elements.strict_csp_value.innerText = "Unsupported";
|
|
elements.strict_csp_value.style.color = "red";
|
|
}else if(webviewOptions.strictCSPEnable) {
|
|
elements.strict_csp_value.innerText = "Enabled";
|
|
elements.strict_csp_value.style.color = "green";
|
|
}else {
|
|
elements.strict_csp_value.innerText = "Disabled";
|
|
elements.strict_csp_value.style.color = "red";
|
|
}
|
|
if(webviewOptions.serverMessageAPIEnabled) {
|
|
elements.message_api_value.innerText = "Enabled";
|
|
elements.message_api_value.style.color = "red";
|
|
}else {
|
|
elements.message_api_value.innerText = "Disabled";
|
|
elements.message_api_value.style.color = "green";
|
|
}
|
|
elements.view_allow_javascript.style.display = "block";
|
|
};
|
|
var beginShowingContentBlocked = function() {
|
|
if(hasErrored) return;
|
|
hideAllViews();
|
|
elements.view_javascript_blocked.style.display = "block";
|
|
};
|
|
var beginShowingSafetyError = function() {
|
|
if(hasErrored) return;
|
|
hasErrored = true;
|
|
hideAllViews();
|
|
elements.view_safety_error.style.display = "block";
|
|
};
|
|
window.addEventListener("load", function() {
|
|
loadElements();
|
|
loadEagtekIcon();
|
|
setupElementListeners();
|
|
websocketInstance = new WebSocket(webSocketURI);
|
|
websocketInstance.binaryType = "arraybuffer";
|
|
websocketInstance.addEventListener("open", function(evt) {
|
|
console.log("Connection to server opened");
|
|
hasOpened = true;
|
|
websocketInstance.send(JSON.stringify({$:0,cspSupport:cspAttrSupport}));
|
|
});
|
|
websocketInstance.addEventListener("message", function(evt) {
|
|
try {
|
|
if(typeof evt.data === "string") {
|
|
var pkt = JSON.parse(evt.data);
|
|
if(typeof pkt.$ !== "number") {
|
|
throw "Packet type is invalid";
|
|
}
|
|
if(webviewOptions === null) {
|
|
if(pkt.$ === 1) {
|
|
handleHandshake(pkt);
|
|
}else if(pkt.$ === 2) {
|
|
handleServerError(pkt);
|
|
}else {
|
|
throw "Unknown packet type " + pkt.$ + " for state handshake!"
|
|
}
|
|
}else {
|
|
if(pkt.$ === 2) {
|
|
handleServerError(pkt);
|
|
}else if(pkt.$ === 6) {
|
|
handleServerWebViewStrMsg(pkt);
|
|
}else {
|
|
throw "Unknown packet type " + pkt.$ + " for state open!"
|
|
}
|
|
}
|
|
}else {
|
|
handleServerWebViewBinMsg(evt.data);
|
|
}
|
|
}catch(ex) {
|
|
console.error("Caught exception processing message from server!");
|
|
console.error(ex);
|
|
}
|
|
});
|
|
websocketInstance.addEventListener("close", function(evt) {
|
|
websocketInstance = null;
|
|
setErrored("Connection to EaglercraftX client lost!");
|
|
});
|
|
websocketInstance.addEventListener("error", function(evt) {
|
|
console.error("WebSocket error: " + evt);
|
|
});
|
|
});
|
|
})();
|
|
</script>
|
|
</head>
|
|
<body style="margin:0px;width:100%;height:100%;overflow:hidden;font-family:sans-serif;user-select:none;">
|
|
<div id="view_loading" style="width:100%;height:100%;display:block;" class="__jsel">
|
|
<div style="padding-top:13vh;">
|
|
<h2 style="text-align:center;" id="loading_text" class="__jsel">Please Wait...</h2>
|
|
</div>
|
|
</div>
|
|
<div id="view_iframe" style="width:100%;height:100%;display:none;" class="__jsel">
|
|
</div>
|
|
<div id="view_allow_javascript" style="width:100%;height:100%;display:none;" class="__jsel">
|
|
<div style="padding-top:13vh;">
|
|
<div style="margin:auto;max-width:450px;border:6px double black;text-align:center;padding:20px;">
|
|
<h2><img width="32" height="32" style="vertical-align:middle;" class="eagtek_icon"> Allow JavaScript</h2>
|
|
<p style="font-family:monospace;text-decoration:underline;word-wrap:break-word;" id="target_url"></p>
|
|
<h4 style="line-height:1.4em;">Strict CSP: <span id="strict_csp_value" class="__jsel"></span> | Message API: <span id="message_api_value" class="__jsel"></span></h4>
|
|
<p><input id="chkbox_remember" type="checkbox" class="__jsel" checked> Remember my choice</p>
|
|
<p><button style="font-size:1.5em;" id="button_allow" class="__jsel">Allow</button> <button style="font-size:1.5em;" id="button_block" class="__jsel">Block</button></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="view_javascript_blocked" style="width:100%;height:100%;display:none;" class="__jsel">
|
|
<div style="padding-top:13vh;">
|
|
<h1 style="text-align:center;"><img width="48" height="48" style="vertical-align:middle;" class="eagtek_icon"> Content Blocked</h1>
|
|
<h4 style="text-align:center;">You chose to block JavaScript execution for this embed</h4>
|
|
<p style="text-align:center;"><button style="font-size:1.0em;" id="button_re_evaluate" class="__jsel">Re-evaluate</button></p>
|
|
</div>
|
|
</div>
|
|
<div id="view_safety_error" style="width:100%;height:100%;display:none;" class="__jsel">
|
|
<div style="padding-top:13vh;">
|
|
<h1 style="text-align:center;"><img width="48" height="48" style="vertical-align:middle;" class="eagtek_icon"> IFrame Safety Error</h1>
|
|
<h4 style="text-align:center;">The content cannot be displayed safely!</h4>
|
|
<h4 style="text-align:center;">Check console for more details</h4>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html> |