简体   繁体   中英

How do I send an array from a content script to a popup script

I am trying to send an array of all the links on a page to my chrome extension. I am grabbing the array data with a content script and using messages to send data to the extension, unfortunately upon receipt of a message from the content script the array has incomplete data.

I am using the sendMessage function to inject my content script, this script then gathers the page information (url of page and links on page) and then sends it via message.

This message is then received by the listener in popup.js and then the information is stored in an object, unfortunately however the information is incomplete.

//Manifest.json
{
    "name": "PHD SEO Tools Test",
    "version": "1.0",
    "description": "SEO Tools Browser Extension First Draft",
    "permissions": [
        "tabs", 
        "activeTab",
        "storage"
    ],
    "background": {
        "scripts": ["background.js"],
        "persistent": false
    },
    "browser_action": {
        "default_popup": "popup.html"
    },
      "options_page": "options.html",
    "manifest_version": 2
}
//ContentScript.js
//Store page information in an object
let pageInfo = {
    currentPageURL: window.location.href,
    links: []
}

//Grab all links on the page
links = document.getElementsByTagName("link");
//Grab URL for each link
for (i = 0; i < links.length; i++) {
    //Push url to pageInfo object
    pageInfo.links.push(links[i]);
}

//Send a message containing the pageInfo properties 
chrome.runtime.sendMessage({
    //To add data to the message payload add another property below
    url: pageInfo.currentPageURL, 
    links: pageInfo.links
}, response => {
    console.log(response);
})
//Popup.js
//Variable to store recieved messages
let pageInfo = {
    currentPageURL: '',
    links: []
}

//Variable to store popup UI components
let ui = {
    popup: document.getElementById("main"),
    displayUrlButton: document.getElementById("displayUrlButton"),
    displayUrl: document.getElementById("displayUrl")
}

//Recieve message from background using the following notation:
//request.url
//request.links
chrome.runtime.onMessage.addListener(
    (request, sender, sendResponse) => {
        console.log(request)
        pageInfo.currentPageURL = request.url;
        pageInfo.links = request.links;
        sendResponse({message: "info recieved by popup"});
    }
);

ui.displayUrlButton.addEventListener('click', () => {
    //If ui.displayUrl is empty
    if(ui.displayUrl.childNodes.length < 2) {
        //create a h2 element
        let urlText = document.createElement("h2");
        //set the content of the h2 element
        urlText.innerHTML = "Current page: " + pageInfo.currentPageURL;
        //Add h2 element to page
        ui.displayUrl.appendChild(urlText);
    }
})

function sendMessage() {
//Query tabs for the active tab in the current window
chrome.tabs.query({active: true, currentWindow: true}, tabs => {
    //Execute a script on the active tab
    chrome.tabs.executeScript(tabs[0].id, {file: 'contentScript.js'});
  });
}

Upon calling the sendMessage() function I would expect to see an object with the URL of the page and an array full of links (The whole html element in object form not just the href). However the output I am getting is this:

{url: "https://www.freecodecamp.org/news/", links: Array(8)}
links: Array(8)
0:
__proto__: Object
1: {}
2: {}
3: {}
4: {}
5: {}
6: {}
7: {}
length: 8
__proto__: Array(0)
url: "https://www.freecodecamp.org/news/"
__proto__: Object

As you can see the URL is passed through from the contentScript and array is being passed from contentScript to popup however unfortunately the array is full of empty items.

How can I get the links array to show the actual contents like this:

(8) [link, link, link, link, link, link, link, link]
0: link
...
baseURI: "https://www.freecodecamp.org/news/"
href: "https://cdn.freecodecamp.org/news-assets/prism-1-16-
outerHTML: "<link rel="stylesheet" type="text/css" href="https://cdn.freecodecamp.org/news-assets/prism-1-16-
__proto__: HTMLLinkElement
...
1: link
2: link
3: link
4: link
5: link
6: link
7: link
length: 8
__proto__: Array(0)

Yes, you cannot pass an array from popup to content or versa. The way around it is to simply create a foreach statement for your array and pass it over one at a time.

Popup.js:

 ary.forEach(element => {
      chrome.tabs.sendMessage(tabs[0].id, element);
 });

In your script that you want to receive the array, you simply just rebuild it.

Content.js

 if(request != 'import' || request != 'scan'){
        arr.push(request);
 }

In the case above, I was only creating two "commands". Those two commands were being sent through chrome.tabs.sendMessage(tab[0], <arg>);

As long you specify that if the argument being send does not have any meaning but to be added to the array, you will successfully rebuild your array. The example of what I am talking about is above in content.js .

You can't send DOM elements. Only simple types are supported like strings/numbers and arrays or objects of such types. You can simply send the URL string. Also note, the popup runs only when shown so you may need to switch the direction of messaging - the popup will send a message via chrome.tabs.sendMessage to the content script which will reply in its onMessage.

Courtesy of – wOxxOm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM