https://wiki.greasespot.net/Greasemonkey_Manual :API
Greasemonkey API 通常是特权操作,并且通常都是同步操作。 内容脚本(几乎)没有 API 访问权限,因此必须传递消息才能执行特权操作。 Web扩展只能得到一个同步消息传递(引文需要)。
因此,每种方法都有其自身的挑战。
更轻松:
GM_getResourceURL
必须同步产生一个结果,但计算起来很简单。GM_addStyle
是微不足道的。GM_log
可能应该退休,或者只是映射到console.log
。GM_openInTab
功能上不会产生任何结果,即使排序也不重要。GM_registerMenuCommand
没有同步行为。GM_setClipboard
不会产生任何结果。GM_xmlhttpRequest
是完全异步的。更难:
GM_deleteValue
不会产生任何结果。 排序仍然很重要(即 X 的删除必须在任何未来的 X 集合之前发生)。GM_setValue
相当于删除。 没有同步结果,但排序很重要。很难:
GM_getValue
必须同步产生一个结果。GM_listValues
必须同步产生结果。 (加上 AFAICT存储没有提供良好的支持 API。唯一的选择是按名称获取一个值,或获取所有名称和值。甚至无法通过脚本进行隔离。)GM_getResourceText
必须同步产生一个结果,它们可能是非常大的值。 (即将它们全部预缓存在内存中可能太昂贵了。)bug1323433和bug1332273可能在这里感兴趣。
感谢您的指点,我同意这些都非常有用。
哦,也许一些同步消息传递是可能的!
测试这个。 这是否可以为上面调用的那些方法使用简单的同步实现(由仅后台 API 支持)?
这会在内容方面返回一个承诺,因此它实际上是异步的。 我认为“同步”在这里用词不当,它更像是将一条消息从子级到父级与响应配对,这样就不必手动跟踪待处理的响应。
Afaik 唯一可用的同步 API 是同步 XHR,然后可以用 webrequest 或类似的东西拦截。
同步 XHR 在内容脚本中无法正常工作:https://bugzilla.mozilla.org/show_bug.cgi?id=1360968,所以目前我们没有任何来自内容 > 后台的同步通道。
看起来GM_setValue
和GM_getValue
被设计为同步操作,在单进程浏览器中,当我们在多个选项卡中操作时它们工作得很好,但在 e10s 中没有(https://github.com/greasemonkey /greasemonkey/issues/2427)。 使用旧的扩展 API 可以很容易地修复它,但在 WebExt 中则不行。 如果没有同步消息(即使对于小数据,也只会发出短值),我们无法在更多选项卡之间正确同步值。 在某些时候,这将永远是一个竞争条件。
无论您如何在 WebExt 版本中解决上述问题,我们都应该获得以异步方式设计的新 set/get 方法,因此我们可以以异步方式编写脚本。 文档应该有一些关于在多个选项卡上操作时缺少GM_setValue
和GM_getValue
行为的信息。
imo,在多个选项卡上使用GM_setValue
/ GM_getValue
并且必须遵循顺序的用例很少见。 因此,在内容脚本中存储 _GM_values_ 的副本(缓存)、始终从缓存中读取、异步写回以及使用后台脚本触发的事件更新缓存应该是可接受的解决方案。
顺便说一句,如果是这样,如果可能的话,添加一个相当于GM_addValueChangeListener
的 API 是很好的。 (而且我不喜欢addValueChangeListener
这个名字,其他东西应该更好也许
在我的Dev分支有支持:
GM.getResourceURL
GM.deleteValue
, GM.getValue
, GM.listValues
, GM.setValue
我计划永远不添加:
GM_log
GM_addStyle
我们仍然需要:
GM_xmlhttpRequest
我计划推迟(或可能放弃):
GM_registerMenuCommand
(这个一直是一个巨大的支持成本)GM_getResourceText
这意味着这里的进展实际上非常接近。
对上述提交的良好反馈,不要忘记。
我只是尝试一下新的附加组件。 似乎在没有 GM_xhr 功能的情况下已经启用了跨域 xhr 请求。 这确实是行为吗?
只需尝试使用以下代码授予无用户脚本:
fetch(prompt()).then(resp => resp.text()).then(text => alert(text)).catch(error => alert(error));
嗯,确认了。 我们目前正在将用户脚本作为扩展的“内容脚本”执行,具有扩展的所有权限。
我已经对此进行了一些研究,但到目前为止,我对如何执行非特权(“网络范围”——现在我们称之为“内容”范围不明确?!)代码一无所知。 我能找到的最接近的就是创建脚本标签,它可以/将被页面的 CSP 阻止,我绝对不想要。
目前修改 CSP 的唯一方法是拦截和修改每个 Document 请求的标头。 从内容 CSP 中豁免 Web 扩展存在一些未解决的问题,但似乎没有太多活动。
我认为除了注入<script>
标签window.eval
还应该在页面范围内运行。
官方术语是“内容脚本范围”与“页面范围”。
另一个问题是他们需要字符串处理来将它们包装在可以定义 GM API 的单独范围中。
我还在 webextensions 中为Sandbox
等价物提交了一个错误,但它也不是高优先级。
AIUI script 和 eval 都容易被 CSP 阻塞。 但我已经确认 eval 会放弃特权。
https://bugzilla.mozilla.org/show_bug.cgi?id=1391669
如果我们要在任何页面上运行内容脚本,我们必须有<all_urls>
。 如果我们要求这样做,那么我们的内容脚本就会得到它,因此可以 XHR 到任何地方。
至少在 Firefox 中( https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#Using_eval ()_in_content_scripts )我们可以下拉到页面范围,但是我们是真正的页面范围,我们如果不将其暴露给页面中运行的任何东西/所有东西(AFAIK),就无法安全地将 API 暴露给脚本,这更糟糕。
可以在内容脚本中覆盖 fetch 和 xhr 吗?
也许提供一个修改后的 fetch 来进行自己的 CORS 检查。
GM.xmlhttpRequest()
被添加到 60a50d05b1e565571d8a3e638b0683a1a9c2beaaGM.getResourceText()
将在 #2548 中介绍GM.registerMenuCommand()
被故意跳过。@the8472在https://github.com/greasemonkey/greasemonkey/issues/2232#issuecomment -326841025 中查看我对withUnsafeWindow()
的实现
它模仿了旧的with (object) ...
函数的行为,只是更安全一些。 (需要现代浏览器。)
@arantius在 7 月 25 日写道:
我计划永远不添加:
GM_log GM_addStyle
这些在创建此票证时(由@arantius于 3 月 3 日)表示为微不足道的(假设 GM_log 到 console.log 的映射)。
根据我的经验,这是两个最常用的 API 调用。 放弃它们不会无缘无故地破坏很多旧脚本吗? 还是您专门指的是开发分支?
在 Tampermonkey 中, GM_addStyle
具有注入样式的特殊能力,可以绕过 CSP 限制(以防内联<style>
被禁止)。 如果我们也能在 Greasemonkey 中拥有这个功能,我会很高兴。
最有用的评论
在 Tampermonkey 中,
GM_addStyle
具有注入样式的特殊能力,可以绕过 CSP 限制(以防内联<style>
被禁止)。 如果我们也能在 Greasemonkey 中拥有这个功能,我会很高兴。