Firefox不尊重Greasemonkey脚本中的Object.defineProperty()吗? [英] Firefox doesn't respect Object.defineProperty() from a Greasemonkey script?
问题描述
我正在写一个用户脚本来阻止网站设置document.body.innerHTML
,这是网站检测到adblock的典型标志:
I'm writing a userscript to prevent a website to set document.body.innerHTML
, this is a typical sign of a website detecting adblock:
(function() {
'use strict';
console.log("Loading ...");
Object.defineProperty(document.body, "innerHTML", {
set: function() {
console.log("malicious activity detected");
throw "Don't try to fool my adblock!";
}
});
console.log("Test setting document.body ...");
try {
document.body.innerHTML = "";
} catch (e) {
console.log(e);
}
}) ();
以上用户脚本适用于Chrome + Tampermonkey.但是它在Firefox + Greasemonkey-4上的行为很奇怪.
The above userscript works fine for Chrome+Tampermonkey. But its behavior on Firefox+Greasemonkey-4 is weird.
控制台中的输出为:
正在加载...
测试设置document.body ...
检测到恶意活动
不要试图欺骗我的adblock!
Loading ...
Test setting document.body ...
malicious activity detected
Don't try to fool my adblock!
因此,用户脚本加载成功,设置器也成功挂接.但是当加载后,我在控制台中尝试:
So the userscript loads successfully, and the setter is successfully hooked as well. But when after loading and I try in the console:
document.body.innerHTML = ""
它只是设置innerHTML
而不会引发错误,就像尚未安装挂钩一样.我已经尝试了所有@run-at
选项,但是它们都不起作用.
it just sets the innerHTML
without throwing error, as if the hook has not been installed. I've tried all @run-at
options, but none of them works.
OTAH,如果我在控制台中使用Object.defineProperty()
,则它将按预期工作.因此,我得出结论,Firefox不尊重用户脚本中的Object.defineProperty()
.
OTAH, if I use Object.defineProperty()
in console, then it works as expected. Therefore I conclude that Firefox doesn't respect Object.defineProperty()
from userscript.
您也可以尝试访问以下网站: https://connectwww.com .通过在Chrome的Tampermonkey中安装上述用户脚本,可以成功拦截网站上的adblock检测.但是该用户脚本不适用于Firefox + Greasemonkey.
You can also try visiting this website: https://connectwww.com. With the above userscript installed in Tampermonkey in Chrome, the adblock-detection on the website is successfully intercepted. But the userscript doesn't work on Firefox+Greasemonkey.
为什么Firefox 不不尊重用户脚本中的Object.defineProperty()
?有什么解决方法吗?
Why does Firefox not respect Object.defineProperty()
from a userscript? Is there any workaround?
上述测试网站的某些知名用户脚本(例如anti-adblock-killer)也可以在Chrome上运行,但不能在Firefox上运行,我想这是出于相同的原因.
Some well-known userscript like anti-adblock-killer also works on Chrome but not Firefox for the above testing website, I guess it's due to the same reason.
推荐答案
Greasemonkey 4 甚至在@grant none
模式下也可以将脚本沙箱化. (这是 Greasemonkey 4 优于Tampermonkey或Violentmonkey的唯一事情.)
Greasemonkey 4 sandboxes your script even in @grant none
mode. (That is about the only thing that Greasemonkey 4 does better than Tampermonkey or Violentmonkey.)
因此,您的脚本正在设置脚本的范围/innerHTML
的副本.
在与目标页面范围共享的Tampermonkey中,但在Greasemonkey中,两个范围的分隔更恰当.因此页面范围(和默认控制台)看不到更改.
So your script is setting the script's scope/copy of innerHTML
.
In Tampermonkey that is shared with the target page scope but, in Greasemonkey, the 2 scopes are more properly separated. So the page scope (and the default console) do not see the change.
In this case, I don't think the unsafeWindow
methods can be made to work; you must inject the override code.
这是一个可以同时用于Greasemonkey 4+和Tampermonkey的脚本(也应该在Violentmonkey上使用,但我没有对此进行测试).它可以在Chrome和Firefox上运行:
Here is a script that works with both Greasemonkey 4+ and Tampermonkey (and should on Violentmonkey too, but I didn't test that). It works on both Chrome and Firefox:
// ==UserScript==
// @name _Overriding Target page functions can be tricky with GM 4
// @match *://YOUR_SERVER.COM/YOUR_PATH/*
// @grant none
// @run-at document-start
// ==/UserScript==
/* eslint-disable no-multi-spaces */
console.log("Loading ...");
function overrideIt () {
//-- Necessary check because of scope madness in TM, VM, etc.
if (document.body.innerHTML) {
Object.defineProperty (document.body, "innerHTML", {
set: function () {
var scopeStr = (typeof GM === "object" && GM.info) ? "script" : "page";
console.log (`Malicious activity detected - ${scopeStr} scope`);
throw "Don't try to fool my adblock!";
}
} );
}
}
overrideIt ();
if (typeof unsafeWindow === "object") {
console.log ("unsafeWindow detected.");
addJS_Node (null, null, overrideIt);
}
console.log ("Test setting document.body ...");
try {
document.body.innerHTML = "";
} catch (e) {
console.log ("Caught: ", e);
}
//-- addJS_Node is a standard(ish) function
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
var D = document;
var scriptNode = D.createElement ('script');
if (runOnLoad) {
scriptNode.addEventListener ("load", runOnLoad, false);
}
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}
这篇关于Firefox不尊重Greasemonkey脚本中的Object.defineProperty()吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!