简体   繁体   English

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

[英]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.

相关问题 Chrome扩展程序,如何从面板向内容脚本发送消息 - Chrome extension, how to send message from panel to content script 在自定义Chrome开发者工具面板和Chrome扩展程序内容脚本之间直接通信 - Communicate directly between custom Chrome devtools panel and Chrome Extension content script Chrome DevTools 和扩展中的内容脚本之间的通信 - Communicating between Chrome DevTools and content script in extension 如何从 chrome 扩展中的内容脚本中获取另一个文件内容 - How to get another file content from content script in chrome extension 在使用 manifest v3 的浏览器扩展中,如何在内容脚本和开发工具面板之间进行通信? - In a browser extension using manifest v3, how can I communicate between a content script and a devtools panel? Chrome DevTools会在元素面板中收听多个相同元素的选择 - Chrome DevTools listen to multiple selections of the same element in the elements panel 如何从扩展程序中获取Chrome DevTools源编辑器中的光标位置? - How to get cursor position in a Chrome DevTools source editor from extension? 如何将 chrome 扩展中的选定文本从后台脚本传递到内容脚本? - how do i pass selected text in chrome extension from background script to content script? chrome扩展内容脚本无法按类获取元素 - chrome extension content script cant get element by class 无法将消息从内容脚本发送到devtools面板 - Can't send message from content script to devtools panel
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM