在Chrome上从Greasemonkey脚本将JS功能注入页面 [英] Injecting JS functions into the page from a Greasemonkey script on Chrome

查看:442
本文介绍了在Chrome上从Greasemonkey脚本将JS功能注入页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Greasemonkey脚本,在Firefox和Opera中运行得很好。然而,我努力让它在Chrome中运行。问题是将一个函数注入到页面中的代码可以调用的页面中。以下是我到目前为止所做的工作:



首先,我得到了 unsafeWindow 。这允许我为FF和Opera(和Chrome,我认为)具有相同的代码。

  var uw =(this。 unsafeWindow)? this.unsafeWindow:window; 

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

  uw.setConfigOption = function(newValue){
setTimeout(setConfigOption,0,newValue);

$ / code>

然后,在脚本中有相应的函数:

  setConfigOption = function(newValue){
//对它做些事情,例如存储在localStorage
}

最后,我将一些HTML注入页面,调用该函数。

  var p = document.createElement('p'); 
p.innerHTML ='< a href =javascript:setConfigOption(1)>将配置选项设置为1< / a>;
document.getElementById('injection-point')。appendChild(p);

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



在Chrome中,我刚刚收到未捕获的ReferenceError:setConfigOption未定义错误。事实上,在控制台中输入window.setConfigOption会产生未定义。在Firebug和Opera开发者控制台中,函数就在那里。

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



我快速浏览了 Greasemonkey wiki上的unsafeWindow的替代品,但它们都显得很丑陋。我完全在错误的轨道上,或者我应该仔细观察这些?

解决方案:我遵循 Max S.的建议和它现在可以在Firefox和Chrome中使用。因为我需要为页面提供的函数必须回调到常规函数中,所以我将整个脚本移动到了页面上,即它完全包含在他称为main()的函数中。



为了让这种黑客变得更加可恶,我现在至少可以放弃使用unsafeWindow和wrappedJSObject。



我仍然没有设法从Greasemonkey维基上获取内容范围转向者。它应该做同样的事情,它似乎执行得很好,但例如,我的函数永远不可访问来自页面的< a> 元素。我还没有弄清楚为什么会这样。

解决方案

是通过DOM的,所以你必须使用黑客来插入一个< script> 标签和你的代码。请注意,如果您的脚本需要在页面上的其他所有内容之前运行,这可能会出现问题。



编辑 Nice Alert扩展程序执行此操作:

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

var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);


I have a Greasemonkey script that works just fine in Firefox and Opera. I struggle with getting it to work in Chrome, however. The problem is injecting a function into the page that can be invoked by code from the page. Here's what I'm doing so far:

First, I get a helper reference to the unsafeWindow for Firefox. This allows me to have the same code for FF and Opera (and Chrome, I thought).

var uw = (this.unsafeWindow) ? this.unsafeWindow : window;

Next, I inject a function into the page. It's really just a very thin wrapper that does nothing but invoking the corresponding function in the context of my GM script:

uw.setConfigOption = function(newValue) {
    setTimeout(setConfigOption, 0, newValue);
}

Then, there's the corresponding function right in my script:

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

Last, I inject some HTML into the page with a link to invoke the function.

var p = document.createElement('p');
p.innerHTML = '<a href="javascript:setConfigOption(1)">set config option to 1</a>';
document.getElementById('injection-point').appendChild(p);

To summarize: In Firefox, when the user clicks that injected link, it will execute the function call on the unsafeWindow, which then triggers a timeout that invokes the corresponding function in the context of my GM script, which then does the actual processing. (Correct me if I'm wrong here.)

In Chrome, I just get a "Uncaught ReferenceError: setConfigOption is not defined" error. And indeed, entering "window.setConfigOption" into the console yields an "undefined". In Firebug and the Opera developer console, the function is there.

Maybe there's another way to do this, but a few of my functions are invoked by a Flash object on the page, which I believe makes it necessary that I have functions in the page context.

I took a quick look at the alternatives to unsafeWindow on the Greasemonkey wiki, but they all look pretty ugly. Am I completely on the wrong track here or should I look more closely into these?

RESOLUTION: I followed Max S.' advice and it works in both Firefox and Chrome now. Because the functions I needed to be available to the page had to call back into the regular ones, I moved my whole script to the page, i.e. it is completely wrapped into the function he called 'main()'.

To make the extra uglyness of that hack a little bit more bearable, I could at least drop the usage of unsafeWindow and wrappedJSObject now.

I still haven't managed to get the content scope runner from the Greasemonkey wiki working. It should do the same and it seems to execute just fine, but my functions are never accessible to <a> elements from the page, for example. I haven't yet figured out why that is.

解决方案

The only way to communicate with the code running on the page in Chrome is through the DOM, so you'll have to use a hack like inserting a <script> tag with your code. Note that this may prove buggy if your script needs to run before everything else on the page.

EDIT: Here's how the Nice Alert extension does this:

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

var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);

这篇关于在Chrome上从Greasemonkey脚本将JS功能注入页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆