在我的Greasemonkey脚本中,我想覆盖网页中仍然存在的功能。
所以我正在使用这个JavaScript代码:
var oldDoWork = DoWork;
unsafeWindow.DoWork = function()
{
// Do some new work
...
oldDoWork(); // Call the old function
}
有效。
但该方法存在两个问题:
unsafeWindow
功能是一个安全问题,来自Greasemonkey说。GM_getValue
和GM_setValue
。使用计时器的解决方法会导致异步作业的其他一些问题。如何在不使用unsafeWindow
的情况下管理上述代码?
答案 0 :(得分:1)
为避免不安全的窗口,您可以使用:
location.assign("javascript:YOUR_CODE_GOES_HERE");
但这不会让你使用GM_ *函数。
使用GM_ *“退出GM范围”的唯一方法是使用计时器。
所以基本上,你的问题的答案是:你是以正确的方式,你只是做不了多少。
如果您的功能没有返回任何内容,我建议您使用location.assign
答案 1 :(得分:0)
如果你想避免unsafeWindow
,请将与页面的JS交互的代码注入页面。请参阅下面的addJS_Node()
。
要在此类活动中触发GM_功能,您应能够通过以下方式进行互动:
编写节点并收听DOMSubtreeModified
(在W3C规范中已弃用)。但是,a bug in FF/GM prevents this for now。
发送自定义事件。再次,GM/FF bugs and features prevent that for now。
请注意,例如,click
事件可以在用户实际点击 时调用使用GM_函数 的代码。但是,以编程方式生成相同的点击事件,但失败并显示"Greasemonkey access violation: unsafeWindow cannot call..."
错误。
所以,目前,解决方法仍然是使用计时器,但如果您愿意,可以避免unsafeWindow
:
//--- Put everything that goes into the main page, inside myJS().
function myJS () {
window.oldDoWork = DoWork;
window.DoWork = function() {
// Do some new work
callGM_setValue ("From target page", "some value");
window.oldDoWork(); // Call the old function
}
function callGM_setValue (varName, varValue) {
//--- Generate and dispatch a synthetic event.
var zEvent = document.createEvent ("CustomEvent");
zEvent.initCustomEvent (
"messageToGM_setvalue", true, false,
{Name: varName, Value: varValue}
);
document.body.dispatchEvent (zEvent);
}
}
document.body.addEventListener (
"messageToGM_setvalue", fireGM_setValue, false
);
function fireGM_setValue (zEvent) {
/*--- setTimeout remains one of the few things that can cleanse
the calling tree of it's "unsafe" origins.
*/
setTimeout (function() {
GM_setValue (zEvent.detail.Name, zEvent.detail.Value);
}, 0);
}
addJS_Node (null, null, myJS);
function addJS_Node (text, s_URL, funcToRun) {
var D = document;
var scriptNode = D.createElement ('script');
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);
}