为什么窗口(和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(); 

unsafeWindowreplacewindow时同样的事情。

但是,当我使用这个小技巧时,一切都像一个魅力:

 // 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了冲突和意外的副作用。

但是,每种浏览器的方法都不同

火狐:

  1. 在XPCNativeWrapper沙箱中运行脚本,除非@grant none有效(从GM 1.0开始)。
  2. 在默认情况下将脚本包装在匿名函数中。
  3. 提供unsafeWindow来访问目标页面的javascript。 但是要注意,敌对网站pipe理员有可能unsafeWindow使用情况追溯到脚本的上下文,从而获得更高的权限来提醒您。

铬:

  1. 在“孤立的世界”运行脚本。
  2. 用匿名函数包装脚本。
  3. 严格禁止脚本访问页面的JS,反之亦然。
    Chrome的最新版本现在提供了一个名为unsafeWindow的对象,用于非常有限的兼容性,但是该对象不提供对目标页面JS的任何访问。 它与脚本范围中的window (在页面范围内不是window )相同。

也就是说,如果正确实施,那么使用unsafeWindow的脚本的版本应该可以在Firefox上工作。 它可能在Chrome上使用Tampermonkey扩展 ,但我现在不打算再次检查。

当你这样做的“伎俩”( var script = document.createElement("script"); ... ),你是注入代码到目标页面。 这绕过沙盒,是一个正常的Chrome用户脚本的脚本与页面的JS进行交互的唯一方法。

注射优点:

  1. 非Tampermonkey用户脚本访问目标页面提供的对象或函数的唯一方法。
  2. Chrome,Firefox,Opera等几乎总是完全兼容(IE一如既往)。
  3. 通常更容易debugging整个脚本; 开发者工具正常工作。

注射缺点:

  1. 脚本,至less是注入的部分,不能使用GM_函数提供的增强权限(特别是跨域) – 尤其是GM_xmlhttpRequest()
    请注意,Chrome 目前仅支持GM_addStyleGM_xmlhttpRequestGM_logGM_openInTab
    然而, GM_几乎完全支持GM_函数。

  2. 可能会导致与页面的JS的副作用或冲突。

  3. 使用外部库引入了更多的冲突和时间问题。 这远不如@require那么简单。
    @require ,也从本地拷贝运行外部JS – 加速执行,除了消除对外部服务器的依赖。

  4. 该页面可以查看,使用,更改或阻止脚本。

  5. 需要启用JS。 Firefox Greasemonkey,特别是可以运行在JS被阻塞的页面上。 这可能是臃肿,蹩脚,和/或侵入性页面上的天赐之物。