Abstract

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.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was produced by the System Applications Working Group. Members of this Working Group have agreed not to progress the Telephony API specification further as a Recommendation track document, electing instead to publish it as an informative Working Group Note under a permissive license with a view to enabling it to form the basis of further work by others, e.g. in a W3C Community Group.

This document was published by the System Applications Working Group as a Working Group Note. If you wish to make comments regarding this document, please send them to public-sysapps@w3.org (subscribe, archives). All comments are welcome.

W3C makes this document available under the terms of the W3C Software and Document License pursuant to W3C's policy for Relicensing Unfinished W3C Specifications. Publication as a Working Group Note does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 1 August 2014 W3C Process Document.

Table of Contents

1. Introduction

This section is non-normative.

The Web Telephony API allows applications to manage interaction with telephony call signaling, but does not handle audio channels management and volume control.

For managing telephony calls, a call state handler needs to be defined, which defines actions on the call states, usually updating the user interface elements enabling interaction with the call, according to what user input different call states require. An example of making and receiving a telephony call is provided below.

Example 1: Dialing a call
var number = '+1234567890';
navigator.telephony.dial(number).then(
  function(call) {
    console.log("The call to " + number +
      " is controlled by TelephonyCall object with id: " + call.callId);
    console.log("Now hanging up...");
    call.disconnect();
  },
  function (err) {
    console.log("Error making the call: " + err.message);
  });
Example 2: Monitoring received and dialed calls
// handle the state changes of both received and dialed calls
function stateHandler(event) {
  var call = event.call;
  var state = call.state;
  if (state == 'incoming' || state == 'waiting') {
    // new TelephonyCall object has been created and added to CallManager
    // display the dialog for incoming/waiting call
    // wait for user input: accept, hangup, hold, deflect
    console.log(state + ' call...');
  } else if (state == 'dialing') {
    console.log('Call is dialing');
  } else if (state == 'alerting') {
    console.log('Outgoing call is alerting the remote party');
  } else if (state == 'ringing') {
    console.log('Incoming call is ringing');
    // wait for user input: accept, hangup, hold, deflect
  } else if (state == 'accepted') {
    console.log('Incoming call is accepted');
  } else if (state == 'held') {
    console.log('Call is on hold');
  } else if (state == 'active') {
    console.log('Call is active');
    if (call.conferenceId)
      console.log('Call is part of a conference call');
  } else if(state == 'disconnected') {
    // the TelephonyCall object has been removed from the CallManager list
    // update call history
    console.log('Call disconnected: ' + call.stateReason);
  }
}

navigator.telephony.addEventListener("callstatechange", stateHandler);

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.

Issue 1

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.

2. Permissions

This section is non-normative.

This API conforms to the permission model defined for System Applications.

Issue 2

The permission model is not finished yet and it will affect on how to expose lower vs higher privilege functionality in this API.

3. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, RECOMMENDED, SHOULD, and SHOULD NOT are to be interpreted as described in [RFC2119].

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.

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

5. Task Source

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

6. Terminology

6.1 Telephony service

A telephony network is the infrastructure providing telephony functionality in a given geographical area, to which the device running the user agent is registered with at the point of operation.

A subscriber identity identifies and authenticates the user in the telephony network. In cellular telephony, subscriber identity is associated with the SIM card (Subscriber Identity Module). A given subscriber identity can be used in different, but interoperable telephony networks.

A telephony provider is the company operating the telephony network. A telephony provider can have multiple telephony networks.

A telephony modem is the software and hardware entity which implements the telephony protocols needed for interacting with the telephony networks, and which exposes an API which is used for implementing this API specification. A modem can be local to the device, or can be a remote modem, used e.g. via a paired Bluetooth device.

A telephony service is an abstract concept used in this API to denote the tuple of a given subscriber identity, and a given telephony modem. If any of these elements is changed, it means a different telephony service. Note that when a device is moving, and eventually changes the telephony network, it continues to see the same telephony service. A telephony service can use different protocols for telephony signaling and media (e.g. GSM, CDMA, VoLTE, etc.) with the same subscriber identity. There may be multiple SIM cards registered with the same provider, which will map to different telephony services.

Note the difference between dual-SIM and multiple-SIM card use cases. In dual-SIM use case the subscriber has two identities, which both can be active in the same time, i.e. could make and receive calls. In the multiple SIM card use case the subscriber has multiple identities, but only one can be active at a given time. These constraints are not exposed by this API, and implementations are expected to encapsulate them.

6.2 Telephony service id

A user agent can access zero or more telephony services. Each telephony service has a unique telephony service id at any given moment, but it is not required to uniquely identify services in call history. In other words, the identifiers MAY be reused as services appear and disappear. Service identifiers SHOULD NOT be saved in call history, only displayable service names.

Access to a telephony service by any origin is restricted by a security policy. See the Security and privacy considerations section for more details.

It is strongly RECOMMENDED that implementations do not use use the MSISDN as the telephony service id. The MSISDN cannot guarantee uniqueness. For telephony services that make use of a SIM card, it is RECOMMENDED that the ICC-ID is used for the service identifier. For reducing fingerprinting, implementations SHOULD choose to use opaque UUID's or SHA signatures as service identifiers, associated in the implementation to the internal service identifiers such as ICC-ID.

6.3 Selected telephony service

The selected telephony service is the telephony service that is used as default for the origin for the methods of this API.

Implementations are not required to initialize a selected service at startup. Instead, clients of this API may choose the preferred moment of initializing the telephony system by invoking the navigator.telephony.service.getServices() (if implemented) or the navigator.telephony.getCalls(), or the navigator.telephony.dial() methods.

If there is no selected telephony service set for the origin, the user agent SHOULD use the underlying system's default telephony service, if available. On implementations that have access to a hardware modem, regulations require supporting emergency number dialing from PIN dialog or dialer interface even in the absence of a SIM card.

6.4 Telephony call

A telephony call means a connected communication link between two or more call participants in a given a telephony service. From an application's point of view, a telephony call is an object which exposes properties and methods to monitor and control telephony calls. A telephony call involving more than two parties are referred to as a conference call or a multiparty call.

6.5 Remote party identifier

A remote party id, e.g. as a phone number, uniquely identifies a remote participant in a telephony call in the given telephony service.

6.6 Outbound and inbound call

Telephony calls initiated by the user using a telephony service in the system is an outbound call. Conversely, a telephony call from a remote party is an inbound call.

6.7 Call identifier

Every telephony call has a call id, which is a string that uniquely identifies the call among the other calls in progress. It is not required that the call id be unique across call history. Clients SHOULD NOT save the call id in call history, but SHOULD maintain their own id space, e.g. using start time and remote party information.

6.8 Call state

A call state represents the state of interaction between a telephony service, the user agent, and one or more remote parties. 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 a defined call state, which can only be changed by using methods of this API, or by the telephony service.

in GSM, there are 3 types of call states:

This would result in a 3-dimensional call state space, where not all combinations are allowed, for example a call cannot be split from a conference call while it is held.

Instead of using a 3-dimensional call state space, this API uses a one dimensional call state model, in which call states map to valid combinations in of 3-dimensional states, and are able to describe valid state transitions.

6.9 Active call

An active call is a telephony 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 connected from a call signaling point of view, but it is not bound to media input and output devices.

6.10 Conference call

A conference call is a telephony call with multiple remote party participants. The way conference calls are handled are quite different depending on the telephony protocol.

Note

This of the API version supports GSM multiparty calls and CDMA 3-way calls. Supporting SIP and XMPP conferences is possible in the future, and would require additional method parameters to conference creation.

Note

Note that the terms "GSM" and "CDMA" refer to the type of interaction needed with the telephony network, rather than the radio technology itself. For instance, 3G and 4G GSM is also using CDMA radio technology, but expose a GSM type interface.

Creating GSM multiparty calls involve the following user interaction:

  1. dial the first number
  2. when the call is active, put the call on hold
  3. dial the second number
  4. when the second call is active, press the 'Conference' button
  5. optionally repeat the steps so far to add more calls
  6. any participating call can be split from the conference call for private chat, during which the conference call is put on hold
  7. during private chat, it is possible to re-merge the call into the conference call using the same procedure as described from step 2.
  8. disconnecting a GSM conference call will disconnect all member calls.

In CDMA, only a limited form of conference call is supported, called 3-way call, which is usually mapped to multiple presses of the 'Call' button, which in background uses modem AT commands (ATD, ATH and Flash) to achieve the desired action. Handling 3-way calls involve the following user interactions:

  1. dial the first number (involves the ATD command)
  2. when the call is active, dial the second number (by sending a Flash command with the second number), which automatically puts the first call on hold
  3. when the second call is active, press the 'Call' button to make 3-way call (by sending a Flash command)
  4. while the 3-way call is active, press the 'Call' button to disconnect the second call (which sends a Flash command
  5. while the 3-way call is active, any incoming call SHOULD be rejected
  6. while the 3-way call is active, pressing 'Hangup' (ATH command) will disconnect all calls.

The common way to support these user interactions by this API, there is possible programmatic support for the following actions:

  1. dial the first call by calling the dial() method
  2. dial the second call, which puts the first call on hold
  3. create the conference call from the held and active calls by calling the createConference() method
  4. disconnecting the second call works from both CDMA and GSM, by calling the disconnect() method on the second call object
  5. disconnecting any other than the last call will work in GSM, but will hang up all calls in CDMA. The last call can be separately disconnected also in CDMA.

This API has been designed so that conference calls could be controlled using the same type object as with a single telephony call.

Every conference call has a conference id that uniquely identifies a conference call in the system.

7. Use cases

This section is non-normative.

7.1 User interaction scenarios

This API has been designed to facilitate typical telephony interaction scenarios, such as:

  1. incoming call dialog
  2. ongoing call dialog
  3. dialing emergency numbers in PIN code dialog
  4. typing MMI commands in dialer
  5. sending DTMF tones in dialer
  6. support telephony service (subscriber identity) selection for dual-SIM and multi-SIM phones. Note that dual-SIM allows both services being active (i.e. receive and dial calls), whereas multi-SIM allows only one active service at a time.

7.2 Technical use cases

The technical use cases requiring elevated permissions are the following:

7.3 Omitted use cases

Further telephony use cases which are currently not explicitly handled by this version of the API, but may be supported in the future:

  1. set the default sound volume for telephony
  2. set the sound volume during a call
  3. mute and unmute the microphone for a call
  4. start the system dialer with a phone URI
  5. select between audio targets (speaker, headsets, etc)
  6. see and manage call capabilities during a call, such as is conference call possible, is video call possible, etc
  7. support network services, such as call forwarding, call barring, network selection mode, call counters, etc.
  8. Man-Machine Interface (MMI) Code Support Global Certification Forum compliancy requires support for MMI codes by dialer applications. Hence dialers need to handle multiple types of input, which can be dialed numbers, MMI codes, PIN codes and other input, all handled by different telephony services, e.g. MMI codes are handled by Supplementary Services in GSM. The API may provide in the future pre-validating and parsing user input in order to determine whether does it match a MMI code sendable to Supplementary Services (otherwise all applications would need to parse all MMI codes themselves). Codes not matched by the implementation need to be handled by the applications using this API.

8. Extension to the Navigator object

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

partial interface Navigator {
    readonly    attribute TelephonyManager telephony;
};

8.1 The telephony attribute

When getting the telephony attribute, the user agent MUST return the TelephonyManager object, which provides telephony related functionality.

9. The TelephonyManager Interface

The TelephonyManager interface provides access to telephony functionality related to telephony call management, sending [DTMF] tones, and handling emergency numbers and calls.

TelephonyManager implements CallManager;
TelephonyManager implements ToneManager;
TelephonyManager implements EmergencyManager;
interface TelephonyManager {
    readonly    attribute ServiceManager? service;
};

The service property MUST return the ServiceManager object exposing functionality concerning telephony services, or null if not supported.

The rest of TelephonyManager properties are described by the CallManager, ToneManager and EmergencyManager interfaces.

10. Telephony Calls

10.1 CallState enum

Within the API, the call states are represented by the CallState enum.

enum CallState {
    "dialing",
    "connecting",
    "alerting",
    "ringing",
    "active",
    "conference",
    "incoming",
    "waiting",
    "accepted",
    "held",
    "disconnected",
    "holding",
    "resuming",
    "redirecting",
    "transferring",
    "disconnecting"
};

The meaning of the call states referenced in this API is the following:

dialing
An outbound call is being dialed by a telephony service.
connecting
A request to establish the outbound call has been made and it is progressing. This state is skipped for CDMA calls. In this API it is also used as an initial state for TelephonyCall objects controlling conference calls, when created.
alerting
The destination number has been reached and alerting is taking place in an outbound call.
ringing
An inbound call is locally alerting (by beep, vibration pattern, ringing, or by other means), and the network can notify the remote party with the alerting state.
active
The call is connected and media channels are attached.
conference
The call is active, i.e. connected and media channels are attached, as part of a conference call.
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 by the remote party and is being connected.
held
The call has been put on hold by the network.
disconnected
The call has been disconnected by the network and this object is invalid for call control.
holding
The call is being put on hold.
resuming
The call, which was on hold, is being resumed.
redirecting
The call is being redirected (deflected) to another remote party.
transferring
The call is being transferred to another remote party.
disconnecting
A request to disconnect the call has been made and it is progressing.
splitting
The call is being split from a multiparty call.

10.2 Call state reason

The call state reason is used primarily for the disconnected state, known as the disconnect reason. In this API the disconnection reasons are represented by the DisconnectReason enum.

10.2.1 DisconnectReason enum

enum DisconnectReason {
    "local",
    "remote",
    "network",
    "busy",
    "rejected",
    "redirected",
    "unreachable",
    "no-answer",
    "network-unreachable",
    "barred",
    "no-service",
    "invalid-number"
};

The meaning of the disconnect reasons in this API is the following:

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.

10.3 Call state transitions

Since call state transitions depend on protocol, network equipment, modem, etc., the implementation SHOULD always re-synchronize any eventual internal states to the current call state reported by the telephony system. The implementation SHOULD NOT set the call state to any other value than specified in the descriptions of the methods of this interface.

Note

Since call states can have slightly different semantics depending on the telephony protocol, the protocol property of TelephonyCall can be used for interpreting the call state in the implementation. See issue 125.

10.3.1 Inbound call state transitions

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 SHOULD be supported in this order:

  1. "incoming" or "waiting"
  2. "accepted"
  3. "active".
Note

On received calls, telephony protocols use the "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). If the modem expects this state to be set, implementations SHOULD make sure to set it.

Note

CDMA cannot report all these states in the expected sequence. The ‘connected’ network 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 no 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.

Fig. 1 The figure depicts the most usual state transitions for received calls.

10.3.2 Outbound call state transitions

For making a call, the telephony service transitions through the following states in order. Errors can occur at each state, which are handled by the telephony network, and may result in the call becoming disconnected:

  1. dialing
  2. [connecting]
  3. alerting
  4. active
Note

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.

Fig. 2 The figure depicts the most usual state transitions for dialed calls.

10.3.3 Conference call state transitions

Valid state transitions for a conference call are:

In addition, Promise objects are used for tracking the protocol transactions (e.g. GSM multiparty states), resolving either to success or error.

10.4 TelephonyCall Interface

Defines the object structure for controlling calls, including conference calls.

interface TelephonyCall {
    readonly    attribute DOMString?          callId;
    readonly    attribute DOMString?          conferenceId;
    readonly    attribute DOMString?          remoteParty;
    readonly    attribute DOMString           serviceId;
    readonly    attribute CallState           state;
    readonly    attribute DOMString           stateReason;
    readonly    attribute TelephonyTechnology technology;
    Promise accept ();
    Promise hold ();
    Promise resume ();
    Promise disconnect ();
    Promise deflect (DOMString remoteParty);
    Promise split ();
};
Note

In the methods implementation the user agent MAY choose to make an early validation of preconditions and parameters, or defer those checks to the underlying telephony system.

10.4.1 The callId attribute

When getting the callId attribute, the user agent MUST return the unique call id. After construction, the value MUST be null. The implementation MUST assign a non-null value when the state property is assigned a value different from 'initializing'.

10.4.2 The conferenceId attribute

When getting the conferenceId attribute, the user agent MUST return the value of the callId attribute of the conference call to which this call is part of, or null if it is not part of any conference call. If the callId and the conferenceId values are equal and not null, then the TelephonyCall object is controlling a conference call.

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

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

10.4.5 The state attribute

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

10.4.6 The stateReason attribute

When getting the stateReason attribute, the user agent MUST return:

  • the DisconnectReason value if the call state is "disconnected"",
  • the value "inbound" for calls that started with the "incoming" or "waiting" state
  • the value "outbound" for calls that started with the "dialing" state.

10.4.7 The technology property

When getting the attribute, the user agent MUST return the current technology used by the telephony provider, if available, or otherwise null.

enum TelephonyTechnology {
    "gsm",
    "cdma",
    "edge",
    "umts",
    "hspa",
    "lte"
};

The following values are supported as telephony technologies:

  • "gsm": used for GSM protocols
  • "cdma": used for CDMA and related protocols
  • "edge": used for EDGE protocol
  • "umts": used for UMTS protocols
  • "hspa": used for HSPA and HSPA+ protocols
  • "lte": used for LTE protocols

10.4.8 The accept() method

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

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. If the value of the state property is not equal to incoming or waiting, then optionally call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "InvalidStateError", and terminate this algorithm.
  3. Return promise and continue the following steps asynchronously.
  4. Save the state of the call
  5. Make a request to the telephony system to accept the call.
  6. Wait for response from the telephony system
  7. If the request fails, then reset the state of the call to the call state on the modem. Then, call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate this algorithm.
  8. If the request is acknowledged, then set state to accepted, execute the state change steps and queue a task to invoke resolver's accept() method.

10.4.9 The hold() method

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

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. If the value of the state property is not equal to active, then optionally call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "InvalidStateError", and terminate this algorithm.
  3. Return promise and continue the following steps asynchronously.
  4. Set the state of the call to holding
  5. Make a request to the telephony system to put the call on hold.
  6. Wait for response from the telephony system
  7. If the request fails, then reset the state of the call to the call state on the modem. Then call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate this algorithm.
  8. If the request is acknowledged, then set state to held, execute the state change steps and queue a task to invoke resolver's accept() method.

10.4.10 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. Let promise be a new Promise object and resolver its associated resolver.
  2. If state is not equal to held, optionally call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "InvalidStateError", and terminate this algorithm.
  3. Return promise and continue the following steps asynchronously.
  4. Set the state of the call to resuming
  5. Make a request to the telephony system to resume the call.
  6. Wait for response from the telephony system
  7. If the request fails, then reset the state of the call to the call state on the modem. Then call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate this algorithm.
  8. If the request is acknowledged, then set state to active, execute the state change steps and queue a task to invoke resolver's accept() method.

10.4.11 The disconnect method

The disconnect method, if invoked on a TelephonyCall which is not controlling a conference call (i.e. its callId is different from its conferenceId), it initiates releasing of the telephony call. If the call is controlling a conference call, then initiates releasing the conference call, including each participating TelephonyCall object.

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. Return promise and continue the following steps asynchronously.
  3. Set the state of the call to disconnecting
  4. Make a request to the telephony system to disconnect the call
  5. Wait for response from the telephony system
  6. If the request fails, then reset the state of the call to the call state on the modem. Then call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate this algorithm.
  7. If the request is acknowledged, then execute the call disconnected steps, and queue a task to invoke resolver's accept() method.
Note

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 GSM multiparty call is not supported. Also, if the controlling party disconnects a call participating in a IS-41 3-way call in CDMA which is not the last dialed call, then all parties are disconnected (other participants should choose to hang up).

10.4.12 The deflect() method

Note

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. Let promise be a new Promise object and resolver its associated resolver.
  2. If the state is not incoming or waiting, then optionally call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "InvalidStateError", and terminate this algorithm.
  3. if the method is not supported by the implementation, optionally call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to NotSupportedError, and terminate these steps.
  4. Return promise and continue the following steps asynchronously.
  5. Make a request to the telephony system to redirect the call to the number indicated in the remoteParty parameter
  6. Set the state of the call to redirecting
  7. Wait for response from the telephony system
  8. If the request fails, then reset the state of the call to the call state on the modem. Then call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError" or "NotSupportedError", and terminate these steps.
  9. If the request is successful, then execute the call disconnected steps and queue a task to invoke resolver's accept() method.

10.4.13 The split() method

The split() method requests the telephony system to split the TelephonyCall object from the conference call it is participating, activate it and put the conference call on hold. When invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. If the conferenceId property is null, or does not match to a conference call in progress, then optionally set conferenceId to null, call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "InvalidModificationError", and terminate this algorithm.
  3. if the method is not supported by the implementation, optionally call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to NotSupportedError, and terminate these steps.
  4. let confCall be the TelephonyCall object controlling the conference call, whose callId and conferenceId property is equal to the conferenceId property.
  5. Return promise and continue the following steps asynchronously.
  6. Set the state of the call and set the state of confCall to splitting.
  7. Make a request to the telephony system to split the call participant from the conference call and wait the response from the telephony system.
  8. If the request fails, then reset the state of the call to the call state on the modem. Then call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError" or NotSupportedError, and terminate these steps.
  9. If the request was successful, reset the conferenceId of the split call to null. The telephony system has by now put the conference call on hold and activated the split call.
  10. Execute the state change steps and queue a task to invoke resolver's accept() method.
Note

In CDMA, only the last dialed call can be split off the 3-way call. For other call participants, calling this method MUST fail.

10.5 The CallManager Interface

The CallManager interface provides access to telephony functionality related to given telephony services, and manages the lifecycle of the TelephonyCall objects. A TelephonyCall object can be created in the following ways:

interface CallManager {
    readonly    attribute TelephonyCall? activeCall;
    Promise getCalls ();
    Promise dial (DOMString remoteParty, DialOptions options);
    Promise transfer ();
    Promise createConference ();
    Promise getParticipantCalls (DOMString conferenceId);
                attribute EventHandler   oncallstatechange;
                attribute EventHandler   onactivecallchange;
};

10.5.1 Event handlers

The following are the event handlers implemented by the CallManager interface.

event handler event name event type description
onactivecallchange activecallchange Event handles a change in the active call
oncallstatechange statechange TelephonyCallStateEvent handles a change in a call state
10.5.1.1 Handling the activecallchange event

When a telephony call becames the active call, the user agent MUST run the following steps:

  1. Let call denote the TelephonyCall object which has become active.
  2. Change the value of the activeCall property of all instances of CallManager, to call.
  3. Queue a task to fire an event named activecallchange at all the instances of CallManager.
10.5.1.2 Handling the callstatechange event

The callstatechange event is used for tracking TelephonyCall objects and based on the current state, applications decide how to change the user interface elements connected to method of this API in order to control the call.

10.5.1.2.1 TelephonyCallStateEvent Interface

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

interface TelephonyCallStateEvent : Event {
    readonly    attribute TelephonyCall call;
};
10.5.1.2.1.1 The call attribute

When getting the call attribute, the user agent MUST return the TelephonyCall object that triggered the event, on which the state property indicates the state which has triggered the event.

Whenever there is a change in the state attribute of a TelephonyCall object, the user agent MUST run the following steps:

  1. Queue a task to fire an event named callstatechange of type TelephonyCallStateEvent, to the CallManager object navigator.telephony.
10.5.1.2.2 Handling inbound (incoming or waiting) calls

Upon a new incoming or waiting call the user agent MUST execute the following onincoming steps:

  1. Let call be a new instance of TelephonyCall.
  2. Set the state of call to incoming in case the underlying telephony system reports that state (which happens when there is no other call in active state),
  3. Or, set the state of call to waiting, in case the underlying telephony system reports that state (which happens if the call waiting service is active and there is already an active call),
  4. Otherwise, if there already is an active call and the call waiting service is not enabled, the telephony system will disconnect the call, the implementation MUST follow the resulting state change and terminate these steps.
  5. If the state of call has been set to either incoming or waiting, then add call to the list of calls managed by CallManager.
  6. Queue a task to fire an event named callstatechange of type TelephonyCallStateEvent to all instances of the CallManager object, with call passed as a property.
10.5.1.2.3 Handling call disconnection

When a telephony call telCall is disconnected, the user agent MUST run the following steps:

  1. >Queue a task to:
  2. Remove the telCall object from all internal lists of CallManager
  3. set the state of telCall to "disconnected".
  4. fire a TelephonyCallStateEvent named statechange at all the CallManager objects, with the call property set to call, whose stateReason property is set to the DisconnectReason. 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.

10.5.2 The activeCall attribute

When getting the activeCall attribute, the user agent MUST return the TelephonyCall object that represents the active call. If there is no active call, return null.

10.5.3 The getCalls() method

When the getCalls() method is invoked, the user agent MUST return a Promise object, which in case of success resolves to an array, which can be empty, of all TelephonyCall objects in the system which have the value of the state property different from 'disconnected', i.e. all telephony calls in progress. TelephonyCall objects belonging to a conference call are also listed here. The applications SHOULD check the conferenceId property of each TelephonyCall object in order to determine whether the call is part of a conference call, and if yes, which is the controlling TelephonyCall object for the conference call.

This method MUST get all calls from all enabled telephony services, hence the getServices() method needs to be called first. If the client has not explicitly called it yet, it is the responsibility of the implementation to retrieve the available telephony services.

10.5.4 The dial() method

The dial(remoteParty) method initiates a new telephony call on the selected telephony service.

When the dial() method is invoked, the user agent MUST run the following dialing steps:

Note

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. However, the user agent SHOULD do a basic validation of the user input.

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. Return promise and continue the following steps asynchronously.
  3. If there is no selected telephony service, then the user agent SHOULD attempt retrieving the available telephony services and set a selected telephony service, then continue these steps. If this fails, then call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate these steps.
  4. Optionally validate the value of the remoteParty property and if it is not valid, resolve promise with an "InvalidCharacterError" error, and terminate this algorithm.
  5. Make a request to the underlying telephony system to dial the call and wait for response from the underlying system.
  6. If it's not possible to fulfill the request for whatever reason: timeout, security, etc., then call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate this algorithm.
  7. Otherwise, if the request is successful, then set the value of the state property to 'dialing', execute the state change steps, and queue a task to invoke resolver's accept(value) method.

10.5.5 The transfer() method

Note

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 joining the active and held calls on the selected telephony service, then disconnects, so that the conversation is continuing between the remote parties of the formerly active and held calls, respectively. The method needs the GSM Explicit Call Transfer supplementary service to be active.The method takes one argument, which represents the held call whose remote party is connected with the remote party of this call (which MUST be the active call). When invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. If there is no active or held calls in progress, then optionally call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "InvalidStateError", and terminate this algorithm.
  3. if the method is not supported by the implementation, optionally call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to NotSupportedError, and terminate these steps.
  4. Set the state of this call to transferring
  5. Return promise and continue the following steps asynchronously.
  6. Make a request to the telephony system to transfer the call to the remote party indicated in the call parameter, and wait for response from the telephony system
  7. If the request fails, then reset the state of the call to the call state on the modem. Then call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError" or "NotSupportedError" and terminate these steps.
  8. If the transfer request is successful, then execute the call disconnected steps, and queue a task to invoke resolver's accept() method.

10.5.6 The createConference() method

When the createConference() method is invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. Return promise and continue the following steps asynchronously.
  3. If there is no active call, or no call in the 'held' state, then optionally resolve promise with a "NoModificationAllowedError" error and terminate this algorithm.
  4. Let service be the value of the serviceId property of the active call.
  5. Let confCall be a new instance of TelephonyCall with a unique callId property having the same value as the conferenceId property, and the value of the serviceId property set to service.
  6. Set the state of confCall to 'connecting' and execute the state change steps.
  7. In the telephony service specified by the serviceId property of service make a request to the telephony system to create a conference call, and wait for the response. In GSM this will mean joining the active and held calls into a conference call. In CDMA, it means joining the waiting or held call with the active call into a 3-way call.
  8. If the request fails, call resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", invalidate confCall and terminate this algorithm.
  9. If the request succeeds, add confCall to the list of managed calls of the CallManager object (navigator.telephony). In the same step, set the conferenceId attribute of all the participating calls to the callId of the conference call confCall, and their state to conference.
  10. Set the state of confCall to 'active' and execute the state change steps, and the active call change steps.
  11. Call resolver's accept(value) method with the value argument set to confCall.

10.5.7 The getParticipantCalls() method

When the getParticipantCalls() method is invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. Return promise and continue the following steps asynchronously.
  3. Let confId be the parameter of type DOMString of this method.
  4. Let confCall be the TelephonyCall object with the callId property equal to confId. If there is no such object, then resolve promise with a "NoModificationAllowedError" error, and terminate this algorithm.
  5. Collect the list of TelephonyCall objects participating in the conference call, i.e. those whose conferenceId property is equal to confId.
  6. queue a task to invoke resolver's accept(value) method with value parameter set to the array containing the list of participant calls.

11. The ToneManager Interface

The ToneManager interface provides [DTMF] related functionality, such as sending a series of tones, and starting and stopping a single tone.

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

Issue 3

The above needs to be converted to ABNF

interface ToneManager {
    Promise sendTones (DOMString tones, optional ToneOptions options);
    Promise startTone (DOMString tone, optional ToneOptions options);
    Promise stopTone (optional DOMString serviceId);
};

11.1 The sendTones() method

The sendTones() method requests a telephony service emit one or more [DTMF] tones.

11.1.1 ToneOptions Dictionary

dictionary ToneOptions {
             unsigned long duration;
             unsigned long gap;
};
11.1.1.1 The duration member

The duration member represents the duration (mark) in milliseconds of the [DTMF] tones to be sent. The minimum value SHOULD be 70 ms.

11.1.1.2 The gap member

The gap member represents the duration in milliseconds of the time gap (space) before a [DTMF] tone. The minimum value SHOULD be 30 ms.

When the sendTones() method is invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. If there is no selected telephony service,then invoke resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate these steps.
  3. Return promise to the caller and continue the following steps asynchronously.
  4. If the ToneOptions parameter specifies the tone duration, then validate and use that value, otherwise use a default value.
  5. If the ToneOptions parameter specifies the tone gap, then validate and use that value, otherwise use a default value.
  6. Request from the telephony system to send the specified tones.
  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.

11.2 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. Let promise be a new Promise object and resolver its associated resolver.
  2. If there is no selected telephony service, then invoke resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate these steps.
  3. Return promise to the caller and continue the following steps asynchronously.
  4. If the platform does not support long press [DTMF] tones or starting tones, then invoke resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NotSuppoertedError", and terminate these steps. In this case applications may then use the sendTones method for sending [DTMF].
  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.

11.3 The stopTone() method

The stopTone() method stops emitting a [DTMF] tone in the selected telephony service. When invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. If there is no selected telephony service, then invoke resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NoModificationAllowedError", and terminate these steps.
  3. Return promise to the caller and continue the following steps asynchronously.
  4. If the platform does not support long press [DTMF] tones or starting tones, then invoke resolver's reject(value) method with the value argument set to a new DOMError object whose name is set to "NotSupportedError", and terminate these steps.
  5. Otherwise, request from the telephony system to stop sending the specified tone.
  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.

12. The EmergencyManager Interface

This interface provides access for reading emergency numbers from the available telephony services.

interface EmergencyManager {
    // on success returns emergency numbers as sequence of DOMString
    Promise getEmergencyNumbers ();
                attribute EventHandler onemergencynumberschanged;
};

12.1 Event handlers

The following are the event handlers implemented by the EmergencyManager interface.

event handler event name
onemergencynumberschanged emergencynumberschanged

When emergency numbers have changed, the changed event of type Event MUST be fired at the object implementing this interface. The applications SHOULD read the emergency numbers by the getEmergencyNumbers() method.

12.2 The getEmergencyNumbers() method

When the getEmergencyNumbers() method is invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. Return promise and continue the following steps asynchronously.
  3. make a request to the underlying telephony system to provide the list of emergency numbers from the selected telephony service, and wait for response.
  4. If it's not possible to retrieve the list of telephony service identifiers for whatever reason: timeout, security, etc., then 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.
  5. Otherwise, combine the emergency numbers into a sequence of distinct DOMString strings, and queue a task to invoke resolver's accept(value) method with the sequence of emergency numbers in the current geographical area, as the value argument. The list can be empty.

13. Security and privacy considerations

Issue 4

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.

13.1 Threats

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

13.2 Mitigations

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

13.3 User interaction guidelines

Implementations SHOULD make sure the phone calls are controllable by the user at any point in time while the call is active.

A. 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 conference call there needs to be a separate CallHistoryEntry object for each call participant, sharing the same value for the conferenceId attribute.

Note

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.

A.1 CallHistoryEntry interface

interface CallHistoryEntry {
    readonly    attribute DOMString          remoteParty;
    readonly    attribute Date               startTime;
    readonly    attribute unsigned long long duration;
    readonly    attribute CallDirection      direction;
    readonly    attribute DisconnectReason?  disconnectReason;
    readonly    attribute boolean            conference;
    readonly    attribute boolean            emergency;
    readonly    attribute DOMString          serviceName;
};

A.1.1 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.

A.1.2 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.

A.1.3 The duration attribute

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

A.1.4 The direction attribute

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

A.1.5 The disconnectReason attribute

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

A.1.6 The emergency attribute

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

A.1.7 The conference attribute

When getting the conference attribute, the user agent MUST return the true if the call has participated in a conference call. Otherwise, return false.

A.1.8 The serviceName attribute

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

A.2 CallDirection enum

enum CallDirection {
    "dialed",
    "received",
    "misse",
    missed-new"
};

The call direction can take the following values:

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

B. Telephony services

This section is non-normative.

B.1 The ServiceManager Interface

The ServiceManager interface manages the state of the TelephonyService objects.

interface ServiceManager : EventTarget {
    readonly    attribute selectedService;
    Promise selectService (DOMString serviceId);
    Promise getServices ();
                attribute EventHandler      onserviceadded;
                attribute EventHandler      onserviceremoved;
                attribute EventHandler      onservicechanged;
                attribute EventHandler      onselectedservicechanged;
};

B.1.1 Event handlers

The following are the event handlers implemented by the ServiceManager interface.

event handler event name event type short description
onserviceadded serviceadded TelephonyServiceEvent handles a new enabled telephony service.
onserviceremoved serviceremoved TelephonyServiceEvent handles a disabled telephony service.
onservicechanged servicechanged TelephonyServiceChangeEvent handles a changed telephony service.
onselectedservicechanged selectedservicechanged TelephonyServiceEvent handles the change of selected telephony service.

B.1.2 Handling events for changes in 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.).

The functionality related to managing telephony services is described in the ServiceManager interface. TelephonyManager implements the ServiceManager interface.

When a telephony service is either added or removed in the system, or the selected telephony service is changed, the user agent MUST run the next steps to change the telephony service:

  1. Let event be a new TelephonyServiceEvent, with the event name set to serviceremoved if the telephony service was removed, or serviceadded if it was added, or selectedservicechanged if the selected telephony service has changed. Or, if a telephony service has changed, let event be a new TelephonyServiceChangeEvent, with the event name set to servicechanged. This event does not bubble, is not cancelable, has no default action, and its serviceId attribute is set to the telephony service id of the telephony service that initiated this algorithm.
  2. If the service has been removed and it's been the selected telephony service for the origin, then change selected telephony service to null and queue a task to fire a selectedservicechange event at the ServiceManager object(s).
  3. Queue a task to fire an event event at the TelephonyManager.
Issue 5

Note that compliant implementations may not be reporting events exactly when they occur, and the implementations may have to poll for these (e.g. OTA SIM update or hot-swappable SIM cards). See issue 127.

B.1.3 The selectedService property

When getting the selectedService attribute, the user agent MUST return the TelephonyService object that represents the selected telephony service, or return null if it is not available.

B.1.4 The selectService() method

The selectService() method provides a means to change the selected telephony service used by the user agent. When invoked, the user agent MUST run the the following steps:

  1. Let serviceId 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 serviceId does not exactly match the identifier of any telephony service known to the user agent,run the following error 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 serviceId exactly matches the telephony service id of the current selected telephony service, invoke resolver's accept() method and terminate these steps.
  6. Otherwise, make a request to the underlying system to change from the currently selected telephony service to the one identified by serviceId.
  7. Wait for response from the underlying system.
  8. If it's not possible to change the selected telephony service for whatever reason: timeout, security, etc., then 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.
  9. Otherwise, queue a task to:
    1. Change the selectedService attribute to the telephony service of the new selected telephony service.
    2. invoke resolver's accept() method.
    3. Fire an event named selectedservicechanged at the ServiceManager object(s).

B.1.5 The getServices() method

The getServices() method provides a means to retrieve the list of telephony service ids representing enabled telephony services. When invoked, the user agent MUST run the following steps:

  1. Let promise be a new Promise object and resolver its associated resolver.
  2. Return promise and continue the following steps asynchronously.
  3. Make a request to the underlying system to retrieve the list of available telephony services.
  4. Wait for response from the underlying system.
  5. If it's not possible to retrieve the list of telephony services for whatever reason: timeout, security, etc., then 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.
  6. Otherwise, queue a task to invoke resolver's accept(value) method with the sequence of TelephonyService objects as value argument, even if the list is empty.

B.2 The TelephonyServiceEvent Interface

Defines a telephony event for notifying about a new or removed telephony service.

interface TelephonyServiceEvent : Event {
    readonly    attribute TelephonyService service;
};

B.2.1 The service attribute

When getting the service, the user agent MUST return the TelephonyService object representing the telephony service that triggered the event.

B.3 The TelephonyServiceChangeEvent Interface

Defines a telephony event for notifying about a changed telephony service.

TelephonyServiceChangeEvent implements TelephonyService;
interface TelephonyServiceChangeEvent {
    readonly    attribute DOMString[] changedProperties;
};

B.3.1 The changedProperties attribute

When getting the changedProperties, the user agent MUST return the sequence of property names of the TelephonyService object service, whose value has been changed.

B.4 The TelephonyProvider Interface

This section is non-normative.

The interface which represents telephony providers present in the system.

[NoInterfaceObject]
interface TelephonyProvider {
                attribute DOMString             name;
    readonly    attribute RegistrationMode?     registrationMode;
    readonly    attribute TelephonyTechnology   technology;
    readonly    attribute TelephonyTechnology[] technologies;
    readonly    attribute double                signalStrength;
    readonly    attribute double                dataStrength;
    readonly    attribute DOMString?            mobileNetworkCode;
    readonly    attribute DOMString?            mobileCountryCode;
    readonly    attribute DOMString?            locationAreaCode;
};

B.4.1 The name property

It MUST return the name of the telephony provider.

B.4.2 The registrationMode property

It MUST return the registration mode used by the telephony provider. The following values are supported:

  • "manual": manual registration
  • "auto": automatic registration

enum TelephonyTechnology {
    "manual",
    "auto"
};

B.4.3 The technology property

It MUST return the current TelephonyTechnology used by the telephony provider, if available, otherwise null.

B.4.4 The technologies property

It MUST return the list of supported technologies of the telephony provider.

B.4.5 The signalStrength property

It MUST return the current radio signal strength with the telephony provider as a number scaled between 0 (no signal) and 1.0 (maximum).

B.4.6 The dataStrength property

It MUST return the current radio signal strength of the High Data Rate network if the provider is a CDMA network, as a value between 0 (no signal) and 1 (full strength), or 0 if not available.

B.4.7 The mobileNetworkCode property

It MUST return the Mobile Network Code of the telephony provider, if available, otherwise null.

B.4.8 The mobileCountryCode property

It MUST return the Mobile Country Code of the telephony provider, if available, otherwise null.

B.4.9 The locationAreaCode property

It MUST return the Location Area Code of the telephony provider, if available, otherwise null.

B.5 The TelephonyService Interface

This section is non-normative.

The interface which manages a given telephony services present in the system. Different services may provide different set of interfaces for managing service specific settings, depending on protocol and the current telephony network to which the device is connected.

[NoInterfaceObject]
interface TelephonyService {
                attribute DOMString            name;
    readonly    attribute DOMString            serviceId;
    readonly    attribute TelephonyServiceType serviceType;
    readonly    attribute boolean              enabled;
    readonly    attribute boolean              emergencyMode;
    readonly    attribute TelephonyProvider    provider;
    Promise setEnabled (boolean enabled);
    Promise getProviders ();
    Promise selectProvider (TelephonyProvider provider);
};

B.5.1 The serviceId property

It MUST return the telephony service id of the telephony service.

B.5.2 The enabled property

It MUST return or set the enabled state of the service, i.e. true if the service is enabled, and false if the service is disabled.

B.5.3 The emergencyMode property

It MUST return true if the service is in emergency mode, i.e. an emergency call is in progress, and false otherwise.

B.5.4 The displayName property

It MUST return the string value as displayed to the user by the application. It MAY be a localization string identifier.

B.5.5 The provider property

It MUST return the TelephonyProvider object selected for the telephony service.

B.5.6 The serviceType property

The following values are supported as telephony service type:

  • "unknown": service type not known
  • "hw": hardware modem
  • "hfp": external modem used through Bluetooth Hands Free Profile (for control and also handles audio)
  • "sap": external modem used through Bluetooth SIM Access Profile (only for control, audio is local)
  • "sw": software modem.

    enum TelephonyServiceType {
        "unknown",
        "hw",
        "hfp",
        "sap",
        "sw"
    };

B.5.7 The setEnabled() method

The setEnabled() method enables or disabled the telephony service . When invoked, the user agent MUST run the following steps:

  1. Let enabled 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. Make a request to the underlying system to enable the telephony service if enabled is true, and disable it otherwise.
  5. Wait for response from the underlying system.
  6. If it was not possible to complete the request for whatever reason: timeout, security, etc., then 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.
  7. Otherwise, when the request has been completed, queue a task to invoke resolver's accept() method. Parallel to this, implementations MUST also follow the steps for handling service change events.

B.5.8 The selectProvider() method

The selectProvider() method registers with the selected provider (network operator). When invoked, the user agent MUST run the following steps:

  1. Let provider 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. Make a request to the underlying system to register with the telephony provider represented by provider.
  5. Wait for response from the underlying system.
  6. If it was not possible to complete the request for whatever reason: timeout, security, etc., then 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.
  7. Otherwise, when the request has been completed, queue a task to invoke resolver's accept() method. Parallel to this, implementations MUST also follow the steps for handling service change events.

B.5.9 Extension possibilities

Note

In the future, TelephonyService could be extended e.g. in the following way:

CellularService implements TelephonyService;
[NoInterfaceObject]
interface CellularService {
    readonly    attribute SimInfo?               simInfo;
    readonly    attribute SimSettings?           simSettings;
    readonly    attribute CallForwarding?        forwarding;
    readonly    attribute CallBarring?           barring;
    readonly    attribute CallMeters?            meters;
    readonly    attribute SupplementaryServices? ss;
    // ... and other interfaces...
};

Depending on implementation, on operator network support and on settings, some of these interfaces may not be available, in which case the value of the corresponding attributes is set to null.

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

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

E. References

E.1 Normative references

[DOM4]
Anne van Kesteren; Aryeh Gregor; Ms2ger; Alex Russell; Robin Berjon. W3C DOM4. 28 April 2015. W3C Last Call Working Draft. URL: http://www.w3.org/TR/dom/
[DTMF]
Q.23 : Technical features of push-button telephone sets. 1 November 1988. In force. URL: http://www.itu.int/rec/T-REC-Q.23/en
[GSM-CALL]
Bruno Landais. GSM TS 23.018 Basic call handling. 28 April 1999. Technical realization. URL: http://www.3gpp.org/ftp/Specs/html-info/23018.htm
[HTML]
Ian Hickson. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[IMS]
Thomas Towle. IP Multimedia Subsystem (IMS). 14 March 2002. Stage 2. URL: http://www.3gpp.org/ftp/Specs/html-info/23228.htm
[JINGLE]
Scott Ludwig; Joe Beda; Peter Saint-Andre; Robert McQueen; Sean Egan; Joe Hildebrand et al. XEP-0166: Jingle. 23 December 2009. Draft Standard. URL: http://xmpp.org/extensions/xep-0166.html
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[WEBIDL]
Cameron McCormack. Web IDL. 19 April 2012. W3C Candidate Recommendation. URL: http://www.w3.org/TR/WebIDL/