4

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?

Amir
  • 1,882
  • 17
  • 22
erez
  • 63
  • 1
  • 6

2 Answers2

5

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');
chulster
  • 2,809
  • 15
  • 14
1

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", {} );
mc.
  • 539
  • 6
  • 15
  • and you'd have to do additional stuff to handle new safari with many pages fetched ahead of time i think – mc. Aug 18 '14 at 21:06