我有一个Greasemonkey脚本,在Firefox和Opera中运行良好。但是,我很难让它在Chrome中运行。问题是在页面中注入一个可以通过页面中的代码调用的函数。以下是我到目前为止所做的事情:
首先,我获得了Firefox unsafeWindow的帮助引用。这允许我为FF和Opera(以及我认为的Chrome)使用相同的代码。
var uw = (this.unsafeWindow) ? this.unsafeWindow : window;
接下来,我在页面中注入一个函数。它实际上只是一个非常薄的包装器,除了在GM脚本的上下文中调用相应的函数之外什么都不做:
uw.setConfigOption = function(newValue) {
setTimeout(setConfigOption, 0, newValue);
}
然后,我的脚本中有相应的功能:
setConfigOption = function(newValue) {
// do something with it, e.g. store in localStorage
}
最后,我在页面中注入一些HTML,并带有一个调用该函数的链接。
var p = document.createElement('p');
p.innerHTML = '<a href="javascript:setConfigOption(1)">set config option to 1</a>';
document.getElementById('injection-point').appendChild(p);
总结一下: 在Firefox中,当用户单击该注入的链接时,它将在unsafeWindow上执行函数调用,然后触发超时,该超时在我的GM脚本的上下文中调用相应的函数,然后执行实际处理。 (如果我在这里错了,请纠正我。)
在Chrome中,我只是得到了“未捕获的ReferenceError:未定义setConfigOption”错误。实际上,在控制台中输入“window.setConfigOption”会产生“未定义”。在Firebug和Opera开发人员控制台中,该功能就在那里。
也许有另一种方法可以做到这一点,但是我的一些函数是由页面上的Flash对象调用的,我认为这使得我必须在页面上下文中有函数。
我快速浏览了Greasemonkey wiki上的alternatives to unsafeWindow,但它们看起来都非常难看。我在这里完全走错了轨道还是应该仔细研究这些?
解决方法:我关注Max S.' advice,现在可以在Firefox和Chrome中使用。因为我需要在页面上使用的函数必须回调常规函数,所以我将整个脚本移动到页面,即它完全包含在他称为“main()”的函数中。
为了使这个hack的额外丑陋更加可以忍受,我现在至少可以放弃unsafeWindow和wrappedJSObject的使用。
我仍然无法从Greasemonkey wiki中获得content scope runner。它应该做同样的事情似乎执行得很好,但是我的函数永远不会被页面中的<a>
元素访问,例如。我还没弄清楚为什么会这样。
答案 0 :(得分:67)
与Chrome中页面上运行的代码进行通信的唯一方法是通过DOM,因此您必须使用hack,例如在代码中插入<script>
标记。请注意,如果您的脚本需要在页面上的其他所有内容之前运行,则可能会出现问题。
编辑:以下是the Nice Alert extension执行此操作的方式:
function main () {
// ...
window.alert = function() {/* ... */};
// ...
}
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);
答案 1 :(得分:15)
我有这个:
contentscript.js:
function injectJs(link) {
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src=link;
document.getElementsByTagName('head')[0].appendChild(scr)
//document.body.appendChild(scr);
}
injectJs(chrome.extension.getURL('injected.js'));
inject.js:
function main() {
alert('Hello World!');
}
main();
答案 2 :(得分:4)
我快速浏览了Greasemonkey wiki上的alternatives to unsafeWindow,但它们看起来都非常难看。我在这里完全走错了轨道还是应该仔细研究这些?
你应该看,因为它是唯一可用的选项。我更愿意使用location hack。
myscript.user.js:
function myFunc(){
alert('Hello World!');
}
location.href="javascript:(function(){" + myFunc + "})()"
example.com/mypage.html
<script>
myFunc() // Hello World!
</script>
当然,这很难看。但它运作良好。
Max S.提到的内容范围运行器方法比位置黑客更好,因为它更容易调试。
答案 3 :(得分:2)
其他答案会强制您使用function expressions,导入external additional file或使用long patched hack。
此答案将直接从源代码中将javascript添加到页面中。它将使用ECMAScript 6(ES6)template literals轻松地将多行javascript字符串放到页面上。
var script = document.createElement('script');
script.type = "text/javascript";
script.innerHTML = `
function test() {
alert(1);
}
`;
document.getElementsByTagName('head')[0].appendChild(script);
请注意定义多行字符串开头和结尾的反引号``
。