Prevent window.stop to block open websockets - javascript

I have a Websocket-based client-server communication protocol, which must be cross-browser compatible.
To prevent some MJPEG streams from running indefinitely on Safari and Chrome as described in this bug report, I launch a window.stop() javascript event under certain conditions.
On Chrome this keeps the websocket connection open, which is good.
On Firefox, however, the websocket is abruptly closed.
Is there a way to force some sockets to stay open with the window.stop() event?
The only workaround, otherwise, would be to use some browser sniffing (bad practice) or to hope that Chrome devs will finally debug the MJPEG issue (which is unlikely).

Related

Event listener for network connection change

In JavaScript (on Chrome) I am trying to perform some task whenever a user switches from one WiFi network to another (assuming that both networks are exactly the same in terms of performance).
I started with looking at the online / offline events of the Window interface and navigator.onLine but it seems like that they are not triggered when we switch networks (disconnect from one network and connect to the other) because
In Chrome and Safari, if the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other conditions return true.
you cannot assume that a true value necessarily means that the browser can access the internet. You could be getting false positives, such as in cases where the computer is running a virtualization software that has virtual ethernet adapters that are always "connected."
Ref1: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine
Ref2: why navigator.onLine() return true even if my internet connection is not working?
Also, the navigator.connection object not necessarily updates to trigger navigator.connection.onchange event in case of switching networks.
I tried using WebRTC with STUN to capture public IP address to differentiate between the two connections but there is no event listener that would reliably tell that a network change has happened.
I understand that JavaScript can not directly access network info through the browser due to security reasons but is there an alternative that can be reliably used to trigger an event whenever the network is switched or there is no actual internet connectivity even though the computer is connected to the LAN/WiFi?
What you are looking for does not have wide browser support, but does exist in Chromium-based browsers: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/change_event
This is known as "walk out of the door" problem. These slides from a 2015 IETF meeting explain it well:
https://www.ietf.org/proceedings/94/slides/slides-94-ice-6.pdf
In a nutshell what you need to do in the browser is to wait for the old connection to get disconnected and initiate an ICE restart to reestablish the connection.

Why doesn't Firefox wait for WebSocket connection?

I'm writing an application that first tries to open a WebSocket connection (to make sure no others are open; address collision checking) before firing off a custom protocol that will launch a one-time WebSocket server with the address that the browser tells it. All communication is done over localhost and some arbitrary port number, say 3000. I'm not doing anything special, just attempting to open a WebSocket:
var socket = new WebSocket("ws://localhost:3000/MyApp/");
socket.onclose = function(e) { console.error(e); }
When testing in Chrome, the WebSocket will actually stay in the CONNECTING state for a little bit, which is ideal, since it gives us some time to actually launch the app through the custom protocol. But in Firefox, the WebSocket immediately closes with code 1006 and I can't figure out why.
I've tried changing the about:config network.websocket.timeout.open setting to be 1000 (from 20), but that doesn't help. I've also found this related post: Websockets - chrome and firefox differences?. That hasn't lead me to finding an answer, either.
What am I missing?
Update 11/16/21
I'm using the Dev Tools in Chrome and FF to check out the requests. The weird thing is that Chrome is actually sending a request header as you'd expect, but in FF, the request is completely empty (0 Bytes). Maybe this is a problem with FF not supporting debugging native WebSockets (no wrapper libraries in use)? Is there some FF setting that nixes the request? But even more confusing is that the browser would hit the close event without ever hitting the open event.
Update 11/17/21
I realize that maybe this has something to do with launching a Custom Protocol Handler? I noticed that it will wait a second to try and connect to a web server if no CPH is launched, but then when I do launch a CPH, that is when it immediately closes the WebSocket. The CPH is launched via a link targeting "_parent".
It looks like the custom protocol is causing FF to stop trying to connect early. I created an anchor element, <a>, in the JS code and called "click()" on it after constructing it. No matter what target I gave it (e.g. _self), it would cause the connection attempt to stop.
So long story short, initiating a link, whether it be a a.click, window.open, or location.replace, will cause Firefox to nix any currently polling WebSockets!
The workaround is to just use an iframe to launch the custom protocol.

How to debug WebSocket / Server Sent Events reconnections on desktop?

I am developing an app that uses Server Sent Events (SSE - basically one-way websockets). If the user uses the site on their mobile chrome browser and then tabs out for about a minute, the SSE connection breaks. If the user then tabs back into the site, it doesn't refresh the page (this is good). But I still need to re-establish the SSE connection so that the server can resume sending messages to them without a refresh.
I'm trying to debug my implementation but having to do it on mobile is very tedious. I have to grab my phone, refresh the page, then tab out, wait 1 minute (so the connection can break), and then tab back in to determine if my code for re-establishing the connection worked properly.
I would much rather be able to debug this on desktop, but I haven't found a way. I have tried the following:
Tried 5 different Chrome extensions for sleeping a tab. Unfortunately, when you navigate back into the tab it just refreshes the page rather than resumes it.
Tried using USB Debugging, but the desktop keeps the tab open at all times even if you tab out on mobile, so the tab never sleeps.
Tried running debugger; in the Chrome Developer Tools console, but even if I let the Javascript sit with its execution frozen for 5+ minutes, it never breaks the SSE connection, so I can't test if reconnecting works.
Tried using an extension to kill the internet for Chrome, but miraculously, this still maintains the active websocket/SSE connections. Apparently Google engineers have deprioritized this effort?
Basically, I am looking to simulate the behavior that happens on mobile when you tab out of your web browser, wait a minute, and then tab back in (the Javascript execution is frozen, the SSE connection is broken after a minute or so, and then tabbing back in resumes Javascript and attempts to reconnect the SSE connection).
Is this possible?
I think that best change you have by emulating your android device. You can do so by installing android studio from https://developer.android.com/studio and then here you have all you need to start and manage your virtual android env https://developer.android.com/studio/run/managing-avds
This it the way I debug my whole mobile development
The most obvious solution to me would be to attach a listener that tracks the events related to tab activation and build some custom solution upon that.
Simply:
window.onfocus = () => {
// Restore SSE session
};
window.onblur = function () {
// Inactive
};
Just for info, SSE is a different protocol from websockets.
In case you are interested in using websockets implementation, I suggest the following library which works very well in my experience: https://www.npmjs.com/package/#stomp/stompjs
Stomp is an abstraction over the websocket protocol, but it also means you would need to implement this on the server side as well.
You can use the chrome://discards to freeze your tab.
You should close and restore the connection based on the Page LifeCycle events.
You Can Try to use pause execution
goto:
Chrome javascript console (Ctrl+Shift+J) > sources > pause script (press f8)
This simulates like a mobile tab switching so you can debug easily
I think this is the simple and easy solution. thanks

How to break off an open websocket in Chrome

I noticed that when I run my website remotely, I had a lot of problems due to a websocket closing after being interrupted. However it never happened locally before. So I was wondering if it is possible to close an active websocket in Google Chrome, without using the normal WebSocket.Close(). Because I really want it to be as if it lost connection, and not just onClose

Does service worker runs on background even if browser is closed?

I see push notification for Facebook web in chrome only when I open chrome. I know that this notification are sent through service worker. I am wondering whether this background sync goes on even though browser is closed or only on opening chrome only these service-worker sync process get started and start sending push notification.
First thing to say is this depends somewhat on the platform. My understanding of chrome is:
On desktop platforms like windows and Mac OS X the browser needs to have some background process running for a service worker to be able to run. On Mac OS X this is quite easy to detect as the browser can have no windows open but the browser still has the glowing dot beneath it.
On mobile platforms it's easier to listen for events and handle them in an efficient manner, so in these cases the platform can wake up the browser which will then handle any corresponding events.
The above applies to any service worker api's.
On Desktop: If the browser is completely closed then service workers can not run and will not dispatch any events (i.e. no push or background sync events)
On Mobile: The events will still be dispatched (i.e. background sync will trigger when the users device comes online and push will be received and cause a push event).
I don't think service worker will be able to run if browser is closed. Because service-worker is able to send push notification only after I open the browser. If it is running in the background then it could have send notification even after closing browser also.
Little offtopic but it is possible to write Chrome extension where background script can run if Chrome is allowed to run in the background (configurable in settings). It can also use GCM.
In the context of receiving push messages on desktop, you will receive
messages when the browser is running, i.e. has the marking underneath
the icon.
This means the browser can have no windows open, and you'll still
receive the push message in your service worker, because the browser
in running in the background.
The only time a push won't be received is when the browser is
completely closed, i.e. not running at all (no marking). The same
applies for Windows, although it's a little trickier to determine
whether or not Chrome is running in the background.
source https://web.dev/push-notifications-faq/#why-doesn't-push-work-when-the-browser-is-closed

Categories