This specification defines an API to manage telephone calls. A typical use case of the Web Telephony API is the implementation of a 'Dialer' application supporting multiparty calls and multiple telephony services.
Implementors should be aware that this specification is not stable. Implementors who are not taking part in the discussions are likely to find the specification changing out from under them in incompatible ways. Vendors interested in implementing this specification before it eventually reaches the Candidate Recommendation stage should join the aforementioned mailing lists and take part in the discussions.
Significant changes to this document since last publication are documented in the Changes section.
The Web Telephony API allows applications to manage interaction with telephony call signaling, but does not handle audio channels management.
An example of making a telephony call is provided below:
var telCall = navigator.telephony.dial('+1234567890'); telCall.onactive = function(e) { window.console.log('Connected!'); } telCall.ondisconnected = function(e) { window.console.log('Disconnected!'); // update call history } telCall.onerror = function(e) { window.console.error(e); }
The use cases for this specification are collected in the wiki page of this API.
The following specifications informed the design of the Web Telephony API: for GSM the [[!GSM-CALL]] suite, for IMS/SIP the [[!IMS]] suite, for XMPP the [[!JINGLE]] specification. Note, however, that IMS/SIP and XMPP are not supported in this version.
It is likely that the same API would work also for SIP and XMPP calls with the exception of multiparty call handling, which is modeled after the cellular multiparty calls. Future versions of this specification will probably add SIP and XMPP conference support.
It is under discussion whether a system message should be propagated when a CDMA telephony call is active, since not all CDMA networks support concurrent services. Therefore, many applications will lose their data connection when the end user is in a voice call.
This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.
Implementations that use ECMAScript to implement the APIs defined in this specification MUST implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [[!WEBIDL]], as this specification uses that specification and terminology.
This specification depends on the following interfaces and concepts defined in other specifications.
The following dependencies are defined in [[!HTML]]:
EventHandler
interface, queue
a task, event
handler, origin,
task
source.
The following dependencies are defined in [[!DOM4]]: the Event
and
the Promise
interfaces, the concepts of a resolver,
fire an
event.
A telephony service manages telephony operations associated with a subscriber identity, which is registered with a telephony service provider. For example, in cellular telephony, a telephony service is associated with SIM card (Subscriber Identity Module). A telephony service can use different protocols for telephony signaling and media (e.g. GSM, CDMA, VoLTE, etc.) with the same identity.
Each telephony service has a unique telephony service id, which identifies a telephony service together with a user identity in the system. For telephony services that make use of a SIM card, it is RECOMMEDED that the ICC-ID be used for the service identifier.
It is strongly RECOMMENDED a implementations do not use use the MSISDN as the telephony service id. The MSISDN cannot guarantee uniqueness.
A user agent can access zero or more telephony services. Which telephony services are available to the user agent is dictated by policy, or by the user choosing which services are available to the user agent. When one or more telephony services is available to the user agent, one serves as the default telephony service.
In the API, telephony services are represented by a DOMString that maps to a telephony service id for each telephony service available to an origin.
Access to a telephony service by any origin is restricted by a security policy. See the security and privacy considerations section for more details.
A telephony service observes the call states of a telephony call in the supported telephony backend(s) and networks and reflects those changes in the API through [[!DOM4]] events and promises.
Telephony services can be added or removed from the system at any time (e.g., the user pops out the SIM card or adds a different SIM card; the user tells the system to only allow certain applications to access a particular telephony service, etc.).
When a telephony service is either added or removed in the system, the user agent MUST run the steps to change the telephony service:
serviceremoved
if the
telephony service was removed, or serviceadded
otherwise.
The default telephony service is the telephony service that serves as default for telephony operations for the origin of an application. The default telephony service can be changed by the user, and if supported, through the changeDefaultService() method of the TelephonyManager object.
If there is no default telephony service for the origin, the user agent SHOULD use the system's default telephony service, if available and if allowed by policy. If there are no telephony services available to use as the default for the origin, the default telephony service is null.
When there is a need to changes default telephony service, the user agent MUST:
null
otherwise.
defaultchanged
, which does not bubble, is
not cancelable, has no default action, and whose serviceId
attribute to service id.
A telephony call results from a telephony service's attempt to establish a connection for communication between two or more parties. Telepony calls involving more than two parties are referred to as a multiparty call.
In the process of establishing and maintaining a connection between multiple parties, a telephony call transitions through various call states. A telephony call is always in some call state, which can change over time.
Telephony calls initiated by a telephony service of the system is an outbound call. Conversely, a telephony calls from a remote party is an inbound call.
Every telephony call has a call id, which is a string that uniquely identifies the call and call history.
An active call is a Call in the active state representing a connected call which is bound to the media input and output devices (e.g. microphone, speaker, tone generator). Note that a call on hold is also active from a call signaling point of view, but not bound to media input and output devices.
Whenever a call is added to or removed from the calls array,
the user agent MUST queue a task to fire an
event named callschanged
.
Within the API, a telephony call is represented by the Call typedef - which encapsulates both objects that implement the TeleponyCall interface and the ConferenceCall interface.
Call
typedef
A multiparty call (also commonly referred to as a conference call) is a telephony call with multiple remote party participants, which is controlled as a single telephony call, i.e. it can be held, activated, disconnected from all participants. Other calls can be joined with a multiparty call.
Every multiparty call has a unique conference id that identifies a multiparty call in the system.
A remote party id uniquely identifies a participant (a.k.a. remote party) in a telephony call in the given telephony service, such as a phone number.
This of the API version supports GSM multiparty calls and CDMA 3-way calls.
In the API, a multiparty call is represented by any object that implements the ConferenceCall interface.
The following needs to be described in an algorithm: For multiparty
calls, the implementation MUST generate a unique identifier stored in
the callId
attribute. In GSM, the callId
of
any participating call could be used in a multiparty operation, and
the telephony network will reply with using the same value. But for
forward compatibility reasons, the implementation MUST generate a
separate callId
value for the multiparty call, which
MUST be unique in the system and the local call history. For GSM
multiparty functionality, The implementation MUST map this to an
appropriate transaction identifier accepted by the telephony service.
Also, the transaction identifiers received from the network MUST be
mapped back by the implementation to the unique conference call
identifier of the multiparty call.
A call state represents the state of interaction between a telephony service, the telephony network, the API, and one or more remote parties.
Within the API, the call states are represented by the
CallState
enum.
The call states referenced in this API are:
Whenever there is a change in the state attribute the user agent MUST:
statechange
with the new value of the state
attribute.
Since call state transitions depend on protocol, network equipment, modem, etc., the implementation MUST NOT fire error events on assumed erroneous state transitions. MUST always re-synchronize any eventual internal states to the current call state reported by the telephony system. The implementation MUST NOT set the call state to any other value than specified in the descriptions of the methods of this interface.
Since call states can differ depending on the protocol, do we need to expose the service and the protocol used for making the call? See issue 125.
Note that compliant implementations may not be reporting such events when they occur (e.g. OTA SIM update or hot-swappable SIM cards). See issue 127.
CallState
enum
enum CallState { "dialing", "connecting", "alerting", "active", "incoming", "waiting", "accepted", "holding", "held", "resuming", "redirecting", "transferring", "disconnecting", "disconnected", "joining", "multiparty", "splitting" };
Some of these states are soft states, that is, transitory states in which the application is placed after making a request to the telephony system and until it is completed. For instance the application remains in "holding" state since it invokes the hold() method and until the telephony system actually holds the call. In some implementations these soft states can be skipped. The following are the soft states defined by this specification: "accepted", "disconnecting", "holding", "resuming".
On the contrary, hard states MUST be supported by the implementation: "dialing", "alerting", "active", "disconnected", "incoming", "waiting", "held". For calls participating in multiparty calls, the following additional call states MUST be supported: "joining", "splitting", "multiparty". For call transfer functionality, the additional "transferring" state MUST be supported.
The device can receive phone calls from any active telephony service, even simultaneously, in which case the user agent arbitrates the calls either by a policy, or by the user by choosing which call to accept.
For call setup on received calls, the following call states MUST be supported in this order:
On received calls, telephony protocols also use a "ringing" state, set by the mobile terminal when local call alerting starts, in order to notify the remote party about the ongoing alerting (ringing can actually be e.g. a beep, ring tone, or vibration pattern). This is considered to be responsibility of implementations: if the modem expects this state to be set, implementations MUST make sure to set it. Dialer applications are not expected to set this state in the current version of the specification.
CDMA cannot report all these states in the expected sequence. The ‘connected’ state (i.e. when the mobile station send the Service Connect Completion Message or Connect Order, depending on whether the call is mobile originated or terminated) is immediately followed by voice media transmission – there is transition to ‘active’ before the media arrives. Therefore it should be up to the implementation to determine which events to fire and in which order. Dialer applications need to be prepared to handle such cases.
Upon a new incoming or waiting call, the user agent MUST execute the following steps:
state
of incomingCall to
"incoming" in case there is no other call in active
state, or otherwise set
it to "waiting".
statechange
at the incomingCall object.
incoming
at the TelephonyManager object
managing the call.
callschanged
at the TelephonyManager object
managing the call.
The following needs to be redefined algorithmically in terms of the telephony service.
To make a call with a remote party identifier, optionally a telephony service, and optionally a hide caller id, the user agent MUST ...
Even if there is no SIM card and no other telephony services are
available, but emergency calls are known to be possible (e.g. because
a cellular modem is present), it is considered as a default service
with only emergency call capability, and the implementation MUST
define a telephony service id for it. When not even emergency
calls are possible (e.g. it is a purely IP based implementation and
there is no cellular modem), the implementation MAY use empty string
for default telephony service id, but it is encouraged that a
default service is created, with the methods throwing a
NotSupported
error.
For making a call, the telephony service transitions through the following states in order. Errors can occur at each state, which can result in the call becoming disconnected:
On the telephony services which support the "connecting" call state (e.g. GSM and CDMA, for call routing, forwarding, voicemail handling etc), implementations SHOULD support this state too, between the "dialing" and "alerting" states. Dialer applications can associate the protocol with the telephony service used for the call.
The reasons why a call can become disconnected are as follows.
Within the API the following disconnection reasons are represented by
the the DisconnectReason
enum.
When a telephony service is notified of call disconnection of the Call object telCall, it MUST run the steps to disconnect:
state
of telCall to
"disconnected".
statechange
at the
telCall object.
disconnected
at the
telCall object.
The param
attribute of the disconnected
event MUST be set to the DisconnectReason, if available, or
otherwise it MUST be set to null
. At least the following
values MUST be supported for the disconnect reason: "local",
"remote" and "network". The rest of the
DisconnectReason values SHOULD be supported.
DisconnectReason
enum
enum DisconnectReason { "local", "remote", "network", "busy", "rejected", "redirected", "unreachable", "no-answer", "network-unreachable", "barred", "no-service", "invalid-number" };
The task source for all tasks queued in this specification is the telephony task source.
Navigator
object
The TelephonyManager interface is exposed on [[!HTML]]'s
Navigator
object.
telephony
attribute
When getting the telephony attribute, the user agent MUST return the TelephonyManager object, which provides the ability to interface with the telephony service of the device.
The TelephonyManager interface provides access to telephony functionality, and manages the lifecycle of the Call objects.
activeCall
attribute
When getting the activeCall attribute, the
user agent MUST return the Call object that represents the
active call. If there is no active Call return
null
.
calls
attribute
When getting the calls attribute, the user agent MUST return an array, which can be empty, of Call objects managed by this objects.
TelephonyCall objects belonging to a multiparty call are managed by the corresponding ConferenceCall object and won't be present in this array.
emergencyNumbers
attribute
When getting the emergencyNumbers attribute, the user agent MUST return an array, which can be empty, of telephone numbers for the emergency services in the current geographical area.
serviceIds
attribute
When getting the serviceIds attribute, the user agent MUST return an array, which can be empty, of telephony service id's.
defaultServiceId
attribute
When getting the defaultServiceId
attribute, the user agent MUST return the DOMString that
represents the id of the default telephony service (if any).
Otherwise, it returns null
.
sendTones()
method
The sendTones() method requests a telephony service emit one or more [[!DTMF]] tones. When invoked, the user agent MUST run the following steps:
duration
, then validate and use that value, otherwise
use a default value.
gap
, then validate and use that value, otherwise use a
default value.
Promise
object and resolver its associated
resolver
.
accept()
method
with no arguments.
reject()
method, with no
arguments.
Tone value can be any of the following characters: 0-9; A-D; *; #.
The above needs to be converted to ABNF
stopTone()
method
The stopTone() method stops emitting a [[!DTMF]] tone in the default or the specified telephony service. When invoked, the user agent MUST run the following steps:
NotSupported
error.
InvalidStateError
error.
Promise
object and resolver its associated
resolver
.
accept()
method
with no arguments.
reject()
method, with no
arguments.
startTone()
method
The startTone() method
starts emitting a [[!DTMF]] tone with the platform default or
specified delay, in the platform default or the specified telephony
service. A Promise
object will be returned in
order to notify the result of the request.
When the startTone
method is invoked, the user agent
MUST run the following steps:
NotSupported
error and finish these steps. In
this case applications may then use the sendTones
method
for sending [[!DTMF]].
duration
, then ignore that value.
gap
, meaning the delay before sending the tone, then
validate and use that value, otherwise use a default value.
stopTone
method is
called.
Promise
object and resolver its associated
resolver
.
accept()
method
with no arguments.
reject()
method, with no
arguments.
dial()
method
The dial(remoteParty, options) method initiates a new telephony call. When invoked the user agent MUST run the following steps:
Note that verification of the format of the remoteParty argument is left to the telephony service. Providing an remoteParty in the invalid format will generally result in the call disconnecting because the telephony service or telephony network will deem it an invalid number.
changeDefaultService()
method
The changeDefaultService() method provides a means to change the default telephony service used by the user agent. When invoked, the user agent runs the the following steps:
Promise
object and resolver its associated resolver.
Promise
.
The steps to change the default service are given by the
following algorithm. This abstract operation takes as an argument a
telephony service id and an optional
Promise
.
Promise
was passed, invoke
resolver's accept(value) method with the id of the new
default service as value argument.
servicechange
at the
telephony attribute of the navigator object.
The following are the event handlers are implemented by the TelephonyManager interface.
event handler | event name | event type | short description |
---|---|---|---|
onincoming
|
incoming
|
TelephonyEvent | handles incoming and waiting calls. |
oncallschanged
|
callschanged
|
Event
|
handles change in the calls array. |
onserviceadded
|
serviceadded
|
TelephonyServiceEvent | handles a new enabled telephony service. |
onserviceremoved
|
serviceremoved
|
TelephonyServiceEvent | handles a disabled telephony service. |
ondefaultchanged
|
defaultchanged
|
TelephonyServiceEvent | handles the change of default telephony service. |
hideCallerId
member
The hideCallerId member represents whether the local party identifier is to be hidden or displayed to the remote party being called. If missing, the user agent uses the default configuration for the telephony service that initiated the call.
Only some protocols support hidding the identity of the local party when making a call.
serviceId
member
The serviceId member represents the telephony service id of the telephony service to be used when dialing.
duration
member
The duration member represents the duration (mark) in milliseconds of the [[!DTMF]] tones to be sent.
gap
member
The gap member represents the duration in milliseconds of the time gap (space) before a [[!DTMF]] tone.
serviceId
member
The serviceId member represents the telephony service id of the telephony service to be used when dialing.
Defines telephony events for TelephonyCall state changes, including handling incoming and waiting calls.
call
attribute
When getting the call attribute, the user agent MUST return the TelephonyCall that triggered the event.
Defines a telephony event for notifying a changed telephony service.
serviceId
attribute
When getting the serviceId, the user agent MUST return the telephony service id of the telephony service that triggered the event.
TelephonyServiceEventInit
dictionary
serviceId
member
The serviceId member represents the telephony service id of a telephony service.
The CallHandler
interface provides common properties and
event handling infrastructure that is implemented
by other interfaces in this specification, e.g. TelephonyCall
and ConferenceCall. It serves as an editorial aid in this
specification, and has no functional utility on its own.
resume()
method
The resume() method requests the telephony system to resume resume a held Call. When invoked, the user agent MUST run the following steps:
hold()
method
The hold() method requests the telephony system put the Call on hold. When invoked, the user agent MUST run the following steps:
state
is not equal to active
, then
an throw and InvalidStateError
exception.
state
to
"holding".
disconnect
method
The disconnect method, if invoked on a TelephonyCall, it initiates releasing of the telephony call. If invoked on a ConferenceCall, it initiates releasing the multiparty call, and each participating TelephonyCall object.
If the telephony service is CDMA, throw "NotSupported
"
DOMError.
Depending on the protocol, there may be restrictions on methods. For instance, GSM does not permit disconnecting a held call. Also, disconnecting a participant in a held multiparty call is not supported. Also, if the controlling party disconnects in IS-41 3-way call in CDMA, then all parties are disconnected, and it is not possible for the controlling party to disconnect only one participant (that participant must choose to hang up).
callId
attribute
When getting the callId attribute, the user agent MUST return the call id.
serviceId
attribute
When getting the serviceId attribute, the user agent MUST return the telephony service id of the telephony service associated with this call.
state
attribute
When getting the state attribute, the user agent MUST return the CallState value that represents the state of for the Call.
The following are the event handlers are exposed by the
CallHandler interface. The event type is Event
.
event handler | event name |
---|---|
onstatechange
|
statechange
|
onerror
|
error
|
Defines the object structure for controlling calls.
remoteParty
attribute
When getting the remoteParty attribute, the
user agent MUST return the remote party id (e.g. telephone
number) of the call participant. If not available (e.g. callerId has
been hidden), return null
.
conferenceId
attribute
When getting the conferenceId attribute, if
this call is managed as a part of a multiparty call then the user
agent MUST return the value of the conferenceId
attribute of the ConferenceCall multiparty call to which this
call is part of. Otherwise, return null
.
accept()
method
The accept() method accepts an incoming or waiting telephony call. When invoked, the user agent MUST run the following steps:
redirect()
method
The telephony service in use needs to have the call deflection feature enabled in order for this method to succeed. For instance, in GSM, the Call Deflection supplementary service needs to be active.
The redirect() method initiates deflecting an incoming or waiting telephone call to a remote party. The method takes one argument, which represents the remote party to which the call is redirected. When invoked, the user agent MUST run the following steps:
InvalidStateError
exception.
state
to
"redirecting".
state
to
"disconnected".
transfer()
method
The telephony service needs to have the call transfer feature enabled in order for this method to succeed. For instance, in GSM, the Call Transfer supplementary service needs to be active.
The transfer() method Initiates transferring the call to a new call between the remote party of this call and another remote party, then disconnects the call. The method takes one argument, which represents the remote party to which the call is transferred. When invoked, the user agent MUST run the following steps:
state
is not equal to "active" or
"held", then throw an InvalidStateError
exception.
state
to "transferring".
state
to "disconnected".
createConference()
method
The createConference() method Creates a multiparty call from the current call. On cellular telephony services, this happens by initiating merging the active and held calls into a multiparty call. Using this method MUST be the only way to create a ConferenceCall object. When invoked, the user agent MUST run the following steps:
state
of telCall to
"joining".
state
of confCall to
"joining".
conferenceId
attribute of the
participating calls to the unique identifier generated for the
multiparty call confCall.
state
to
'multiparty'
.
state
of confCall to
"active".
participantadded
at confCall.
object
To handle changes in telephony state, the TelephonyCall
interface implements the following event handlers. The event
type for the events is Event
.
event handler | event name / telephony state |
---|---|
ondialing
|
dialing |
onalerting
|
alerting |
onaccepted
|
accepted |
onconnecting
|
connecting |
onactive
|
active |
ondisconnecting
|
disconnecting |
ondisconnected
|
disconnected |
onholding
|
holding |
onheld
|
held |
onresuming
|
resuming |
onredirecting
|
redirecting |
ontransferring
|
transferring |
onjoining
|
joining |
onmultiparty
|
multiparty |
onsplitting
|
splitting |
Describes the object controlling multiparty calls, and managing the TelephonyCall objects participating in the multiparty call.
conferenceId
attribute
When getting the conferenceId attribute, the user agent MUST return the conference identifier unique in the system and in call history. It MUST NOT be the empty string.
calls
attribute
When getting the calls, the user agent MUST return the array of TelephonyCall objects managed by the multiparty call object.
split()
method
The split() method requests the telephony system split the specified participant TelephonyCall object, activate it and put this multiparty call on hold. The method takes one argument, which represents the TelephonyCall object of the call participant to be split from the multiparty call. When invoked, the user agent MUST run the following steps:
InvalidModificationError
exception.
state
of the
participantCall and that of this ConferenceCall
object to "splitting".
conferenceId
of the split call to
null
.
In CDMA, only 3-way calling is supported. This is an IS-41 CN limitation (see Network Interworking between GSM-MAP and TIA-41, 3GPP2 document, p. 1-50 provides a comparison of multiparty call and 3-way call.
To handle changes in telephony state, the
ConferenceCall interface implements the following event
handlers. The event type for the events is
Event
.
event handler | event name/telephony state |
---|---|
onparticipantadded
|
participantadded |
onparticipantremoved
|
participantremoved |
onjoining
|
joining |
onactive
|
active |
onsplitting
|
splitting |
onholding
|
holding |
onheld
|
held |
onresuming
|
resuming |
ondisconnecting
|
disconnecting |
ondisconnected
|
disconnected |
To be improved. See bug 26.
This API provides access to a potentially dangerous and valuable feature of a device. As a result, misuse of the API would have a large cost to users and other system stakeholders. This API should, therefore, not be implemented without careful consideration of security and privacy issues.
This section provides a limited overview of security and privacy considerations relevant for this API. It includes a set of threats to users and other stakeholders, as well as requirements for mitigating them.
However, this section cannot cover all of the potential threats, nor can it reflect the context in which a conformant implementation may be operating. As a result, this security section should be considered only the starting point for implementers.
The following list of threats should be considered by the implementer. Note that these are not given in any order.
The following mechanisms may be employed to help an implementer mitigate the threats outlined in the previous section.
TODO
The CallHistoryEntry interface describes the minimum set of properties which a user agent would need to support for call history entries. For multiparty call there needs to be a separate CallHistoryEntry object for each call participant, sharing the same value for the conferenceId attribute.
It is up the the implementations and applications how to store and access call history. This document only specifies the minimum content of the data to be saved.
CallHistoryEntry
interface
remoteParty
attribute
When getting the remoteParty attribute, the user agent MUST return the remote party id (e.g. telephone number) of the call participant.
serviceId
attribute
When getting the serviceId attribute, the user agent MUST return the telephony service id of the telephony service used for the call.
conferenceId
attribute
When getting the conferenceId attribute, the
user agent MUST return the conference id of the call, if the
call has participated in a multiparty call. Otherwise, return
null
. string.
startTime
attribute
When getting the startTime attribute, the user agent MUST return the starting time of the call, measured from when the call is in active state.
duration
attribute
When getting the duration attribute, the user agent MUST return the duration of the call expressed in milliseconds.
direction
attribute
When getting the direction attribute, the user agent MUST return the CallDirection.
disconnectReason
attribute
When getting the disconnectReason
attribute, the user agent MUST return the DisconnectReason
if available, or return null
otherwise.
emergency
attribute
When getting the emergency attribute, the user
agent MUST return true
if the call was an emergency
call, or false
otherwise.
The following is a list of substantial changes to the document. For a complete list of changes, see the change log on Github. You can also view the recently closed bugs.
The editors would like to express their gratitude to the Mozilla B2G Team for their technical guidance, implementation work and support, especially to Ben Turner and Jonas Sicking, the authors of the B2G WebTelephony API. Also, thanks to Denis Kenzior (ofono maintainer) and Oleg Zhurakivskyy of Intel Open Source Technology Center, and many others for their advice and support.