繁体   English   中英

Chrome DevTools扩展:如何从内容脚本中的元素面板中获取所选元素?

[英]Chrome DevTools extension: how to get selected element from elements panel in content script?

我已经完成了我的研究并且在这方面挣扎了一段时间,但我需要你的帮助。

我正在构建Chrome DevTools扩展程序。 它应该从“Elements”面板传递当前选定的元素, 作为对内容脚本中定义的JS对象的引用

重要的是我将引用传递给所选元素,或者从内容脚本中识别元素的其他方式。

我了解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引用不能在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'Elements'面板中选择的元素?

chrome.devtools.inspectedWindow的API 已更新,以支持在内容脚本的上下文中执行脚本。

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

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

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

我这样做也是一种黑客攻击...你可以注入一个脚本标签,而不是注入你的扩展中定义的内容脚本,或者在本地,相对于检查的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扩展。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM