为什么jQuery不会加载到Facebook?

时间:2013-03-04 04:44:43

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

情况:我正在撰写适用于任何网页的Chrome扩展程序。

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

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

  1. 当jQuery通过chrome扩展加载时 表面上分开 JSVM执行上下文,Facebook megamind 以某种方式知道这个表面上单独的 JSVM执行 上下文,并阻止它。
  2. jQuery是通过script.src加载并阻止它 (当我使用通过HTTPS服务的Google CDN而不是 jQuery一个没有方法2的工作,但是还不够 回答)。
  3. DATA

    我怎么知道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答案(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"
                                  ],
    

3 个答案:

答案 0 :(得分:45)

  

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

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

Animation of how-to get access to the execution environment of the Chromne extension

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

答案 1 :(得分: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());

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

有效!

答案 2 :(得分:0)

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

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