mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 823512: Part 2: Update PeerConnection to spec. states + DataChannel. r=bz,rjesup,ekr
This commit is contained in:
parent
7921c9c1e4
commit
9386baa685
@ -1553,6 +1553,7 @@ addExternalIface('DeviceRotationRate', headerFile='nsIDOMDeviceMotionEvent.h', n
|
||||
addExternalIface('DOMError')
|
||||
addExternalIface('CSSRuleList')
|
||||
addExternalIface('DOMStringList')
|
||||
addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel')
|
||||
addExternalIface('File')
|
||||
addExternalIface('FileCallback', nativeType='nsIFileCallback',
|
||||
headerFile='nsIDOMHTMLCanvasElement.h')
|
||||
|
@ -15,6 +15,7 @@ const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
|
||||
const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
|
||||
const PC_ICEEVENT_CONTRACT = "@mozilla.org/dom/rtcpeerconnectioniceevent;1";
|
||||
const MSEVENT_CONTRACT = "@mozilla.org/dom/mediastreamevent;1";
|
||||
const DCEVENT_CONTRACT = "@mozilla.org/dom/datachannelevent;1";
|
||||
|
||||
const PC_CID = Components.ID("{9878b414-afaa-4176-a887-1e02b3b047c2}");
|
||||
const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
|
||||
@ -22,6 +23,7 @@ const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
|
||||
const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
|
||||
const PC_ICEEVENT_CID = Components.ID("{b9cd25a7-9859-4f9e-8f84-ef5181ff36c0}");
|
||||
const MSEVENT_CID = Components.ID("{a722a8a9-2290-4e99-a5ed-07b504292d08}");
|
||||
const DCEVENT_CID = Components.ID("{d5ed7fbf-01a8-4b18-af6c-861cf2aac920}");
|
||||
|
||||
// Global list of PeerConnection objects, so they can be cleaned up when
|
||||
// a page is torn down. (Maps inner window ID to an array of PC objects).
|
||||
@ -176,6 +178,28 @@ MediaStreamEvent.prototype = {
|
||||
get stream() { return this._stream; }
|
||||
};
|
||||
|
||||
function RTCDataChannelEvent() {
|
||||
this.type = this._channel = null;
|
||||
}
|
||||
RTCDataChannelEvent.prototype = {
|
||||
classDescription: "RTCDataChannelEvent",
|
||||
classID: DCEVENT_CID,
|
||||
contractID: DCEVENT_CONTRACT,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
||||
Ci.nsIDOMGlobalPropertyInitializer]),
|
||||
|
||||
init: function(win) { this._win = win; },
|
||||
|
||||
__init: function(type, dict) {
|
||||
this.type = type;
|
||||
this.__DOM_IMPL__.initEvent(type, dict.bubbles || false,
|
||||
dict.cancelable || false);
|
||||
this._channel = dict.channel;
|
||||
},
|
||||
|
||||
get channel() { return this._channel; }
|
||||
};
|
||||
|
||||
function RTCPeerConnectionIceEvent() {
|
||||
this.type = this._candidate = null;
|
||||
}
|
||||
@ -192,7 +216,7 @@ RTCPeerConnectionIceEvent.prototype = {
|
||||
this.type = type;
|
||||
this.__DOM_IMPL__.initEvent(type, dict.bubbles || false,
|
||||
dict.cancelable || false);
|
||||
this._candidate = dict.candidate || null;
|
||||
this._candidate = dict.candidate;
|
||||
},
|
||||
|
||||
get candidate() { return this._candidate; }
|
||||
@ -224,17 +248,12 @@ function RTCPeerConnection() {
|
||||
*/
|
||||
this._pending = false;
|
||||
|
||||
// Event handlers
|
||||
this.onopen = null;
|
||||
this.onremovestream = null;
|
||||
this.onstatechange = null;
|
||||
this.ongatheringchange = null;
|
||||
this.onicechange = null;
|
||||
// States
|
||||
this._iceGatheringState = this._iceConnectionState = "new";
|
||||
|
||||
// Data channel.
|
||||
this.ondatachannel = null;
|
||||
this.onconnection = null;
|
||||
this.onclosedconnection = null;
|
||||
// Deprecated callbacks
|
||||
this._ongatheringchange = null;
|
||||
this._onicechange = null;
|
||||
}
|
||||
RTCPeerConnection.prototype = {
|
||||
classDescription: "mozRTCPeerConnection",
|
||||
@ -257,6 +276,16 @@ RTCPeerConnection.prototype = {
|
||||
throw new Components.Exception("Can't create RTCPeerConnections when the network is down");
|
||||
}
|
||||
|
||||
this.makeGetterSetterEH("onaddstream");
|
||||
this.makeGetterSetterEH("onicecandidate");
|
||||
this.makeGetterSetterEH("onnegotiationneeded");
|
||||
this.makeGetterSetterEH("onsignalingstatechange");
|
||||
this.makeGetterSetterEH("onremovestream");
|
||||
this.makeGetterSetterEH("ondatachannel");
|
||||
this.makeGetterSetterEH("onconnection");
|
||||
this.makeGetterSetterEH("onclosedconnection");
|
||||
this.makeGetterSetterEH("oniceconnectionstatechange");
|
||||
|
||||
this._pc = Cc["@mozilla.org/peerconnection;1"].
|
||||
createInstance(Ci.IPeerConnection);
|
||||
this._observer = new PeerConnectionObserver(this);
|
||||
@ -445,25 +474,45 @@ RTCPeerConnection.prototype = {
|
||||
this.__DOM_IMPL__.dispatchEvent(event);
|
||||
},
|
||||
|
||||
getEventHandler: function(type) {
|
||||
getEH: function(type) {
|
||||
return this.__DOM_IMPL__.getEventHandler(type);
|
||||
},
|
||||
|
||||
setEventHandler: function(type, handler) {
|
||||
setEH: function(type, handler) {
|
||||
this.__DOM_IMPL__.setEventHandler(type, handler);
|
||||
},
|
||||
|
||||
get onaddstream() { return this.getEventHandler("onaddstream"); },
|
||||
get onicecandidate() { return this.getEventHandler("onicecandidate"); },
|
||||
makeGetterSetterEH: function(name) {
|
||||
Object.defineProperty(this, name,
|
||||
{
|
||||
get:function() { return this.getEH(name); },
|
||||
set:function(h) { return this.setEH(name, h); }
|
||||
});
|
||||
},
|
||||
|
||||
set onaddstream(handler) { this.setEventHandler("onaddstream", handler); },
|
||||
set onicecandidate(h) { this.setEventHandler("onicecandidate", h); },
|
||||
get onicechange() { return this._onicechange; },
|
||||
get ongatheringchange() { return this._ongatheringchange; },
|
||||
|
||||
set onicechange(cb) {
|
||||
this.deprecated("onicechange");
|
||||
this._onicechange = cb;
|
||||
},
|
||||
set ongatheringchange(cb) {
|
||||
this.deprecated("ongatheringchange");
|
||||
this._ongatheringchange = cb;
|
||||
},
|
||||
|
||||
deprecated: function(name) {
|
||||
dump(name + " is deprecated!\n");
|
||||
},
|
||||
|
||||
createOffer: function(onSuccess, onError, constraints) {
|
||||
if (!constraints) {
|
||||
constraints = {};
|
||||
}
|
||||
|
||||
if (!onError) {
|
||||
this.deprecated("calling createOffer without failureCallback");
|
||||
}
|
||||
this._mustValidateConstraints(constraints, "createOffer passed invalid constraints");
|
||||
this._onCreateOfferSuccess = onSuccess;
|
||||
this._onCreateOfferFailure = onError;
|
||||
@ -476,6 +525,9 @@ RTCPeerConnection.prototype = {
|
||||
},
|
||||
|
||||
_createAnswer: function(onSuccess, onError, constraints, provisional) {
|
||||
if (!onError) {
|
||||
this.deprecated("calling createAnswer without failureCallback");
|
||||
}
|
||||
this._onCreateAnswerSuccess = onSuccess;
|
||||
this._onCreateAnswerFailure = onError;
|
||||
|
||||
@ -531,10 +583,12 @@ RTCPeerConnection.prototype = {
|
||||
case "answer":
|
||||
type = Ci.IPeerConnection.kActionAnswer;
|
||||
break;
|
||||
case "pranswer":
|
||||
throw new Components.Exception("pranswer not yet implemented",
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
default:
|
||||
throw new Components.Exception("Invalid type " + desc.type +
|
||||
" provided to setLocalDescription");
|
||||
break;
|
||||
}
|
||||
|
||||
this._queueOrRun({
|
||||
@ -560,10 +614,12 @@ RTCPeerConnection.prototype = {
|
||||
case "answer":
|
||||
type = Ci.IPeerConnection.kActionAnswer;
|
||||
break;
|
||||
case "pranswer":
|
||||
throw new Components.Exception("pranswer not yet implemented",
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
default:
|
||||
throw new Components.Exception("Invalid type " + desc.type +
|
||||
" provided to setRemoteDescription");
|
||||
break;
|
||||
}
|
||||
|
||||
this._queueOrRun({
|
||||
@ -575,8 +631,8 @@ RTCPeerConnection.prototype = {
|
||||
},
|
||||
|
||||
updateIce: function(config, constraints) {
|
||||
throw new Components.Exception ("updateIce not yet implemented",
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
throw new Components.Exception("updateIce not yet implemented",
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
},
|
||||
|
||||
addIceCandidate: function(cand, onSuccess, onError) {
|
||||
@ -606,9 +662,14 @@ RTCPeerConnection.prototype = {
|
||||
},
|
||||
|
||||
removeStream: function(stream) {
|
||||
//Bug844295: Not implemeting this functionality.
|
||||
throw new Components.Exception ("removeStream not yet implemented",
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
//Bug 844295: Not implementing this functionality.
|
||||
throw new Components.Exception("removeStream not yet implemented",
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
},
|
||||
|
||||
getStreamById: function(id) {
|
||||
throw new Components.Exception("getStreamById not yet implemented",
|
||||
Cr.NS_ERROR_NOT_IMPLEMENTED);
|
||||
},
|
||||
|
||||
close: function() {
|
||||
@ -618,6 +679,7 @@ RTCPeerConnection.prototype = {
|
||||
wait: false
|
||||
});
|
||||
this._closed = true;
|
||||
this.changeIceConnectionState("closed");
|
||||
},
|
||||
|
||||
getLocalStreams: function() {
|
||||
@ -630,11 +692,15 @@ RTCPeerConnection.prototype = {
|
||||
return this._getPC().remoteStreams;
|
||||
},
|
||||
|
||||
// Four backwards-compatible attributes (to pass mochitests)
|
||||
get localStreams() { return this.getLocalStreams(); },
|
||||
get remoteStreams() { return this.getRemoteStreams(); },
|
||||
set localDescription(desc) { this.setLocalDescription(desc); },
|
||||
set remoteDescription(desc) { this.setLocalDescription(desc); },
|
||||
// Backwards-compatible attributes
|
||||
get localStreams() {
|
||||
this.deprecated("localStreams");
|
||||
return this.getLocalStreams();
|
||||
},
|
||||
get remoteStreams() {
|
||||
this.deprecated("remoteStreams");
|
||||
return this.getRemoteStreams();
|
||||
},
|
||||
|
||||
get localDescription() {
|
||||
this._checkClosed();
|
||||
@ -656,7 +722,21 @@ RTCPeerConnection.prototype = {
|
||||
sdp: sdp });
|
||||
},
|
||||
|
||||
get signalingState() { return "stable"; }, // not yet implemented
|
||||
get iceGatheringState() { return this._iceGatheringState; },
|
||||
get iceConnectionState() { return this._iceConnectionState; },
|
||||
|
||||
changeIceGatheringState: function(state) {
|
||||
this._iceGatheringState = state;
|
||||
},
|
||||
|
||||
changeIceConnectionState: function(state) {
|
||||
this._iceConnectionState = state;
|
||||
this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
|
||||
},
|
||||
|
||||
get readyState() {
|
||||
this.deprecated("readyState");
|
||||
// checking for our local pc closed indication
|
||||
// before invoking the pc methods.
|
||||
if(this._closed) {
|
||||
@ -885,23 +965,29 @@ PeerConnectionObserver.prototype = {
|
||||
}
|
||||
|
||||
switch (this._dompc._pc.iceState) {
|
||||
case Ci.IPeerConnection.kIceGathering:
|
||||
this.callCB(this._dompc.ongatheringchange, "gathering");
|
||||
break;
|
||||
case Ci.IPeerConnection.kIceWaiting:
|
||||
this.callCB(this._dompc.onicechange, "starting");
|
||||
this._dompc.changeIceConnectionState("completed");
|
||||
this.callCB(this._dompc.ongatheringchange, "complete");
|
||||
this.callCB(this._onicechange, "starting");
|
||||
// Now that the PC is ready to go, execute any pending operations.
|
||||
this._dompc._executeNext();
|
||||
break;
|
||||
case Ci.IPeerConnection.kIceChecking:
|
||||
this.callCB(this._dompc.onicechange, "checking");
|
||||
this._dompc.changeIceConnectionState("checking");
|
||||
this.callCB(this._onicechange, "checking");
|
||||
break;
|
||||
case Ci.IPeerConnection.kIceGathering:
|
||||
this._dompc.changeIceGatheringState("gathering");
|
||||
this.callCB(this._ongatheringchange, "gathering");
|
||||
break;
|
||||
case Ci.IPeerConnection.kIceConnected:
|
||||
// ICE gathering complete.
|
||||
this.callCB(this._dompc.onicechange, "connected");
|
||||
this.callCB(this._dompc.ongatheringchange, "complete");
|
||||
this._dompc.changeIceConnectionState("connected");
|
||||
this.callCB(this._onicechange, "connected");
|
||||
break;
|
||||
case Ci.IPeerConnection.kIceFailed:
|
||||
this.callCB(this._dompc.onicechange, "failed");
|
||||
this._dompc.changeIceConnectionState("failed");
|
||||
this.callCB(this._onicechange, "failed");
|
||||
break;
|
||||
default:
|
||||
// Unknown state!
|
||||
@ -925,20 +1011,20 @@ PeerConnectionObserver.prototype = {
|
||||
},
|
||||
|
||||
notifyDataChannel: function(channel) {
|
||||
this.callCB(this._dompc.ondatachannel,
|
||||
{ channel: channel, __exposedProps__: { channel: "r" } });
|
||||
this.dispatchEvent(new this._dompc._win.RTCDataChannelEvent("datachannel",
|
||||
{ channel: channel }));
|
||||
},
|
||||
|
||||
notifyConnection: function() {
|
||||
this.callCB (this._dompc.onconnection);
|
||||
this.dispatchEvent(new this._dompc._win.Event("connection"));
|
||||
},
|
||||
|
||||
notifyClosedConnection: function() {
|
||||
this.callCB (this._dompc.onclosedconnection);
|
||||
this.dispatchEvent(new this._dompc._win.Event("closedconnection"));
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
|
||||
[GlobalPCList, RTCIceCandidate, RTCSessionDescription, RTCPeerConnection,
|
||||
RTCPeerConnectionIceEvent, MediaStreamEvent]
|
||||
RTCPeerConnectionIceEvent, MediaStreamEvent, RTCDataChannelEvent]
|
||||
);
|
||||
|
@ -4,6 +4,7 @@ component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
|
||||
component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
|
||||
component {b9cd25a7-9859-4f9e-8f84-ef5181ff36c0} PeerConnection.js
|
||||
component {a722a8a9-2290-4e99-a5ed-07b504292d08} PeerConnection.js
|
||||
component {d5ed7fbf-01a8-4b18-af6c-861cf2aac920} PeerConnection.js
|
||||
|
||||
contract @mozilla.org/dom/peerconnection;1 {9878b414-afaa-4176-a887-1e02b3b047c2}
|
||||
contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
|
||||
@ -11,3 +12,4 @@ contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067b
|
||||
contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}
|
||||
contract @mozilla.org/dom/rtcpeerconnectioniceevent;1 {b9cd25a7-9859-4f9e-8f84-ef5181ff36c0}
|
||||
contract @mozilla.org/dom/mediastreamevent;1 {a722a8a9-2290-4e99-a5ed-07b504292d08}
|
||||
contract @mozilla.org/dom/datachannelevent;1 {d5ed7fbf-01a8-4b18-af6c-861cf2aac920}
|
||||
|
@ -1,34 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=837421
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bug 837421</title>
|
||||
<script type="application/javascript">
|
||||
function finish() {
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
function start() {
|
||||
var o0 = mozRTCPeerConnection();
|
||||
var o1 = new mozRTCIceCandidate({"candidate":"127 15 UDP 1 stun.sipgate.net 134117531 type 2001:db8:85a3:0:0:8a2e:370:3478 rport","sdpMid":"application 3566220586 RTP/AVP 5000","sdpMLineIndex":-32767});
|
||||
o0.connectDataConnection(3478,-1);
|
||||
o0.connectDataConnection(-1,3478,2);
|
||||
var o2 = mozRTCPeerConnection();
|
||||
try {o2.addIceCandidate(o1);} catch(e) {} // bug 842075 - remove try when fixed
|
||||
o2.connectDataConnection(-1,3478,0.5);
|
||||
o2.connectDataConnection(3478,-1,0.5);
|
||||
var o3 = new mozRTCIceCandidate({"candidate":"31 2097151 IP 33554431 ::ffff:192.0.2.128 3999799469 type numb.viagenie.ca host","sdpMid":"application 1261077875 RTP/AVP 5000","sdpMLineIndex":16777215});
|
||||
o2.connectDataConnection(1,3478);
|
||||
o2.connectDataConnection(3478,1);
|
||||
try {o2.updateIce()} catch(e) {}
|
||||
try {o2.addIceCandidate(o3);} catch(e) {} // bug 842075 - remove try when fixed
|
||||
finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="setTimeout(start, 100)">
|
||||
</html>
|
@ -10,7 +10,6 @@ load 812785.html
|
||||
load 834100.html
|
||||
load 836349.html
|
||||
load 837324.html
|
||||
load 837421.html
|
||||
load 855796.html
|
||||
load 860143.html
|
||||
load 861958.html
|
||||
|
21
dom/webidl/RTCDataChannelEvent.webidl
Normal file
21
dom/webidl/RTCDataChannelEvent.webidl
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCDataChannelEvent
|
||||
*/
|
||||
|
||||
interface RTCDataChannel;
|
||||
|
||||
dictionary RTCDataChannelEventInit : EventInit {
|
||||
RTCDataChannel? channel = null;
|
||||
};
|
||||
|
||||
[Pref="media.peerconnection.enabled",
|
||||
JSImplementation="@mozilla.org/dom/datachannelevent;1",
|
||||
Constructor(DOMString type, optional RTCDataChannelEventInit eventInitDict)]
|
||||
interface RTCDataChannelEvent : Event {
|
||||
readonly attribute RTCDataChannel? channel;
|
||||
};
|
@ -36,6 +36,17 @@ enum RTCIceConnectionState {
|
||||
"closed"
|
||||
};
|
||||
|
||||
dictionary RTCDataChannelInit {
|
||||
boolean outOfOrderAllowed;
|
||||
unsigned short maxRetransmitTime;
|
||||
unsigned short maxRetransmitNum;
|
||||
DOMString protocol;
|
||||
boolean preset;
|
||||
unsigned short stream;
|
||||
};
|
||||
|
||||
interface RTCDataChannel;
|
||||
|
||||
[Pref="media.peerconnection.enabled",
|
||||
JSImplementation="@mozilla.org/dom/peerconnection;1",
|
||||
Constructor (optional RTCConfiguration configuration,
|
||||
@ -54,8 +65,8 @@ interface mozRTCPeerConnection : EventTarget {
|
||||
void setRemoteDescription (mozRTCSessionDescription description,
|
||||
optional VoidFunction successCallback,
|
||||
optional RTCPeerConnectionErrorCallback failureCallback);
|
||||
readonly attribute mozRTCSessionDescription localDescription;
|
||||
readonly attribute mozRTCSessionDescription remoteDescription;
|
||||
readonly attribute mozRTCSessionDescription? localDescription;
|
||||
readonly attribute mozRTCSessionDescription? remoteDescription;
|
||||
readonly attribute RTCSignalingState signalingState;
|
||||
void updateIce (optional RTCConfiguration configuration,
|
||||
optional object? constraints);
|
||||
@ -80,7 +91,19 @@ interface mozRTCPeerConnection : EventTarget {
|
||||
|
||||
// Mozilla extensions.
|
||||
partial interface mozRTCPeerConnection {
|
||||
// Backwards-compatible attributes
|
||||
// Deprecated callbacks (use causes warning)
|
||||
attribute RTCPeerConnectionErrorCallback onicechange;
|
||||
attribute RTCPeerConnectionErrorCallback ongatheringchange;
|
||||
|
||||
// Deprecated attributes (use causes warning)
|
||||
readonly attribute object localStreams;
|
||||
readonly attribute object remoteStreams;
|
||||
readonly attribute DOMString readyState;
|
||||
|
||||
// Data channel.
|
||||
RTCDataChannel createDataChannel (DOMString label,
|
||||
optional RTCDataChannelInit dataChannelDict);
|
||||
attribute EventHandler ondatachannel;
|
||||
attribute EventHandler onconnection;
|
||||
attribute EventHandler onclosedconnection;
|
||||
};
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
dictionary RTCPeerConnectionIceEventInit : EventInit {
|
||||
mozRTCIceCandidate? candidate;
|
||||
mozRTCIceCandidate? candidate = null;
|
||||
};
|
||||
|
||||
[Pref="media.peerconnection.enabled",
|
||||
|
@ -194,6 +194,7 @@ webidl_files = \
|
||||
Rect.webidl \
|
||||
RGBColor.webidl \
|
||||
RTCConfiguration.webidl \
|
||||
RTCDataChannelEvent.webidl \
|
||||
RTCIceCandidate.webidl \
|
||||
RTCPeerConnection.webidl \
|
||||
RTCPeerConnectionIceEvent.webidl \
|
||||
|
Loading…
Reference in New Issue
Block a user