为什么jQuery不会加载到Facebook?

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

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

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

  1. 当jQuery通过chrome扩展在一个表面上独立的 JSVM执行上下文中加载时,Facebook megamind以某种方式知道这个表面上独立的 JSVM执行上下文,并阻止它。
  2. jQuery是通过script.src加载并阻止的 (当我使用通过HTTPS服务的谷歌CDN而不是方法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?

方法1(必需但失败)

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

 "content_scripts" : [ { "matches" : [""], "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浏览器的单独执行上下文将是一个主要的安全漏洞(打破沙箱),并且不太可能被制裁。 因此,我可能是偏执狂,忽视了明显的,希望你们中的一个人会看到。

附录(其他相关代码)

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

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

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

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

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

答案

看来我的“实验方法”存在缺陷。 有关Chrome控制台无所不知的假设是错误的。 Chrome控制台似乎无法访问内容脚本的执行上下文。 因此虽然控制台报告说jQuery无法访问该页面,但它实际上是从内容脚本的执行上下文中获得的。

通过向manifest.json添加内容脚本test.js来validation这一点:

 "content_scripts" : [ { "matches" : [""], "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实例。 这可能会造成混乱,但我一直这样做。