将@grant添加到GM脚本会破坏XMLHttpRequest.prototype.open的重载吗?

时间:2013-05-22 14:54:07

标签: javascript xmlhttprequest prototype greasemonkey overloading

我正在写一个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。当我将以下行添加到meta部分时,我的代码会中断,并且不再调用myOpen

// @grant       GM_getValue

这可能是任何GM API,我的代码中断了。 即使使用GM API,我脚本中的其他所有内容也能正常运行,这只是XMLHttpRequest.prototype.open函数的重载。

我可以使用waitForKeyElements来解决这个问题,但是,我不喜欢它,因为它会因为它使用的时间间隔而降低浏览器的速度。

为什么GM API会打破XMLHttpRequest.prototype.open来电的过载?

非常感谢,

彼得

1 个答案:

答案 0 :(得分:0)

The @grant directive重新启用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_函数和注入的代码可能会变得棘手。如果有一种方法,请参阅"How to use GM_xmlhttpRequest in Injected Code?"