Firefox не уважает Object.defineProperty () из скрипта Greasemonkey? - PullRequest
0 голосов
/ 02 февраля 2019

Я пишу пользовательский сценарий, чтобы веб-сайт не устанавливал document.body.innerHTML, это типичный признак обнаружения веб-сайта рекламного блока:

(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 странное.

Вывод в консоли:

Загрузка ...
Проверка настроек document.body ...
обнаружена вредоносная активность
Не пытайтесь обмануть мой рекламный блок!

Итак, пользовательский скрипт успешно загружается, и сеттер также успешно подключается.Но когда после загрузки я пытаюсь в консоли:

document.body.innerHTML = ""

, он просто устанавливает innerHTML без ошибок, как если бы ловушка не была установлена.Я перепробовал все @run-at опции, но ни один из них не работает.


OTAH, если я использую Object.defineProperty() в консоли, то он работает как положено.Поэтому я прихожу к выводу, что Firefox не учитывает Object.defineProperty() из пользовательского сценария.

Вы также можете попробовать посетить этот веб-сайт: https://connectwww.com. Если указанный выше пользовательский сценарий установлен в Tampermonkey в Chrome, обнаружение adblock насайт успешно перехвачен.Но пользовательский скрипт не работает в Firefox + Greasemonkey.

Почему Firefox не уважает Object.defineProperty() из пользовательского скрипта?Есть ли обходной путь?

Примечание:

Некоторые известные пользовательские скрипты, такие как anti-adblock-killer, также работают на Chrome, но не Firefox для вышеуказанного сайта тестирования, я полагаюэто по той же причине.

1 Ответ

0 голосов
/ 02 февраля 2019

Greasemonkey 4 помещает ваш сценарий в песочницу даже в режиме @grant none. (Это единственное, что Greasemonkey 4 делает лучше, чем Tampermonkey или Violentmonkey.)

Таким образом, ваш сценарий устанавливает область действия сценария/ копия innerHTML.
В Tampermonkey, которая используется совместно с целевой областью страницы, но в Greasemonkey, две области более правильно разделены.Поэтому область страницы (и консоль по умолчанию) не видят изменений.

В этом случае я не думаю, что методы unsafeWindow можно заставить работать; Вы должны ввести код переопределения .

Вот скрипт, который работает как с Greasemonkey 4+, так и с Tampermonkey (и должен также работать с Violentmonkey, но я этого не проверял).Работает как на Chrome, так и на 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);
}
...