Commit fa714c67 authored by Henrik Boström's avatar Henrik Boström Committed by Commit Bot

Fix crash: add/remove track on an addStream()-stream after pc.close().

MediaStreams added to an RTCPeerConnection using the legacy addStream()
API is wired up such that the RTCPeerConnection is informed when tracks
are added or removed from the MediaStream so that the corresponding
sender can be added/removed from the PC.

OnStreamAddTrack/OnStreamRemoveTrack was wired up to call addTrack() and
removeTrack(), the crash occurred if these operations were to throw an
exception even though we just want to suppress any exceptions thrown.
The ExceptionState is updated to allow an exception to be thrown before
being cleared. This fixes the referenced bug.

Bug: 814139
Change-Id: I7798d7cf43bb71d42b7b8108f40ffba36dc95946
Reviewed-on: https://chromium-review.googlesource.com/992321Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Commit-Queue: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547754}
parent 3400947e
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
// This is not an external/wpt/webrtc/ test because it tests APIs and behaviors // This is not an external/wpt/webrtc/ test because it tests APIs and behaviors
// that are not in the spec. // that are not in the spec.
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
pc.addStream(stream); pc.addStream(stream);
...@@ -18,7 +18,7 @@ promise_test(async function() { ...@@ -18,7 +18,7 @@ promise_test(async function() {
assert_equals(pc.getSenders()[0].track, stream.getTracks()[0]); assert_equals(pc.getSenders()[0].track, stream.getTracks()[0]);
}, 'addStream() adds to local streams and senders.'); }, 'addStream() adds to local streams and senders.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
let sender = pc.addTrack(stream.getTracks()[0], stream); let sender = pc.addTrack(stream.getTracks()[0], stream);
...@@ -26,7 +26,7 @@ promise_test(async function() { ...@@ -26,7 +26,7 @@ promise_test(async function() {
assert_array_equals(pc.getSenders(), [ sender ]); assert_array_equals(pc.getSenders(), [ sender ]);
}, 'addTrack() adds to local streams and senders.'); }, 'addTrack() adds to local streams and senders.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
pc.addStream(stream); pc.addStream(stream);
...@@ -39,7 +39,7 @@ promise_test(async function() { ...@@ -39,7 +39,7 @@ promise_test(async function() {
}; };
}, 'addTrack() fails after addStream().'); }, 'addTrack() fails after addStream().');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true, let stream = await navigator.mediaDevices.getUserMedia({audio:true,
video:true}); video:true});
...@@ -55,7 +55,7 @@ promise_test(async function() { ...@@ -55,7 +55,7 @@ promise_test(async function() {
assert_equals(pc.getSenders().length, 2); assert_equals(pc.getSenders().length, 2);
}, 'addStream() after addTrack() adds the remaining track.'); }, 'addStream() after addTrack() adds the remaining track.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true, let stream = await navigator.mediaDevices.getUserMedia({audio:true,
video:true}); video:true});
...@@ -72,7 +72,7 @@ promise_test(async function() { ...@@ -72,7 +72,7 @@ promise_test(async function() {
'PC knows about the videoTrack after stream.addTrack()'); 'PC knows about the videoTrack after stream.addTrack()');
}, 'Adding a track to an addStream()-stream adds it to the PC.'); }, 'Adding a track to an addStream()-stream adds it to the PC.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true, let stream = await navigator.mediaDevices.getUserMedia({audio:true,
video:true}); video:true});
...@@ -87,7 +87,30 @@ promise_test(async function() { ...@@ -87,7 +87,30 @@ promise_test(async function() {
'PC does not know about the track after stream.removeTrack()'); 'PC does not know about the track after stream.removeTrack()');
}, 'Removing a track from an addStream()-stream removes it from the PC.'); }, 'Removing a track from an addStream()-stream removes it from the PC.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true,
video:true});
let videoTrack = stream.getVideoTracks()[0];
stream.removeTrack(videoTrack);
pc.addStream(stream);
pc.close();
stream.addTrack(videoTrack);
}, 'Adding a track to an addStream()-stream after the PC closed is safe.');
promise_test(async t => {
let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true,
video:true});
let videoTrack = stream.getVideoTracks()[0];
pc.addStream(stream);
pc.close();
stream.removeTrack(videoTrack);
}, 'Removing a track from an addStream()-stream after the PC closed is safe.');
promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true, let stream = await navigator.mediaDevices.getUserMedia({audio:true,
video:true}); video:true});
...@@ -105,7 +128,7 @@ promise_test(async function() { ...@@ -105,7 +128,7 @@ promise_test(async function() {
'PC does not know about the videoTrack after stream.addTrack()'); 'PC does not know about the videoTrack after stream.addTrack()');
}, 'The PC stops observing the stream after removeStream().'); }, 'The PC stops observing the stream after removeStream().');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
pc.addStream(stream); pc.addStream(stream);
...@@ -116,7 +139,7 @@ promise_test(async function() { ...@@ -116,7 +139,7 @@ promise_test(async function() {
assert_array_equals(pc.getSenders(), []); assert_array_equals(pc.getSenders(), []);
}, 'removeStream() after addStream() removes from local streams and senders.'); }, 'removeStream() after addStream() removes from local streams and senders.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
pc.addTrack(stream.getTracks()[0], stream); pc.addTrack(stream.getTracks()[0], stream);
...@@ -127,7 +150,7 @@ promise_test(async function() { ...@@ -127,7 +150,7 @@ promise_test(async function() {
assert_array_equals(pc.getSenders(), []); assert_array_equals(pc.getSenders(), []);
}, 'removeStream() after addTrack() removes from local streams and senders.'); }, 'removeStream() after addTrack() removes from local streams and senders.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true, let stream = await navigator.mediaDevices.getUserMedia({audio:true,
video:true}); video:true});
...@@ -143,7 +166,7 @@ promise_test(async function() { ...@@ -143,7 +166,7 @@ promise_test(async function() {
assert_array_equals(pc.getSenders(), []); assert_array_equals(pc.getSenders(), []);
}, 'removeStream() after removeTrack() removes remaining tracks.'); }, 'removeStream() after removeTrack() removes remaining tracks.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
pc.addStream(stream); pc.addStream(stream);
...@@ -154,7 +177,7 @@ promise_test(async function() { ...@@ -154,7 +177,7 @@ promise_test(async function() {
assert_array_equals(pc.getSenders(), []); assert_array_equals(pc.getSenders(), []);
}, 'removeTrack() after addStream() removes from local streams and senders.'); }, 'removeTrack() after addStream() removes from local streams and senders.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
let sender = pc.addTrack(stream.getTracks()[0], stream); let sender = pc.addTrack(stream.getTracks()[0], stream);
...@@ -165,14 +188,14 @@ promise_test(async function() { ...@@ -165,14 +188,14 @@ promise_test(async function() {
assert_array_equals(pc.getSenders(), []); assert_array_equals(pc.getSenders(), []);
}, 'removeTrack() after addTrack() removes from local streams and senders.'); }, 'removeTrack() after addTrack() removes from local streams and senders.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
pc.addStream(stream); pc.addStream(stream);
pc.createDTMFSender(stream.getTracks()[0]); pc.createDTMFSender(stream.getTracks()[0]);
}, 'createDTMFSender() with addStream()-track.'); }, 'createDTMFSender() with addStream()-track.');
promise_test(async function() { promise_test(async t => {
let pc = new RTCPeerConnection(); let pc = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({audio:true}); let stream = await navigator.mediaDevices.getUserMedia({audio:true});
let track = stream.getTracks()[0]; let track = stream.getTracks()[0];
......
...@@ -1515,8 +1515,9 @@ void RTCPeerConnection::NoteSdpCreated(const RTCSessionDescription& desc) { ...@@ -1515,8 +1515,9 @@ void RTCPeerConnection::NoteSdpCreated(const RTCSessionDescription& desc) {
void RTCPeerConnection::OnStreamAddTrack(MediaStream* stream, void RTCPeerConnection::OnStreamAddTrack(MediaStream* stream,
MediaStreamTrack* track) { MediaStreamTrack* track) {
ExceptionState exception_state(nullptr, ExceptionState::kUnknownContext, ExceptionState exception_state(v8::Isolate::GetCurrent(),
nullptr, nullptr); ExceptionState::kExecutionContext, nullptr,
nullptr);
MediaStreamVector streams; MediaStreamVector streams;
streams.push_back(stream); streams.push_back(stream);
addTrack(track, streams, exception_state); addTrack(track, streams, exception_state);
...@@ -1530,8 +1531,9 @@ void RTCPeerConnection::OnStreamRemoveTrack(MediaStream* stream, ...@@ -1530,8 +1531,9 @@ void RTCPeerConnection::OnStreamRemoveTrack(MediaStream* stream,
MediaStreamTrack* track) { MediaStreamTrack* track) {
auto sender = FindSenderForTrackAndStream(track, stream); auto sender = FindSenderForTrackAndStream(track, stream);
if (sender) { if (sender) {
ExceptionState exception_state(nullptr, ExceptionState::kUnknownContext, ExceptionState exception_state(v8::Isolate::GetCurrent(),
nullptr, nullptr); ExceptionState::kExecutionContext, nullptr,
nullptr);
removeTrack(sender, exception_state); removeTrack(sender, exception_state);
// If removeTracl() failed most likely the connection is closed. The // If removeTracl() failed most likely the connection is closed. The
// exception can be suppressed, there is nothing to do. // exception can be suppressed, there is nothing to do.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment