user1141649 user1141649 - 4 months ago 31
Javascript Question

Why addon page cannot recieve message?

I am trying to send message from addon (webextension) to html page which is in the addon. The webextension API is using chrome interface which is compatible with Chrome browser. I am using Firefox 48 beta.

This is the background script (the "initiate-page" message is important):

chrome.runtime.onMessage.addListener(
function(package, sender
){
switch (package.message){
case "open":
if (package.subject == "tab")
{
win = myNamespace.tabs[package.module];
result = win ? false : true;

if (result)
chrome.tabs.create(
{"url": package.url },
function(tab) {
if (chrome.extension.lastError )
console.log(chrome.extension.lastError);
else
myNamespace.tabs[package.module] = tab.id;
chrome.tabs.onRemoved.addListener(
function( tabId, removeInfo )
{
for (var k in myNamespace.tabs )
{
if (tabId === myNamespace.tabs[k])
{
myNamespace.tabs[k] = null;
break;
}
}
}
);
}
);
}
break;
case "initiate-page":
if (package.subject == "html-add-listeners")
{
switch(package.module){
case "easy_options":
case "advanced_options":
case "images_options":
chrome.tabs.sendMessage(
package.sender.id,
{ message:"initiate-page-response",
subject:"accept-namespace",
recepient: {id: package.sender.id },
module: package.module,
namespace: myNamespace,
info: "response to tab exists message"
}
)
break;
}
}
break;
}
}
)


So, when the addon receives message from module "easy_options", it means that easy_options.html needs some data to load to its document. Therefor I send message with namespace which contains the data.

Now the addons page easy_options.js (again, the second part is imporant where chrome.runtime.onMessage listener is added):

chrome.tabs.query(
{ active: true, currentWindow: true},
function(tabs) {
browser.runtime.sendMessage(
{ message:"initiate-page",
subject: "html-add-listeners",
module: "easy_options",
sender:{id:tabs[0].id}
}
)
}
);

chrome.runtime.onMessage.addListener(
function(package, sender
){
switch (package.message){
case "initiate-page-response":
if (package.subject == "accept-namespace")
{
switch(package.module){
case "easy_options":
document.addEventListener('DOMContentLoaded', myNamespace.easy.restore);
document.getElementById("easy_form_save").addEventListener("submit", myNamespace.easy.save);
document.getElementById("easy_form_restore").addEventListener("submit", myNamespace.easy.restore);
document.getElementById("easy_form_remove_item").addEventListener("submit", myNamespace.easy.remove_profiles);
document.getElementById("easy_form_remove_profiles").addEventListener("submit", myNamespace.easy.remove_profiles);
document.getElementById("list").addEventListener("change", myNamespace.easy.restoreDefault);
break;
}
}
break;
}
}
)


What happens is:
1) I send message (A) to background listener and it accepts the message
2) background listener sends message (B)
3) addons options script receives the first message (A) in the runtime.OnMessage listener (I do not want to process this message)

What should happen
1) I send message (A) to background listener and it accepts the message
2) background listener sends message (B)
3) addons options script receives the first message (A) in the runtime.OnMessage listener (I do not want to process this message)
4) addons options script should receive the second message (B) in the runtime.OnMessage listener and I should process it

Question:
Why the fourth step does not happen? Why the message (B alias "initiate-page-response") is not received?

Maybe Chrome addon programmers can help too, I think the things should work similarly.

Xan Xan
Answer

Since it's an extension page, and not a content script, chrome.tabs.sendMessage is not going to reach it.

You need to broadcast your message with chrome.runtime.sendMessage to reach chrome-extension:// pages such as an options page.

If you don't like the broadcast nature of runtime.sendMessage, you should use sendResponse callback argument to pass a response back to sender (probably preferable), or establish a long-lived port with runtime.connect.