State of the Network Information API specification

Hi,

There has been a lot of discussions lately regarding the Network
Information API. I took some time today to think about what has been
said and how it could be solved.

The first part of the API is the 'bandwidth' attribute. The intent of
the specification with this attribute is to have a clear way to check if
a client has enough speed to do a certain type of actions.

A few use cases would be: I want to provide high resolution images by
default if the client has a bandwidth of at least X kb/s; or, I want to
automatically fetch email attachments if the client has at least X kb/s
(to not kill its connection); even, I will not try to sync emails if the
client has less than X kb/s of bandwidth (think of fetching emails when
you are on Edge).

It is up to the user agent to decide how the bandwidth is computed. It
might indeed be hard to have a precise bandwidth for each domain the
client is accessing but this is actually not the intent of the
specification. The user agent should provide something that has enough
precision to be usable (not 1 Mb/s precision for example) but it doesn't
need to be very precise (like 1 kb/s precision).

The spirit of the specification is that the vendors will come up with
more or less sophisticated implementations.
For example, the experimental implementation in Firefox for Android is
simplistic and has space for improvements. We currently have hard-coded
values that are returned depending on the connection type. There are
different ways to improve that: we can randomize the returned value, we
can have steps (there is no need to differentiate 22kb/s and 28kb/s for
example). A more complex way to improve that would be to estimate the
bandwidth while Firefox is running (on a given Mozilla server for
example) and use it as a value for all websites. Actually, that kind of
information could be used by a mobile browser for various reasons.
None of those improvements would fully follow the specifications because
the estimation wouldn't be compared to the current document but to an
arbitrary server. However, those improvements are not complex and would
make the implementation closer to the ideal one without having to change
the specification nor the web pages.

The only alternative I've been able to come up with is to change the
bandwidth attribute to an enum. The enum might look like it would ease
the implementation complexity but this is not really the case. In
addition, it would make the attribute's behaviour hard to specify so
hard to understand for the authors.

Indeed, we could have something like { "slow", "fast" } or {
"very-slow", "slow", "fast", "very-fast" } but "slow" or "fast" have a
relative meaning. The speed of a connection depends on what you want to
do, the type of connection you have and the country you are in, etc. It
is very hard for a user agent to know if a website will consider a given
connection speed as fast or slow.

In addition, using an enum wouldn't really ease the implementation, it
will just be less visible that the implementation is simplistic: it is
very simple to see that an implementation is returning pre-defined
values for the bandwidth as a double but it is harder to see that if the
bandwidth is an enum.

In my opinion, the only real alternative to the current bandwidth
specification is to simply remove it from the specification because it
is proven unrealistic and not implementable. Although that has often
been said, no actual implementer came here to give its feedback.
Therefore, I think the attribute should stay as-is until an implementer
formally express its incapacity to implement it - taking in
consideration what has been said above.

Regarding the second attribute, 'metered', I think the intent of the
specification has often been misunderstood. The attribute should return
true if the connection is sensitive to heavy data usage. Again, that
doesn't mean that any connection with a cap should be marked as metered.
If the cap is at 100GB, there is no point in marking it metered as long
as the user is far from the 100GB.

The use cases for this attribute are pretty much obvious and very useful
in a mobile word. It can be summarized as preventing [large] downloads
while using a metered connection. Typical examples would be app updates,
email fetching, synchronisation frequency...

As bandwidth, the metered attribute has been said to be not
implementable. Currently, the Firefox for Android implementation simply
mark mobile data connections as metered and others as not metered. This
is indeed a poor implementation. However, since this specification has
been written, Android came with an API to get that information [1], such
as Windows 8 [2]. This make this attribute easily implementable on those
platforms and is a proof that it is actually implementable.

In addition, as for bandwidth, even if the first implementations are not
perfect, metered can always be improved. An implementation like the one
in Firefox for Android is always better than nothing and it is possible
to improve it with the Android API now.
The implementation could have been/be improved also by an option in the
user interface to mark the current connection as metered. Maybe even
having a first run experience that asked the user if his/her mobile
connection is metered.

There were two major ideas to improve this behaviour of the metered
attribute. The first one is to make it more granular: how bad is it
metered? or why is it metered? As much as I agree that could be an
interesting idea, in practice, it is likely too early to go that far. I
think introducing another attribute later like "meteringType" if needed
would be a better idea.

The other idea was to make metered a tri-state: { true, false, unknown
}. I think that could be interesting but I see two major culprits
because of the fact that such a tri-state would require 'true' or
'false' to be always exact and 'unknown' being the fallback value
(otherwise, unknown would be useless):
- you can't rely on implementations to have something not perfect and
improve over time because strictly following the specification, most of
them would have to return 'unknown' for the moment;
- using an API like the one in Android that only returns true/false
would be a violation from the specification because it is certain that
Android doesn't know for sure and fallback to a value or an heuristic.
I also think that having an 'unknown' value wouldn't help web developers
because they will not be able to know what to do if the returned value
is 'unknown'. Likely, they will follow the true or false path. Relying
on the user agent to do the right thing seems better for everybody I
believe.

I would be really interested in feedback. If you are implementing or
tried to implement this specification, I would love to hear about your
experience.

[1]
https://developer.android.com/reference/android/net/ConnectivityManager.html#isActiveNetworkMetered%28%29
[2] http://msdn.microsoft.com/en-us/library/windows/apps/hh465399.aspx#adapt

Thank you for reading.

--
Mounir

Received on Thursday, 24 January 2013 20:57:34 UTC