3

EDIT -- added background script

I need to get a message from the popup script in my chrome extension to the content script. It should send the message when a button inside the popup is clicked.

After reading more, it seems like you can't communicate directly between the popup script and the content script.

I think I need to go: popup.js > background.js > script.js

I've tried doing this, but I can't seem to get it to work. There are a couple different ways to implement message passing, but not much documentation for this use case.

here's the code (it doesn't seem to pass a message at all right now):

popup.js

/* when something is saved in local storage... */
        chrome.storage.sync.set({'myFilter': filter}, function(){

            /* send message to background script */
            chrome.runtime.sendMessage({greeting: "hello from popup"}, function(response) {
                console.log(response.farewell);
            });
            chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
              chrome.tabs.sendMessage(tabs[0].id, {greeting: "new filter saved"}, function(response) {
                console.log(response.farewell);

              });
            });
        });

background.js

 /*listen for message from popup, send message to content script */
chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a background script:" + sender.tab.url :
                "from the extension");
    if (request.greeting == "hello from popup") {
        alert("message passed to background script");
        console.log("message passed to background script");

         /* send message to content script */
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
                  chrome.tabs.sendMessage(tabs[0].id, {greeting: "popup sent message"}, function(response) {
                    console.log(response.farewell);

                  });
                });
         return true;
       sendResponse({farewell: "goodbye"});
    }
    return false;
  });

script.js

    /* get notice from background script*/
chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if (request.greeting == "popup sent message") {
        alert("message passed to content script");
        console.log("message passed to content script");
        location.reload();
        walkWithFilter();
         return true;
       sendResponse({farewell: "goodbye"});
    }
    return false;
  });

manifest.json

{
  "manifest_version": 2,
  "name": "filter",
  "description": "This extension allows twitter users to filter content in their feed",
  "version": "1.0",
  "content_scripts": 
  [
    {
      "matches": ["*://*/*"],
      "js": ["bower_components/jquery/dist/jquery.min.js", "script.js"],
      "run_at": "document_end"
    }
  ],

  "permissions": [
    "tabs",
    "storage",
    "contextMenus",
    "background",
    "https://twitter.com/",
    "http://twitter.com/"  
  ],

  "icons": {
    "16": "fa-moon.png"
  },

  "background": {
    "scripts": ["background.js"]
  },

  "browser_action": {       
   "default_title": "filter",
    "default_icon": "fa-moon.png",
    "default_popup": "popup.html"
  }
}

right now this is doing nothing -- no alert message pops up and nothing is printed to the console when I pressed the button with the click event.

This is how it should run:

1) User enters input into popup window 'save-button' and clicks save

2) onclick of the save-button, input is saved in localstorage (this part works)

3) onclick of the save-button, message is sent from popup.js to script.js telling it that new input has been saved to localstorage

4) Script.js receives message and prints to the regular console "message passed"

The reason I'm doing this is that I need to make the content script do some logic when it receives notice that new input has been saved in local storage. Does this seem reasonable?

10
  • Where is the "save-button"? Is it in current web page or just popup page? Commented Jun 18, 2016 at 5:41
  • 1
    See stackoverflow.com/questions/36107503/… to debug why you don't see the console.logs. Commented Jun 18, 2016 at 9:51
  • 1
    My gut says your problem is onclick and that you should look at stackoverflow.com/q/13591983/2336725. Commented Jun 20, 2016 at 3:48
  • @HaibaraAi the save-button is a button in the popup window. You can input text and then save it to localstorage (this part is working) Commented Jun 20, 2016 at 17:50
  • 1
    The assumption that you cannot send messages from the popup to the content script is wrong: You can directly send a message from the popup to the content script. How is popup.js being loaded? And did you know that if you hard-reload the extension, that the existing content scripts cannot communicate with your extension until the page is reload? Commented Jun 21, 2016 at 19:41

2 Answers 2

3
+50

You can actually go directly from popup.js > script.js since the background page's messaging api is accessible to the popup too.

manifest.json

{
  "manifest_version": 2,
  "name": "filter",
  "description": "This extension allows twitter users to filter content in their feed",
  "version": "1.0",
  "content_scripts": 
  [
    {
      "matches": ["<all_urls>"],
      "js": ["script.js"],
      "run_at": "document_end"
    }
  ],

  "permissions": [
    "tabs",
    "storage",
    "contextMenus",
    "background",
    "https://twitter.com/",
    "http://twitter.com/"  
  ],

  "icons": {
  },

  "background": {
    "scripts": []
  },

  "browser_action": {       
    "default_title": "filter",
    "default_popup": "popup.html"
  }
}

popup.html

<button id="save-button">save-button</button>
<script src="/popup.js" type='text/javascript'></script>

popup.js

document.getElementById("save-button").onclick = function(){
    console.log("clicked button");

    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
        if(tabs.length == 0){ 
            console.log("could not send mesage to current tab");
        }else{
            chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello, how are you content script?"}, function(response) {
                console.log("received message from content script: "+response.farewell);
            });
        }
    });
}

script.js

chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");


    console.log("received message from popup: "+request.greeting);

    sendResponse({farewell: "I'm good, thank you popup!"});
});
Sign up to request clarification or add additional context in comments.

3 Comments

That finally made it send the message! I'm getting this error after the message sends: extensions::uncaught_exception_handler:8 Error in event handler for runtime.onMessage: Error: Attempting to use a disconnected port object at chrome-extension://nbcngiipoendfnhjhjgbpkaiecjidagb/script.js:49:5
I'm happy it worked for you :) That error isn't coming from my example scripts since it works fine when i test it. That error message must be coming from another part of your script.js that isn't using chrome.tabs.connect() api correctly. look up the error on google.
Are you able to see what OP was doing wrong? I wasn't, and I'm not seeing what change you made.
0

A very important permission for message passing i.e. tabs which is used to interact with the browser's tab system, is missing in your permission list.

Replace permissions array in manifest.json with

"permissions": [
    "tabs",
    "storage",
    "contextMenus",
    "background",
    "https://twitter.com/",
    "http://twitter.com/"  
  ],

2 Comments

thanks added that! Can you think of a better way to test if the message passing is working? I'm still not seeing the console.log, but perhaps there is a better way to test if a message is passing from popup to the content script
The tabs permission is only needed if the OP wants to read the url, title or faviconUrl properties, which appears to not be the case here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.