javascript - 如何在选项卡的主窗口对象上定义属性?

标签 javascript google-chrome-extension scope defineproperty

我正在尝试使用 setter 中的代码从内容脚本定义 window 对象上的属性 jQuery。这样,当定义了实际的 jQuery 对象时,我可以立即使用它。不过,我似乎无法做到正确。

目标网站是 Outlook.com。这是 Outlook 的网络邮件版本。

我试图将代码直接放在内容脚本中,但即使我将 "all_frames": true 放在 list 的 content_scripts 部分(所以代码被注入(inject)每一帧),它不起作用。

function afterInit(){
  var _jQuery;
  console.log('This gets logged');
  Object.defineProperty(window, 'jQuery', {
    get: function() { return _jQuery; },
    set: function(newValue) {
      _jQuery = $ = newValue;

      console.log('This is never logged!');

      $(document.body).append($('<span>I want to use jQuery here</span>'));
    }
  });
}
afterInit();

我验证了 window.jQuery 之后由实际的 jQuery 函数/对象正确定义,但我的 setter 代码从未执行过。
我还通过消息传递尝试了它:我将带有代码的消息作为字符串发送到后台脚本,并使用 executeScript 在正确的选项卡上执行它,但这也不起作用。

chrome.runtime.sendMessage(
    {action:'jQueryPreInit', value: '('+afterInit.toString()+')();'});

在我的后台脚本中:

chrome.runtime.onMessage.addListener(function(message, sender, callback) {
  switch (message.action){
    case "jQueryPreInit": chrome.tabs.executeScript(sender.tab.id, {code: message.value});
  }
});

如果我在 executeScript 代码中放置 Object.defineProperty 代码之外的其他代码,则可以正常工作。我只是在定义属性时遇到问题。

最佳答案

(引自评论)

I want to use the jQuery provided by the page itself. I could try inserting the same jQuery file as Outlook does and hope it gets loaded from cache, but I'd rather just keep my extension as clean as possible, and use what is already available.

您优化扩展的尝试不可行/不推荐。

首先,由于 the isolation between content script and webpage code ,您将无法使用该页面的代码。您无法获得对页面自己的 jQuery/$ 的引用。

但让我们暂时假设您可以。然后该站点将 jQuery 更新到另一个版本,重命名 jQuery 对象或完全停止使用它,这是您无法控制的。结果:您的分机坏了。这首先是隔离背后的部分原因。

作为上下文隔离的结果,您可以保证您的 jQuery 副本与站点上运行的任何内容之间没有冲突。所以您无需担心:使用您的副本,并使用标准的 $ 访问它。

将 <100 KB 的文件与您的扩展捆绑在一起作为一次性下载,确保代码在 100% 的时间内可用,并且在最坏的情况下磁盘访问延迟不会降低它的“干净度”,恰恰相反。这是一种常见的做法,并且是 enshrined in the docs


查看您的实际代码,它在内容脚本上下文中执行(无论是通过 manifest 还是 executeScript ),而不是在页面上下文中。因此,无论页面做什么,都不会在那里定义 $

I verified that window.jQuery is properly defined afterwards by the actual jQuery function/object [...]

我假设您尝试在控制台中执行 window.jQuery;默认情况下,executes it in the page context, not in your content script context(因此,不反射(reflect)内容脚本上下文的状态并且不调用您的 getter/setter)。如果您想测试您的内容脚本,您需要将控制台上方上下文下拉列表中的 top 更改为您的扩展程序的上下文。


尽管如此,

When all is said and done, I want to use jQuery's ajaxSuccess function to execute code every time an e-mail is opened in the read pane.

这里我们遇到了一个问题。由于内容脚本代码和网页代码是隔离的,您的代码永远不会知道在页面副本中执行的 AJAX(无论如何都不会通过 ajaxSuccess)。

可能的行动方案:

  1. 依靠其他方法来检测您想要的事件。也许 monitoring the DOM
  2. 注入(inject)一些代码into the page itself;这样做的唯一方法是从内容脚本中将 <script> 标记注入(inject)页面。在那里,您可以访问该页面的 jQuery 副本,在发生某些事情时附加您的监听器和 message your content script
  3. 依靠后台页面来检测您需要使用 webRequest API 的事件。这可能会拦截 AJAX 调用,但不会给您回复内容。

最后说明:这可能不像 AJAX 调用那么简单;也许该页面维护一个 WebSocket 连接以获取实时推送更新。 Tapping into this 比较棘手。

关于javascript - 如何在选项卡的主窗口对象上定义属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37318513/

相关文章:

javascript - 从 JS 中的 'success' block 返回值(Azure 移动服务)

javascript - WinJS 内联绑定(bind)语法

javascript - 检查是否所有值都是字段

javascript - Chrome 扩展 : Cant appendchild in my popup file

ios - 带有常量和作用域的 Swift 可选绑定(bind)

在 onclick 属性内部使用时,JavaScript 函数不起作用

javascript - 使用 Bootstrap 清除文本的按钮

javascript - Rails form_tag 与嵌套资源嵌套

javascript - Chrome 扩展中的 TreeWalker

javascript - (Chrome 扩展) 如何测试 onUpdateAvailable