Skip to content

Instantly share code, notes, and snippets.

@e9x
Created July 30, 2024 17:03
Show Gist options
  • Select an option

  • Save e9x/0a63735055180b45dabcea97d186d230 to your computer and use it in GitHub Desktop.

Select an option

Save e9x/0a63735055180b45dabcea97d186d230 to your computer and use it in GitHub Desktop.
who cares about blur

Who cares about blur?

Problem: Learning management systems are picky about what tabs you have open, and if you're switching between tabs during an exam.

Solution: This script completly disables any detection of the window being blurred and suppresses any events.

This script can be installed via Tampermonkey and is tested to work on Firefox and Chrome.

// ==UserScript==
// @name who cares about blur
// @namespace https://github.com/e9x
// @version 1.0.0
// @description Prevent pages from detecting when they lose focus
// @author e9x
// @homepageURL https://github.com/e9x
// @match *://*/*
// @grant none
// @run-at document-start
// ==/UserScript==
// IMPORTANT STEPS FOR TAMPERMONKEY
// 1. Go to Tampermonkey Dashboard.
// 2. Click on settings.
// 3. Change Config mode to Advanced.
// 4. Scroll to the bottom of the dashboard and find "Experimental". Change Inject Mode to Instant.
// PROTECTION #1: INVOKE ORIGINAL HANDLERS WITH `this` TO THROW ORIGINAL ERRORS
// TODO: PROTECT FUNCTION SOURCE WITH HELPERS
// PROPERTIES
const STATE_VISIBLE = "visible";
const visibilityState = Object.getOwnPropertyDescriptor(Document.prototype, "visibilityState");
Object.defineProperty(Document.prototype, "visibilityState", {
configurable: true,
enumerable: true,
get() {
// PROTECTION #1
Reflect.apply(visibilityState.get, this, []);
return STATE_VISIBLE;
},
});
const webkitVisibilityState = Object.getOwnPropertyDescriptor(Document.prototype, "webkitVisibilityState");
Object.defineProperty(Document.prototype, "webkitVisibilityState", {
configurable: true,
enumerable: true,
get() {
// PROTECTION #1
Reflect.apply(webkitVisibilityState.get, this, []);
return STATE_VISIBLE;
},
});
const hidden = Object.getOwnPropertyDescriptor(Document.prototype, "hidden");
Object.defineProperty(Document.prototype, "hidden", {
configurable: true,
enumerable: true,
get() {
// PROTECTION #1
Reflect.apply(hidden.get, this, []);
// always never hidden
return false;
},
});
// FUNCTIONS
const { hasFocus } = Document.prototype;
Document.prototype.hasFocus = function () {
// PROTECTION #1
Reflect.apply(hasFocus, this, []);
// ermm we're always focused
return true;
}
// WINDOW EVENTS
window.addEventListener("blur", (e) => {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
});
window.addEventListener("focus", (e) => {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
});
// DOM EVENTS
document.addEventListener("visibilitychange", (e) => {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
});
// MOUSE EVENTS
const { addEventListener } = EventTarget.prototype;
const mouseEvents = ["mousemove", "mouseenter", "mouseleave", "mouseover", "mouseout"];
EventTarget.prototype.addEventListener = function(type, callback, options) {
if (mouseEvents.includes(type)) {
console.log("ermmm no mouse event!");
return;
}
return Reflect.apply(addEventListener, this, [type, callback, options]);
}
for (const event of mouseEvents) {
const prop = "on" + event;
// define the handler on window & element protos
for (const proto of [HTMLElement.prototype, window]) {
const { get, set } = Object.getOwnPropertyDescriptor(proto, prop);
let v = null;
Object.defineProperty(proto, prop, {
configurable: true,
enumerable: true,
get() {
// PROTECTION #1
Reflect.apply(get, this, []);
return v;
},
set(value) {
// PROTECTION #1
Reflect.apply(get, this, []);
if (typeof value === "function") v = value;
else v = null;
},
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment