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

标签 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 之前,这一直很有效。当我将以下行添加到元部分时,我的代码会中断,并且不再调用 myOpen:

// @grant       GM_getValue

这实际上可以是任何 GM API,但我的代码会损坏。 即使使用 GM API,我的脚本中的其他所有内容也能正常工作,只是 XMLHttpRequest.prototype.open 函数的重载会中断。

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

知道为什么 GM API 会破坏 XMLHttpRequest.prototype.open 调用的重载吗?

非常感谢,

彼得

最佳答案

The @grant directive重新打开 Greasemonkey 的沙箱——它必须使用任何 GM_ 函数。

prototype 覆盖只会影响脚本范围,而您希望它影响页面范围。为了解决这个问题,您需要注入(inject)覆盖。就像这样:

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_ 函数和注入(inject)代码可能会变得很棘手。请参阅"How to use GM_xmlhttpRequest in Injected Code?"一种方法来做到这一点。

关于javascript - 将 @grant 添加到 GM 脚本会破坏 XMLHttpRequest.prototype.open 的过载吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16695062/

相关文章:

javascript - 通过cookie切换主页

javascript - 将 JSON 发送到服务器并返回 JSON,无需 JQuery

javascript - 从 XHR 请求中获取 BLOB 数据

asp.net - 1-2 天后发生 URL 意外以 '/Convert' 结尾的请求格式无法识别

javascript - Meteor 无法更新 mongo?

javascript - 在不同的单选按钮值上显示额外字段

javascript - 使用map循环遍历数组时返回null而不是JSX

javascript - 原型(prototype)和嵌套返回函数,帮助!

c++ - 数组/指针/引用混淆

Javascript 库对象方法声明