Chrome DevTools extension: how to get the selected item from the toolbox in the content script?

I did my research and struggled with it for a while, but I need your help.

I am creating a Chrome DevTools extension. It should pass the currently selected item from the Elements panel as a reference to the JS object defined in the script content.

It is important that I pass the link to the selected element or another way to identify the element from the contents of the script.

I understand the workflow with "isolated worlds" in Chrome DevTools. I also understand the messaging between extension pages, background page, and content scripts. This only happens with JSON primitives, therefore, the JS transfer fails.

How to transfer the element selected on the devtools Elements toolbar to the content script that is on the checked page?

Edit

Here is what I know so far:

Getting a link to the selected item:

chrome.devtools.inspectedWindow.eval("(" + function(){ console.log($0) }.toString() + ")()") 
  • This function expression will be executed in the context of the page being checked, and not in the context of the devtools extension, and not in the context of an "isolated world" of script content. I do not believe that you can pass a link to another context using closure.

  • The reference to the selected DOM element $0 cannot be returned, because it cannot be serialized in JSON due to circular references.

  • The chrome.devtools namespace is not available outside the devtools extension page. Reference $0 cannot be used outside the evaluated expression in chrome.devtools.inspectedWindow

Bypass

As a workaround, I decided to use a common DOM to mark the selected item with a data attribute and use it to reselect in the context of the script content. Messages are used to pass a data attribute marker.

Here is a simplified version of the code:

On the devtools extension page:

 // 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 contents of the 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 +']') }) 

This is not a clean solution, but I can use it for my needs.

Is there an easier way to achieve the same result - to identify from the contents of the script element selected in the panel "Elements" devtools?

+8
javascript google-chrome-devtools google-chrome-extension
source share
2 answers

The API for chrome.devtools.inspectedWindow updated to support scripting in the context of script content.

This update in the official Chrome API now describes our hacks as described above. Now we can achieve the expected result with:

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

The $0 parameter will refer to the item selected in the Elements panel.

+6
source share

My way of doing it is also kind of like a hack. instead of embedding the script content defined in your extension, you can enter a script tag that points to your files online (or locally, relative to the verified 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 global:

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

and devtools can call it and pass it the selected item:

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

however, I did not find a way to send the link back from the checked window to the devtools extension with this setting.

+2
source share

All Articles