UserScripts&Greasemonkey:调用网站的JavaScript函数

seb*_*ian 33 javascript greasemonkey userscripts google-chrome-extension

我正在为Firefox和Chrome创建一个UserScript扩展,我正在尝试使用网站JavaScript中的一些代码,例如:

function: myFunction(){
    return  Grooveshark.playNextSong();
}
Run Code Online (Sandbox Code Playgroud)

问题是当我测试这段代码时, Grooveshark是一个空引用.

我知道还有其他人做过:

见BetterGrooveshark

但我不知道为什么我的简单扩展无法调用Grooveshark的JavaScript函数.

我是否需要将我的脚本"附加"到文档中才能使其正常工作?: document.document.body.appendChild(script);

不是Greasemonkey已经注入我的扩展JavaScript吗?请允许有人为我澄清这一点.

谢谢.

Way*_*ett 74

背景

不是Greasemonkey已经注入我的扩展JavaScript吗?请允许有人为我澄清这一点.

Greasemonkey在沙箱中执行您的脚本,沙箱是一个受限制的环境,无法直接访问页面中的JavaScript.早期版本的Greasemonkey将脚本直接注入页面,但这引入了严重的安全漏洞.在旧模型中,脚本使用浏览器chrome的提升权限运行,这允许远程页面使用一些聪明的JavaScript访问Greasemonkey的内置函数.这很糟糕:

Greasemonkey脚本包含它们自己的GM_xmlhttprequest对象,与普通的xmlttprequest对象不同,它可以访问任何本地文件,或者对任意站点发出任意请求,而不考虑通常适用于xmlhttprequest的相同源策略.(资源)

window今天从Greasemonkey脚本访问对象时,你得到的是一个间接引用实际属性的包装器对象window.此包装器对象可以安全地修改,但具有重要的局限性.通过unsafeWindow(简写window.wrappedJSObject)提供对实际窗口对象的访问.使用unsafeWindow重新打开Greasemonkey的所有原始安全问题,但在Chrome中不可用.应尽可能避免.

好消息:至少有两种方法可以安全地使用Greasemonkey的新安全模型.

脚本注入

既然Greasemonkey脚本可以安全地访问DOM,那么在目标文档中注入一个<script>标记是微不足道的<head>.创建一个这样的函数:

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
}
Run Code Online (Sandbox Code Playgroud)

它使用简单:

exec(function() {
    return Grooveshark.playNextSong();
});
Run Code Online (Sandbox Code Playgroud)

位置黑客

在某些情况下,脚本注入可能过度,特别是当您需要的是修改页面中变量的值或执行单个函数时.该位置黑客利用javascript:的URL在文档的内容访问代码.这很像在Greasemonkey脚本中运行bookmarklet.

location.assign("javascript:Grooveshark.playNextSong();void(0)");
Run Code Online (Sandbox Code Playgroud)

奖金脚本

这是一个完整的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);
Run Code Online (Sandbox Code Playgroud)

  • 你的新词汇很好.GM维基过于偏执和律师式(这可能是最好的).这就像警告你永远不要开车因为你可能在车祸中死去.如果您知道目标页面,使用unsafeWindow的风险可以忽略不计. (3认同)
  • 尤扎!你的手现在疼吗? (2认同)
  • 我不知道"偶尔使用"的意思是什么意思?如果您肯定脚本只在您控制的页面上或您绝对信任的页面上执行,那么您应该只使用unsafeWindow.您公开unsafeWindow的任何页面都有可能使用此处描述的技术提升其访问权限:http://groups.google.com/group/greasemonkey-dev/tree/browse_frm/thread/933ecdb307c4386d/864b5121ad4698cb (2认同)
  • @PointedEars最近版本的Chrome确实支持`unsafeWindow`. (2认同)

And*_*y E 11

由于显而易见的原因,GreaseMonkey脚本(和Chrome的用户脚本)中声明的函数和变量与网页声明的函数和变量保持独立.对于Firefox中的GM脚本,您可以通过访问全局变量unsafeWindow.

安全性和兼容性的最佳方法是使用脚本元素将函数注入页面.我在用户脚本中使用以下代码段:

function addFunction(func, exec) {
  var script = document.createElement("script");
  script.textContent = "-" + func + (exec ? "()" : "");
  document.body.appendChild(script);
}
Run Code Online (Sandbox Code Playgroud)

"-"这里,使某些功能被解析为以使得表达exec可用于立即执行在添加它.你这样调用函数:

function myFunction () {
    return Grooveshark.playNextSong();
}

// Inject the function and execute it:
addFunction(myFunction, true);
Run Code Online (Sandbox Code Playgroud)