【问题标题】:Chrome DevTools extension: how to get selected element from elements panel in content script?Chrome DevTools 扩展:如何从内容脚本的元素面板中获取选定的元素?
【发布时间】:2013-06-20 12:54:29
【问题描述】:

我已经完成了我的研究并为此苦苦挣扎了一段时间,但我需要你的帮助。

我正在构建一个 Chrome DevTools 扩展。它应该将当前选择的元素从“元素”面板作为参考传递给内容脚本中定义的 JS 对象。

我将 reference 传递给所选元素,或者通过其他方式从内容脚本中识别元素,这一点很重要。

我了解 Chrome DevTools 中“孤立世界”的工作流程。我还了解扩展页面、背景页面和内容脚本之间的消息传递。这只发生在 JSON 原语中,因此没有 JS 范围传递。

如何将在 devtools Elements 面板中选择的元素传递给检查页面中的内容脚本?

编辑

这是我目前所知道的:

获取对选定元素的引用:

chrome.devtools.inspectedWindow.eval("(" + function(){ console.log($0) }.toString() + ")()")
  • 该函数表达式将在被检查页面的上下文中运行,而不是在 devtools 扩展的上下文中,也不在内容脚本的“孤立世界”的上下文中。我不相信可以使用闭包传递对不同上下文的引用。

  • 无法返回对所选DOM元素$0的引用,因为循环引用无法序列化为JSON。

  • chrome.devtools 命名空间在 devtools 扩展页面之外不可用。 $0 引用不能在chrome.devtools.inspectedWindow 中的评估表达式之外使用

解决方法

作为一种解决方法,我选择使用共享 DOM 来使用数据属性标记所选元素,并使用它在内容脚本的上下文中重新选择它。消息用于传递数据属性标记。

这是代码的简化版本:

devtools 扩展页面中:

// setup a communication port
port = chrome.runtime.connect({name: "devtools"});

chrome.devtools.panels.elements.onSelectionChanged.addListener(function(){

  // expression to run in the context of the inspected page
  var expression = "(" + mark.toString() + ")()"

  // evaluate the expression and handle the result
  chrome.devtools.inspectedWindow.eval(expression, dispatchToContentScript)
});


function mark(){

  // mark the currently selected element
  $0.setAttribute('data-selected')

  // send the marker to the callback
  return { marker: 'data-selected' }
}

function dispatchToContentScript(data){

  // dispatch data to the content script which is listening to the same port.
  port.postMessage(data)
}

内容脚本中:

var port = chrome.runtime.connect({name: "devtools"});

port.onMessage.addListener(function(data) {

  // re-select the element in the context of the content script
  var el = document.querySelector('['+ data.marker +']')
})

这不是一个干净的解决方案,但我可以根据需要使用它。

是否有更简单的方法来实现相同的结果 - 从内容脚本中识别在 devtools 的“元素”面板中选择的元素?

【问题讨论】:

  • 您能否编辑您的问题以包含用于获取对当前选定元素的引用的代码和/或应该获取引用的代码?这将使您更容易理解您想要实现的目标。
  • 我已编辑我的问题以回答您的问题并分享解决方法。
  • 我建议发布解决方法作为答案。我可以想到另一种解决方案,但这是一个太大的锤子,特别是因为您已经找到了合理的解决方法。
  • 请给我一个关于您的解决方案的提示。我尝试了许多其他方法,但都失败了。

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


【解决方案1】:

chrome.devtools.inspectedWindowhas been updated 的 API 支持在内容脚本的上下文中执行脚本。

官方 Chrome API 中的此更新淘汰了我们上述的黑客攻击。我们现在可以通过以下方式实现预期结果:

chrome.devtools.inspectedWindow.eval("aContentScriptFunction($0)", 
    { useContentScriptContext: true });

$0 参数将引用在 Elements 面板中选择的元素。

【讨论】:

  • 只有当我删除{ useContentScriptContext: true }时它才对我有效
【解决方案2】:

我的做法也是一种 hack。 您可以在线(或本地,相对于检查的 html )注入指向您的文件的脚本标签,而不是注入在您的扩展中定义的内容脚本:

//devtools.js
var str = "var s = document.createElement('script');" +
      "s.src = 'http://extentionDomain/extentionFile.js';" +
      "document.body.appendChild(s);";
chrome.devtools.inspectedWindow.eval(str);

在线文件定义了一个全局:

var myExtention = { doStuff: function(selectedElement){ ..}}

devtools 可以调用它并将所选元素传递给它:

chrome.devtools.panels.elements.onSelectionChanged.addListener(function(){
    chrome.devtools.inspectedWindow.eval('myExtention.doStuff($0)');});

但是,我还没有找到一种方法可以使用此设置将参考从检查的窗口发送回 devtools 扩展。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2023-04-06
    • 2012-06-18
    相关资源
    最近更新 更多