Reputation: 3611
I am trying to send a message from addon (webextension) to a html page which is in the addon. The webextension API is using the 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 a message from the module "easy_options", it means that easy_options.html needs some data to load to its document. Therefore I send a message with namespace which contains the data.
Now the addons page easy_options.js (again, the second part is important 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 does the fourth step not happen? Why is the message (B alias "initiate-page-response") not received?
Maybe Chrome addon programmers can help too, I think the things should work similarly.
Upvotes: 1
Views: 69
Reputation: 3611
Thanks to Xan's explanation, I have found this works like charm
background script:
chrome.runtime.onMessage.addListener(
function(package, sender, sendResponse
){
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":
sendResponse(
{ message:"initiate-page-response",
subject:"accept-namespace",
recepient: {id: package.sender.id },
module: package.module,
namespace: myNamespace,
info: "response to initiate-page message"
}
)
break;
}
}
break;
}
}
)
Addon's option page script:
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}
},
function response(message){
console.log("RESPONSE:");
console.log(message);
return true;
}
)
}
);
Upvotes: 1
Reputation: 77482
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
.
Upvotes: 3