错误:访问属性“handler”的权限被拒绝

13

我有一个适用于Firefox的Greasemonkey脚本,昨天它完美地运行了。今天我尝试使用它(未修改任何代码),但发现它已经停止工作了。经过进一步检查,我发现该脚本现在会抛出以下错误:

Error: Permission denied to access property 'handler'

这个错误是在以下代码块中抛出的:

$('body').click(function() {
    // code here
});
今天,当这个脚本昨天还能顺利运行的时候,出现了这个神奇的错误。我不明白为什么只是试图在jQuery中添加一个事件处理程序这样基本的操作会导致出现这个错误。
我的脚本使用的是jQuery,在页面中已经使用了它,所以我使用了这段代码来让它对GM可访问:
var $ = unsafeWindow.jQuery;

如果需要参考,请查看我在脚本中使用的以下Greasemonkey函数:

// @grant       GM_getResourceText
// @grant       GM_addStyle
// @grant       GM_xmlhttpRequest
// @grant       GM_getResourceURL

我已经尝试研究这个错误,但无法找到任何答案。所有看起来可能有帮助的问题都涉及iframes,但我的代码或运行网站中没有一个iframe。我还尝试删除并重新安装脚本,但问题仍未解决。

3个回答

20

刚刚将Greasemonkey 2.0推送到了所有设置为自动更新的 Firefox 浏览器中。 (GM 2于2014年6月17日发布,但可能需要几周的时间才能通过审查过程。)

Greasemonkey 2.0 彻底改变了unsafeWindow处理方式

 

不兼容更改:

 

通常,要快速访问页面函数或变量,您可以切换到新方法,但在您的情况下,您正在使用var $ = unsafeWindow.jQuery; - 这总是一种不好的做法。

jQuery 是一个特殊情况,来回克隆它会破坏事情。
请使用@require jQuery,例如:

// ==UserScript==
// @name        _YOUR_SCRIPT_NAME
// @include     http://YOUR_SERVER.COM/YOUR_PATH/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @grant       GM_getResourceText
// @grant       GM_addStyle
// @grant       GM_xmlhttpRequest
// @grant       GM_getResourceURL
// ==/UserScript==
...

4
谢谢!cloneInto() 对我有用。在我的情况下,我试图从我的 GM 脚本将一个对象传递给另一个脚本,当那个脚本尝试访问它时,它抛出了一个权限被拒绝的错误。 - Thomas Glaser
4
MDN 文章: cloneInto, exportFunction, createObjectIncloneInto: 该函数可将一个对象复制到指定的沙盒或内容窗口中,以防止对原始对象的更改。该函数需要两个参数,第一个参数是要复制的对象,第二个参数是要复制到的目标上下文。exportFunction: 该函数可使一个函数从一个沙盒或内容脚本暴露给另一个沙盒或内容脚本。该函数需要两个参数,第一个参数是要暴露的函数,第二个参数是要将该函数暴露给的目标沙盒或内容脚本。createObjectIn: 该函数可在指定的沙盒或内容窗口中创建一个新的 JavaScript 对象。该函数需要一个参数,即要在其中创建对象的目标沙盒或内容窗口。 - Oriol
由于 MDN 链接已经失效,所以这里提供一个快速示例来注入一个带有嵌套函数的对象 (foo = {bar: function(){..}):unsafeWindow.foo = cloneInto({}, unsafeWindow); unsafeWindow.foo["bar"] = exportFunction(function() {}, unsafeWindow.foo); - Janaka Bandara

0

如果使用了@grant而不是none,则noConflict是多余的--就像在这个问题中一样。@require已经在我的答案中涵盖了。 - Brock Adams
@BrockAdams:我的理解是,上面的代码始终有效,无论启用哪些@grant。我问题的重点在于这是官方解决方案。 - Aaron Digulla
@BrockAdams:这个在最新的Firefox(34?35?)和GM上不再起作用了。我之前使用了@grant,可以访问unsafeWindowunsafeWindow.$,但是现在unsafeWindow.$.each()会报错"accessing call() from different context"。我猜测官方文档可能已经过时了。 - Aaron Digulla
@BrockAdams:我的意思是,无论你有什么样的授权或没有授权,在页面的jQuery实例中调用函数都不再起作用了。 - Aaron Digulla
不,即使在@grant none生效时,unsafeWindow.$.each(...)仍然可以正常工作。我刚在最新的FF release(34.0.5)上进行了双重检查。这是因为在该模式下,unsafeWindow === window - Brock Adams
显示剩余4条评论

0
你正在使用unsafeWindow - 如其名所示,这并不是一个安全的使用方法 - 问题可能就出在这里;Firefox对跨段对象进行了更改:

https://blog.mozilla.org/addons/2014/04/10/changes-to-unsafewindow-for-the-add-on-sdk/

这篇博客文章提到了Add-on SDK,但是变化发生在平台上,这也会影响到Greasemonkey。

所以你基本上是从一个隔间(jQuery,从“unsafeWindow”)中获取一个对象,并在你的沙盒中使用。你现在的做法可能不能再起作用了。你可以尝试使用文章中提到的API,但我担心像jQuery这样的整个库被复制可能会有一些问题。事实上,最好的方法可能是在你的Greasemonkey隔间中也加载jQuery,而不是重用页面上的那个。

错误可能是因为你已经更新了Firefox版本或者它自动更新了。


这不是SDK的变化,而是影响SDK工作方式的平台变化。事实上,文章指出了wrappedJSObject的使用也受到影响——这意味着无论SDK如何都会受到影响。我知道这一点是因为我在团队中参与了这个变化。我对GM不是很了解,但正如所说,这是一个平台变化,GM是基于它构建的。我不知道他们决定如何处理这样的新限制,但不管是GM还是SDK都会受到影响。 - ZER0
wrappedJSObject 文档 没有任何改变。而且,据我所知,Scriptish 没有受到同样的影响。该文章仅讨论了 SDK 对变化的影响,没有提到 Firefox 本身的任何更改 —— 尽管我们知道这三个 Components.utils 函数是新的。 - Brock Adams
1
另外,需要注意的是:FF 30没有破坏这些“unsafeWindow”脚本。GM 2.0才做到了这一点。 - Brock Adams
可能wrappedJSObject的文档已经过时了,我会和我的团队成员确认一下。请注意,此更改特别涉及具有不同特权的不同隔离区域,例如沙盒环境(如SDK或GM)和内容环境。本文重点介绍SDK,因为我们在那里受到了主要影响 - GM并非由Mozilla提供。Scriptish可能不符合这种情况。您可以在Bugzilla的Core / XPConnect下找到有关Firefox平台的许多更改。再次强调,这不是SDK的更改;在我们的情况下,它只影响大部分SDK。 - ZER0
你说得对。FF即将发生的变化驱动了SDK的变化,进而导致GM的变化。因此,即使GM现在不必立即打破事物(或以这种安装基础瘫痪的方式),变化也将发生。 - Brock Adams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接