为什么Chrome unsafeWindow技巧不支持XMLHttpRequest Send override

why isn't Chrome unsafeWindow trick supporting XMLHttpRequest send override?

本文关键字:XMLHttpRequest Send override 不支持 Chrome unsafeWindow 为什么      更新时间:2023-09-26

我想覆盖XMLHttpRequest的发送,以便让我的用户脚本知道何时通过此类请求在页面上更新数据。我的覆盖代码如下所示:

var oldSend = unsafeWindow.XMLHttpRequest.prototype.send;
unsafeWindow.XMLHttpRequest.prototype.send = function(){
    console.log("notified of XHR update");
    oldSend.apply(this, arguments);
}

如果我将其注入页面(没有unsafeWindow引用),它可以正常工作,但我想从用户脚本范围使其工作。 unsafeWindow在Firefox中对此起作用,但在Chrome中则不然。 所以我抓住了Brock Adams的伎俩,在Chrome中创建了一个工作unsafeWindow

var bGreasemonkeyServiceDefined     = false;
try {
    if (typeof Components.interfaces.gmIGreasemonkeyService === "object") {
        bGreasemonkeyServiceDefined = true;
    }
}
catch (err) {
    //Ignore.
}
if ( typeof unsafeWindow === "undefined"  ||  ! bGreasemonkeyServiceDefined) {
    unsafeWindow    = ( function () {
        var dummyElem   = document.createElement('p');
        dummyElem.setAttribute ('onclick', 'return window;');
        return dummyElem.onclick ();
    } ) ();
}

但是,当我将两者结合起来时,没有任何反应。 这一切都可以粘贴到控制台中,但是从用户脚本运行它时既没有错误也没有输出。 我做错了什么,还是这超出了这个技巧的能力?

嗯,只是尝试了一些更简单的东西,比如:unsafeWindow.document.title = 'testing';,这也不起作用,所以也许它不是特定于XMLHttpRequest.

如果可能的话,我试图避免注入页面。

这个:

/*--- Create a proper unsafeWindow object on browsers where it doesn't exist
    (Chrome, mainly).
    Chrome now defines unsafeWindow, but does not give it the same access to
    a page's javascript that a properly unsafe, unsafeWindow has.
    This code remedies that.
*/
var bGreasemonkeyServiceDefined     = false;
try {
    if (typeof Components.interfaces.gmIGreasemonkeyService === "object") {
        bGreasemonkeyServiceDefined = true;
    }
}
catch (err) {
    //Ignore.
}
if ( typeof unsafeWindow === "undefined"  ||  ! bGreasemonkeyServiceDefined) {
    unsafeWindow    = ( function () {
        var dummyElem   = document.createElement('p');
        dummyElem.setAttribute ('onclick', 'return window;');
        return dummyElem.onclick ();
    } ) ();
}

其次是这个:

unsafeWindow.document.title = 'testing';

从我的测试用户脚本中工作正常。

这些也可以按照unsafeWindow技巧工作:

unsafeWindow.foo = function () {
    console.log ("In foo().");
};
unsafeWindow.alert = function (s) {
    console.log ("Alert: ", s);
};

(在脚本运行的页面上,在控制台中输入foo()会产生:"In foo()"。 alert()不会生成弹出窗口,但会打印到控制台。

我不知道为什么(还)覆盖XMLHttpRequest.prototype.send不能像Chrome用户脚本那样工作,但我无论如何都不建议使用unsafeWindow方法。

注入覆盖代码。 如果您不(或不能)注入整个脚本,请使用postMessage()(也适用于Chrome)在页面范围和脚本范围之间进行通信。