2

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 :)

agro
  • 57
  • 12
  • Please [edit] the question to be on-topic: include a [mcve] that *duplicates the problem*. For Chrome extensions or Firefox WebExtensions you almost always need to include your *manifest.json* and some of the background, content, and/or popup scripts/HTML, and often webpage HTML/scripts. Questions seeking debugging help ("why isn't my code working the way I want?") must include: (1) the desired behavior, (2) a specific problem or error and (3) the shortest code necessary to reproduce it *in the question itself*. Please also see: [What topics can I ask about here?](/help/on-topic), and [ask]. – Makyen Sep 26 '17 at 01:16
  • I suggest you read the [Chrome extension overview](https://developer.chrome.com/extensions/overview) (perhaps along with the pages linked from the overview). The [architecture section](https://developer.chrome.com/extensions/overview#arch) has overall architecture information which should help your understanding of how things are generally organized/done. You should also read [Content Scripts](https://developer.chrome.com/extensions/content_scripts). – Makyen Sep 26 '17 at 01:21
  • Why do you think your popup has access to `_Img`? You haven't shown us how you define it in the popup, so it's not clear why you think it should have access. – Makyen Sep 26 '17 at 01:24
  • @Makyen I think the popup has access to _Img - because if instead of: _Img = { storage = [] } I will try to write: _Img = {    storage = [1,2,3,4,5] } Then it's such a simple list like the one I put up in the picture. – agro Sep 26 '17 at 04:51
  • The content script(s) for each webpage/tab exist(s) in it's/their own context, separate from any other parts of your extension (including content scripts in other tabs, and specifically your popup). It's *not possible* for your content script & popup to *directly* share an Object, or any data. You can [pass messages](//developer.chrome.com/extensions/messaging), use `chrome.storage`, set cookies (rare, but sometimes how you need to do it, e.g. if the data must be obtained in the content script synchronously at `document-start`) or use some method of communication outside of the extension. – Makyen Sep 26 '17 at 05:15
  • @Makyen Can you help me with this? I have no idea how to do this. Should this should look like this: _Img = {   storage = [] }   chrome.storage.sync.set ({'value': _Img}, function () {               message ('Settings saved'); }) And here's the rest of the content script: window.addEventListener ("message", function (event) { code here }) Is it enough? Do I have to have in the popup.js some receiver? Could it be a bad idea at all? And as I understand in the manifest file I have to give: "content_scripts": [      {        "run_at": "document_start" }    ] – agro Sep 26 '17 at 06:24
  • Mentioning `document_start` was just covering all bases for communicating with content scripts. It's a special case when using `document_start` *and* needing data from the background synchronously (it's significantly more complex). I'm not sufficiently familiar with what you are trying to do to be able to say if it needs to run at `document_start`, or not. Communication with the popup requires that the popup is open at the time you attempt communication. If the popup isn't not open, it doesn't exist. Frankly, without a [mcve], including a *manifest.json*, it's hard for anyone to help. – Makyen Sep 26 '17 at 16:02
  • BTW: It would be a good idea to link to "cakery", as it's unclear what that is. When I try to Google "cakery", I get 8M hits about cakes. Even limiting a search to also include JavaScript, results in 77k hits, still about cakes. – Makyen Sep 26 '17 at 16:05
  • @Makyen I just noticed it - I do not know how it was found in the post "cakery". It was supposed to be - communication problem. I do not know how I could not notice it. I edited the post - I described the problem a little wider. – agro Sep 27 '17 at 08:05

1 Answers1

0

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>";
        }
    }
});
  });
agro
  • 57
  • 12