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.

Introduction

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.

Dependencies

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.

Telephony services

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.

Changing telephony services

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:

  1. Let name be serviceremoved if the telephony service was removed, or serviceadded otherwise.
  2. Let event be a new TelephonyServiceEvent, with name as the event name, which does not bubble, is not cancelable, has no default action, and whose serviceId attribute is set to the telephony service id of the telephony service that initiated this algorithm.
  3. If the service has been removed and it's the default telephony service for the origin, then change default telephony service.
  4. Queue a task to fire an event event at the TelephonyManager.

Default Telephony Service

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:

  1. Let service id be the telephony service id of the new default telephony service, or null otherwise.
  2. Let event be a new TelephonyServiceEvent with the event name defaultchanged, which does not bubble, is not cancelable, has no default action, and whose serviceId attribute to service id.
  3. Queue a task to change the defaultServiceId attribute of the TelephonyManager object to sercive id, and fire event at the TelephonyManager.

Telephony Calls

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

Multiparty calls

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.

Call states

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:

dialing
An outbound call is being dialed by a telephony service.
connecting
A request to establish the call has been made and it is progressing.
alerting
The destination number has been reached and alerting is taking place.
active
The call is ongoing.
incoming
An incoming call is being received whilst no other call is progressing.
waiting
An incoming call that has been received whilst there was another call progressing, and the call waiting service is active.
accepted
An incoming call has been accepted and is being connected.
holding
The call is being put on hold.
held
The call has been put on hold.
resuming
The call, which was on hold, is being resumed.
redirecting
The call is being redirected to another remote party from the same telephony service.
transferring
The call is being transferred to another remote party from the same telephony service.
disconnecting
A request to disconnect the call has been made and it is progressing.
disconnected
The call has been disconnected and this object is invalid for call control.
joining
The call is being joined with another call to become a multiparty call.
multiparty
The call is a multiparty call.
splitting
The call is being split from a multiparty call.

State changes

Whenever there is a change in the state attribute the user agent MUST:

  1. Queue a task to fire an event named 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.

Receiving calls (inbound states)

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:

  1. "incoming"/"waiting".
  2. "accepted".
  3. "active".

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:

  1. Let incomingCall be a new instance of TelephonyCall.
  2. Set the state of incomingCall to "incoming" in case there is no other call in active state, or otherwise set it to "waiting".
  3. Add incomingCall to the calls array.
  4. Queue a task to fire an event named statechange at the incomingCall object.
  5. Queue a task to fire an event named incoming at the TelephonyManager object managing the call.
  6. Queue a task to fire an event named callschanged at the TelephonyManager object managing the call.
The figure depicts the most usual state transitions for received calls.

Making calls (outbound states)

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:

  1. dialing
  2. alerting
  3. active

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 figure depicts the most usual state transitions for dialed calls.

Disconnecting calls

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.

local
The call was disconnected by the user, or the device, and no more specific reason is known.
remote
The call was disconnected by the remote party, and no more specific reason is known.
network
The call was disconnected by the network, and no more specific reason is known.
busy
The call was disconnected by the network, because the remote party was busy.
rejected
The call was disconnected because the remote party rejected the call.
redirected
The call has been redirected to another subscriber.
unreachable
The call was disconnected by the network, because the remote party was unreachable by the network.
no-answer
The call was disconnected by the network, because the remote party has not answered and the call has timed out.
network-unreachable
The call was disconnected because the network was unreachable.
barred
The call was disconnected because it was barred.
no-service
The call was not made because there is no telephony service set up and enabled (e.g. no SIM card).
invalid-number
The call was disconnected by the network, because the remote party identifier was invalid.

When a telephony service is notified of call disconnection of the Call object telCall, it MUST run the steps to disconnect:

  1. Queue a task to:
    1. Remove the telCall object from the calls array.
    2. set the state of telCall to "disconnected".
    3. fire an event named statechange at the telCall object.
    4. fire an event named 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"
};   

Task Source

The task source for all tasks queued in this specification is the telephony task source.

Extensions to Navigator object

The TelephonyManager interface is exposed on [[!HTML]]'s Navigator object.

readonly attribute TelephonyManager telephony

The 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.

TelephonyManager Interface

The TelephonyManager interface provides access to telephony functionality, and manages the lifecycle of the Call objects.

readonly attribute Call? activeCall
readonly attribute Call[] calls
readonly attribute DOMString[] emergencyNumbers
readonly attribute DOMString[] serviceIds
readonly attribute DOMString? defaultServiceId
Promise changeDefaultService(DOMString serviceId)
TelephonyCall dial (DOMString remoteParty, optional DialOptions options)
Promise sendTones(DOMString tones, optional ToneOptions options)
Promise startTone(DOMString tone, optional ToneOptions options)
Promise stopTone(optional DOMString serviceId)
attribute EventHandler onincoming
attribute EventHandler oncallschanged
attribute EventHandler onserviceadded
attribute EventHandler onserviceremoved
attribute EventHandler ondefaultchanged

The 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.

The 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.

The 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.

The serviceIds attribute

When getting the serviceIds attribute, the user agent MUST return an array, which can be empty, of telephony service id's.

The 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.

The 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:

  1. If the ToneOptions parameter specifies the serviceId to be used, then validate and use that value, otherwise use the default telephony service for sending the tones.
  2. If the ToneOptions parameter specifies the tone duration, then validate and use that value, otherwise use a default value.
  3. If the ToneOptions parameter specifies the tone gap, then validate and use that value, otherwise use a default value.
  4. Request from the telephony system to send the specified tones.
  5. Let promise be a new Promise object and resolver its associated resolver.
  6. Return promise to the caller and continue the following steps asynchronously.
  7. If the request to the telephony system is successful, or if the telephony system does not support feedback about the result of the request, invoke resolver's accept() method with no arguments.
  8. If the request to the telephony system is unsuccessful, invoke resolver's reject() method, with no arguments.

Tones

Tone value can be any of the following characters: 0-9; A-D; *; #.

The above needs to be converted to ABNF

The 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:

  1. If the platform does not support long press [[!DTMF]] tones, throw a NotSupported error.
  2. If the provided parameters are invalid, or there is no tone playing on the specified telephony service, throw an InvalidStateError error.
  3. Otherwise, request from the telephony system to stop sending the specified tone.
  4. Let promise be a new Promise object and resolver its associated resolver.
  5. Return promise to the caller and continue the following steps asynchronously.
  6. If the request to the telephony system is successful, or if the telephony system does not support feedback about the result of the request, invoke resolver's accept() method with no arguments.
  7. If the request to the telephony system is unsuccessful, invoke resolver's reject() method, with no arguments.

The 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:

  1. If the platform does not support long press [[!DTMF]] tones, throw a NotSupported error and finish these steps. In this case applications may then use the sendTones method for sending [[!DTMF]].
  2. If the ToneOptions parameter specifies the serviceId to be used, then validate and use that value, otherwise use the default telephony service for sending the tones.
  3. If the ToneOptions parameter specifies the tone duration, then ignore that value.
  4. If the ToneOptions parameter specifies the tone gap, meaning the delay before sending the tone, then validate and use that value, otherwise use a default value.
  5. Request from the telephony system to start sending the specified tone. The tone SHOULD play until the stopTone method is called.
  6. Let promise be a new Promise object and resolver its associated resolver.
  7. Return promise to the caller and continue the following steps asynchronously.
  8. If the request to the telephony system is successful, or if the telephony system does not support feedback about the result of the request, invoke resolver's accept() method with no arguments.
  9. If the request to the telephony system is unsuccessful, invoke resolver's reject() method, with no arguments.

The 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.

  1. Let remote party be the value of the value of the remoteParty argument.
  2. Let service initially be either the default telephony service, if one is available to the document's effective script origin, or null otherwise.
  3. If the options argument is used, and it has a serviceId member:
    1. If the value of serviceId member exactly matches the telephony service id accessible to the document's effective script origin, then let service be the telephony service that matches that value.
    2. If the serviceId member is not an empty string and that does not match any telephony service id available to the document, throw a "NotFoundError" exception and terminate these steps.
  4. If the options argument is used, and it has a hideCallerId member, then let hide caller id be the value of the hideCallerId member.
  5. Let telCall be a new instance of TelephonyCall.
  6. Set telCall's remoteParty attribute to remote party id.
  7. Return telCall and continue asynchronously.
  8. Make a call using remote party, service and, and, if it was defined, hide caller id.

The 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:

  1. Let potential service be the first argument passed to this operation.
  2. Let promise be a new Promise object and resolver its associated resolver.
  3. Return promise and continue the following steps asynchronously.
  4. If potential service does not exactly match the identifier of any telephony service known to the user agent, run the following sub-steps and terminate this algorithm:
    1. Let error be a new DOMError object whose name is "NotFoundError".
    2. Invoke resolver's reject(value) method with error as the value argument.
  5. If potential service exactly matches the service id of the current default telephony service, run the following sub-steps and terminate this algorithm:
    1. Invoke resolver's accept(value) method with potential service as the value argument.
  6. Otherwise, run the steps to change the default service, with potential service as the telephony service id, and promise as the 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.

  1. Make a platform/system specific request to the underlying system to change from the current default telephony service to the one identified by service id.
  2. Possibly wait indefinitely.
  3. If it's not possible (for whatever reason: timeout, security, etc.) to change the default telephony service, and if promise was passed, run the following sub steps and terminate this algorithm:
    1. Let error be a new DOMError object whose name is "NoModificationAllowedError".
    2. Call resolver's reject(value) method with error as the value argument.
  4. Otherwise, queue a task to:
    1. Change the defaultServiceId attribute to the telephony service id of the new default telephony service.
    2. If Promise was passed, invoke resolver's accept(value) method with the id of the new default service as value argument.
    3. Fire an event named servicechange at the telephony attribute of the navigator object.

Event handlers

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.

DialOptions Dictionary

boolean hideCallerId
DOMString serviceId

The 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.

The serviceId member

The serviceId member represents the telephony service id of the telephony service to be used when dialing.

ToneOptions Dictionary

unsigned long duration
unsigned long gap
DOMString serviceId

The duration member

The duration member represents the duration (mark) in milliseconds of the [[!DTMF]] tones to be sent.

The gap member

The gap member represents the duration in milliseconds of the time gap (space) before a [[!DTMF]] tone.

The serviceId member

The serviceId member represents the telephony service id of the telephony service to be used when dialing.

TelephonyEvent Interface

Defines telephony events for TelephonyCall state changes, including handling incoming and waiting calls.

readonly attribute Call call

The call attribute

When getting the call attribute, the user agent MUST return the TelephonyCall that triggered the event.

TelephonyServiceEvent Interface

Defines a telephony event for notifying a changed telephony service.

readonly attribute DOMString serviceId

The 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

DOMString serviceId

The serviceId member

The serviceId member represents the telephony service id of a telephony service.

CallHandler interface

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.

void resume()
void hold()
void disconnect()
readonly attribute DOMString callId
readonly attribute DOMString serviceId
readonly attribute CallState state
attribute EventHandler onerror
attribute EventHandler onstatechange

The 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:

  1. If state is not equal to "held", then throw an InvalidStateError exception.
  2. Otherwise make a request to the telephony system to resume the call. If the request is acknowledged, then set state to "resuming".

The hold() method

The hold() method requests the telephony system put the Call on hold. When invoked, the user agent MUST run the following steps:

  1. If state is not equal to active, then an throw and InvalidStateError exception.
  2. Otherwise make a request to the telephony system to hold the call.
  3. Return, and continue these steps asynchronously.
  4. If the request is acknowledged then set state to "holding".

The 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).

The callId attribute

When getting the callId attribute, the user agent MUST return the call id.

The serviceId attribute

When getting the serviceId attribute, the user agent MUST return the telephony service id of the telephony service associated with this call.

The state attribute

When getting the state attribute, the user agent MUST return the CallState value that represents the state of for the Call.

Event handlers

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

TelephonyCall Interface

Defines the object structure for controlling calls.

readonly attribute DOMString? remoteParty
readonly attribute DOMString? conferenceId
void accept()
void redirect(DOMString remoteParty)
void transfer(DOMString thirdParty)
ConferenceCall createConference()
attribute EventHandler ondialing
attribute EventHandler onalerting
attribute EventHandler onaccepted
attribute EventHandler onconnecting
attribute EventHandler onactive
attribute EventHandler ondisconnecting
attribute EventHandler ondisconnected
attribute EventHandler onholding
attribute EventHandler onheld
attribute EventHandler onresuming
attribute EventHandler onredirecting
attribute EventHandler ontransferring
attribute EventHandler onjoining
attribute EventHandler onmultiparty
attribute EventHandler onsplitting

The 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.

The 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.

The accept() method

The accept() method accepts an incoming or waiting telephony call. When invoked, the user agent MUST run the following steps:

  1. If state is not equal to "incoming" or "waiting", then throw an InvalidStateError exception.
  2. Otherwise make a request to the telephony system to accept the call. If the request is acknowledged then set state to "accepted".

The 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:

  1. If the state is not "incoming" or "waiting", then throw an InvalidStateError exception.
  2. Otherwise make a request to the telephony system to redirect the call to the number indicated in the remoteParty parameter, return, and continue these steps asynchronously.
  3. If the request is acknowledged, then set state to "redirecting".
  4. When the telephony service is notified that the call has been successfully redirected it MUST set state to "disconnected".

The 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:

  1. If state is not equal to "active" or "held", then throw an InvalidStateError exception.
  2. Otherwise make a request to the telephony system to transfer the call to the number indicated in the thirdParty parameter. Note that in GSM this requires putting the current call on hold, dialing a new call to the third party, then initiating the call transfer procedure. If there is an error, the original call MUST be resumed and then queue a task to fire a simple event named "error" without modifying the call state. If the request is acknowledged, then set state to "transferring".
  3. When the telephony service is notified that the call has been successfully transferred and the original call is disconnected, it MUST set state to "disconnected".

The 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:

  1. Let telCall be the telephony call on which this method was invoked.
  2. Set the state of telCall to "joining".
  3. Then, in cellular telephony services, make a request to the telephony system to join the active and held calls into a multiparty call.
  4. If one of the calls is already a ConferenceCall object, use it as confCall in these steps.
  5. Otherwise create a new ConferenceCall object with a unique conference id, named confCall.
  6. Set the state of confCall to "joining".
  7. Return the confCall object, and continue these steps asynchronously.
  8. If the request to the telephony system is successful,
    1. set the conferenceId attribute of the participating calls to the unique identifier generated for the multiparty call confCall.
    2. Add the calls participating in the multiparty call to the calls attribute of the confCall object, remove them from the calls array of the TelephonyManager object, and set their state to 'multiparty'.
    3. Add the confCall object to the calls array of the TelephonyManager object.
    4. Set the state of confCall to "active".
    5. Queue a task to fire an event named participantadded at confCall. object
    6. Follow the state changes of confCall through the state change events.

Event handlers

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

ConferenceCall Interface

Describes the object controlling multiparty calls, and managing the TelephonyCall objects participating in the multiparty call.

readonly attribute DOMString conferenceId
readonly attribute TelephonyCall[] calls
void split(TelephonyCall participantCall)
attribute EventHandler onparticipantadded
attribute EventHandler onparticipantremoved
attribute EventHandler onjoining
attribute EventHandler onactive
attribute EventHandler onsplitting
attribute EventHandler onholding
attribute EventHandler onheld
attribute EventHandler onresuming
attribute EventHandler ondisconnecting
attribute EventHandler ondisconnected

The 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.

The calls attribute

When getting the calls, the user agent MUST return the array of TelephonyCall objects managed by the multiparty call object.

The 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:

  1. If the provided participantCall does not identify a valid TelephonyCall object which is part of this multiparty call, then an throw an InvalidModificationError exception.
  2. Otherwise, set the state of the participantCall and that of this ConferenceCall object to "splitting".
  3. Make a request to the telephony system to split the call participant from the multiparty call.
  4. Return, and continue these steps asynchronously.
  5. If the request was successful, the telephony system will put the multiparty call on hold and activate the split call. The implementation MUST follow the state transitions on the calls as described in this specification.
  6. Reset the 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.

Event handlers

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

Security and privacy considerations

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.

Threats

The following list of threats should be considered by the implementer. Note that these are not given in any order.

Mitigations

The following mechanisms may be employed to help an implementer mitigate the threats outlined in the previous section.

User interaction guidelines

TODO

Managing call history

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

readonly attribute DOMString remoteParty
readonly attribute DOMString serviceId
readonly attribute DOMString? conferenceId
readonly attribute Date startTime
readonly attribute unsigned long long duration
readonly attribute CallDirection direction
readonly attribute DisconnectReason? disconnectReason
readonly attribute boolean emergency

The remoteParty attribute

When getting the remoteParty attribute, the user agent MUST return the remote party id (e.g. telephone number) of the call participant.

The serviceId attribute

When getting the serviceId attribute, the user agent MUST return the telephony service id of the telephony service used for the call.

The 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.

The 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.

The duration attribute

When getting the duration attribute, the user agent MUST return the duration of the call expressed in milliseconds.

The direction attribute

When getting the direction attribute, the user agent MUST return the CallDirection.

The disconnectReason attribute

When getting the disconnectReason attribute, the user agent MUST return the DisconnectReason if available, or return null otherwise.

The emergency attribute

When getting the emergency attribute, the user agent MUST return true if the call was an emergency call, or false otherwise.

CallDirection enum

dialed
The call has been dialed.
received
The call has been received.
missed
The call has been missed.
missed-new
The call was a missed call not seen yet by the user.

Changes

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.

Acknowledgements

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.

  翻译: