UserScripts&Greasemonkey:调用网站的JavaScript函数
我正在为Firefox和Chrome创build一个UserScript扩展,我正在尝试使用网站JavaScript中的一些代码,例如:
function: myFunction(){ return Grooveshark.playNextSong(); }
问题是当我testing这个代码时, Grooveshark
是一个空引用。
我知道还有其他人已经做到了:
看BetterGrooveshark
但是我不知道为什么我的简单扩展名不能调用Grooveshark的JavaScript函数。
我需要'追加'我的脚本到文件才能这个工作吗?: document.document.body.appendChild(script);
Greasemonkey是否已经注入我的扩展JavaScript? 有人能为我澄清这个请。
谢谢。
背景
Greasemonkey是否已经注入我的扩展JavaScript? 有人能为我澄清这个请。
Greasemonkey在沙箱中执行脚本,这是一个受限制的环境,无需直接访问页面中的JavaScript。 早期版本的Greasemonkey直接将脚本注入到页面中,但是这引入了严重的安全漏洞。 在旧模型中,脚本使用浏览器chrome的提升权限运行,允许远程页面使用一些聪明的JavaScript访问Greasemonkey的内置函数。 这很糟糕:
Greasemonkey脚本包含自己的GM_xmlhttprequest对象,与一般的xmlttprequest对象不同,它可以访问任何一台计算机的本地文件,或者对任意站点进行任意的请求,而不考虑通常适用于xmlhttprequest的同一个源策略。 (资源)
当你今天从Greasemonkey脚本访问window
对象时,你得到的是一个间接引用实际window
属性的包装对象 。 这个包装器对象可以被安全地修改,但是具有重要的限制 。 访问实际的窗口对象由unsafeWindow
提供(简写为window.wrappedJSObject
)。 使用unsafeWindow
重新打开Greasemonkey的所有原始安全问题,并且在Chrome中不可用。 应尽可能避免。
好消息是,至less有两种方式可以安全地使用Greasemonkey的新安全模型。
脚本注入
既然Greasemonkey脚本可以安全地访问DOM,那么在目标文档的<head>
中注入一个<script>
标签是很简单的。 创build一个这样的function:
function exec(fn) { var script = document.createElement('script'); script.setAttribute("type", "application/javascript"); script.textContent = '(' + fn + ')();'; document.body.appendChild(script); // run the script document.body.removeChild(script); // clean up }
使用起来很简单:
exec(function() { return Grooveshark.playNextSong(); });
位置哈克
在某些情况下,脚本注入可能是矫枉过正的,特别是当您需要修改页面中某个variables的值或执行单个函数时。 Location Hack利用javascript:
URL访问文档内容中的代码。 这就像在Greasemonkey脚本中运行一个书签一样。
location.assign("javascript:Grooveshark.playNextSong();void(0)");
奖金脚本
这是一个完整的Greasemonkey脚本,演示了上面的例子。 你可以在这个页面上运行它。
// ==UserScript== // @name Content Function Test // @namespace lwburk // @include http://stackoverflow.com/questions/5006460/userscripts-greasemonkey-calling-a-websites-javascript-functions // ==/UserScript== function exec(fn) { var script = document.createElement('script'); script.setAttribute("type", "application/javascript"); script.textContent = '(' + fn + ')();'; document.body.appendChild(script); // run the script document.body.removeChild(script); // clean up } window.addEventListener("load", function() { // script injection exec(function() { // alerts true if you're registered with Stack Overflow alert('registered? ' + isRegistered); }); // location hack location.assign("javascript:alert('registered? ' + isRegistered);void(0)"); }, false);
您的GreaseMonkey脚本(和Chrome的用户脚本)中声明的函数和variables与网页声明的函数和variables保持分离,原因很明显。 对于Firefox中的GM脚本,可以通过unsafeWindow
访问全局variables。
安全性和兼容性的最佳方法是使用脚本元素将您的函数注入到页面中。 我在我的用户脚本中使用以下片段:
function addFunction(func, exec) { var script = document.createElement("script"); script.textContent = "-" + func + (exec ? "()" : ""); document.body.appendChild(script); }
这里的"-"
确保函数被parsing为一个expression式,这样exec
可以被用来在添加它时立即执行。 你可以这样调用函数:
function myFunction () { return Grooveshark.playNextSong(); } // Inject the function and execute it: addFunction(myFunction, true);