cdeng
cdeng

Reputation: 245

How to get the data of a D3 node in Chrome Extension content script

The D3 example we were using is this: https://bl.ocks.org/mbostock/raw/1341021/

If you copy & paste the following code into console and run, all bounded data will be shown in the console.

var svgs = document.getElementsByTagName("svg");
for (var i = 0; i < svgs.length; i++) {
    var babbies = svgs[i].getElementsByTagName("*");
    for (var j = 0; j < babbies.length; j++) {
        console.log(babbies[j].__data__);
    }
}

Unfortunately, if we use the same code in content script of the Chrome Extension, the data of all nodes (babbies[j].__data__) are showing undefined. We have ran the debugger and the nodes babbies in content script looked great though.

So we did some research on the content scripts and realized that Content scripts are executed in an "isolated world" environment. Due to that reason, content scripts seemed not to be able to read the bounded data of D3 node.

We also tried to inject scripts into the page via this method. However, injected scripts behave as they were included by the page itself, and are not connected to the extension in any way.

We were wondering if there is any way to access bounded data of D3 node in content script or extension code?

Upvotes: 0

Views: 370

Answers (1)

Makyen
Makyen

Reputation: 33316

As you found out, you can not directly access the page script scope (e.g. variables and functions). However, you can communicate with the script which you have injected into the page context through the DOM. Usually, this means using window.postMessage() and window.addEventListener(), but you could also use custom events. If you are wanting to manipulate the data within your content script, you will need to inject a script to the page context and message the data back to your content script.

An example from MDN (while intended for WebExtensions, it works just fine in a Chrome extension) [The code below is copied from that MDN page.]:

page-script.js:

var messenger = document.getElementById("from-page-script");

messenger.addEventListener("click", messageContentScript);

function messageContentScript() {
  window.postMessage({
    direction: "from-page-script",
    message: "Message from the page"
  }, "*");

content-script.js:

window.addEventListener("message", function(event) {
  if (event.source == window &&
      event.data.direction &&
      event.data.direction == "from-page-script") {
    alert("Content script received message: \"" + event.data.message + "\"");
  }
});

This also works in reverse to send messages from your content script to page scripts.

With respect to this method of communicating with the content script, there is nothing special about the page script you injected into the page (other than that you are the author). If you also control the website, code to communicate with your content script could be in the code served with the webpage. I say that you need to be in control of the website because it is unlikely that some random website will know to have code to try to communicate with your content script.

References:

Upvotes: 1

Related Questions