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
InvalidStateError
DOMException
. -
If the algorithm is not triggered by user activation then return a promise rejected with a
SecurityError
DOMException
. -
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
InvalidStateError
DOMException
and 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
ContactInfo
s), 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
properties
of the contact will be shared. -
The UI MUST provide a way to select individual contacts. If select options'
multiple
member 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'
property
member contains `name
`, then:-
Append all name data in selectedContact to contactInfo’s
name
member.
-
-
If select options'
property
member contains `email
`, then:-
Append all email data in selectedContact to contactInfo’s
email
member.
-
-
If select options'
property
member contains `tel
`, then:-
Append all telephone data in selectedContact to contactInfo’s
tel
member.
-
-
Append contactInfo to selected contacts.
-
-
If select options'
multiple
member 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.