在正确使用@grant 的同时拦截 Greasemonkey 中的 XMLHttpRequest

Intercepting XMLHttpRequest in Greasemonkey while using @grant the right way

所以我的目标是劫持所有 XMLHttpRequest 响应并在我的脚本范围内对它们进行处理。但是因为我 @grant 必须使用 unsafeWindow 的东西不能简单地完成。 (我不知道为什么,但我无法更改 unsafeWindow.XMLHttpRequest.prototype.open。没有错误,但 XMLHttpRequest 根本不起作用。)所以我最终得到了这段代码:

// ==UserScript==
// @name        a
// @include     *
// @version     1
// @grant       GM_xmlhttpRequest
// ==/UserScript==

realProcess = function(xhr) {
    // do something
}

function hijackAjax(process) {
    if(typeof process != "function") {
        process = function(e){ console.log(e); };
    }
    window.addEventListener("hijack_ajax", function(event) {
        process(event.detail);
    }, false);
    function injection() {
        var open = XMLHttpRequest.prototype.open;
        XMLHttpRequest.prototype.open = function() {
            this.addEventListener("load", function() {
                window.dispatchEvent(new CustomEvent("hijack_ajax", {detail: this}));
            }, false);
            open.apply(this, arguments);
        };
    }
    window.setTimeout("(" + injection.toString() + ")()", 0);
}
hijackAjax(realProcess);

我的问题是:能不能做到better/faster/more优雅?

编辑: 根据提示更新了代码。

解决方案取决于您想如何进行交互。您可以将所有逻辑注入网站的范围,但是,如果您想进行交互,则用户脚本的范围和网站的范围之间存在障碍。在两个范围之间交换数据并非易事。 unsafeWindow 是邪恶的,避免使用。将逻辑作为字符串注入到 setTimeout(String) 中进行评估,以便它在站点范围内执行。如果您需要在特权范围内与用户脚本交互,请使用 window.dispatchEvent(new CustomEvent('eventname', {'detail': scalarData})); 设置消息系统。您将无法传输在具有其他权限的范围内声明的复杂数据类型。