为什么窗口(和unsafeWindow)从脚本不像从一个<script>标记相同?
我在开发这个小用户脚本时遇到了一个问题。 当我想用我的脚本阻止正在运行的网站的每个XMLHttpRequest
,没有任何事情发生(至less在Chrome中):
function main() { // Override XHR.open with a custom function window.XMLHttpRequest.prototype.open = function() { // Nothing... so it's supposed to block every xhr.open() call } } main();
用unsafeWindow
replacewindow
时同样的事情。
但是,当我使用这个小技巧时,一切都像一个魅力:
// No more call to main(), and: var script = document.createElement("script"); script.textContent = "(" + main.toString() + ")();"; document.body.appendChild(script);
每个调用xhr.open
都被我的自定义函数取代,不再有AJAX。
所以我猜想,当从脚本内部调用main
时, window
元素与从<script></script>
容器调用main
时不一样。 有人能解释我为什么吗?
请参阅“Chrome用户脚本是否与Greasemonkey脚本全局命名空间分离?” 。 Chrome用户脚本/内容脚本和Greasemonkey脚本都与网页的javascript隔离。 这样做是为了防止被黑客入侵,同时也减less了冲突和意外的副作用。
但是,每种浏览器的方法都不同
火狐:
- 在XPCNativeWrapper沙箱中运行脚本,除非
@grant none
有效(从GM 1.0开始)。 - 在默认情况下将脚本包装在匿名函数中。
- 提供
unsafeWindow
来访问目标页面的javascript。 但是要注意,敌对网站pipe理员有可能将unsafeWindow
使用情况追溯到脚本的上下文,从而获得更高的权限来提醒您。
铬:
- 在“孤立的世界”运行脚本。
- 用匿名函数包装脚本。
- 严格禁止脚本访问页面的JS,反之亦然。
Chrome的最新版本现在提供了一个名为unsafeWindow
的对象,用于非常有限的兼容性,但是该对象不提供对目标页面JS的任何访问。 它与脚本范围中的window
(在页面范围内不是window
)相同。
也就是说,如果正确实施,那么使用unsafeWindow
的脚本的版本应该可以在Firefox上工作。 它可能在Chrome上使用Tampermonkey扩展 ,但我现在不打算再次检查。
当你这样做的“伎俩”( var script = document.createElement("script"); ...
),你是注入代码到目标页面。 这绕过沙盒,是一个正常的Chrome用户脚本的脚本与页面的JS进行交互的唯一方法。
注射优点:
- 非Tampermonkey用户脚本访问目标页面提供的对象或函数的唯一方法。
- Chrome,Firefox,Opera等几乎总是完全兼容(IE一如既往)。
- 通常更容易debugging整个脚本; 开发者工具正常工作。
注射缺点:
-
脚本,至less是注入的部分,不能使用
GM_
函数提供的增强权限(特别是跨域) – 尤其是GM_xmlhttpRequest()
。
请注意,Chrome 目前仅支持GM_addStyle
,GM_xmlhttpRequest
,GM_log
和GM_openInTab
。
然而,GM_
几乎完全支持GM_
函数。 -
可能会导致与页面的JS的副作用或冲突。
-
使用外部库引入了更多的冲突和时间问题。 这远不如
@require
那么简单。
@require
,也从本地拷贝运行外部JS – 加速执行,除了消除对外部服务器的依赖。 -
该页面可以查看,使用,更改或阻止脚本。
-
需要启用JS。 Firefox Greasemonkey,特别是可以运行在JS被阻塞的页面上。 这可能是臃肿,蹩脚,和/或侵入性页面上的天赐之物。