【问题标题】:Why will jQuery not load in Facebook?为什么 jQuery 不会在 Facebook 中加载?
【发布时间】:2013-02-18 03:16:13
【问题描述】:

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

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

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

  1. 当通过 chrome 扩展加载 jQuery 时 表面上 独立 JSVM 执行上下文,Facebook megamind 不知何故知道这个表面上单独的JSVM执行 上下文,并阻止它。
  2. jQuery 通过 script.src 加载并阻止它 (当我使用通过 HTTPS 而不是 没有方法 2 的 jQuery 之一,,但不足以 回答)。

数据

我怎么知道 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?

方法一(需要但失败)

通过 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 答案 (load jQuery into console) 中描述的方法,修改为允许正确的协议:

    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 浏览器的单独执行上下文将是一个重大的安全漏洞(破坏该沙盒),并且不太可能受到制裁。因此,我可能是偏执狂并忽略了显而易见的事情,希望你们中的一个人会看到。

附录(其他相关代码)

所有non-standard.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"
                              ],

【问题讨论】:

  • 所以您的扩展程序可以在 Facebook 以外的任何其他网站上运行?
  • @SimonBoudrias 好问题。其实没有。我只检查了 Stackoverflow(但似乎他们加载了自己的 jQuery,所以我得到了误报)。我的扩展程序也不适用于 Google。好点子!也许我需要更改问题的标题,尽管现在这可能太分散注意力了。
  • 他们实现的那个小 $ 函数很有趣,它只是假装它做了什么,但实际上它只是一个欺骗性的错误消息。据推测,他们正试图吸引大量试图挖掘 Facebook 胆量的人。
  • 好吧,这与 Facebook megamind 或任何东西无关。只是您没有正确加载脚本。此外,请确保通过调用noConflict 来防止与其他 jquery 实例发生冲突。顺便说一句,我不确定内容脚本是如何工作的,但可能值得尝试只使用一个串联脚本。
  • @SimonBoudrias 您是否认为控制台的执行上下文与注入的内容脚本的执行上下文不同?

标签: javascript jquery facebook google-chrome-extension google-chrome-devtools


【解决方案1】:

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

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

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

【讨论】:

  • 这是我见过的最棒的答案。主题动画 gif 需要 10,000 次投票才能完全回答问题并教会了我 5 个新事物。你是怎么做这个 gif 的?
  • @CrisStringfellow 我正在使用 Byzanz。请参阅 this answer on Ask Ubuntu 了解我的启动该工具的 shell 脚本。生成的 GIF 具有合理的质量和大小。例如,看看this animation。它的持续时间为 40 秒,只有 3.7Mb。
  • 2019 年,DevTools 控制台选项栏有所不同。现在只有一个合并的“JavaScript 上下文”下拉列表,其中包含嵌套条目,它不是按“chrome-extension://[ID]”而是按扩展名列出扩展名。
【解决方案2】:

答案

看来我的“实验方法”有缺陷。关于 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());

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

有效!

【讨论】:

    【解决方案3】:

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

    在 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 实例。这可能会引起混乱,但我总是这样做。

    【讨论】:

      猜你喜欢
      • 2021-08-24
      • 1970-01-01
      • 2011-09-26
      • 2017-01-27
      • 2015-01-28
      • 2020-12-10
      • 1970-01-01
      • 1970-01-01
      • 2016-12-14
      相关资源
      最近更新 更多