Bug 834270 - Fix PeerConnection error callbacks to return code/reason phrase r=ekr,jsmith

This commit is contained in:
Adam Roach [:abr] 2013-03-29 15:30:16 -05:00
parent 1308f76652
commit c739458274
9 changed files with 229 additions and 93 deletions

View File

@ -478,26 +478,16 @@ PeerConnection.prototype = {
this._onCreateAnswerFailure = onError;
if (!this.remoteDescription) {
this._observer.onCreateAnswerError(3); // PC_INVALID_REMOTE_SDP
/*
This needs to be matched to spec -- see bug 834270. The final
code will be of the form:
this._observer.onCreateAnswerError(ci.IPeerConnection.kInvalidState,
this._observer.onCreateAnswerError(Ci.IPeerConnection.kInvalidState,
"setRemoteDescription not called");
*/
return;
}
if (this.remoteDescription.type != "offer") {
this._observer.onCreateAnswerError(3); // PC_INVALID_REMOTE_SDP
/*
This needs to be matched to spec -- see bug 834270. The final
code will be of the form:
this._observer.onCreateAnswerError(ci.IPeerConnection.kInvalidState,
this._observer.onCreateAnswerError(Ci.IPeerConnection.kInvalidState,
"No outstanding offer");
*/
return;
}
@ -738,6 +728,39 @@ PeerConnectionObserver.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.IPeerConnectionObserver,
Ci.nsISupportsWeakReference]),
// These strings must match those defined in the WebRTC spec.
reasonName: [
"NO_ERROR", // Should never happen -- only used for testing
"INVALID_CONSTRAINTS_TYPE",
"INVALID_CANDIDATE_TYPE",
"INVALID_MEDIASTREAM_TRACK",
"INVALID_STATE",
"INVALID_SESSION_DESCRIPTION",
"INCOMPATIBLE_SESSION_DESCRIPTION",
"INCOMPATIBLE_CONSTRAINTS",
"INCOMPATIBLE_MEDIASTREAMTRACK",
"INTERNAL_ERROR"
],
callErrorCallback: function(callback, code, message) {
if (code > Ci.IPeerConnection.kMaxErrorType) {
code = Ci.IPeerConnection.kInternalError;
}
if (typeof message !== "string") {
message = this.reasonName[code];
}
if (callback) {
try {
callback.onCallback({
name: this.reasonName[code], message: message,
__exposedProps__: { name: "rw", message: "rw" }
});
} catch(e) {}
}
},
onCreateOfferSuccess: function(offer) {
if (this._dompc._onCreateOfferSuccess) {
try {
@ -750,12 +773,8 @@ PeerConnectionObserver.prototype = {
this._dompc._executeNext();
},
onCreateOfferError: function(code) {
if (this._dompc._onCreateOfferFailure) {
try {
this._dompc._onCreateOfferFailure.onCallback(code);
} catch(e) {}
}
onCreateOfferError: function(code, message) {
this.callErrorCallback (this._dompc._onCreateOfferFailure, code, message);
this._dompc._executeNext();
},
@ -771,68 +790,58 @@ PeerConnectionObserver.prototype = {
this._dompc._executeNext();
},
onCreateAnswerError: function(code) {
if (this._dompc._onCreateAnswerFailure) {
try {
this._dompc._onCreateAnswerFailure.onCallback(code);
} catch(e) {}
}
onCreateAnswerError: function(code, message) {
this.callErrorCallback (this._dompc._onCreateAnswerFailure, code, message);
this._dompc._executeNext();
},
onSetLocalDescriptionSuccess: function(code) {
onSetLocalDescriptionSuccess: function() {
this._dompc._localType = this._dompc._pendingType;
this._dompc._pendingType = null;
if (this._dompc._onSetLocalDescriptionSuccess) {
try {
this._dompc._onSetLocalDescriptionSuccess.onCallback(code);
this._dompc._onSetLocalDescriptionSuccess.onCallback();
} catch(e) {}
}
this._dompc._executeNext();
},
onSetRemoteDescriptionSuccess: function(code) {
onSetRemoteDescriptionSuccess: function() {
this._dompc._remoteType = this._dompc._pendingType;
this._dompc._pendingType = null;
if (this._dompc._onSetRemoteDescriptionSuccess) {
try {
this._dompc._onSetRemoteDescriptionSuccess.onCallback(code);
this._dompc._onSetRemoteDescriptionSuccess.onCallback();
} catch(e) {}
}
this._dompc._executeNext();
},
onSetLocalDescriptionError: function(code) {
onSetLocalDescriptionError: function(code, message) {
this._dompc._pendingType = null;
if (this._dompc._onSetLocalDescriptionFailure) {
try {
this._dompc._onSetLocalDescriptionFailure.onCallback(code);
} catch(e) {}
}
this.callErrorCallback (this._dompc._onSetLocalDescriptionFailure, code,
message);
this._dompc._executeNext();
},
onSetRemoteDescriptionError: function(code) {
onSetRemoteDescriptionError: function(code, message) {
this._dompc._pendingType = null;
if (this._dompc._onSetRemoteDescriptionFailure) {
this._dompc._onSetRemoteDescriptionFailure.onCallback(code);
}
this.callErrorCallback (this._dompc._onSetRemoteDescriptionFailure, code,
message);
this._dompc._executeNext();
},
onAddIceCandidateSuccess: function(code) {
onAddIceCandidateSuccess: function() {
this._dompc._pendingType = null;
if (this._dompc._onAddIceCandidateSuccess) {
this._dompc._onAddIceCandidateSuccess.onCallback(code);
this._dompc._onAddIceCandidateSuccess.onCallback();
}
this._dompc._executeNext();
},
onAddIceCandidateError: function(code) {
onAddIceCandidateError: function(code, message) {
this._dompc._pendingType = null;
if (this._dompc._onAddIceCandidateError) {
this._dompc._onAddIceCandidateError.onCallback(code);
}
this.callErrorCallback (this._dompc._onAddIceCandidateError, code, message);
this._dompc._executeNext();
},

View File

@ -24,7 +24,7 @@ interface IPeerConnectionManager : nsISupports
*
* See media/webrtc/signaling/include/PeerConnectionImpl.h
*/
[scriptable, uuid(e61821ba-7772-4973-b583-1715e4bbaeed)]
[scriptable, uuid(85ba28da-53d0-401d-afed-9cad69f727ff)]
interface IPeerConnectionObserver : nsISupports
{
/* Constants */
@ -35,15 +35,15 @@ interface IPeerConnectionObserver : nsISupports
/* JSEP callbacks */
void onCreateOfferSuccess(in string offer);
void onCreateOfferError(in unsigned long code);
void onCreateOfferError(in unsigned long name, in string message);
void onCreateAnswerSuccess(in string answer);
void onCreateAnswerError(in unsigned long code);
void onSetLocalDescriptionSuccess(in unsigned long code);
void onSetRemoteDescriptionSuccess(in unsigned long code);
void onSetLocalDescriptionError(in unsigned long code);
void onSetRemoteDescriptionError(in unsigned long code);
void onAddIceCandidateSuccess(in unsigned long code);
void onAddIceCandidateError(in unsigned long code);
void onCreateAnswerError(in unsigned long name, in string message);
void onSetLocalDescriptionSuccess();
void onSetRemoteDescriptionSuccess();
void onSetLocalDescriptionError(in unsigned long name, in string message);
void onSetRemoteDescriptionError(in unsigned long name, in string message);
void onAddIceCandidateSuccess();
void onAddIceCandidateError(in unsigned long name, in string message);
/* Data channel callbacks */
void notifyDataChannel(in nsIDOMDataChannel channel);
@ -67,7 +67,7 @@ interface IPeerConnectionObserver : nsISupports
void foundIceCandidate(in string candidate);
};
[scriptable, uuid(cc8327f5-66f4-42f4-820d-9a9db0474b6e)]
[scriptable, uuid(2bba7b2b-e152-4ae7-b7d4-f84e41a2211b)]
interface IPeerConnection : nsISupports
{
const unsigned long kHintAudio = 0x00000001;
@ -96,6 +96,19 @@ interface IPeerConnection : nsISupports
const unsigned short kDataChannelPartialReliableRexmit = 1;
const unsigned short kDataChannelPartialReliableTimed = 2;
/* Constants for 'name' in error callbacks */
const unsigned long kNoError = 0; // Test driver only
const unsigned long kInvalidConstraintsType = 1;
const unsigned long kInvalidCandidateType = 2;
const unsigned long kInvalidMediastreamTrack = 3;
const unsigned long kInvalidState = 4;
const unsigned long kInvalidSessionDescription = 5;
const unsigned long kIncompatibleSessionDescription = 6;
const unsigned long kIncompatibleConstraints = 7;
const unsigned long kIncompatibleMediaStreamTrack = 8;
const unsigned long kInternalError = 9;
const unsigned long kMaxErrorType = 9; // Same as final error
/* Must be called first. Observer events will be dispatched on the thread provided */
[implicit_jscontext] void initialize(in IPeerConnectionObserver observer, in nsIDOMWindow window,
[optional] in jsval iceServers,

View File

@ -35,7 +35,7 @@ interface nsIDOMRTCIceCandidate : nsISupports
};
/* See http://dev.w3.org/2011/webrtc/editor/webrtc.html */
[scriptable, uuid(f888648c-5e6b-4af9-91ad-a911e53d7a39)]
[scriptable, uuid(474074ab-11f9-4933-a200-8ea1a5f84e4c)]
interface nsIDOMRTCPeerConnection : nsISupports
{
void createOffer(in RTCPeerConnectionCallback successCallback,
@ -48,11 +48,11 @@ interface nsIDOMRTCPeerConnection : nsISupports
[optional] in bool createProvisionalAnswer);
void setLocalDescription(in nsIDOMRTCSessionDescription desc,
[optional] in RTCPeerConnectionCallback successCallback,
[optional] in RTCPeerConnectionCallbackVoid successCallback,
[optional] in RTCPeerConnectionCallback failureCallback);
void setRemoteDescription(in nsIDOMRTCSessionDescription desc,
[optional] in RTCPeerConnectionCallback successCallback,
[optional] in RTCPeerConnectionCallbackVoid successCallback,
[optional] in RTCPeerConnectionCallback failureCallback);
void updateIce([optional] in jsval configuration,
@ -60,7 +60,7 @@ interface nsIDOMRTCPeerConnection : nsISupports
[optional] in bool restart);
void addIceCandidate(in nsIDOMRTCIceCandidate candidate,
[optional] in RTCPeerConnectionCallback successCallback,
[optional] in RTCPeerConnectionCallbackVoid successCallback,
[optional] in RTCPeerConnectionCallback failureCallback);
void addStream(in nsIDOMMediaStream stream,

View File

@ -29,9 +29,10 @@ MOCHITEST_FILES = \
test_peerConnection_basicAudioVideo.html \
test_peerConnection_basicAudioVideoCombined.html \
test_peerConnection_basicVideo.html \
test_peerConnection_errorCallbacks.html \
test_peerConnection_bug822674.html \
test_peerConnection_bug827843.html \
test_peerConnection_bug825703.html \
test_peerConnection_bug827843.html \
test_peerConnection_bug834153.html \
test_peerConnection_bug835370.html \
test_peerConnection_bug840344.html \

View File

@ -147,6 +147,11 @@ function runTest(aCallback, desktopSupportedOnly) {
* The object fired back from the callback
*/
function unexpectedCallbackAndFinish(aObj) {
ok(false, "Unexpected error callback with " + aObj);
if (aObj && aObj.name && aObj.message) {
ok(false, "Unexpected error callback with name = '" + aObj.name +
"', message = '" + aObj.message + "'");
} else {
ok(false, "Unexpected error callback with " + aObj);
}
SimpleTest.finish();
}

View File

@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="head.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "834270",
title: "Align PeerConnection error handling with WebRTC specification"
});
function errorCallback(nextStep) {
return function (err) {
ok(err, "Error is set");
ok(err.name && err.name.length, "Error name = " + err.name);
ok(err.message && err.message.length, "Error message = " + err.message);
nextStep();
}
};
function successCallback(message) {
return function () {
unexpectedCallbackAndFinish(message);
}
};
function testCreateAnswerError() {
var pc = new mozRTCPeerConnection();
info ("Testing createAnswer error callback");
pc.createAnswer(successCallback("createAnswer before offer should fail"),
errorCallback(testSetLocalDescriptionError));
};
function testSetLocalDescriptionError() {
var pc = new mozRTCPeerConnection();
info ("Testing setLocalDescription error callback");
pc.setLocalDescription(
{sdp: "Ralph Waldo Picklechips!", type: "offer"},
successCallback("setLocalDescription with nonsense SDP should fail"),
errorCallback(testSetRemoteDescriptionError));
};
function testSetRemoteDescriptionError() {
var pc = new mozRTCPeerConnection();
info ("Testing setRemoteDescription error callback");
pc.setRemoteDescription(
{sdp: "I don't know him.", type: "offer"},
successCallback("setRemoteDescription with nonsense SDP should fail"),
errorCallback(testAddIceCandidateError));
};
function testAddIceCandidateError() {
var pc = new mozRTCPeerConnection();
info ("Testing addIceCandidate error callback");
pc.addIceCandidate(
{candidate: "Pony Lords, jump for your lives!",
sdpMid: "whee", sdpMLineIndex: 1},
successCallback("addIceCandidate with nonsense candidate should fail"),
errorCallback(SimpleTest.finish));
};
// No test for createOffer errors -- there's nothing we can do at this
// level to evoke an error in createOffer.
runTest(function () {
testCreateAnswerError();
}, true);
</script>
</pre>
</body>
</html>

View File

@ -142,6 +142,10 @@ public:
~PeerConnectionObserverDispatch(){}
NS_IMETHOD Run() {
CSFLogInfo(logTag, "PeerConnectionObserverDispatch processing "
"mCallState = %d (%s)", mCallState, mStateStr.c_str());
switch (mCallState) {
case CREATEOFFER:
mObserver->OnCreateOfferSuccess(mSdpStr.c_str());
@ -152,47 +156,57 @@ public:
break;
case CREATEOFFERERROR:
mObserver->OnCreateOfferError(mCode);
mObserver->OnCreateOfferError(
PeerConnectionImpl::kInternalError,
"Unspecified Error processing createOffer");
break;
case CREATEANSWERERROR:
mObserver->OnCreateAnswerError(mCode);
mObserver->OnCreateAnswerError(
PeerConnectionImpl::kInternalError,
"Unspecified Error processing createAnswer");
break;
case SETLOCALDESC:
// TODO: The SDP Parse error list should be copied out and sent up
// to the Javascript layer before being cleared here.
mPC->ClearSdpParseErrorMessages();
mObserver->OnSetLocalDescriptionSuccess(mCode);
mObserver->OnSetLocalDescriptionSuccess();
break;
case SETREMOTEDESC:
// TODO: The SDP Parse error list should be copied out and sent up
// to the Javascript layer before being cleared here.
mPC->ClearSdpParseErrorMessages();
mObserver->OnSetRemoteDescriptionSuccess(mCode);
mObserver->OnSetRemoteDescriptionSuccess();
break;
case SETLOCALDESCERROR:
// TODO: The SDP Parse error list should be copied out and sent up
// to the Javascript layer before being cleared here.
mPC->ClearSdpParseErrorMessages();
mObserver->OnSetLocalDescriptionError(mCode);
mObserver->OnSetLocalDescriptionError(
PeerConnectionImpl::kInternalError,
"Unspecified Error processing setLocalDescription");
break;
case SETREMOTEDESCERROR:
// TODO: The SDP Parse error list should be copied out and sent up
// to the Javascript layer before being cleared here.
mPC->ClearSdpParseErrorMessages();
mObserver->OnSetRemoteDescriptionError(mCode);
mObserver->OnSetRemoteDescriptionError(
PeerConnectionImpl::kInternalError,
"Unspecified Error processing setRemoteDescription");
break;
case ADDICECANDIDATE:
mObserver->OnAddIceCandidateSuccess(mCode);
mObserver->OnAddIceCandidateSuccess();
break;
case ADDICECANDIDATEERROR:
mObserver->OnAddIceCandidateError(mCode);
mObserver->OnAddIceCandidateError(
PeerConnectionImpl::kInternalError,
"Unspecified Error processing addIceCandidate");
break;
case REMOTESTREAMADD:
@ -225,7 +239,8 @@ public:
break;
default:
CSFLogDebug(logTag, ": **** UNHANDLED CALL STATE : %s", mStateStr.c_str());
CSFLogError(logTag, ": **** UNHANDLED CALL STATE : %d (%s)",
mCallState, mStateStr.c_str());
break;
}

View File

@ -136,6 +136,19 @@ public:
kRoleAnswerer
};
enum Error {
kNoError = 0,
kInvalidConstraintsType = 1,
kInvalidCandidateType = 2,
kInvalidMediastreamTrack = 3,
kInvalidState = 4,
kInvalidSessionDescription = 5,
kIncompatibleSessionDescription = 6,
kIncompatibleConstraints = 7,
kIncompatibleMediaStreamTrack = 8,
kInternalError = 9
};
NS_DECL_ISUPPORTS
NS_DECL_IPEERCONNECTION

View File

@ -175,7 +175,7 @@ public:
ResponseState state;
char *lastString;
uint32_t lastStatusCode;
sipcc::PeerConnectionImpl::Error lastStatusCode;
uint32_t lastStateType;
int addIceSuccessCount;
bool onAddStreamCalled;
@ -199,11 +199,12 @@ TestObserver::OnCreateOfferSuccess(const char* offer)
}
NS_IMETHODIMP
TestObserver::OnCreateOfferError(uint32_t code)
TestObserver::OnCreateOfferError(uint32_t code, const char *message)
{
lastStatusCode = code;
lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
state = stateError;
cout << "onCreateOfferError" << endl;
cout << "onCreateOfferError = " << code
<< " (" << message << ")" << endl;
return NS_OK;
}
@ -217,47 +218,50 @@ TestObserver::OnCreateAnswerSuccess(const char* answer)
}
NS_IMETHODIMP
TestObserver::OnCreateAnswerError(uint32_t code)
TestObserver::OnCreateAnswerError(uint32_t code, const char *message)
{
lastStatusCode = code;
cout << "onCreateAnswerError = " << code << endl;
lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
cout << "onCreateAnswerError = " << code
<< " (" << message << ")" << endl;
state = stateError;
return NS_OK;
}
NS_IMETHODIMP
TestObserver::OnSetLocalDescriptionSuccess(uint32_t code)
TestObserver::OnSetLocalDescriptionSuccess()
{
lastStatusCode = code;
lastStatusCode = sipcc::PeerConnectionImpl::kNoError;
state = stateSuccess;
cout << "onSetLocalDescriptionSuccess = " << code << endl;
cout << "onSetLocalDescriptionSuccess" << endl;
return NS_OK;
}
NS_IMETHODIMP
TestObserver::OnSetRemoteDescriptionSuccess(uint32_t code)
TestObserver::OnSetRemoteDescriptionSuccess()
{
lastStatusCode = code;
lastStatusCode = sipcc::PeerConnectionImpl::kNoError;
state = stateSuccess;
cout << "onSetRemoteDescriptionSuccess = " << code << endl;
cout << "onSetRemoteDescriptionSuccess = " << endl;
return NS_OK;
}
NS_IMETHODIMP
TestObserver::OnSetLocalDescriptionError(uint32_t code)
TestObserver::OnSetLocalDescriptionError(uint32_t code, const char *message)
{
lastStatusCode = code;
lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
state = stateError;
cout << "onSetLocalDescriptionError = " << code << endl;
cout << "onSetLocalDescriptionError = " << code
<< " (" << message << ")" << endl;
return NS_OK;
}
NS_IMETHODIMP
TestObserver::OnSetRemoteDescriptionError(uint32_t code)
TestObserver::OnSetRemoteDescriptionError(uint32_t code, const char *message)
{
lastStatusCode = code;
lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
state = stateError;
cout << "onSetRemoteDescriptionError = " << code << endl;
cout << "onSetRemoteDescriptionError = " << code
<< " (" << message << ")" << endl;
return NS_OK;
}
@ -373,20 +377,21 @@ TestObserver::FoundIceCandidate(const char* strCandidate)
}
NS_IMETHODIMP
TestObserver::OnAddIceCandidateSuccess(uint32_t code)
TestObserver::OnAddIceCandidateSuccess()
{
lastStatusCode = code;
lastStatusCode = sipcc::PeerConnectionImpl::kNoError;
state = stateSuccess;
addIceSuccessCount++;
return NS_OK;
}
NS_IMETHODIMP
TestObserver::OnAddIceCandidateError(uint32_t code)
TestObserver::OnAddIceCandidateError(uint32_t code, const char *message)
{
lastStatusCode = code;
lastStatusCode = static_cast<sipcc::PeerConnectionImpl::Error>(code);
state = stateError;
cout << "onAddIceCandidateError = " << code << endl;
cout << "onAddIceCandidateError = " << code
<< " (" << message << ")" << endl;
return NS_OK;
}