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?

user146303
  • 417
  • 1
  • 5
  • 19
  • Where is the "save-button"? Is it in current web page or just popup page? – Haibara Ai Jun 18 '16 at 05:41
  • 1
    See http://stackoverflow.com/questions/36107503/console-log-not-working-when-i-load-my-chrome-extension to debug why you don't see the console.logs. – John Hoffman Jun 18 '16 at 09:51
  • 1
    My gut says your problem is `onclick` and that you should look at http://stackoverflow.com/q/13591983/2336725. – Teepeemm Jun 20 '16 at 03: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) – user146303 Jun 20 '16 at 17:50
  • @Teepeemm I also save information to chrome storage onclick and that part is working. I edited my question with more info! – user146303 Jun 20 '16 at 18:02
  • @JohnHoffman thanks! I've checked in both the dom console and the popup console. I would expect to see it in the dom console because it is the content script that i have printing a message. I edited the question to make it more clear! – user146303 Jun 20 '16 at 18:04
  • It would be great if you could also provide `manifest.json`. And are you sure there isn't any alert/console outputs? – Haibara Ai Jun 20 '16 at 23:52
  • Have you included `popup.js` in your `popup.html`? – Haibara Ai Jun 20 '16 at 23:58
  • @HaibaraAi yeah I have - and other interactions between popup.js/popup.html/script.js are working. Just not message passing – user146303 Jun 21 '16 at 00:00
  • 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? – Rob W Jun 21 '16 at 19:41

2 Answers2

3

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!"});
});
Marc Guiselin
  • 3,064
  • 2
  • 22
  • 36
  • 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 – user146303 Jun 21 '16 at 20:39
  • 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. – Marc Guiselin Jun 21 '16 at 21:03
  • Are you able to see what OP was doing wrong? I wasn't, and I'm not seeing what change you made. – Teepeemm Jun 22 '16 at 05:07
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/"  
  ],
Shweta Matkar
  • 271
  • 1
  • 10
  • 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 – user146303 Jun 21 '16 at 15:31
  • 1
    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. – Rob W Jun 21 '16 at 19:37