将@grant添加到GM脚本中可以打破XMLHttpRequest.prototype.open的过载

Adding @grant to a GM script breaks the overload of XMLHttpRequest.prototype.open?

本文关键字:prototype XMLHttpRequest open 添加 @grant GM 脚本      更新时间:2023-09-26

我正在编写一个Greasemonkey脚本,我想重载XMLHttpRequest.prototype.open函数来劫持页面上的Ajax调用。

我使用下面的代码:

// ==UserScript==
// @name        name
// @namespace   namespace
// @description desc
// @include     https://url*
// @version     1.0
// ==/UserScript==
if (XMLHttpRequest.prototype) {
    //New Firefox Versions
    XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open;
    var myOpen = function(method, url, async, user, password) {
        //call original
        this.realOpen (method, url, async, user, password);
        myCode();
    }  
    //ensure all XMLHttpRequests use our custom open method
    XMLHttpRequest.prototype.open = myOpen ;
}


在我开始使用GM api之前,这种方法运行良好。当我将以下行添加到元部分时,我的代码中断了,并且myOpen不再被称为:

// @grant       GM_getValue

这可能是任何GM API真的,我的代码中断。我的脚本中的其他所有内容都可以正常工作,即使使用GM api,它只是XMLHttpRequest.prototype.open函数的过载。

我可以通过使用waitForKeyElements来解决它,但是,我不喜欢它,因为它使用的间隔使浏览器变慢。

你知道为什么GM api打破了XMLHttpRequest.prototype.open调用的过载吗?

许多谢谢,

彼得

@grant指令打开Greasemonkey的沙盒——它必须使用任何GM_函数。

那个prototype覆盖将只影响脚本作用域,而您希望它影响页面作用域。要解决这个问题,您需要注入重写。像这样:

function overrideXhrFunctions () {
    if (XMLHttpRequest.prototype) {
        //New Firefox Versions
        XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open;
        var myOpen = function(method, url, async, user, password) {
            //call original
            this.realOpen (method, url, async, user, password);
            myCode();
        }
        //ensure all XMLHttpRequests use our custom open method
        XMLHttpRequest.prototype.open = myOpen ;
    }
}
addJS_Node (null, null, overrideXhrFunctions) {
//-- 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);
}


注意,混合GM_函数和注入代码可能会很棘手。查看"如何在注入代码中使用GM_xmlhttpRequest ?"了解一种方法。