从Chrome上的Greasemonkey脚本将JS函数注入页面

Hen*_*ger 38 javascript greasemonkey google-chrome userscripts google-chrome-extension

我有一个Greasemonkey脚本,在Firefox和Opera中运行良好.但是,我很难让它在Chrome中运行.问题是在页面中注入一个可以通过页面中的代码调用的函数.这是我到目前为止所做的事情:

首先,我得到一个帮助引用Firefox 的unsafeWindow.这让我可以使用相同的FF和Opera代码(我认为是Chrome).

var uw = (this.unsafeWindow) ? this.unsafeWindow : window;
Run Code Online (Sandbox Code Playgroud)

接下来,我在页面中注入一个函数.它实际上只是一个非常薄的包装器,除了在GM脚本的上下文中调用相应的函数之外什么都不做:

uw.setConfigOption = function(newValue) {
    setTimeout(setConfigOption, 0, newValue);
}
Run Code Online (Sandbox Code Playgroud)

然后,我的脚本中有相应的功能:

setConfigOption = function(newValue) {
    // do something with it, e.g. store in localStorage
}
Run Code Online (Sandbox Code Playgroud)

最后,我在页面中注入一些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);
Run Code Online (Sandbox Code Playgroud)

总结一下:在Firefox中,当用户单击该注入的链接时,它将在unsafeWindow上执行函数调用,然后触发超时,该超时在我的GM脚本的上下文中调用相应的函数,然后执行实际处理.(如果我错了,请纠正我.)

在Chrome中,我只是得到一个"未捕获的ReferenceError:setConfigOption未定义"错误.实际上,在控制台中输入"window.setConfigOption"会产生"未定义".在Firebug和Opera开发人员控制台中,功能就在那里.

也许有另一种方法可以做到这一点,但是我的一些函数是由页面上的Flash对象调用的,我认为这使得我必须在页面上下文中使用函数.

我在Greasemonkey维基上快速浏览了unsafeWindow替代品,但它们看起来都非常难看.我在这里完全走错了轨道还是应该仔细研究这些?

决议:我跟着Max S. 建议,现在可以在Firefox和Chrome中使用.因为我需要对页面可用的函数必须回调常规函数,所以我将整个脚本移动到页面,即它完全包含在他称为"main()"的函数中.

为了使这个hack的额外丑陋更加可以忍受,我至少可以放弃unsafeWindow和wrappedJSObject的使用.

我还没有设法从Greasemonkey wiki中获取内容范围运行器.它应该做同样的事情似乎执行得很好,但是我的函数永远不会<a>被页面中的元素访问,例如.我还没弄清楚为什么会这样.

Max*_*keh 68

与Chrome中页面上运行的代码进行通信的唯一方法是通过DOM,因此您必须使用hack,例如<script>在代码中插入标记.请注意,如果您的脚本需要在页面上的其他所有内容之前运行,则可能会出现问题.

编辑:这是尼斯警报扩展如何做到这一点:

function main () {
  // ...
  window.alert = function() {/* ... */};
  // ...
}

var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);
Run Code Online (Sandbox Code Playgroud)


小智 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'));
Run Code Online (Sandbox Code Playgroud)

inject.js:

function main() {
     alert('Hello World!');
}

main();
Run Code Online (Sandbox Code Playgroud)

  • 这个很棒!使用jQuery的人的快捷方式:`function injectjs(link){$('<script type ="text/javascript"src ="'+ link +'"/>').appendTo($('head')); }` (2认同)

use*_*036 6

其他答案要么强迫您使用函数表达式,导入外部附加文件,要么使用长时间修补的 hack

此答案将直接从源代码将 JavaScript 添加到页面中。它将使用 ECMAScript 6 (ES6)模板文字轻松地将多行 JavaScript 字符串放到页面上。

var script = document.createElement('script'); 
script.type = "text/javascript"; 
script.innerHTML = ` 
   function test() {
      alert(1);
   }
`;
document.getElementsByTagName('head')[0].appendChild(script);
Run Code Online (Sandbox Code Playgroud)

``请注意定义多行字符串的开头和结尾的反引号。