Broken Offline Support

The state of offline detection in desktop browsers is broken and it needs to fixed or at least get better, but I can’t see this happening unless we push against the browser vendors to fix this.

Currently, as of April 2011, offline and online events are broken, as is the navigator.onLine property. The only exception appears to be WebKit/MobileSafari on mobile (though I’ve only successfully tested Android’s 2.3.3 and iOS 4.3). Here’s the test url: jsbin.com/otudo5 (source)

Browsers support these events, don’t they?

All the browsers support these events…in a way. In fact, even IE has good broken support for these events for a long time now (pre-IE7?).

When the browser goes in to an offline mode, it’ll fire the offline event. This is currently supported in Opera, IE and Firefox. When the offline event fires, it switches navigator.onLine to read false.

So if this is the state of support, what am I getting my knickers in a twist for? How they get in to “offline mode” is the problem.

Work Offline

The browsers I’ve listed to having an offline mode, only trigger the event when the end user decides to hit the “file” menu and then select the “Work Offline” menu item.

This is not the way this event should work, and it needs to be fixed.

If I’m sat on a train, with a 3G connection to the web, and I run through a black spot of connectivity, I expect the offline event to fire, indicating to the web app that I’m using to run offline. As a developer, I need to be able to handle this event.

Do we really need the event?

Actually, no, but it’s misleading to developers to see these events in the HTML5 spec. At the very minimum we need navigator.onLine to work properly.

There is no situation in Safari & Chrome (i.e. WebKit) that you can get navigator.onLine to return false – that’s pretty darn broken.

Could we do without these events?

I think so.

It would seem to be easier to drop these events from the specification and only support navigator.onLine properly. The problem with the events is that they need something to poll, somewhere to check for connectivity. Polling isn’t great, and I can understand that. Equally, what do you poll? A service could go down. Sure Google probably isn’t ever going to go down…but it might.

How important is it to suddenly announce to the user of your web app “OMG, YOU DON’T HAVE THE INTERNETS!”? I think it’s more appropriate to handle a user initiated activity that requires the Internet with a test against navigator.onLine (where the offline appcache doesn’t already handle the process for us).

It should be straight forward to change navigator.onLine to run a blocking test for connectivity.

I’ve managed to write something similar for Chrome that polyfills navigator.onLine:

navigator.__defineGetter__('onLine', function () {
  // test the connection using try/catch with XHR 
  var onLine = false;
  // make sync-ajax request
  var xhr = new XMLHttpRequest();
  // phone home
  xhr.open('HEAD', '/', false); // async = false
  try {
    xhr.send();
    onLine = true;
  } catch (e) {
    // throws NETWORK_ERR when disconnected
    onLine = false;
  }

  return onLine
});

The reason the polyfill doesn’t work with the other browsers is because they either don’t throw a NETWORK_ERR on the XHR request when the network is down (This is part of the XHR spec, so that’s broken too), or in Safari’s case, you can’t overload the onLine property.

If my XHR hack worked in the other browsers, I wouldn’t be so frustrated with browser support for these events. But it doesn’t fully work, so now the only alternative is to call for browsers to fix their offline event and/or navigator.onLine support.

If you work for a browser vendor, please can you get some eyes on this issue. We developers want to build apps that work correctly without the web to run on your browser, so help us to make it the best it can be.

15 Responses to “Broken Offline Support”

  1. Might be useful to add links to the bug tickets for the different browsers.

    I know this has been reported a long time ago for Chrome. Comment 7 on that page is interesting:

    navigator.onLine and online/offline events are not supported because they are not useful. They only tell you about the status of your immediate network adapter. It doesn’t say anything about whether or not you can actually connect to a server. Your ISP connection may be down for example, and your local operating system would have no idea. Your OS would just be able to tell you that “yes, you have a connection to your router.” WONTFIX

  2. @Mathias – this I didn’t know about. But then the comments continue on to suggest they’re fixing it on Windows…

  3. @Remy: Yeah, luckily the Chrome team had a change of mind. Just saying that what’s described in that comment be one of the reasons browser vendors aren’t actively working on improving offline support.

    Did you file any bugs (or find existing ones) we can subscribe to / vote on?

  4. @Mathias – not yet. Step 1: articulate my thoughts on blog and get some exposure to see if other people are pissed too. Step 2: raise bugs for vendors. Step 3: raise bug on HTML5 spec (which I’m running out of time on!)

  5. My experience with Internet Explorer is that it has triggered online/offline events directly when losing connection, thus having the best support for it.

    It’s an interesting discussion, especially given the above comment regarding detecting true connectivity or not. Personally, though, I think I’d rather have an event-driven design where I can take action/change things around when any of the event gets triggered rather than polling/using assertions to detect navigator.onLine in a lot of spread out code.

  6. As far as I know Firefox < 4 had good support for these events. Whenever the connection dropped, the File > Work Offline menu item appeared checked and offline events were triggered in web pages. When the connection was back again, the reverse happened. However, it seems that Firefox 4 turned off this behaviour, and it can be re-enabled by setting network.manage-offline-status to true in about:config. Not a solution, of course, but makes me wonder why would they ship with this option turned off by default.

  7. @IonuÈ› – I ran some tests early last year whilst I was researching and writing Introducing HTML5, and I found Firefox didn’t fire these events. I’m not saying you’re making it up (at all!), but I wonder if there’s in fact a flag, is it possible there was a default configuration that has this flag set to false, as it is in FF4?

  8. I don’t know for sure if that flag existed before, but the events were surely fired when I was pulling off the internet cable. That was almost instantaneous. There were indeed problems when the connection dropped, but the cable was still plugged, but I’m not sure how to interpret this because even the OS network preference pane reported the connection as being online at that point.

    Anyway, the situation is even worse now, because just as you said, you have to manually enter offline mode. Unplugging the cable or not makes no difference.

    And it matters for other usability issues, like the fact that if my connection drops, I don’t notice and I hit refresh on a web page, I lose that web page, whereas before Firefox would have served me the page from its cache. Now I have to go to the menu and explicitly enter offline mode, then hit refresh again, and maybe I get that page from cache.

  9. Hi @rem,

    It appears that this preference has been turned off by default in Firefox4 because the browser was often unable to report its online status properly (bugs with gnome NetworkManager and when WindowsXP wakes up from hibernation).
    It has been decided that only the user would have the ability to switch between modes.
    The bug “responsible” for this change is the following: https://bugzilla.mozilla.org/show_bug.cgi?id=620472

    I agree that this isn’t ideal. As the easiest way to fix your problems seems to be to fix the NETWORK_ERR bug, I’ll start by making sure that this is reported.

    Regards,

    Louis-Rémi

  10. Firefox throws just fine when send() hits a network error.

    Your problem in the code above is that trying to get a resource while offline is NOT automatically a network error. It’ll work just fine if the resource is cached. And since you always ask for the same resource, chances are it’s cached. Just tossing a random (in the Math.random() sense) query string on the end of the URI you fetch should fix that issue.

  11. Louis-Rémi,

    I think the Chrome team has (had?) the right idea. On/off-line is misleading because the issue is not whether or not the local network is active but whether or not you can access a particular resource.

    Would it not be better to assume that every XHR request is going to timeout or somehow fail at somepoint. Then write your app to first assume that it has failed (used locally cached values, with sensible behaviour when the caches are empty) and update local caches when the data is available? POST/PUT/DELETE requests can handled in a similar fashion; getting a reliable ONLINE event would be beneficial here but workers and polling will work well.

    Adam

  12. @Boris – that’s not the case – don’t worry, I did test it! However – I guess for Louis-Rémi, it looks like it’s been fixed in FF4. I ran my tests in Firefox 3.6 (or whatever was latest). FF3.6 would take 60 seconds for the connection to timeout.

    Either way on all of these points – what’s worth noting is that the mobile devices have the support for these events cracked. If the mobile device can support the events, then a desktop device should be able to too (and by “desktop”, in fact I mean a laptop in my case, which is very mobile, hence the problem).

  13. Please remember that “offline” also means “the server is down” (or the route to the server BTW).

    This could not be automatically handled using these global property and events. That’s why I usually advocate against using navigator.onLine or the events, in addition to what you comment here.

  14. [...] Sharp blogged recently about the issues of the navigator.onLine property and online/offline events. Let see how they can [...]

  15. On Android 2.2 and later you can look at the navigator.connection.type property. If the value = 20 you are offline and anything else means you are on-line. The W3C is pushing this as a way for all browsers to represent connectivity in their DAP.

    http://dev.w3.org/2009/dap/netinfo/

Leave a Reply
Not required

CODE: Please escape code and wrap in <pre><code>, doing so will automatically syntax highlight