我试图使用Greasemonkey(已安装4.9版)来操纵网站完成的XMLHttpRequest。拦截应该很简单(How can I intercept XMLHttpRequests from a Greasemonkey script?),但对我不起作用。较新版本的Greasemonkey可能会改变一切吗?
我显然尝试了链接问题中的示例,但是它们没有任何作用-尽管我的自定义打开函数中有console.log(...)
,但控制台上没有任何内容打印。
接下来,我尝试了unsafeWindow
。不需要它。我的用户脚本以@grant none
运行,文档(see here)表示我的脚本应在内容范围内运行。
使用unsafeWindow
,我得到了效果,但是它完全破坏了XMLHttpRequest
// ==UserScript==
// @name Test
// @version 1
// @include *
// @run-at document-start
// @grant none
// ==/UserScript==
"use strict";
let realOpen = unsafeWindow.XMLHttpRequest.prototype.open
console.log("Real: " + realOpen)
unsafeWindow.XMLHttpRequest.prototype.open = function() {
console.log("Called for " + this + " with URL: " + arguments[0])
//call original
return realOpen.apply(this, arguments)
};
window.addEventListener ("load", function() {
console.log ("Page loaded");
});
console.log("Unsafe: ", unsafeWindow.XMLHttpRequest.prototype.open.toString())
console.log("Normal: ", XMLHttpRequest.prototype.open.toString())
这将在控制台中提供以下输出:
Real: function open() {
[native code]
}
Unsafe: function() {
console.log("Called for " + this + " with URL: " + arguments[0])
//call original
return realOpen.apply(this, arguments)
}
Normal: function open(method, url) {
// only include method and url parameters so the function length is set properly
if (arguments.length >= 2) {
let newUrl = new URL(arguments[1], document.location.href);
arguments[1] = newUrl.toString();
}
return origOpen.apply(this, arguments);
}
==> Page loaded
如上所述,XMLHttpRequest的功能已损坏。当我使用Firefox开发人员控制台进行进一步查看时,会看到此信息
>> window.XMLHttpRequest.prototype.open
Restricted { }
在window
上设置的任何属性(如window.foobar = "foobar"
)在控制台中不存在,但在unsafeWindow
上设置的属性则存在。我认为这与Greasemonkey的沙箱有关。
即使使用@grant none
,为什么也有两个XMLHttpRequest版本?为什么我的自定义功能受到限制?我可以避免吗?当我在窗口上安装事件侦听器时,为什么它可以正常工作?
接下来,我尝试了unsafeWindow。不需要它。我的用户脚本没有@grant运行,文档(请参阅此处)说我的脚本应在内容范围内运行。
对于Greasemonkey 4的announcement中所述,这是错误的:
由于新扩展系统给我们提供的功能更加有限,我们目前无法使@grant没有脚本以相同的方式工作。最重要的是,它们与unsafeWindow有不同的连接。至少就短期而言,采用cloneInto and exportFunction是个好主意。
另请参见另一个问题Firefox doesn't respect Object.defineProperty() from a Greasemonkey script?
此更改解释了观察结果,但不知道为什么要在窗口工作中添加侦听器。