1

I am working on a Chrome extension using JavaScript and need to be able to pass a message from a background script to a content script using a custom entry in the context menu as a trigger for this.

manuscript.json

{
 "manifest_version": 2,
 "name": "Admin Tools",
 "version": "0.3",
 
 "permissions": [
  "contextMenus",
  "tabs",
  "activeTab"
 ],
 
 "content_scripts": [
  {
   "matches": ["https://*/*", "http://*/*"],
   "js": ["lead_partner_search_content.js"]
  }
 ],
 
 "background": {
  "scripts": ["admin_search.js", "company_id_search.js","order_id_search.js","lead_partner_search.js"]
 }
}

lead_partner_search.js (background script)

//lead_partner_search.js

var backgroundScriptMessage = " purple monkey dishwasher";

function returnMessage(messageToReturn) {
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      var joinedMessage = messageToReturn + backgroundScriptMessage;
          alert("Background script is sending a message to contentscript:'" + joinedMessage +"'");
      chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"});
    });
}

chrome.contextMenus.create({
 "title": "Search leads by company name",
 "contexts": ["selection"],
 "onclick": returnMessage("test")
})

lead_partner_search_content.js (content script)

//lead_partner_search_content.js

chrome.runtime.onMessage.addListener( function(request, sender) {
    alert("Contentscript has received a message from from background script: '" + request.message + "'");
    return true;
});

Following another example from Stack Overflow, this should show one alert as:

Background script is sending a message to contentscript:'test purple monkey dishwasher'

And then a second as:

Contentscript has received a message from from background script: 'test purple monkey dishwasher'

However, what actually happens is when the extension is loaded, the first message alert appears instantly and nothing further happens even when triggering the context menu entry.

I am unsure as to why this is and do not wholly understand message passing in Google Chrome despite searching on this and other sites for information.

Any assistance is appreciated.

Ethan Field
  • 3,965
  • 2
  • 18
  • 35
  • 1
    Have you tried wrapping the `onclick` assignment in a `function() { }` wrapper? Doesn't seem like it should matter but sometimes JavaScript is weird like that. `"onclick": function() { returnMessage("test"); }` – freginold Aug 01 '17 at 14:50
  • 1
    That has prevented the issue with the alert flashing up as soon as the extension is loaded and I can now trigger the first alert with the context menu entry, however, I still receive no second alert, it seems like the message isn't being picked up by the content script. – Ethan Field Aug 01 '17 at 14:52
  • 1
    Do you get any errors or messages in the console? – freginold Aug 01 '17 at 14:54
  • No, after triggering the context menu entry the console remains blank – Ethan Field Aug 01 '17 at 14:55
  • 1
    Try adding two `console.log` commands: one at the top of your content script (to make sure the content script is being loaded) and the second inside the `onMessage` listener. – freginold Aug 01 '17 at 15:05
  • Adding `console.log("content")` to the top of my content file causes the console to print `content` however adding `console.log(joinedMessage)` underneath the declaration of the aforementioned variable does not print anything when triggering the context menu entry however still produces the alert – Ethan Field Aug 01 '17 at 15:17
  • @EthanField are you saying if you put a `console.log` after the `var joinedMessage` line, the console message doesn't print but the alert right after it does? – freginold Aug 01 '17 at 16:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/150764/discussion-between-ethan-field-and-freginold). – Ethan Field Aug 01 '17 at 20:32
  • You should not `return true;` in your `runtime.onMessage` listener unless you actually intend to send a response using `sendResponse`, which you clearly don't do in this code. – Makyen Aug 01 '17 at 21:04
  • 2
    Don't, by default, use `alert()` for debugging. It can cause/resolve timing issues/race conditions which can be harder to debug. If you're not going to use the actual debugger, then use `console` output. The *occasional* `alert()` might be acceptable, but it should not be your default, go to way to show progress. If for no other reason, `console` output allows you to go back over the output in the console multiple times rather, than having to remember what happened/was displayed in `alert()` and in what order. – Makyen Aug 01 '17 at 21:07

1 Answers1

0

Taking advice from the comments I was able to change the background script to the below:

//lead_partner_search.js
function returnMessage() {
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"});
    });
}

chrome.contextMenus.create({
    "title": "Search leads by company name",
    "contexts": ["selection"],
    "onclick": returnMessage
})

And to my content script to the below:

//lead_partner_search_content.js
chrome.runtime.onMessage.addListener( function(request, sender) {
    console.log("Contentscript has received a message from background script: '" + request.greeting + "'");
});

This produces the desired output in the console of:

Contentscript has received a message from background script: 'hello'

Based on what I now understand it seems that I was calling a part of the message which didn't exist request.message where I should have been calling request.greeting as this is what I was declaring when sending the message from the background script.

Ethan Field
  • 3,965
  • 2
  • 18
  • 35