2

I'm learning how to make chrome extensions. I have a content script that will obtain some data and I want to pass them to the popup.html page to display them on the popup DOM. I've read about the message passing in the Chrome documentation but I'm unable to make it work. Can anyone help me?

My code:

content script file: main.js

(function($){
  $(document).ready(function(){
    console.log('Extension Started!');
    var el = $(document).find('#stories_tray');
      var child = el.find('._827c');
        $.each(child, function(i){
          var div = $(child[i])
            .find('._7h4p')
            .attr('data-onkeypress');
          var d = JSON.parse(div);
          if( typeof d[0].a != 'undefined' ){
            console.log(d[0].a[0].preloadImageURIs[0]);
            var l = d[0].a[0].preloadImageURIs[0];

            chrome.runtime.sendMessage({imageURIs: l}, function(response) {
              console.log(response.farewell);
            });
          }
        });
  });
}(jQuery));

popup javascript file: popup.js

// window.onload = function(){
//   $('.spinner-grow').delay('300')
//     .css({'transition':'ease-out','display':'none'});
// }

(function($){
  $(document).ready(function(){
    console.log('Extension Started!');
    chrome.runtime.onMessage.addListner(function(request, sender, sendResponse){
      console.log(sender.tab ? "from a content script:" + sender.tab.url : "from the extension");
      console.log(request.imageURIs);
      sendResponse({farwell: "ok"});
    });
  });
}(jQuery));


Maybe I'm doing something wrong with the code.

I get this errors in the console:

// content script console error
Error handling response: TypeError: Cannot read property 'farewell' of undefined

//popup.js console error
jQuery.Deferred exception: chrome.runtime.onMessage.addListner is not a function TypeError: chrome.runtime.onMessage.addListner is not a function:

Uncaught TypeError: chrome.runtime.onMessage.addListner is not a function

UPDATE

I've managed how to pass the message from the content script to the popup.js but I need a way to hold the message until the user click on the extension icon. How can I achieve also this?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
jihuuNI
  • 551
  • 2
  • 5
  • 17
  • Are you new to programming in general? I think this might be a bit of a hard topic to start on buddy – Panomosh Aug 29 '19 at 22:20
  • @Panomosh I have experience with php but I'm new to js for the front-end part. This is why I'm having some problems in chrome extension develop. I'm doing a training to improve my skiils – jihuuNI Aug 29 '19 at 22:44
  • addListner seems to be misspelled. I'm not positive if a message from a content script will be heard by the popup; if not, you may have to go through a background page (popup sends message to background, sends message to tabs, sends message back to background, back to popup). – jagthebeetle Aug 29 '19 at 23:04
  • @jagthebeetle The main problem is that the popup will work only if user open it. the data I want to pass from content script are grabbed after the matched page load. I've tested and the data are passed, but the popup needs to be opened first. I have no idea of how to pass te message o background.js and then to popup. An example will be appreciated – jihuuNI Aug 29 '19 at 23:09
  • @jihuuNI there are plenty of examples on how to pass messages within an extension from a page to the background. You should pass the data to the background using a message and store it in a variable to keep it, then use another message from the popup to the background to request such data. – Marco Bonelli Aug 29 '19 at 23:22

2 Answers2

3

In general, it will not work to send a message from a content script to a popup unless you know the popup is open: the popup does not exist until you open it.

Given this, it will likely be most decoupled to have your content script send its message to a persistent background (which is the default btw) and serve as the repository for your messages until the popup requests them.

background.js

const messageQueue = [];
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  // Arbitrary string allowing the background to distinguish
  // message types. You might also be able to determine this
  // from the `sender`.
  if (message.type === 'from_content_script') {
    messageQueue.push(message);
  } else if (message.type === 'from_popup') {
    sendResponse(messageQueue);
  }
});

Now from content script, send chrome.runtime.sendMessage({imageURIs: l, type: 'from_content_script'}... and from the popup send

chrome.runtime.sendMessage({type: 'from_popup'}, (response) => {
  // do stuff with response (which will be the value of messageQueue
  // sent from background.js).
});

Of course the strings 'from_popup' and 'from_content_script' mean nothing; they are just there for clarity.

If you need the popup to initiate the flow, you will need to:

  • send a message from the popup
  • to the background, to send a message to the content scripts
  • which should respond to the background
  • which should respond to the popup
jagthebeetle
  • 705
  • 6
  • 11
  • Thank you, your answer is very clear, I will rework my code to implement your suggested workflow. – jihuuNI Aug 29 '19 at 23:24
0

Chrome runtime have not onMessage method please see this link,hope this will hep you

jihuuNI
  • 551
  • 2
  • 5
  • 17
  • I've read that question, it's not the same problem I have because I need to pass the message from the content script that is interacting with the page and the popup that will not receive messages if is not opened. – jihuuNI Aug 29 '19 at 19:27