|
// ==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; |
|
}, |
|
}); |
|
} |
|
} |