dictionary RTCConfiguration {
    sequence<RTCIceServer>   iceServers;
    RTCIceTransportPolicy    iceTransportPolicy = "all";
    RTCBundlePolicy          bundlePolicy = "balanced";
    RTCRtcpMuxPolicy         rtcpMuxPolicy = "require";
    DOMString                peerIdentity;
    sequence<RTCCertificate> certificates;
    [EnforceRange]
    octet                    iceCandidatePoolSize = 0;
};

enum RTCIceCredentialType {
    "password",
    "token"
};

dictionary RTCIceServer {
    required (DOMString or sequence<DOMString>) urls;
             DOMString                          username;
             DOMString                          credential;
             RTCIceCredentialType               credentialType = "password";
};

enum RTCIceTransportPolicy {
    "relay",
    "all"
};

enum RTCBundlePolicy {
    "balanced",
    "max-compat",
    "max-bundle"
};

enum RTCRtcpMuxPolicy {
    // At risk due to lack of implementers' interest.
    "negotiate",
    "require"
};

dictionary RTCOfferAnswerOptions {
    boolean voiceActivityDetection = true;
};

dictionary RTCOfferOptions : RTCOfferAnswerOptions {
    boolean iceRestart = false;
    boolean offerToReceiveAudio;
    boolean offerToReceiveVideo;
};

dictionary RTCAnswerOptions : RTCOfferAnswerOptions {
};

[Constructor(optional RTCConfiguration configuration)]
interface RTCPeerConnection : EventTarget {
    Promise<RTCSessionDescriptionInit> createOffer(optional RTCOfferOptions options);
    Promise<RTCSessionDescriptionInit> createAnswer(optional RTCAnswerOptions options);
    Promise<void>                      setLocalDescription(RTCSessionDescriptionInit description);
    readonly        attribute RTCSessionDescription?    localDescription;
    readonly        attribute RTCSessionDescription?    currentLocalDescription;
    readonly        attribute RTCSessionDescription?    pendingLocalDescription;
    Promise<void>                      setRemoteDescription(RTCSessionDescriptionInit description);
    readonly        attribute RTCSessionDescription?    remoteDescription;
    readonly        attribute RTCSessionDescription?    currentRemoteDescription;
    readonly        attribute RTCSessionDescription?    pendingRemoteDescription;
    Promise<void>                      addIceCandidate((RTCIceCandidateInit or RTCIceCandidate) candidate);
    readonly        attribute RTCSignalingState         signalingState;
    readonly        attribute RTCIceGatheringState      iceGatheringState;
    readonly        attribute RTCIceConnectionState     iceConnectionState;
    readonly        attribute RTCPeerConnectionState    connectionState;
    readonly        attribute boolean?                  canTrickleIceCandidates;
    static readonly attribute FrozenArray<RTCIceServer> defaultIceServers;
    RTCConfiguration                   getConfiguration();
    void                               setConfiguration(RTCConfiguration configuration);
    void                               close();
                    attribute EventHandler              onnegotiationneeded;
                    attribute EventHandler              onicecandidate;
                    attribute EventHandler              onicecandidateerror;
                    attribute EventHandler              onsignalingstatechange;
                    attribute EventHandler              oniceconnectionstatechange;
                    attribute EventHandler              onicegatheringstatechange;
                    attribute EventHandler              onconnectionstatechange;
                    attribute EventHandler              onfingerprintfailure;
};

partial interface RTCPeerConnection {
    Promise<void> createOffer(RTCSessionDescriptionCallback successCallback,
                              RTCPeerConnectionErrorCallback failureCallback,
                              optional RTCOfferOptions options);
    Promise<void> setLocalDescription(RTCSessionDescriptionInit description,
                                      VoidFunction successCallback,
                                      RTCPeerConnectionErrorCallback failureCallback);
    Promise<void> createAnswer(RTCSessionDescriptionCallback successCallback,
                               RTCPeerConnectionErrorCallback failureCallback);
    Promise<void> setRemoteDescription(RTCSessionDescriptionInit description,
                                       VoidFunction successCallback,
                                       RTCPeerConnectionErrorCallback failureCallback);
    Promise<void> addIceCandidate((RTCIceCandidateInit or RTCIceCandidate) candidate,
                                  VoidFunction successCallback,
                                  RTCPeerConnectionErrorCallback failureCallback);
};

enum RTCSignalingState {
    "stable",
    "have-local-offer",
    "have-remote-offer",
    "have-local-pranswer",
    "have-remote-pranswer"
};

enum RTCIceGatheringState {
    "new",
    "gathering",
    "complete"
};

enum RTCPeerConnectionState {
    "new",
    "connecting",
    "connected",
    "disconnected",
    "failed",
    "closed"
};

enum RTCIceConnectionState {
    "new",
    "checking",
    "connected",
    "completed",
    "failed",
    "disconnected",
    "closed"
};

callback RTCPeerConnectionErrorCallback = void (DOMException error);

callback RTCSessionDescriptionCallback = void (RTCSessionDescriptionInit description);

callback RTCStatsCallback = void (RTCStatsReport report);

enum RTCSdpType {
    "offer",
    "pranswer",
    "answer",
    "rollback"
};

[Constructor(RTCSessionDescriptionInit descriptionInitDict)]
interface RTCSessionDescription {
    readonly attribute RTCSdpType type;
    readonly attribute DOMString  sdp;
    serializer = {attribute};
};

dictionary RTCSessionDescriptionInit {
    required RTCSdpType type;
             DOMString  sdp = "";
};

[Constructor(RTCIceCandidateInit candidateInitDict)]
interface RTCIceCandidate {
    readonly attribute DOMString               candidate;
    readonly attribute DOMString?              sdpMid;
    readonly attribute unsigned short?         sdpMLineIndex;
    readonly attribute DOMString?              foundation;
    readonly attribute unsigned long?          priority;
    readonly attribute DOMString?              ip;
    readonly attribute RTCIceProtocol?         protocol;
    readonly attribute unsigned short?         port;
    readonly attribute RTCIceCandidateType?    type;
    readonly attribute RTCIceTcpCandidateType? tcpType;
    readonly attribute DOMString?              relatedAddress;
    readonly attribute unsigned short?         relatedPort;
    readonly attribute DOMString?              ufrag;
    serializer = {candidate, sdpMid, sdpMLineIndex, ufrag};
};

dictionary RTCIceCandidateInit {
    DOMString       candidate = "";
    DOMString?      sdpMid = null;
    unsigned short? sdpMLineIndex = null;
    DOMString       ufrag;
};

enum RTCIceProtocol {
    "udp",
    "tcp"
};

enum RTCIceTcpCandidateType {
    "active",
    "passive",
    "so"
};

enum RTCIceCandidateType {
    "host",
    "srflx",
    "prflx",
    "relay"
};

[Constructor(DOMString type, optional RTCPeerConnectionIceEventInit eventInitDict)]
interface RTCPeerConnectionIceEvent : Event {
    readonly attribute RTCIceCandidate? candidate;
    readonly attribute DOMString?       url;
};

dictionary RTCPeerConnectionIceEventInit : EventInit {
    RTCIceCandidate? candidate;
    DOMString?       url;
};

[Constructor(DOMString type, RTCPeerConnectionIceErrorEventInit eventInitDict)]
interface RTCPeerConnectionIceErrorEvent : Event {
    readonly attribute DOMString      hostCandidate;
    readonly attribute DOMString      url;
    readonly attribute unsigned short errorCode;
    readonly attribute USVString      errorText;
};

dictionary RTCPeerConnectionIceErrorEventInit : EventInit {
             DOMString      hostCandidate;
             DOMString      url;
    required unsigned short errorCode;
             USVString      statusText;
};

enum RTCPriorityType {
    "very-low",
    "low",
    "medium",
    "high"
};

partial interface RTCPeerConnection {
    static Promise<RTCCertificate> generateCertificate(AlgorithmIdentifier keygenAlgorithm);
};

dictionary RTCCertificateExpiration {
    [EnforceRange]
    DOMTimeStamp expires;
};

interface RTCCertificate {
    readonly attribute DOMTimeStamp                    expires;
    readonly attribute FrozenArray<RTCDtlsFingerprint> fingerprints;
    AlgorithmIdentifier getAlgorithm();
};

partial interface RTCPeerConnection {
    sequence<RTCRtpSender>      getSenders();
    sequence<RTCRtpReceiver>    getReceivers();
    sequence<RTCRtpTransceiver> getTransceivers();
    RTCRtpSender                addTrack(MediaStreamTrack track,
                                         MediaStream... streams);
    void                        removeTrack(RTCRtpSender sender);
    RTCRtpTransceiver           addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
                                               optional RTCRtpTransceiverInit init);
    attribute EventHandler ontrack;
};

dictionary RTCRtpTransceiverInit {
    RTCRtpTransceiverDirection         direction = "sendrecv";
    sequence<MediaStream>              streams;
    sequence<RTCRtpEncodingParameters> sendEncodings;
};

enum RTCRtpTransceiverDirection {
    "sendrecv",
    "sendonly",
    "recvonly",
    "inactive"
};

interface RTCRtpSender {
    readonly attribute MediaStreamTrack? track;
    readonly attribute RTCDtlsTransport? transport;
    readonly attribute RTCDtlsTransport? rtcpTransport;
    static RTCRtpCapabilities getCapabilities(DOMString kind);
    Promise<void>      setParameters(optional RTCRtpParameters parameters);
    RTCRtpParameters   getParameters();
    Promise<void>      replaceTrack(MediaStreamTrack withTrack);
};

dictionary RTCRtpParameters {
    DOMString                                 transactionId;
    sequence<RTCRtpEncodingParameters>        encodings;
    sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
    RTCRtcpParameters                         rtcp;
    sequence<RTCRtpCodecParameters>           codecs;
    RTCDegradationPreference                  degradationPreference = "balanced";
};

dictionary RTCRtpEncodingParameters {
    unsigned long       ssrc;
    RTCRtpRtxParameters rtx;
    RTCRtpFecParameters fec;
    RTCDtxStatus        dtx;
    boolean             active;
    RTCPriorityType     priority;
    unsigned long       maxBitrate;
    unsigned long       maxFramerate;
    DOMString           rid;
    double              scaleResolutionDownBy = 1;
};

enum RTCDtxStatus {
    "disabled",
    "enabled"
};

enum RTCDegradationPreference {
    "maintain-framerate",
    "maintain-resolution",
    "balanced"
};

dictionary RTCRtpRtxParameters {
    unsigned long ssrc;
};

dictionary RTCRtpFecParameters {
    unsigned long ssrc;
};

dictionary RTCRtcpParameters {
    DOMString cname;
    boolean   reducedSize;
};

dictionary RTCRtpHeaderExtensionParameters {
    DOMString      uri;
    unsigned short id;
    boolean        encrypted;
};

dictionary RTCRtpCodecParameters {
    unsigned short payloadType;
    DOMString      mimeType;
    unsigned long  clockRate;
    unsigned short channels = 1;
    DOMString      sdpFmtpLine;
};

dictionary RTCRtpCapabilities {
    sequence<RTCRtpCodecCapability>           codecs;
    sequence<RTCRtpHeaderExtensionCapability> headerExtensions;
};

dictionary RTCRtpCodecCapability {
    DOMString      mimeType;
    unsigned long  clockRate;
    unsigned short channels = 1;
    DOMString      sdpFmtpLine;
};

dictionary RTCRtpHeaderExtensionCapability {
    DOMString uri;
};

interface RTCRtpReceiver {
    readonly attribute MediaStreamTrack  track;
    readonly attribute RTCDtlsTransport? transport;
    readonly attribute RTCDtlsTransport? rtcpTransport;
    static RTCRtpCapabilities          getCapabilities(DOMString kind);
    RTCRtpParameters                   getParameters();
    sequence<RTCRtpContributingSource> getContributingSources();
};

interface RTCRtpContributingSource {
    readonly attribute DOMHighResTimeStamp timestamp;
    readonly attribute unsigned long       source;
    readonly attribute byte?               audioLevel;
    readonly attribute boolean?            voiceActivityFlag;
};

interface RTCRtpTransceiver {
    readonly attribute DOMString?                  mid;
    [SameObject]
    readonly attribute RTCRtpSender                sender;
    [SameObject]
    readonly attribute RTCRtpReceiver              receiver;
    readonly attribute boolean                     stopped;
    readonly attribute RTCRtpTransceiverDirection  direction;
    readonly attribute RTCRtpTransceiverDirection? currentDirection;
    void setDirection(RTCRtpTransceiverDirection direction);
    void stop();
    void setCodecPreferences(sequence<RTCRtpCodecCapability> codecs);
};

interface RTCDtlsTransport {
    readonly attribute RTCIceTransport       transport;
    readonly attribute RTCDtlsTransportState state;
    sequence<ArrayBuffer> getRemoteCertificates();
             attribute EventHandler          onstatechange;
};

enum RTCDtlsTransportState {
    "new",
    "connecting",
    "connected",
    "closed",
    "failed"
};

dictionary RTCDtlsFingerprint {
    DOMString algorithm;
    DOMString value;
};

interface RTCIceTransport {
    readonly attribute RTCIceRole           role;
    readonly attribute RTCIceComponent      component;
    readonly attribute RTCIceTransportState state;
    readonly attribute RTCIceGathererState  gatheringState;
    sequence<RTCIceCandidate> getLocalCandidates();
    sequence<RTCIceCandidate> getRemoteCandidates();
    RTCIceCandidatePair?      getSelectedCandidatePair();
    RTCIceParameters?         getLocalParameters();
    RTCIceParameters?         getRemoteParameters();
             attribute EventHandler         onstatechange;
             attribute EventHandler         ongatheringstatechange;
             attribute EventHandler         onselectedcandidatepairchange;
};

dictionary RTCIceParameters {
    DOMString usernameFragment;
    DOMString password;
};

dictionary RTCIceCandidatePair {
    RTCIceCandidate local;
    RTCIceCandidate remote;
};

enum RTCIceGathererState {
    "new",
    "gathering",
    "complete"
};

enum RTCIceTransportState {
    "new",
    "checking",
    "connected",
    "completed",
    "failed",
    "disconnected",
    "closed"
};

enum RTCIceRole {
    "controlling",
    "controlled"
};

enum RTCIceComponent {
    "rtp",
    "rtcp"
};

[Constructor(DOMString type, RTCTrackEventInit eventInitDict)]
interface RTCTrackEvent : Event {
    readonly attribute RTCRtpReceiver           receiver;
    readonly attribute MediaStreamTrack         track;
    readonly attribute FrozenArray<MediaStream> streams;
    readonly attribute RTCRtpTransceiver        transceiver;
};

dictionary RTCTrackEventInit : EventInit {
    required RTCRtpReceiver        receiver;
    required MediaStreamTrack      track;
             sequence<MediaStream> streams = [];
    required RTCRtpTransceiver     transceiver;
};

partial interface RTCPeerConnection {
    readonly attribute RTCSctpTransport? sctp;
    RTCDataChannel createDataChannel([TreatNullAs=EmptyString] USVString label,
                                     optional RTCDataChannelInit dataChannelDict);
             attribute EventHandler      ondatachannel;
};

interface RTCSctpTransport {
    readonly attribute RTCDtlsTransport transport;
    readonly attribute unsigned long    maxMessageSize;
};

interface RTCDataChannel : EventTarget {
    readonly attribute USVString           label;
    readonly attribute boolean             ordered;
    readonly attribute unsigned short?     maxPacketLifeTime;
    readonly attribute unsigned short?     maxRetransmits;
    readonly attribute USVString           protocol;
    readonly attribute boolean             negotiated;
    readonly attribute unsigned short?     id;
    readonly attribute RTCPriorityType     priority;
    readonly attribute RTCDataChannelState readyState;
    readonly attribute unsigned long       bufferedAmount;
             attribute unsigned long       bufferedAmountLowThreshold;
             attribute EventHandler        onopen;
             attribute EventHandler        onbufferedamountlow;
             attribute EventHandler        onerror;
             attribute EventHandler        onclose;
    void close();
             attribute EventHandler        onmessage;
             attribute DOMString           binaryType;
    void send(USVString data);
    void send(Blob data);
    void send(ArrayBuffer data);
    void send(ArrayBufferView data);
};

dictionary RTCDataChannelInit {
    boolean         ordered = true;
    unsigned short  maxPacketLifeTime;
    unsigned short  maxRetransmits;
    USVString       protocol = "";
    boolean         negotiated = false;
    [EnforceRange]
    unsigned short  id;
    RTCPriorityType priority = "low";
};

enum RTCDataChannelState {
    "connecting",
    "open",
    "closing",
    "closed"
};

[Constructor(DOMString type, RTCDataChannelEventInit eventInitDict)]
interface RTCDataChannelEvent : Event {
    readonly attribute RTCDataChannel channel;
};

dictionary RTCDataChannelEventInit : EventInit {
    required RTCDataChannel channel;
};

partial interface RTCRtpSender {
    readonly attribute RTCDTMFSender? dtmf;
};

interface RTCDTMFSender : EventTarget {
    void insertDTMF(DOMString tones,
                    optional unsigned long duration = 100,
                    optional unsigned long interToneGap = 70);
             attribute EventHandler ontonechange;
    readonly attribute DOMString    toneBuffer;
};

[Constructor(DOMString type, RTCDTMFToneChangeEventInit eventInitDict)]
interface RTCDTMFToneChangeEvent : Event {
    readonly attribute DOMString tone;
};

dictionary RTCDTMFToneChangeEventInit : EventInit {
    required DOMString tone;
};

partial interface RTCPeerConnection {
    Promise<RTCStatsReport> getStats(optional MediaStreamTrack? selector = null);
};

interface RTCStatsReport {
    readonly maplike<DOMString, object>;
};

dictionary RTCStats {
    DOMHighResTimeStamp timestamp;
    RTCStatsType        type;
    DOMString           id;
};

enum RTCStatsType {
};

[Global,
 Exposed=RTCIdentityProviderGlobalScope]
interface RTCIdentityProviderGlobalScope : WorkerGlobalScope {
    readonly attribute RTCIdentityProviderRegistrar rtcIdentityProvider;
};

[Exposed=RTCIdentityProviderGlobalScope]
interface RTCIdentityProviderRegistrar {
    void register(RTCIdentityProvider idp);
};

dictionary RTCIdentityProvider {
    required GenerateAssertionCallback generateAssertion;
    required ValidateAssertionCallback validateAssertion;
};

callback GenerateAssertionCallback = Promise<RTCIdentityAssertionResult> (DOMString contents,
                                                                          DOMString origin,
                                                                          RTCIdentityProviderOptions options);

callback ValidateAssertionCallback = Promise<RTCIdentityValidationResult> (DOMString assertion,
                                                                           DOMString origin);

dictionary RTCIdentityAssertionResult {
    required RTCIdentityProviderDetails idp;
    required DOMString                  assertion;
};

dictionary RTCIdentityProviderDetails {
    required DOMString domain;
             DOMString protocol = "default";
};

dictionary RTCIdentityValidationResult {
    required DOMString identity;
    required DOMString contents;
};

partial interface RTCPeerConnection {
    void               setIdentityProvider(DOMString provider,
                                           optional RTCIdentityProviderOptions options);
    Promise<DOMString> getIdentityAssertion();
    readonly attribute Promise<RTCIdentityAssertion> peerIdentity;
    readonly attribute DOMString?                    idpLoginUrl;
    readonly attribute DOMString?                    idpErrorInfo;
};

dictionary RTCIdentityProviderOptions {
    DOMString protocol = "default";
    DOMString usernameHint;
    DOMString peerIdentity;
};

[Constructor(DOMString idp, DOMString name)]
interface RTCIdentityAssertion {
    attribute DOMString idp;
    attribute DOMString name;
};

partial dictionary MediaStreamConstraints {
    DOMString peerIdentity;
};

partial interface MediaStreamTrack {
    readonly attribute boolean      isolated;
             attribute EventHandler onisolationchange;
};

[Exposed=Window,
 Constructor(DOMString type, RTCErrorEventInit eventInitDict)]
interface RTCErrorEvent : Event {
    readonly attribute RTCError? error;
};

dictionary RTCErrorEventInit : EventInit {
    RTCError? error = null;
};
