Firefox不尊重Greasemonkey脚本中的Object.defineProperty()吗? [英] Firefox doesn't respect Object.defineProperty() from a Greasemonkey script?

查看:99
本文介绍了Firefox不尊重Greasemonkey脚本中的Object.defineProperty()吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个用户脚本来阻止网站设置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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆