1. Introduction
Contact pickers are frequently seen in native mobile applications for a variety of use cases, and in various desktop applications such as e-mail clients and calendars.
This specification defines an API to bring contact pickers to the web. The contact picker model was chosen to give full control to users over the shared data, allowing users to choose exactly which contacts to provide to the website. The contact picker model also gives websites one-off access to a user’s contacts, meaning developers have to request access to the user’s contacts every time they need it. This differs from some native contact APIs, but is necessary for ensuring users' contacts are not accessed without their knowledge and explicit consent.
1.1. Use cases
-
Bootstrapping a user’s social graph for social networks.
-
Selecting the recipients of a message within an e-mail application.
1.2. Example
selectRecipientsButton. addEventListener( 'click' , async() => { const contacts= await navigator. contacts. select({ properties: [ 'name' , 'email' ], multiple: true , }); if ( ! contacts. length) { // Either no contacts were selected in the picker, or the picker could // not be launched. Exposure of the API implies expected availability. return ; } // Use the names and e-mail addresses in |contacts| to populate the // recipients field in the website’s UI. populateRecipients( contacts); });
In the above example selectRecipientsButton is a HTMLButtonElement, and populateRecipients is a developer-defined function.
2. Privacy Considerations
Exposing contact information has a clear privacy impact, in terms of exposing PII of uninvolved parties. A picker model is enforced so that the user agent can offer a user experience that makes it clear what information is going to be shared with the website and when.
The following constraints are also enforced:
-
The API is only available in a top-level browsing context which must also be a secure context. These restrictions help ensure that the provided contact information reaches its intended recipient.
-
A user gesture is needed to initiate the API, to disallow programmatic requests to the user’s contacts.
3. API Description
3.1. Extensions to Navigator
[Exposed =(Window ,SecureContext )]partial interface Navigator {readonly attribute ContactsManager ; };contacts
3.2. ContactsManager
dictionary {ContactInfo sequence <USVString >;name sequence <USVString >;sequence <USVString >; };tel enum {ContactProperty ,"email" ,"name" };"tel" dictionary {ContactsSelectOptions required sequence <ContactProperty >;properties boolean =multiple false ; }; [Exposed =(Window ,SecureContext )]interface {ContactsManager Promise <sequence <ContactInfo >>select (ContactsSelectOptions ); };options
3.2.1. select()
select(options) method, when invoked, runs these steps:
-
Let promise be a new
Promise. -
Let selectQueue be a new parallel queue.
-
If the browsing context is not a top-level browsing context, then return a promise rejected with an
InvalidStateErrorDOMException. -
If the algorithm is not triggered by user activation then return a promise rejected with a
SecurityErrorDOMException. -
Enqueue the following steps to selectQueue:
-
Launch a new contact picker with select options set to options. If this fails, then reject promise with an
InvalidStateErrorDOMExceptionand abort these steps. -
Wait for contact picker's contacts selected flag to be set.
-
Resolve promise with contact picker's selected contacts.
-
-
Return promise.
4. Contact Picker
A contact picker instance consists of:
-
A contacts selected flag, initially unset.
-
Selected contacts (a list of
ContactInfos), initially empty. -
Select options (a
ContactsSelectOptions), initially undefined.
Note: It is up to the user agent to choose the source of the contact information displayed in the picker.
-
The UI MUST prominently display the browsing context's origin.
-
The UI MUST make it clear which
propertiesof the contact will be shared. -
The UI MUST provide a way to select individual contacts. If select options'
multiplemember is false, only one contact should be pickable. -
The UI MUST provide an option to cancel/return without sharing any contacts, in which case set contacts selected flag.
-
The UI MUST provide an a way for users to indicate that they are done selecting, in which case complete contact picker.
4.1. Complete contact picker
-
For each selectedContact of the user’s chosen contacts:
-
Let contactInfo be a new
ContactInfo. -
If select options'
propertymember contains `name`, then:-
Append all name data in selectedContact to contactInfo’s
namemember.
-
-
If select options'
propertymember contains `email`, then:-
Append all email data in selectedContact to contactInfo’s
emailmember.
-
-
If select options'
propertymember contains `tel`, then:-
Append all telephone data in selectedContact to contactInfo’s
telmember.
-
-
Append contactInfo to selected contacts.
-
-
If select options'
multiplemember is false, and selected contacts' size is greater than 1, then remove all items not equal to selected contacts[0].
TODO: Add more details about shared contact info.