Webextension firefox andoid - content script does not receive messages

Messages send from a background-script to a content-script are not received in the content-script in ff on android.

content script

var myPort = browser.runtime.connect({name:"port-from-cs"});
myPort.postMessage({greeting: "hello from content script"});

myPort.onMessage.addListener(function(m) {
  console.log("In content script, received message from background script: "); // never fires
  console.log(m.greeting); // never fires
});

document.body.addEventListener("click", function() {
  myPort.postMessage({greeting: "they clicked the page!"});
});

background script

var portFromCS;

function connected(p) {
  portFromCS = p;
  console.log("post message from background") // ok
  portFromCS.postMessage({greeting: "hi there content script!"}); // never received
  portFromCS.onMessage.addListener(function(m) {
    console.log("In background script, received message from content script")
    console.log(m.greeting); // ok
    console.log(portFromCS); // ok
    console.log(portFromCS.name) // ok
   portFromCS.postMessage({greeting: "hi there FROM BACKROUND script!"}); // never received
  });

On firefox on windows, things work, on android, the messages to the content-script are lost in the void :confused:

Is this a known bug, and are there any known solutions?

After more research, the problem seems to be that in the background-script when a content-script connects by the listener browser.runtime.onConnect.addListener(connected), the property port.sender.tab is not set for the port argument in the callback function connected. (oddly, port.sender.url is set)

This only goes wrong for the first tab, when i open a new tab, then when a content script connects the tab object is set and the content-script receives messages from the background script. Pretty troubling that things don’t seem to work well on android, especially seeing web-extension are the only extension allowed nowadays.

As a crude, hopefully temporary, workaround i now check whether the tab is set in my connect callback. If not, i close the tab and open a new one with the same location. It’s an annoying user experience, but at least it makes messaging work.

> function connected(port) {
> 	var id = globalId++
> 	console.log(port)
> 	console.log("BS: connect with id: " + id)
> 	if(!port.sender.tab) {
> 		// close tab, reopen
> 		console.log("trouble, port not set!!!!!")
> 		browser.tabs.query({url: port.sender.url}).then(function(tabs) {
> 			console.log("AFTER TROUBLE TABS FOUNND");
> 			if(tabs.length >= 1) {
> 				var tab = tabs[0]				
> 				browser.tabs.remove(tab.id)
> 				browser.tabs.create({url: port.sender.url, active: tab.active})
> 			}
> 		})
> 	} else {
> 		portsToCSs.set(id, port)
> 	  	port.onMessage.addListener(function(m) {
> 	    console.log("BS: received message from content script: " + m)
> 	    for (var i = listeners.length - 1; i >= 0; i--) {
> 		    	listeners[i](m, id, "")
> 		    }
> 		});
> 		port.onDisconnect.addListener(function(p) { 
> 		   	portsToCSs.delete(id)
> 		})
> 	}
> }

Now that you mention it, I actually ran into the missing port.sender.tab problem as well. I didn’t know that it only happens for some tabs. Unfortunately, everything that’s got to do with tabs is still quite unstable in Fennec.

I think I hit this ‘first tab’ problem using browser.tabs.sendMessage in Fx Android 56, but it seems to be OK in 57.
Was there a bug for this?