为什么 jQuery 不会加载到 Facebook 中?

IT技术 javascript jquery facebook google-chrome-extension google-chrome-devtools
2021-03-02 19:47:23

情况:我正在编写一个适用于任何页面的 chrome 扩展。

问题问题:我无法将 jQuery 加载到 Facebook,我想了解发生了什么。

假设:Facebook 拥有一些超先进的技术,可以以某种方式检测到两者:

  1. 当 jQuery 通过 chrome 扩展加载到一个表面上独立的JSVM 执行上下文中时,Facebook 的 megamind 以某种方式知道这个表面上独立的JSVM 执行上下文,并阻止它。
  2. 该 jQuery 通过 script.src 加载并阻止它 (当我使用通过 HTTPS 提供服务的 Google CDN 而不是方法 2 不起作用但不足以回答的 jQuery CDN 时)。

数据

我怎么知道 jQuery 没有加载?

j在 Chrome 中调出控制台。当我做 :

    > jQuery
    >> ReferenceError : jQuery is not defined.
    > $('body')
    >> Error : Tried to get element "body" but it is not present on the page.

我如何尝试在 facebook 中加载 jQuery?

方法 1(必需但失败)

通过 manifest.json 文件中的以下代码:

"content_scripts"         :   [
                                  {
                                    "matches"   : ["<all_urls>"],
                                    "js"        : [ 
                                                    "javascript/jq/jquery-1.9.1.min.js",                                            
                                                    "javascript/jq/non-standard.js"
                                                  ],
                                    "all_frames": true // (or false, same failure)
                                  } 
                              ]

方法2(有效,但不够)

通过此 SO 答案中描述的方法(将jQuery 加载到控制台),修改为允许正确的协议:

    var jq = document.createElement('script');
    jq.src = "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js";
    document.getElementsByTagName('head')[0].appendChild(jq);
    jQuery.noConflict();

概括

假设 1 似乎不太可能,因为覆盖 Web 浏览器的单独执行上下文将是一个主要的安全漏洞(破坏沙箱),并且不太可能受到制裁。因此,我可能是偏执的并且忽略了显而易见的事情,希望你们中的一个人会看到。

附录(其他相关代码)

所有非标准.js

    $.fn.in_groups_of = function( countPerGroup ) {
        var groups = [], offset = 0, $group;
        while ( ($group = this.slice( offset, (countPerGroup + offset) )).length ) {
            groups.push( $group );
            offset += countPerGroup;
        }
        return groups;
    };

更多manifest.json

"manifest_version"        :   2,
"permissions"             :   [
                                  "http://*/",
                                  "https://*/",
                                  "tabs",
                                  "storage",
                                  "unlimitedStorage"
                              ],
3个回答

Chrome 控制台似乎无权访问内容脚本的执行上下文。

错了,确实如此。你需要看正确的地方:

如何访问 Chromne 扩展的执行环境的动画

之前的截屏显示,Chrome 开发者工具的 Console 选项卡底部有两个下拉框,可用于更改开发者工具控制台的执行环境。
左侧可用于更改框架上下文(顶部框架,因此 iframe,...),右侧可用于更改脚本上下文(页面,内容脚本,...)。

这是我见过的最棒的答案。对于完全回答问题并教会我 5 个新事物的主题动画 gif,它需要被投票 10,000 次。你是怎么做那个gif的?
2021-04-21 19:47:23
@CrisStringfellow 我正在使用 Byzanz。请参阅Ask Ubuntu for my shell script上的这个答案来启动该工具。生成的 GIF 具有合理的质量和大小。例如,看看这个动画它的持续时间为 40 秒,并且只有3.7Mb。
2021-04-24 19:47:23
在 2019 年,DevTools Console 选项栏有所不同。现在只有一个带有嵌套条目的合并的“JavaScript 上下文”下拉列表,它不是按“chrome-extension://[ID]”而是按扩展名列出扩展名。
2021-05-02 19:47:23

答案

看来我的“实验方法”是有缺陷的。关于 Chrome 控制台无所不知的假设是不正确的。Chrome 控制台似乎无权访问内容脚本的执行上下文。因此,尽管控制台报告 jQuery 无权访问该页面,但实际上它确实从内容脚本的执行上下文中访问了该页面。

这是通过向 manifest.json 添加内容脚本 test.js 来验证的:

"content_scripts"         :   [
                                  {
                                    "matches"   : ["<all_urls>"],
                                    "js"        : [
                                                    "javascript/jq/jquery-1.9.1.min.js",
                                                    "javascript/jq/non-standard.js",
                                                    "javascript/test.js" // <-- add
                                                  ],

test.js 的内容是:

    var jtest = $('body');
    alert(jtest);
    alert(jtest.text());

现在无论我导航到哪个页面,两个警告框都会按预期弹出。

有用!

你现在可能知道所有这些,但我认为有人仍然觉得这些很有用。

在 Chrome 扩展程序中,

你有一些“脚本世界”:

  • 原始页面脚本:页面本身的脚本。
  • 内容脚本:您编写这些脚本,然后它们在页面上运行
  • 弹出脚本:如果您有弹出页面,它们会在弹出窗口上运行。
  • 后台脚本:运行在全局后台页面。

Google 在文档方面做得非常出色,因此有大量关于所有这些脚本的文档https://developer.chrome.com/extensions

但就您而言,请注意:页面脚本和内容脚本存在于不同的世界中,它们确实共享 DOM 和一些 Chrome 本机对象,但不共享它们创建的变量(或对象)。

对于这种情况,如果您的内容脚本中有 jQuery,那么您将有 $ 和 jQuery 准备好在您的内容脚本中使用。您可以使用它来查询 DOM(尽管某些 jQuery 事件可能无法按预期工作)。但是在页面上,你不会有 $ 和 jQuery,(你可能有 $,但它不是 jQuery ^^)。

你上面的方法2,它实际上是将jQuery注入到页面中,jQuery将成为页面脚本。并且您不能在内容脚本中使用 $ 或 jQuery。

如果同时使用这两种方法,则可以在页面脚本中使用 jQuery 1,在内容脚本中使用 jQuery 2,它们是 2 个不同的 jQuery 实例。这可能会引起混乱,但我总是这样做。