1. Introduction
This section is non-normative.
The Geofencing API lets webapps set up geographic boundaries around specific locations and then receive notifications when the hosting device enters or leaves those areas. While it would be possible to implement something similar using the Geolocation API [GEOLOCATION-API], there are a few differences that could make this API a better choice:
-
Because of the limited API surface of the Geofencing API, user agents can implement the API in a more (power) efficient way than could be achieved by regularly checking the current geographic position with the Geolocation API.
-
The Geofencing API is built around Service Workers. This makes it possible for a webapp to receive notifications from the Geofencing API even after the user has closed the webapp.
1.1. Examples
The following code extracts illustrate how to use this API to be notified of geographic regions being entered or left.
// https://example.com/webapp.js navigator.serviceWorker .register('serviceworker.js') .then((swRegistration) => { let region = new CircularGeofenceRegion({ name: 'myfence', latitude: 37.421999, longitude: -122.084015, radius: 1000 }); let options = { includePosition: true }; swRegistration.geofencing.add(region, options) .then( // If more than just a name needs to be stored with a geofence, now // would be the time to store this in some storage. (geofence) => console.log(geofence.id), (error) => console.log(error) ); });
// https://example.com/serviceworker.js self.ongeofenceenter = (event) => { console.log(event.geofence.id); console.log(event.geofence.region.name); // If this is not a geofence of interest anymore, remove it. if (event.geofence.region.name !== "myfence") { event.waitUntil(event.geofence.remove()); } };
// https://example.com/serviceworker.js self.ongeofenceerror = (event) => { console.log(event.geofence.id); console.log(event.geofence.region.name); console.log(event.error); // Some error condition occurred. The region is no longer monitored, and won’t // trigger any more events. // Try to re-monitor, although depending on the error this might fail. event .waitUntil(self.registration.geofencing.add(event.geofence.region)) .then((geofence) => { // re-monitoring succeeded, new geofence will have a different ID. }, (error) => { // re-monitoring failed. }); };
// https://example.com/serviceworker.js // Either look geofence up by name: self.onsomeevent = (event) => { event .waitUntil( self.registration.geofencing.getAll({ name: 'myfence' }) ) .then( geofences => geofences.forEach(fence => fence.remove()) ); }; // Or look geofence up by ID: self.onsomeotherevent = (event) => { let geofence_id = ''; /* somehow get the ID of a geofence */ event .waitUntil(self.registration.geofencing.getById(geofence_id)) .then(geofence => geofence.remove()); };
2. Model
The term webapp#webappReferenced in:1. Introduction (2) (3)3.1. Privacy considerations for implementers of the Geofencing API 4.2. GeofenceManager interface (2) (3) refers to a Web application, i.e. an application implemented using Web technologies, and executing within the context of a Web user agent, e.g. a Web browser or other Web runtime environment.
A service worker registration has an associated list of geofences#list-of-geofencesReferenced in:2. Model2.1. Implementation considerations (2)4.2. GeofenceManager interface (2) (3) (4)4.3. Geofence interface (2) whose element type is a geofence.
A geofence#geofence-termReferenced in:2. Model (2) (3) (4) (5) (6) (7) (8) (9) (10)3.1. Privacy considerations for implementers of the Geofencing API (2) (3) (4)4.2. GeofenceManager interface (2) (3)4.3. Geofence interface (2) (3) (4) (5)4.6.1. The geofenceenter and geofenceleave events 4.6.2. GeofenceErrorEvent is one specific registration of a geograhpic region as a geofence.
A geofence has a name#geofence-nameReferenced in:2.1. Implementation considerations4.2. GeofenceManager interface (a string).
A geofence has an associated geographic region.
A geofence has a geofence ID#geofence-idReferenced in:4.2. GeofenceManager interface (2)4.3. Geofence interface, a string uniquely identifying it. This ID is generated by the user agent and MUST be unique among all geofences associated with all service worker registrations at the same origin. A user agent SHOULD NOT reuse the ID from an old geofence for a new one.
A geofence has an include position#include-positionReferenced in:4.2. GeofenceManager interface4.6.1. The geofenceenter and geofenceleave events flag, a boolean indicating if events associated with this geofence should include the exact geographic position.
A geofence has an associated state#stateReferenced in:3.1. Privacy considerations for implementers of the Geofencing API 4.2. GeofenceManager interface (2)4.3. Geofence interface4.6.2. GeofenceErrorEvent (2), which is one of active#activeReferenced in:2. Model3.1. Privacy considerations for implementers of the Geofencing API 4.2. GeofenceManager interface4.6.2. GeofenceErrorEvent or inactive#inactiveReferenced in:4.2. GeofenceManager interface4.3. Geofence interface4.6.2. GeofenceErrorEvent.
The user agent SHOULD be monitoring all active geofences for breach events.
A geographic region#geographic-regionReferenced in:2. Model (2)4.2. GeofenceManager interface4.3. Geofence interface is a circular region defined by a geographic coordinate representing the center of the region and a radius representing the size of the region.
The geographic coordinate#geographic-coordinateReferenced in:2. Model reference system used by the attributes in this API is the World Geodetic System (2d) [WGS84]. No other reference system is supported.
A geofence is said to be breached#breachedReferenced in:2. Model3.1. Privacy considerations for implementers of the Geofencing API 4.2. GeofenceManager interface4.6.1. The geofenceenter and geofenceleave events (2) (3) (4) (5) if the current geographical location changed from being inside the geographic region to outside (a leave event), or vice versa (an enter event).
2.1. Implementation considerations
A user agent MAY impose limits#name-limitReferenced in:4.2. GeofenceManager interface on the maximum size of a geofence name. If a limit is imposed, this limit SHOULD allow for at least 100 characters.
A user agent MAY impose limits#geofence-limitReferenced in:4.2. GeofenceManager interface on the total number of geofences that can be registered by a single origin. If a limit is imposed, this limit SHOULD allow at least 20 geofences to be registered on a single origin.
3. Security and privacy considerations
The same security and privacy considerations that apply to the Geolocation API [GEOLOCATION-API] also apply to this API. Furthermore since this API effectively gives access to geographic location information after a user has stopped interacting with a webapp, a few other considerations should be taken into account.
3.1. Privacy considerations for implementers of the Geofencing API
User agents MUST NOT provide Geofencing API access to webapps without the express permission of the user. User agents MUST acquire consent for permission through a user
interface for each call to the add(initialRegion, options)
method, unless a
previous permission grant has been persisted, or a prearranged trust relationship applies.
Permissions that are preserved beyond the current browsing session MUST be revocable.
The user agent MAY consider the GeofenceRegion
and/or the GeofenceOptions
when
acquiring permission or determining the permission status.
When a permission is revoked, all geofences added with that permission MUST be deactivated.
When permission is granted for unlimited use of the Geofencing API by a service worker registration, the state of all associated geofences SHOULD be set to active, and the user agent SHOULD start monitoring these geofences for breach events.
When a service worker registration is unregistered, any associated geofences MUST be deactivated.
User agents MUST allow access to the Geofencing API from secure contexts only.
This should somehow mention how the [permissions] API is related to this.
3.2. Privacy considerations for recipients of location information
TODO
3.3. Additional implementation considerations
This section is non-normative.
TODO
4. API Description
4.1. Extensions to the ServiceWorkerRegistration
interface
The Service Worker specification defines a ServiceWorkerRegistration
interface, which
this specification extends.
partial interface ServiceWorkerRegistration { readonly attribute GeofenceManager geofencing; };
4.2. GeofenceManager
interface
The GeofenceManager
interface defines operations that enable webapps to establish access to geofencing services.
[NoInterfaceObject] interface GeofenceManager#geofencemanagerReferenced in:4.1. Extensions to the ServiceWorkerRegistration interface 4.2. GeofenceManager interface (2) (3) (4) (5) { Promise<Geofence> add(GeofenceRegion initialRegion, optional GeofenceOptions options); Promise<sequence<Geofence>> getAll(optional GeofenceQueryOptions options); Promise<Geofence> getById(DOMString id); }; dictionary GeofenceOptions#dictdef-geofenceoptionsReferenced in:3.1. Privacy considerations for implementers of the Geofencing API 4.2. GeofenceManager interface { boolean includePosition = false; }; dictionary GeofenceQueryOptions#dictdef-geofencequeryoptionsReferenced in:4.2. GeofenceManager interface { DOMString? name; };
A GeofenceManager
has an associated service worker registration, represented by the ServiceWorkerRegistration
instance on which the GeofenceManager
was exposed.
The add(initialRegion, options)#dom-geofencemanager-addReferenced in:3.1.
Privacy considerations for implementers of the Geofencing API 4.2. GeofenceManager interface
method when invoked MUST return a new promise promise and run the following steps in parallel:
- Let serviceWorkerRegistration be the
GeofenceManager
's associated service worker registration. - If initialRegion is not a
CircularGeofenceRegion
instance, reject promise with aTypeError
. - If the length of the
name
property of initialRegion exceeds a user agent defined limit, reject promise with aRangeError
. - If the
latitude
property of initialRegion is less than-90
or greater than90
, reject promise with aRangeError
. - If the
longitude
property of initialRegion is less than-180
or greater than180
, reject promise with aRangeError
. - If the total number of geofences for all service worker registrations in the current origin
is more than the user agent defined limit, reject promise with a
QuotaExceededError
and terminate these substeps. - Let geofence be a new geofence.
- Set the geofence ID of geofence to a newly generated value.
- Set the geographic region of geofence to a the region represented by initialRegion.
- Set the include position flag of geofence to options.includePosition, or
false
if no options were specified. - Set the state of geofence to inactive.
- Add geofence to the list of geofences associated with serviceWorkerRegistration.
- Resolve promise with a new
Geofence
instance representing geofence. - Ask the user whether they allow the webapp to monitor geofences, unless a prearranged trust relationship applies or the user has already granted or denied permission explicitly for this webapp to use this API.
-
If permission is not granted, invoke the Handle Functional Event algorithm with serviceWorkerRegistration and the algorithm represented by
the following substeps as arguments.
- Let globalObject be the global object these steps are invoked with.
- Create a trusted event event that uses the
GeofenceErrorEvent
interface, with event typegeofenceerror
. - Let the
geofence
atrribute of event be initialized to a newGeofence
instance representing geofence. - Let the
error
attribute of event be initialized toPermissionDeniedError
. - Dispatch event at globalObject.
-
Else if permission is granted, run the following substeps:
- Set the state of geofence to active and start monitoring the geofence for breach events.
- If the current geographic position is inside the newly added region, fire a geofenceenter event.
Somehow mention that the region that is saved as part of the registration can be slightly different from the region passed to register. An implementation may adjust parameters to be in range of what is possible, or otherwise modify the region.
If the includePosition#dom-geofenceoptions-includepositionReferenced in:4.2. GeofenceManager interface
attribute is set to true, GeofenceEvent
s for this registration will have a position
attribute. When set to false, the position
attribute will always be undefined.
The getAll(options)#dom-geofencemanager-getallReferenced in:4.2. GeofenceManager interface
method when invoked MUST return a new promise promise and run the following steps in parallel:
- Let geofences be a new
sequence
. - For each geofence geofence in the list of geofences associated with this service worker registration, run the following substeps:
- Resolve promise with geofences.
The getById(id)#dom-geofencemanager-getbyidReferenced in:4.2. GeofenceManager interface
method when invoked MUST return a new promise promise and run the following
steps in parallel:
-
For each geofence geofence in the list of geofences associated
with this service worker registration, run the following substeps:
- If the geofence ID of geofence is not equal to the passed in id, skip the rest of these substeps and continue with the next geofence.
- Resolve promise with a new
Geofence
instance representing geofence.
- If promise was not resolved, resolve promise with
null
.
4.3. Geofence
interface
An instance of the Geofence
interface represents a geofence.
[Exposed=(Window,Worker)]
interface Geofence#geofenceReferenced in:4.2. GeofenceManager interface (2) (3) (4) (5) (6) (7)4.3. Geofence interface (2) (3)4.6.1.
The geofenceenter and geofenceleave events
(2)4.6.2. GeofenceErrorEvent (2) {
readonly attribute DOMString id;
readonly attribute GeofenceRegion region;
Promise<boolean> remove();
};
When getting the id#dom-geofence-idReferenced in:4.3. Geofence interface
attribute, the user
agent MUST return the geofence ID of the geofence.
When getting the region#dom-geofence-regionReferenced in:4.3. Geofence interface
attribute, the user agent MUST return the geographic region of this geofence.
The remove()#dom-geofence-removeReferenced in:4.3. Geofence interface
method when invoked
MUST return a new promise promise and run the following steps in parallel:
- Let geofence be the geofence represented by this
Geofence
instance. - If geofence is not currently in the list of geofences associated with a service worker registration, resolve promise with
false
and abort the remainder of these steps. - Remove geofence from the list of geofences associated with the current service worker registration. No more events related to this geofence will be fired after this.
- Set the state of geofence to inactive, but do not trigger the steps that are normally triggered when a geofence is deactivated.
- Resolve promise with
true
.
4.4. GeofenceRegion
interface
[Exposed=(Window,Worker)] interface GeofenceRegion#geofenceregionReferenced in:3.1. Privacy considerations for implementers of the Geofencing API 4.2. GeofenceManager interface4.3. Geofence interface4.4. GeofenceRegion interface4.5. CircularGeofenceRegion interface { readonly attribute DOMString name; }; dictionary GeofenceRegionInit#dictdef-geofenceregioninitReferenced in:4.4. GeofenceRegion interface4.5. CircularGeofenceRegion interface { DOMString? name#dom-geofenceregioninit-nameReferenced in:4.4. GeofenceRegion interface; };
The name#dom-geofenceregion-nameReferenced in:4.2. GeofenceManager interface4.4. GeofenceRegion interface
attribute MUST return
the value it was initialized to. When the object is created, this attribute MUST be set to the
value of the name
property in the GeofenceRegionInit
dictionary, or
an empty string if that property wasn’t set.
4.5. CircularGeofenceRegion
interface
[Constructor(CircularGeofenceRegionInit init), Exposed=(Window,Worker)] interface CircularGeofenceRegion#circulargeofenceregionReferenced in:4.2. GeofenceManager interface4.5. CircularGeofenceRegion interface (2) : GeofenceRegion { readonly attribute double latitude; readonly attribute double longitude; readonly attribute double radius; }; dictionary CircularGeofenceRegionInit#dictdef-circulargeofenceregioninitReferenced in:4.5. CircularGeofenceRegion interface : GeofenceRegionInit { double latitude; double longitude; double radius; };
The CircularGeofenceRegion
constructor when invoked MUST initialize the properties of the
newly created object to the corresponding attributes in the initializer.
The latitude#dom-circulargeofenceregion-latitudeReferenced in:4.2. GeofenceManager interface4.5. CircularGeofenceRegion interface
attribute
MUST return the value it was intialized to. This value represents the latitude in
circular degrees of the center of the circular region.
The longitude#dom-circulargeofenceregion-longitudeReferenced in:4.2. GeofenceManager interface4.5. CircularGeofenceRegion interface
attribute MUST return the value it was intialized to. This value represents the longitude
in circular degrees of the center of the circular region.
The radius#dom-circulargeofenceregion-radiusReferenced in:4.5. CircularGeofenceRegion interface
attribute MUST
return thev value it was initialized to. This value represents the radius in meters of the
circular region.
4.6. Events
The Service Worker specification defines a ServiceWorkerGlobalScope
interface, which this
specification extends.
partial interface ServiceWorkerGlobalScope { attribute EventHandler ongeofenceenter; attribute EventHandler ongeofenceleave; attribute EventHandler ongeofenceerror; };
The ongeofenceenter#dom-serviceworkerglobalscope-ongeofenceenterReferenced in:4.6. Events
attribute is
an event handler whose corresponding event handler event type is geofenceenter#geofenceenterReferenced in:4.6.1.
The geofenceenter and geofenceleave events
.
The ongeofenceleave#dom-serviceworkerglobalscope-ongeofenceleaveReferenced in:4.6. Events
attribute is
an event handler whose corresponding event handler event type is geofenceleave#geofenceleaveReferenced in:4.6.1.
The geofenceenter and geofenceleave events
.
The ongeofenceerror#dom-serviceworkerglobalscope-ongeofenceerrorReferenced in:4.6. Events
attribute is
an event handler whose corresponding event handler event type is geofenceerror#geofenceerrorReferenced in:4.2. GeofenceManager interface4.6.2. GeofenceErrorEvent
.
4.6.1. The geofenceenter
and geofenceleave
events
The GeofenceEvent
interface represents a geofence being breached.
[Exposed=ServiceWorker] interface GeofenceEvent#geofenceeventReferenced in:4.2. GeofenceManager interface4.6.1. The geofenceenter and geofenceleave events (2) : ExtendableEvent { readonly attribute Geofence geofence#dom-geofenceevent-geofenceReferenced in:4.6.1. The geofenceenter and geofenceleave events ; readonly attribute Position? position#dom-geofenceevent-positionReferenced in:4.2. GeofenceManager interface (2)4.6.1. The geofenceenter and geofenceleave events ; };
Upon detecting a breach of a geofence geofence, the user agent MUST run the following steps to fire a geofence event#fire-a-geofence-eventReferenced in:4.2. GeofenceManager interface4.6.1. The geofenceenter and geofenceleave events :
- Let serviceWorkerRegistration be the service worker registration geofence is associated with.
-
Invoke the Handle Functional Event algorithm with serviceWorkerRegistration and the algorithm represented by the following substeps as arguments.
- Let globalObject be the global object these steps are invoked with.
- Let eventType be
geofenceenter
orgeofenceleave
, corresponding to the type of breach event being processed. - Create a trusted event event that uses the
GeofenceEvent
interface, with event type equal to eventType. - Let the
geofence
atrribute of event be initialized to a newGeofence
instance representing geofence. - If the include position flag of geofence is true, set the
position
attribute of event to the current geographical position. - Dispatch event at globalObject.
The user agent MAY delay firing a geofence event until some time and/or distance has passed after the breach was detected to make sure that the geofence really was breached.
4.6.2. GeofenceErrorEvent
[Exposed=ServiceWorker] interface GeofenceErrorEvent#geofenceerroreventReferenced in:4.2. GeofenceManager interface4.6.2. GeofenceErrorEvent (2) : ExtendableEvent { readonly attribute Geofence geofence#dom-geofenceerrorevent-geofenceReferenced in:4.2. GeofenceManager interface4.6.2. GeofenceErrorEvent; readonly attribute DOMString error#dom-geofenceerrorevent-errorReferenced in:4.2. GeofenceManager interface4.6.2. GeofenceErrorEvent; readonly attribute DOMString message#dom-geofenceerrorevent-messageReferenced in:4.6.2. GeofenceErrorEvent; };
When a geofence geofence is deactivated#deactivatedReferenced in:3.1. Privacy considerations for implementers of the Geofencing API (2)4.3. Geofence interface, the user agent SHOULD run the following steps:
- Let serviceWorkerRegistration be the service worker registration geofence is associated with.
- Let oldState be the state of geofence.
- Set the state of geofence to inactive.
-
If oldState is active, invoke the Handle Functional Event algorithm with serviceWorkerRegistration and the algorithm represented by
the following substeps as arguments.
- Let globalObject be the global object these steps are invoked with.
- Create a trusted event event that uses the
GeofenceErrorEvent
interface, with event typegeofenceerror
. - Let the
geofence
atrribute of event be initialized to a newGeofence
instance representing geofence. - Let the
error
attribute of event be initialized to an error name. - Let the
message
attribute of event be initialized to a descriptive message for the error that occurred. - Dispatch event at globalObject.
5. Exceptions
The Geofencing API uses the new PermissionDeniedError
DOMException
name.