Search code examples
javascriptgoogle-chrome-extensionmessage-passing

chrome extension communication web page -> content_script -> popup.js


i have a problem when writing chrome extension with communication. A few words about how to work this extension:

is a page (not part of the extension) that generates objects. These objects will be sent to the extension where they are to be listed and displayed to the user in the form: simply list

Ok, to the point. The code looks like this:

manifest.json

"name": "Img_",
"version": "1.0",

"browser_action": {
"default_icon":"icon.png",
"default_popup":"popup.html"
},

"permissions": [
"activeTab", "tabs", "<all_urls>", "http://*/*",
"https://*/*",
"https://www.google.com/*",
"http://www.google.com/*",
"storage"

],

"externally_connectable": {
"matches": ["The address of the external server to which we are connecting"]
},

"content_scripts": [
{
  "matches": ["*://*/*"],
  "js": ["content_script.js"],
  "run_at": "document_start"

}
]

}

web page (not part of the extension)

<body>
<button id="theButton"> klik </button>

 <script>

// Here is the code that will be responsible for generating the 
  // objects to be sent

 document.getElementById("theButton").addEventListener("click",
     function() {
       window.postMessage({ type: "FROM_PAGE", value: {name: "xyx", age: 111}}, "*");
         window.postMessage({ type: "FROM_PAGE", value: {name:"ccv", age: 222}}, "*");

     }, false);
 </script>

content_script:

_Img= {
storage: []
}



window.addEventListener("message", function(event) {


if (event.source != window)
    return;

if (event.data.type && (event.data.type == "FROM_PAGE")) {
    console.log("Connection works!! ");

    __Img.storage.push(event.data.value)
    console.log(event.data.value);
    console.log(_Img.storage) // It shows the values that sent the page without problem

    console.log("we have  "+ _Img.storage.length + " instance") // show 0 

 List= _Img.storage.forEach(function(element) {
      console.log(element);
    return
   }); // List the values that the page sent - works ok



};

}, false);


  console.log(_Img) // This is displayed before clicking on the button - so _Img is obviously empty

It looks like: console

popup.js

$(function () {

demoP = document.getElementById("demo");
result = document.getElementById("app");


const Result = _Img.storage.length;

result.innerText = result.innerText + "Instance -" + Result

const List =_Img.storage.forEach(myFunction)

function myFunction(item) {

    demoP.innerHTML = demoP.innerHTML + item + "<br>";
}


  }); // Here nothing is displayed - for popup.js _Img is still empty

Popup.js has access to _Img (if I manually enter some values into the storage- as in the example below - this list is doing no problem - and looks like this as simple list as shown above)

content.script:

_Img= {
    storage: [{name: "opop", age: 121}, {name:"qwe", age: 333}]
}

window.addEventListener("message", function(event) { Here's the code 
as above - no changes } )

How do popup.js update the _Img state? What should I do to get popup.js to access _Img only after content_script receives the message?

Alternatively, I can change the web page to send all _Img to content_script:

 <script>
 _Img = {
     storage: []
 }


 document.getElementById("theButton").addEventListener("click",
     function() {
        window.postMessage({ type: "FROM_PAGE", value: _Img.storage}, "*");


     }, false);
 </script>

then the content script looks like this:

window.addEventListener("message", function(event) {

    if (event.source != window)
        return;

    if (event.data.type && (event.data.type == "FROM_PAGE")) {
         console.log("we have a connection");

       console.log(event.data.value);
       console.log("we have"+ event.data.value.length + " instance")

      List= event.data.value.forEach(function(element) {
         console.log(element);
        return
       });



  };

}, false);

-but I have no idea how this could help :)


Solution

  • Ok, hurra - problem solved! I looked over Stack Overflow and found it at Pass a variable from content script to popup - @Xan thank you! -thanks to this post I solved my problem

    Just added background and bam! It works the way I wanted to.

    Here's the code - maybe someday someone will help it:

    manifest.json:

    {
     "manifest_version": 2,
    
    
    "name": "Img",
    "version": "1.0",
    
    "browser_action": {
    "default_icon":"icon.png",
    "default_popup":"popup.html"
    },
    
    "permissions": [
    "activeTab", "tabs", "<all_urls>", "http://*/*",
    "https://*/*",
    "https://www.google.com/*",
    "http://www.google.com/*",
    "storage"
    
    ],
    "background": {
    "scripts": ["background.js"],
    "persistent" : false
    
    },
    
    "externally_connectable": {
    "matches": ["The address of the external server to which we are connecting"]
    },
    
     "content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": ["content_script.js"],
      "run_at": "document_start"
    
    }
    ]
    
    }
    

    example.html (is not part of the extension):

    <script>
    
        _Img = {
      storage: [{name: "opop", age: 121}, {name:"qwe", age: 333}]
     }
    
    
    
     document.getElementById("theButton").addEventListener("click",
         function() {
             window.postMessage({ type: "FROM_PAGE", value: _Img.storage}, "*");
    
    
    
    
         }, false);
    

    backkground.js:

    chrome.runtime.onMessage.addListener(
        function(message, sender, sendResponse) {
           switch(message.type) {
               case "setValidator":
                temp = message.validator;
                break;
               case "getValidator":
                sendResponse(temp);
                break;
            default:
                console.error("Unrecognised message: ", message);
        }
    }
    

    );

    content_script.js:

    window.addEventListener("message", function (event) {
    
    if (event.source != window)
        return;
    
    if (event.data.type && (event.data.type == "FROM_PAGE")) {
        console.log("Connection works! ");
        console.log(event.data.value);
        console.log(event.data.value.length + " instancc")
    
        _ImgG= event.data.value;
    
        chrome.runtime.onMessage.addListener(
            function(message, sender, sendResponse) {
                switch(message.type) {
                    case "getValidator":
                        sendResponse(_ImgG);
                        break;
                    default:
                        console.error("Unrecognised message: ", message);
                }
            }
        );
        List = event.data.value.forEach(function (element) {
            console.log(element.name);
            return
        });
    
    }
    ;
    
    }, false);
    

    popup.js:

    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) 
    {
    chrome.tabs.sendMessage(tabs[0].id, {type: "getValidator"}, 
    function(validator) {
        if(typeof validator == "undefined") {
            console.log("error")
            if(chrome.runtime.lastError) {
                console.log("counldn't talk")
            }
        } else {
            console.log (validator)
            result = document.getElementById("app");
            result.innerText = result.innerText + "Instancji: " + validator.length
    
            demoP = document.getElementById("demo");
            const List = validator.forEach(myFunction)
    
            function myFunction(item) {
    
                demoP.innerHTML = demoP.innerHTML + item.name + "<br>";
            }
        }
    });
      });