UserScripts & Greasemonkey:调用网站的 JavaScript 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5006460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UserScripts & Greasemonkey: calling a website's JavaScript functions
提问by sebastian
I'm creating a UserScript extension for Firefox & Chrome and I'm trying to use some of the code in the website's JavaScript, e.g.:
我正在为 Firefox 和 Chrome 创建一个 UserScript 扩展,我正在尝试使用网站 JavaScript 中的一些代码,例如:
function: myFunction(){
return Grooveshark.playNextSong();
}
The problem is when I test this code, Grooveshark
is a null reference.
问题是当我测试这段代码时, Grooveshark
是一个空引用。
I know there are other people who have done it:
我知道还有其他人这样做了:
But I don't know why my simple extension can't call Grooveshark's JavaScript functions.
但是我不知道为什么我的简单扩展不能调用 Grooveshark 的 JavaScript 函数。
Do I need to 'append' my script to the document in order for this to work?:
document.document.body.appendChild(script);
我是否需要将我的脚本“附加”到文档中才能使其工作?:
document.document.body.appendChild(script);
Doesn't Greasemonkey inject my extensions JavaScript already? Can someone clarify this for me please.
Greasemonkey 不是已经注入我的扩展 JavaScript 了吗?有人可以为我澄清这一点。
Thanks.
谢谢。
回答by Wayne
Background
背景
Doesn't Greasemonkey inject my extensions JavaScript already? Can someone clarify this for me please.
Greasemonkey 不是已经注入我的扩展 JavaScript 了吗?有人可以为我澄清这一点。
Greasemonkey executes your scripts in a sandbox, which is a restricted environment without direct access to the JavaScript in the page. Earlier versions of Greasemonkey injected scripts directly into the page, but this introduced serious security vulnerabilities. In the old model, scripts ran with the elevated rights of the browser chrome, which allowed remote pages to access Greasemonkey's built-in functions using some clever JavaScript. This was bad:
Greasemonkey 在沙箱中执行您的脚本,沙箱是一个受限环境,无法直接访问页面中的 JavaScript。早期版本的 Greasemonkey 将脚本直接注入页面,但这引入了严重的安全漏洞。在旧模型中,脚本以浏览器 chrome 的提升权限运行,允许远程页面使用一些巧妙的 JavaScript访问 Greasemonkey 的内置函数。这很糟糕:
Greasemonkey scripts contained their own GM_xmlhttprequest object which, unlike a normal xmlttprequest object, could access any local files one one's computer or make arbitrary requests to arbitrary sites without regard for the same origin policy that typically applies to xmlhttprequest. (source)
Greasemonkey 脚本包含它们自己的 GM_xmlhttprequest 对象,与普通的 xmlttprequest 对象不同,该对象可以访问自己计算机的任何本地文件或向任意站点发出任意请求,而无需考虑通常适用于 xmlhttprequest 的同源策略。(来源)
When you access the window
object from a Greasemonkey script today, what you get is a wrapper objectthat indirectly references the actual window
's properties. This wrapper object can be modified safely, but has important limitations. Access to the actual window object is provided by unsafeWindow
(shorthand for window.wrappedJSObject
). Use of unsafeWindow
re-opens all of Greasemonkey's original security problems and isn't available in Chrome. It should be avoided wherever possible.
当您window
今天从 Greasemonkey 脚本访问对象时,您得到的是一个包装对象,它间接引用了实际window
的属性。这个包装对象可以安全地修改,但有重要的限制。对实际窗口对象的访问由unsafeWindow
( 的简写window.wrappedJSObject
)提供。使用unsafeWindow
重新打开所有 Greasemonkey 的原始安全问题,并且在 Chrome 中不可用。应尽可能避免。
The good news: there are at least two ways to work with Greasemonkey's new security model in a safe way.
好消息:至少有两种方法可以安全地使用 Greasemonkey 的新安全模型。
Script Injection
脚本注入
Now that Greasemonkey scripts can safely access the DOM, it's trivial to inject a <script>
tag into the <head>
of the target document. Create a function like this:
既然 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
}
It's simple to use:
使用起来很简单:
exec(function() {
return Grooveshark.playNextSong();
});
Location Hack
定位黑客
Script injection may be overkill in some cases, especially when all you need is to modify the value of a variable in the page or execute a single function. The Location Hackleverages javascript:
URLs to access code in the document's content. It's a lot like running a bookmarklet from within a Greasemonkey script.
在某些情况下,脚本注入可能有点过头,尤其是当您只需要修改页面中变量的值或执行单个函数时。该位置黑客利用javascript:
URL来访问代码的文档的内容。这很像在 Greasemonkey 脚本中运行书签。
location.assign("javascript:Grooveshark.playNextSong();void(0)");
Bonus Script
奖金脚本
Here's a complete Greasemonkey script that demonstrates the examples above. You can run it on this page.
这是一个完整的 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);
回答by Andy E
Functions and variables declared in your GreaseMonkey scripts (and Chrome's user scripts) are kept separate from the ones declared by the web page, for obvious reasons. For GM scripts in Firefox, you can access global variables via unsafeWindow
.
出于显而易见的原因,在您的 GreaseMonkey 脚本(和 Chrome 的用户脚本)中声明的函数和变量与网页声明的函数和变量分开保存。对于 Firefox 中的 GM 脚本,您可以通过unsafeWindow
.
The best approach for safety and compatibility is to inject your functions into the page using a script element.?I use the following snippet in my user scripts:
安全性和兼容性的最佳方法是使用脚本元素将您的功能注入页面。我在我的用户脚本中使用以下代码段:
function addFunction(func, exec) {
var script = document.createElement("script");
script.textContent = "-" + func + (exec ? "()" : "");
document.body.appendChild(script);
}
The "-"
here makes certain the function is parsed as an expression so that exec
can be used to immediately execute upon adding it.?You call the function like so:
在"-"
这里,使某些功能被解析为以使得表达exec
可用于立即执行在添加it.?You调用该函数,如下所示:
function myFunction () {
return Grooveshark.playNextSong();
}
// Inject the function and execute it:
addFunction(myFunction, true);