Closed Bug 1406167 Opened 7 years ago Closed 6 years ago

port.disconnect() doesn't trigger port.onDisconnect on unload on window close

Categories

(WebExtensions :: General, defect, P3)

56 Branch
defect

Tracking

(firefox57 wontfix)

RESOLVED DUPLICATE of bug 1392067
Tracking Status
firefox57 --- wontfix

People

(Reporter: baptiste.themine, Assigned: robwu)

Details

User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Build ID: 20170926190823

Steps to reproduce:

A content script is connected to the background script and is disconnected explicitly inside window.onunload as below :

//content script
var port;
window.onload = function(){
    console.log("port connect");
    port = browser.runtime.connect({name: "test"});
};
window.onunload = function(){
    console.log("port disconnect");
    port.disconnect();
};

//background script
browser.runtime.onConnect.addListener(function(port){
    console.log("port "+port.name+" is connected");
    port.onDisconnect.addListener(function(){
         console.log("port "+port.name+" is disconnected");
    });
});


Actual results:

On tab close, window.unload is triggered and port.onDisconnect is correctly triggered.
On window close, window.unload is triggered but not port.onDisconnect.


Expected results:

port.onDisconnect should be triggered in both case. An alternative solution is to use window.onbeforeunload instead of window.onload.
instead of window.onunload, sorry.
Component: Untriaged → WebExtensions: General
Product: Firefox → Toolkit
Priority: -- → P3
Summary: WebExtensions : port.disconnect() doesn't trigger port.onDisconnect on unload on window close → port.disconnect() doesn't trigger port.onDisconnect on unload on window close
I just noticed another issue, window.onbeforeunload is never triggered inside browserAction popup. As a result, port.onDisconnect is never triggered (automatically or manually) on window close when browserAction popup is opened.
For information, this issue is not present in Chrome: closing a window containing a tab that opened a port to the background does trigger the port.onDisconnect event on the background side.

Furthermore, there is no way (at least that i could find) for the background to know the port has been silently closed: calling port.postMessage() generates an entry in the console ("No matching message handler for the given recipient."), but does not throw an exception.

This bug prevents having a proper port-based communication between background and content (background having no way to know the content is no longer existing). Any workaround you could think of ?
(In reply to Baptiste Thémine from comment #2)
> I just noticed another issue, window.onbeforeunload is never triggered
> inside browserAction popup. As a result, port.onDisconnect is never
> triggered (automatically or manually) on window close when browserAction
> popup is opened.

That is not what i see: for the browserAction popup, i get the port.onDisconnect event called. Haven't checked whether window.onbeforeunload was triggered or not.
(In reply to Michel Gutierrez from comment #4)
> (In reply to Baptiste Thémine from comment #2)
> > I just noticed another issue, window.onbeforeunload is never triggered
> > inside browserAction popup. As a result, port.onDisconnect is never
> > triggered (automatically or manually) on window close when browserAction
> > popup is opened.
> 
> That is not what i see: for the browserAction popup, i get the
> port.onDisconnect event called. Haven't checked whether
> window.onbeforeunload was triggered or not.

I just tested it on Firefox 56 and Nightly 59. When I open a new window, then I click the browserAction button to open the popup, then I close the window while the popup is still opened, port.onDisconnect is not triggered at all even if I call port.disconnect() in window.onunload or window.onbeforeunload.
(In reply to Baptiste Thémine from comment #5)
> I just tested it on Firefox 56 and Nightly 59. When I open a new window,
> then I click the browserAction button to open the popup, then I close the
> window while the popup is still opened, port.onDisconnect is not triggered
> at all even if I call port.disconnect() in window.onunload or
> window.onbeforeunload.

Ok, i confirm that behaviour. So there is the same problem with tabs and browserAction popup.

For now, as a workaround, i track the tab id along with the port, so when i received an event about the tab being closed, i handle this as a port disconnect.

I would be much cleaner to trigger the port.onDisconnect event whenever a port is actually closed.
(In reply to Michel Gutierrez from comment #6)
> Ok, i confirm that behaviour. So there is the same problem with tabs and
> browserAction popup.
> 
> For now, as a workaround, i track the tab id along with the port, so when i
> received an event about the tab being closed, i handle this as a port
> disconnect.
> 
> I would be much cleaner to trigger the port.onDisconnect event whenever a
> port is actually closed.

This is not the better solution because I think that browserAction popup doesn't have a tabId in all browsers such as Chrome for example, and I reported an issue on https://bugzilla.mozilla.org/show_bug.cgi?id=1418799 about browserAction popup not triggering the browser.tabs.onRemoved on Firefox Android.
For now, the workaround I am using is to call port.postMessage inside a try catch.
(In reply to Baptiste Thémine from comment #7)
> For now, the workaround I am using is to call port.postMessage inside a try
> catch.

That was the first workaround i thought of but from my tests, port.postMessage() did not throw an exception when used on a port that was silently closed.
(In reply to Michel Gutierrez from comment #8)
> That was the first workaround i thought of but from my tests,
> port.postMessage() did not throw an exception when used on a port that was
> silently closed.

Did you try to use both port.onDisconnect and try catch?
Normally, if the port is correctly closed, port.onDisconnect is triggered, else if the port is not closed, you catch an exception with port.postMessage(). I didn't face yet the problem where no event happened.
Yes, i used both port.onDisconnect and try catch around around the port.postMessage.

What i was trying to do the following:
- listen to closed windows with windows.onRemoved
- when triggered, call all ports with some kind of "ping" message
- the ports generating an exception must have been silently closed and are treated as such

When i postMessage to a closed port, i get a message in the console "No matching message handler for the given recipient." but i don't get any exception in the catch.

I will try again.
If you are interested, the code I am using for port communication is https://pastebin.ubuntu.com/26044523/
It works on Firefox, Chrome and Opera.
Based on the descriptions above, I believe that this bug has the same root cause as bug 1392067 .
Assignee: nobody → rob
Status: UNCONFIRMED → RESOLVED
Closed: 6 years ago
Resolution: --- → DUPLICATE
Product: Toolkit → WebExtensions
You need to log in before you can comment on or make changes to this bug.