16

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

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

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

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

数据

我怎么知道 jQuery 没有加载?

一世⌘</kbd>⌥</kbd>j to bring up the console in Chrome. When I do :

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

附录(其他相关代码)

所有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"
                              ],
4

3 回答 3

45

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

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

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

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

于 2013-03-04T09:11:33.873 回答
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());

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

有用!

于 2013-03-04T05:15:48.103 回答
0

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

在 Chrome 扩展程序中,

你有一些“脚本世界”:

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

谷歌在文档方面做得很好,所以关于所有这些脚本的大量文档https://developer.chrome.com/extensions

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

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

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

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

于 2016-05-21T03:15:20.260 回答