【问题标题】:why isn't Chrome unsafeWindow trick supporting XMLHttpRequest send override?为什么 Chrome unsafeWindow 技巧不支持 XMLHttpRequest 发送覆盖?
【发布时间】:2012-06-19 02:48:15
【问题描述】:

我想覆盖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' nifty trick to create a working unsafeWindow in Chrome

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

如果可能,我会尽量避免注入页面。

【问题讨论】:

    标签: javascript userscripts


    【解决方案1】:

    这个:

    /*--- 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)在页面范围和脚本范围之间进行通信。

    【讨论】:

    • brock,感谢postMessage() 的建议。我试图避免注入代码,部分是为了响应您阅读了有关该主题的优缺点列表 (stackoverflow.com/a/10828021/348496) --- 主要是为了保护脚本不被主机站点关闭或阻止。听起来你无论如何都建议注射?我会看看postMessage() 并重新考虑是否应该全部注入。
    • 对于Chrome,这种东西,注入是最好的。 unsafeWindow 实际上可以像注入的 JS 一样容易地被阻止,但最终你总是在网站上占上风。然而,unsafeWindow 为恶意网站打开了一个潜在的渠道来获得提升的权限。注射没有。 ...就我个人而言,除了对页面 JS 的最微不足道的访问(而且很少这样做)之外,我还需要任何其他访问。人们希望脚本拦截 AJAX 的大多数实际情况,最好通过轮询更改的内容来解决。这可以完全保留在安全沙箱中。
    • 如果我可以在没有任何注入 JS 的情况下让事情正常工作,那仍然是最好的选择吗?还是不值得额外的麻烦(调试等)?
    • 是的,避免注入(和 unsafeWindow)AMAP 总是最好的(更快、更健壮、更安全)。但避免这种情况并不总是可能的。例如,如果您真的需要拦截AJAX,则至少必须注入一些代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 2023-03-02
    • 2013-02-22
    • 2010-09-30
    • 2018-02-22
    相关资源
    最近更新 更多