Safari extension send message to a specific tab
-
26-05-2021 - |
Question
Is there a way to send a message from the global page to a specific tab?
What I'm currently doing is, on tab creation the injected script creates a unique id and sends a message with this number to the global page and the global page saves this number.
If the global page needs to send some data to a tab (i.e: tab #3
) then the global page will "broadcast" a message to all tabs with the number #3
as part of the data passed to the tabs (iterate over all tabs and send a message to each tab).
Is there something like Chrome: (i.e: chrome.tabs.sendRequest(tabID, {action: 'respond', params:[channel,msg,async]});
)?
Right now what I'm doing is that on the injected script side, each script has a listener that will catch this message. If a content script unique number is equal to the number sent by the global page then this message is for it, else doNothing
.
Is there an easier more elegant way to do this in Safari?
Solution
Within the global page's message event handler, event.target
refers to the tab from which a message was received. For example:
function handleMessage(e) {
if (e.name === 'whatIsMyUrl?') {
e.target.page.dispatchMessage('yourUrlIs', e.target.url);
}
}
safari.application.addEventListener("message", handleMessage, false);
The Safari extension API doesn't have tab IDs, but you could just keep each tab in an associative array and use its index to address it later. For example:
function handleMessage(e) {
if (e.name === 'hereIsMyId') {
myTabs[e.message] = e.target;
}
}
safari.application.addEventListener("message", handleMessage, false);
// later...
myTabs[someId].page.dispatchMessage('haveSomeCake');
OTHER TIPS
Safari Answer
In your global page save directly to the tab.. so for instance on message from injected script
// global page
safari.application.addEventListener("message", function(event){
switch(event.name){
case "saveData":
event.target.page.tabData = { data: myData }
break;
case "getData":
event.target.page.dispatchMessage("tabData", myData);
break;
}
}, false);
-
// injected page
// first save data
safari.self.tab.dispatchMessage("saveData", {firstname:"mike", age: 25} );
// setup listner to recevie data
safari.self.addEventListener("message", function(event){
switch(event.name){
case "tabData":
// get data for page
console.debug(event.message);
// { firstname: "mike", age: 25 }
break;
}
}, false);
// send message to trigger response
safari.self.tab.dispatchMessage("getData", {} );