Bug 823512: Part 2: Update PeerConnection to spec. states + DataChannel. r=bz,rjesup,ekr

This commit is contained in:
Jan-Ivar Bruaroey 2013-05-16 19:40:23 -04:00
parent 7921c9c1e4
commit 9386baa685
9 changed files with 181 additions and 82 deletions

View File

@ -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')

View File

@ -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]
);

View File

@ -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}

View File

@ -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>

View File

@ -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

View 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;
};

View File

@ -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;
};

View File

@ -8,7 +8,7 @@
*/
dictionary RTCPeerConnectionIceEventInit : EventInit {
mozRTCIceCandidate? candidate;
mozRTCIceCandidate? candidate = null;
};
[Pref="media.peerconnection.enabled",

View File

@ -194,6 +194,7 @@ webidl_files = \
Rect.webidl \
RGBColor.webidl \
RTCConfiguration.webidl \
RTCDataChannelEvent.webidl \
RTCIceCandidate.webidl \
RTCPeerConnection.webidl \
RTCPeerConnectionIceEvent.webidl \