我已经完成了我的研究并且在这方面挣扎了一段时间,但我需要你的帮助。
我正在构建Chrome DevTools扩展程序。它应该将当前选中的元素从“Elements”面板作为参考传递给内容脚本中定义的JS对象。
将引用传递给所选元素或从内容脚本中识别元素的其他方式非常重要。
我了解Chrome DevTools中“孤立世界”的工作流程。我也理解扩展页面,后台页面和内容脚本之间的消息传递。这只发生在JSON原语中,因此没有JS范围传递。
如何将devtools Elements面板中选定的元素传递给检查页面中的内容脚本?
修改
这是我目前所知道的:
获取对所选元素的引用:
chrome.devtools.inspectedWindow.eval("(" + function(){ console.log($0) }.toString() + ")()")
该函数表达式将在被检查页面的上下文中运行,而不是在devtools扩展的上下文中运行,而不是在内容脚本的“孤立世界”的上下文中运行。我不相信可以使用闭包传递对不同上下文的引用。
无法返回对所选DOM元素$0
的引用,因为由于循环引用而无法将其序列化为JSON。
在devtools扩展页面之外,chrome.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'Elements'面板中选择的元素?
答案 0 :(得分:9)
chrome.devtools.inspectedWindow
has been updated的API,用于支持在内容脚本的上下文中执行脚本。
官方Chrome API中的此更新废弃了我们上述的黑客攻击。我们现在可以通过以下方式实现预期结果:
chrome.devtools.inspectedWindow.eval("aContentScriptFunction($0)",
{ useContentScriptContext: true });
$0
参数将引用在 Elements 面板中选择的元素。
答案 1 :(得分:2)
我这样做的方式也是一种黑客攻击.. 而不是注入在您的扩展中定义的内容脚本,您可以注入一个脚本标记,指向您的文件在线(或本地,相对于检查的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扩展。