Added the stealthy overlay, no version number change yet

This commit is contained in:
An0 2020-09-04 17:14:16 +00:00
parent cbaaa7a376
commit d21b981514

View file

@ -38,6 +38,7 @@
// @grant GM_deleteValue // @grant GM_deleteValue
// @grant GM_xmlhttpRequest // @grant GM_xmlhttpRequest
// @grant GM_openInTab // @grant GM_openInTab
// @grant unsafeWindow
// @license GNU General Public License v3.0 or later // @license GNU General Public License v3.0 or later
// @supportURL qmining.frylabs.net // @supportURL qmining.frylabs.net
// @contributionURL qmining.frylabs.net // @contributionURL qmining.frylabs.net
@ -208,6 +209,86 @@
// all dom getting stuff are in this sections, so on // all dom getting stuff are in this sections, so on
// moodle dom change, stuff breaks here // moodle dom change, stuff breaks here
//Stealth by An0 with love
function StealthOverlay() { //call this before the document scripts
const document = window.document;
const neverEqualPlaceholder = Symbol(`never equal`); //block probing for undefined values in the hooks
let shadowRootHost = neverEqualPlaceholder;
let shadowRootNewHost = neverEqualPlaceholder;
const apply = Reflect.apply; //save some things in case they get hooked (only for unsafe contexts)
if(unsafeWindow.Error.hasOwnProperty('stackTraceLimit')) {
Reflect.defineProperty(unsafeWindow.Error, 'stackTraceLimit', { value: undefined, writable: false, enumerable: false, configurable: false });
}
const shadowGetHandler = { apply: (target, thisArg, argumentsList) => apply(target, (thisArg === shadowRootHost) ? shadowRootNewHost : thisArg, argumentsList) };
const original_attachShadow = unsafeWindow.Element.prototype.attachShadow;
const attachShadowProxy = new Proxy(original_attachShadow, shadowGetHandler);
unsafeWindow.Element.prototype.attachShadow = attachShadowProxy;
const getShadowRootProxy = new Proxy(Object.getOwnPropertyDescriptor(unsafeWindow.Element.prototype, 'shadowRoot').get, shadowGetHandler);
Object.defineProperty(unsafeWindow.Element.prototype, 'shadowRoot', { get: getShadowRootProxy });
const getHostHandler = { apply: function() { let result = apply(...arguments); return (result === shadowRootNewHost) ? shadowRootHost : result; } };
const getHostProxy = new Proxy(Object.getOwnPropertyDescriptor(unsafeWindow.ShadowRoot.prototype, 'host').get, getHostHandler);
Object.defineProperty(unsafeWindow.ShadowRoot.prototype, 'host', { get: getHostProxy });
const shadowRootSetInnerHtml = Object.getOwnPropertyDescriptor(ShadowRoot.prototype, 'innerHTML').set;
const documentFragmentGetChildren = Object.getOwnPropertyDescriptor(DocumentFragment.prototype, 'children').get;
const documentGetBody = Object.getOwnPropertyDescriptor(Document.prototype, 'body').get;
const nodeAppendChild = Node.prototype.appendChild;
const overlay = document.createElement('div');
overlay.style.cssText = "position:absolute;left:0;top:0";
const addOverlay = () => {
shadowRootHost = apply(documentGetBody, document, []);
const shadowRoot = apply(original_attachShadow, shadowRootHost, [{mode:'closed'}]);
apply(shadowRootSetInnerHtml, shadowRoot, [`<div><slot></slot></div>`]);
shadowRootNewHost = apply(documentFragmentGetChildren, shadowRoot, [])[0];
apply(nodeAppendChild, shadowRoot, [overlay]);
};
if (!document.body) {
document.addEventListener('DOMContentLoaded', addOverlay);
}
else {
addOverlay();
}
return overlay;
}
const overlay = StealthOverlay();
function createHoverOver(target) {
const overlayElement = document.createElement('div');
overlayElement.style.cssText = "position:fixed; pointer-events: none; user-select: none; z-index:10000";
overlay.append(overlayElement);
let currX, currY, currWidth, currHeight;
const copyBoundingRect = () => {
let { x, y, width, height } = target.getBoundingClientRect();
if(x !== currX) { overlayElement.style.left = x + 'px'; currX = x; }
if(y !== currY) { overlayElement.style.top = y + 'px'; currY = y; }
if(width !== currWidth) { overlayElement.style.width = width + 'px'; currWidth = width; }
if(height !== currHeight) { overlayElement.style.height = height + 'px'; currHeight = height; }
};
copyBoundingRect();
const interval = setInterval(copyBoundingRect, 30);
overlayElement.destroy = () => {
clearInterval(interval);
overlayElement.remove();
};
return overlayElement;
}
class QuestionsPageModell { class QuestionsPageModell {
GetAllQuestionsDropdown () { GetAllQuestionsDropdown () {
if (logElementGetting) { Log('getting dropdown question') } if (logElementGetting) { Log('getting dropdown question') }
@ -716,8 +797,8 @@
} }
if (forceTestPage || forceResultPage || forceDefaultPage) { if (forceTestPage || forceResultPage || forceDefaultPage) {
if (document.getElementById('scriptMessage')) { if (overlay.querySelector('#scriptMessage')) {
document.getElementById('scriptMessage').style.background = 'green' overlay.querySelector('#scriptMessage').style.background = 'green'
} }
} }
} }
@ -852,7 +933,7 @@
lastestVersion = inf.version lastestVersion = inf.version
motd = inf.motd motd = inf.motd
subjInfo = inf.subjinfo subjInfo = inf.subjinfo
document.getElementById('infoMainDiv').innerText = `${subjInfo.subjects} tárgy, ${subjInfo.questions} kérdés. Felh #${inf.uid}` overlay.querySelector('#infoMainDiv').innerText = `${subjInfo.subjects} tárgy, ${subjInfo.questions} kérdés. Felh #${inf.uid}`
// FIXME: if cwith() throws an unhandled error it sais server is not avaible // FIXME: if cwith() throws an unhandled error it sais server is not avaible
cwith() cwith()
}).catch(() => { }).catch(() => {
@ -1299,7 +1380,12 @@
if (results[0].match === 100) { // if the result is 100% correct if (results[0].match === 100) { // if the result is 100% correct
if (type !== 'radio' || toColor.length === 1) { // FIXME why not radio if (type !== 'radio' || toColor.length === 1) { // FIXME why not radio
for (let i = 0; i < toColor.length; i++) { // going through "toColor" for (let i = 0; i < toColor.length; i++) { // going through "toColor"
answers[toColor[i]].style.backgroundColor = '#8cff66' let highlight = createHoverOver(answers[toColor[i]]);
Object.assign(highlight.style, {
border: "7px solid rgba(100, 240, 100, 0.8)",
borderRadius: "10px",
margin: "-13px 0 0 -8px"
});
} }
} }
} // and coloring the correct index } // and coloring the correct index
@ -1328,11 +1414,7 @@
// : Minor UI stuff {{{ // : Minor UI stuff {{{
function ClearAllMessages () { function ClearAllMessages () {
let elem = document.getElementById('scriptMessage') overlay.querySelectorAll('#scriptMessage').forEach(x => x.remove())
while (elem) {
elem.parentNode.removeChild(elem)
elem = document.getElementById('scriptMessage')
}
} }
// shows a message with "msg" text, "matchPercent" tip and transp, and "timeout" time // shows a message with "msg" text, "matchPercent" tip and transp, and "timeout" time
@ -1360,7 +1442,7 @@
isSimpleMessage = true isSimpleMessage = true
} }
var appedtTo = document.body // will be appended here var appedtTo = overlay // will be appended here
var width = window.innerWidth - window.innerWidth / 6 // with of the box var width = window.innerWidth - window.innerWidth / 6 // with of the box
var startFromTop = 25 // top distance var startFromTop = 25 // top distance
@ -1551,7 +1633,7 @@
// shows a fancy menu // shows a fancy menu
function ShowMenu () { function ShowMenu () {
try { try {
var appedtTo = document.body // will be appended here var appedtTo = overlay // will be appended here
// mainDiv.style.left = (window.innerWidth - width) / 2 + 'px'; // mainDiv.style.left = (window.innerWidth - width) / 2 + 'px';
@ -1763,7 +1845,7 @@
} }
function SafeGetElementById (id, next) { function SafeGetElementById (id, next) {
let element = document.getElementById(id) let element = overlay.querySelector('#' + id)
if (element) { if (element) {
next(element) next(element)
} else { } else {