[英]Chrome DevTools extension: how to get selected element from elements panel in content script?
I've done my research and struggled with this for a while, but I need your help. 我已经完成了我的研究并且在这方面挣扎了一段时间,但我需要你的帮助。
I'm building a Chrome DevTools extension. 我正在构建Chrome DevTools扩展程序。 It should should pass the currently selected element from the 'Elements' panel as a reference to a JS object defined in a content script. 它应该从“Elements”面板传递当前选定的元素, 作为对内容脚本中定义的JS对象的引用 。
It is important that I pass the reference to the selected element, or some other way of identifying the element from the content script. 重要的是我将引用传递给所选元素,或者从内容脚本中识别元素的其他方式。
I understand the workflow with 'isolated worlds' in Chrome DevTools. 我了解Chrome DevTools中“孤立世界”的工作流程。 I also understand messaging between extension pages, background page and content scripts. 我也理解扩展页面,后台页面和内容脚本之间的消息传递。 This only happens with JSON primitives, hence no JS scope passing. 这只发生在JSON原语中,因此没有JS范围传递。
How can I pass the element selected in devtools Elements panel to the content script that lives in the inspected page? 如何将devtools Elements面板中选定的元素传递给检查页面中的内容脚本?
Edit 编辑
Here's what I know so far: 这是我目前所知道的:
Getting a reference to the selected element: 获取对所选元素的引用:
chrome.devtools.inspectedWindow.eval("(" + function(){ console.log($0) }.toString() + ")()")
That function expression will run in the context of the inspected page, not in the context of the devtools extension and not in the context of the 'isolated world' of the content script. 该函数表达式将在被检查页面的上下文中运行,而不是在devtools扩展的上下文中运行,而不是在内容脚本的“孤立世界”的上下文中运行。 I don't believe it is possible to pass in a reference to a different context using closures. 我不相信可以使用闭包传递对不同上下文的引用。
The reference to the selected DOM element $0
can't be returned because it can't be serialized to JSON due to circular references. 无法返回对所选DOM元素$0
的引用,因为由于循环引用而无法将其序列化为JSON。
The chrome.devtools
namespace isn't available outside the devtools extension page. chrome.devtools
命名空间在devtools扩展页面之外不可用。 The $0
reference can't be used outside the evaluated expression in chrome.devtools.inspectedWindow
$0
chrome.devtools.inspectedWindow
引用不能在chrome.devtools.inspectedWindow
的计算表达式之外使用
Workaround 解决方法
As a workaround, I chose to use the shared DOM to mark the selected element with a data attribute and use that to re-select it in the context of the content script. 作为一种解决方法,我选择使用共享DOM来使用数据属性标记所选元素,并使用它在内容脚本的上下文中重新选择它。 Messaging is used to pass the data attribute marker around. 消息传递用于传递数据属性标记。
Here's a simplified version of the code: 这是代码的简化版本:
In the devtools extension page: 在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)
}
In the content script : 在内容脚本中 :
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 +']')
})
It's not a clean solution but I can use it for my needs. 这不是一个干净的解决方案,但我可以根据我的需要使用它。
Is there a simpler way to achieve the same result - identify from a content script the element selected in the devtools 'Elements' panel? 有没有更简单的方法来实现相同的结果 - 从内容脚本中识别在devtools'Elements'面板中选择的元素?
The API for chrome.devtools.inspectedWindow
has been updated to support executing scripts in the context of the content script. chrome.devtools.inspectedWindow
的API 已更新,以支持在内容脚本的上下文中执行脚本。
This update in the official Chrome API obsoletes our hacks described above. 官方Chrome API中的此更新废弃了我们上面描述的黑客攻击。 We can now achieve the expected result with: 我们现在可以通过以下方式实现预期结果
chrome.devtools.inspectedWindow.eval("aContentScriptFunction($0)",
{ useContentScriptContext: true });
The $0
parameter will reference the element selected in the Elements panel. $0
参数将引用在“ 元素”面板中选择的元素 。
my way of doing it is sort of a hack too.. instead of injecting a content script defined in your extention you can inject a script tag pointing to your files online (or locally, relative to inspected html ): 我这样做也是一种黑客攻击...你可以注入一个脚本标签,而不是注入你的扩展中定义的内容脚本,或者在本地,相对于检查的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);
online file defines a global: 在线文件定义全局:
var myExtention = { doStuff: function(selectedElement){ ..}}
and devtools can call it and pass it the selected element: 和devtools可以调用它并将选中的元素传递给它:
chrome.devtools.panels.elements.onSelectionChanged.addListener(function(){
chrome.devtools.inspectedWindow.eval('myExtention.doStuff($0)');});
however i have not found a way to send a reference back from the inspected window to the devtools extention with this setup. 但是,我没有找到一种方法,通过此设置将检查窗口中的引用发送回devtools扩展。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.