(This is an extension to my proposal for the NetworkInformation.type enum at w3c/netinfo#9 to cover edge cases. Licensed as CC0 / public domain.)
The Network Information API is designed to allow websites / WebApps to change their behaviour depending on the type of connection their device has. Discriminating by whether you are currently connected via WiFi or 3G, however, provides a footgun to developers: E.g. when you are roaming and tethering to your smartphone but your device indicates it's on a WiFi connection, you may assume that the user is on a high-bandwith, low-latency, low-cost connection but the exact opposite is the case.
Furthermore, the proposal to just expose "ethernet", "wifi", "cellular",
"bluetooth", and "unknown" limits the spec to currently (= at time of
specification) known networking methods (while it does not even cover all known
link types, e.g. IrDA, USB Wireless, ZigBee, …), and lumps together operating
modes (e.g. ad-hoc) of these connections.
Hence the cellular
vs local
vs personal
network classification.
Some use cases may however require the knowledge of the exact link type and operating mode. And in the spirit of the extensible web manifesto, I'd like to introduce the NetworkLink interface.
Fancy WebIDL(-ish):
[Exposed=Window,Worker]
interface NetworkLink : EventTarget {
readonly attribute LinkType type;
readonly attribute OperationMode mode;
readonly attribute unsigned long maxBandwith; // see below
attribute EventHandler onlinkchange;
};
partial interface NetworkInformation {
readonly attribute NetworkLink link;
};
enum LinkType {
"ethernet",
"wifi",
"mobile",
"bluetooth",
"other",
"none"
};
// this is for illustration purposes only, and should probably be just a string
enum OperationMode {
// for type == 'ethernet'
"10BASE",
"100BASE",
"1000BASE",
"10GBASE",
// for type == 'wifi'
"a",
"g", // etc.
"g-adhoc", // etc.
"n-direct", // etc.
"ac",
// for type == 'mobile'
"GPRS",
"EDGE",
"3G",
"HSPA", // or "3.5G"?
"LTE",
"CDMA",
// for type == 'bluetooth'
"LAP", // etc.
// this value denotes "unkown" or "other" and is valid for all link types
// it may also be used by implementations to avoid fingerprinting
"" // empty string
};
Most of this should be pretty self-explanatory (for the purpose of this
proposal). Whenever the type
, mode
, or maxBandwith
attributes change, the
linkchange
event is fired on the NetworkLink
interface (it may bubble to
NetworkInformation
if that provides any value – might also be worthwhile to
think about moving this up the chain).
The maxBandwith
attribute is not intended to indicate any real-world
connection speed. Instead, it should indicate the maximum theoretically
achievable connection speed with the current type of link and hardware, in
bps. This value may not map directly to an OperationMode
, and is determined
by the current hardware state, as long as this information is available. E.g.
it may be known that an 802.11n-capable device has only one antenna and thus
cannot achieve 600Mbps at all, or (sometime in the future) a mobile connection
can be queried for a metered bandwith. 3G
also has different levels of max
bandwith (the flavors of HSPA) which the hardware knows about. A value of 0
denotes an unknown maxBandwith
.
The attribute is not guaranteed to provide an "actionable" value. It may
provide value in situations where the connection speed is known to be slow or
very slow (e.g. GPRS, EDGE) without introducing arbitrary classifications of
slowness. Best guess for implementers is to always provide a value of 0
which
should be fully conforming to the spec.
var link = navigator.connection.link.type;
var mode = navigator.connection.link.mode;
var maxBandwith = navigator.connection.link.maxBandwith;
var nonlocal = (navigator.connection.type === 'cellular') || (navigator.connection.type === 'personal');
if (maxBandwith === 0) {
console.log("I don't know how fast I can go!");
}
else if (nonlocal && maxBandwith > 200000) {
// we are likely on a reasonably fast mobile connection
console.log("link type: " + link);
console.log("link mode: " + mode);
}
else if (navigator.connection.type === 'local')
console.log("This is your best guess for large-ish downloads.");
}
By far the most developers should only need the cellular
, local
, or
personal
connection type. The extra depth provides an API-level "safeguard"
and distinction between "actionable" values and hardware state.
Also, mixing connection
and link
information may be confusing.
No. This proposal is intended as a discussion basis.
Feel free to extend the lists. Especially the OperationMode
is for
illustration purposes only, and should probably be a custom string.
cellular
can cover more than what's known as mobile
(in the sense of GSM,
and whoever is responsible for CMDA2000 and EV-DO), it's also more in line with
local
and personal
. The link type however is indeed a GSM(-like) network,
thus mobile
.
Please comment below or contact me on Twitter.
I'm happy to hear your thoughts!