| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>RTCPeerConnection-ontrack</title> |
| <script src="../../resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| </head> |
| <body> |
| <script> |
| |
| // TODO(hbos): Consider removing this file, it duplicates wpt tests. |
| |
| promise_test(function() { |
| let pc = new RTCPeerConnection(); |
| let pc2 = new RTCPeerConnection(); |
| let eventSequence = []; |
| return createStreams({audio:true, video:false}, 1) |
| .then(function(streams) { |
| pc.addStream(streams[0]); |
| let resolvers = Resolver.createResolvers(2); |
| pc2.ontrack = function() { |
| eventSequence.push('ontrack'); |
| resolvers.shift().resolve(); |
| } |
| createAndSetRemoteDescription(pc, pc2).then(function() { |
| eventSequence.push('setRemoteDescription'); |
| resolvers.shift().resolve(); |
| }); |
| return Promise.all(Resolver.promises(resolvers)); |
| }).then(function() { |
| let expectedEventSequence = [ 'ontrack', 'setRemoteDescription' ]; |
| assert_array_equals(expectedEventSequence, eventSequence); |
| }); |
| }, 'ontrack fires before negotiation done.'); |
| |
| promise_test(function() { |
| let pc = new RTCPeerConnection(); |
| let pc2 = new RTCPeerConnection(); |
| let eventSequence = []; |
| return createStreams({audio:true, video:false}, 1) |
| .then(function(streams) { |
| pc.addStream(streams[0]); |
| let resolvers = Resolver.createResolvers(2); |
| pc2.onaddstream = function() { |
| eventSequence.push('onaddstream'); |
| resolvers.shift().resolve(); |
| } |
| createAndSetRemoteDescription(pc, pc2).then(function() { |
| eventSequence.push('setRemoteDescription'); |
| resolvers.shift().resolve(); |
| }); |
| return Promise.all(Resolver.promises(resolvers)); |
| }).then(function() { |
| let expectedEventSequence = [ 'onaddstream', 'setRemoteDescription' ]; |
| assert_array_equals(eventSequence, expectedEventSequence); |
| }); |
| }, 'onaddstream fires before negotation done.'); |
| |
| promise_test(function() { |
| let pc = new RTCPeerConnection(); |
| let pc2 = new RTCPeerConnection(); |
| let eventSequence = []; |
| return createStreams({audio:true, video:false}, 2) |
| .then(function(streams) { |
| pc.addStream(streams[0]); |
| pc.addStream(streams[1]); |
| let resolvers = Resolver.createResolvers(4); |
| pc2.onaddstream = function(event) { |
| eventSequence.push('stream:' + event.stream.id); |
| resolvers.shift().resolve(); |
| }; |
| pc2.ontrack = function(event) { |
| eventSequence.push('track:' + event.track.id); |
| resolvers.shift().resolve(); |
| }; |
| return Promise.all( |
| Resolver.promises(resolvers).concat( |
| createAndSetRemoteDescription(pc, pc2))); |
| }).then(function() { |
| let expectedEventSequence = |
| [ 'stream:' + pc2.getRemoteStreams()[0].id, |
| 'track:' + pc2.getRemoteStreams()[0].getAudioTracks()[0].id, |
| 'stream:' + pc2.getRemoteStreams()[1].id, |
| 'track:' + pc2.getRemoteStreams()[1].getAudioTracks()[0].id ]; |
| assert_array_equals(eventSequence, expectedEventSequence); |
| }); |
| }, 'ontrack and onaddstream fires in the expected relative order.'); |
| |
| promise_test(function() { |
| let pc = new RTCPeerConnection(); |
| let pc2 = new RTCPeerConnection(); |
| let eventSequence = []; |
| return createStreams({audio:true, video:false}, 1) |
| .then(function(streams) { |
| pc.addStream(streams[0]); |
| let resolvers = Resolver.createResolvers(3); |
| let callback = function() { |
| if (eventSequence.length == 0) { |
| setTimeout(function() { |
| eventSequence.push('new task'); |
| resolvers.shift().resolve(); |
| }, 0); |
| } |
| eventSequence.push('track or stream fired'); |
| resolvers.shift().resolve(); |
| } |
| pc2.onaddstream = callback; |
| pc2.ontrack = callback; |
| return Promise.all( |
| Resolver.promises(resolvers).concat( |
| createAndSetRemoteDescription(pc, pc2))); |
| }).then(function() { |
| assert_array_equals( |
| eventSequence, |
| [ 'track or stream fired', 'track or stream fired', 'new task' ]); |
| }); |
| }, 'ontrack and onaddstream fires in the same task.'); |
| |
| promise_test(function() { |
| let pc = new RTCPeerConnection(); |
| let pc2 = new RTCPeerConnection(); |
| return createStreams({audio:true, video:false}, 1) |
| .then(function(streams) { |
| pc.addStream(streams[0]); |
| let resolver = new Resolver(); |
| pc2.ontrack = function(event) { |
| let remoteStream = pc2.getRemoteStreams()[0]; |
| let remoteAudioTrack = remoteStream.getAudioTracks()[0]; |
| assert_equals(event.track, remoteAudioTrack); |
| resolver.resolve(); |
| }; |
| return Promise.all([ resolver.promise, |
| createAndSetRemoteDescription(pc, pc2) ]); |
| }); |
| }, 'ontrack event\'s track matches track in getRemoteStreams().'); |
| |
| promise_test(function() { |
| let pc = new RTCPeerConnection(); |
| let pc2 = new RTCPeerConnection(); |
| return createStreams({audio:true, video:false}, 1) |
| .then(function(streams) { |
| pc.addStream(streams[0]); |
| let resolver = new Resolver(); |
| pc2.ontrack = function(event) { |
| let receiver = pc2.getReceivers()[0]; |
| assert_equals(event.receiver, receiver); |
| resolver.resolve(); |
| }; |
| return Promise.all([ resolver.promise, |
| createAndSetRemoteDescription(pc, pc2) ]); |
| }); |
| }, 'ontrack event\'s receiver matches getReceivers().'); |
| |
| promise_test(function() { |
| let pc = new RTCPeerConnection(); |
| let pc2 = new RTCPeerConnection(); |
| return createStreams({audio:true, video:false}, 1) |
| .then(function(streams) { |
| pc.addStream(streams[0]); |
| let resolver = new Resolver(); |
| pc2.ontrack = function(event) { |
| assert_array_equals(event.streams, pc2.getRemoteStreams()) |
| resolver.resolve(); |
| }; |
| return Promise.all([ resolver.promise, |
| createAndSetRemoteDescription(pc, pc2) ]); |
| }); |
| }, 'ontrack event\'s streams match getRemoteStreams().'); |
| |
| promise_test(function() { |
| let pc = new RTCPeerConnection(); |
| let pc2 = new RTCPeerConnection(); |
| let firedForAudioTrack = false; |
| let firedForVideoTrack = false; |
| return createStreams({audio:true, video:true}, 1) |
| .then(function(streams) { |
| pc.addStream(streams[0]); |
| let resolvers = Resolver.createResolvers(2); |
| pc2.ontrack = function(event) { |
| let remoteStream = pc2.getRemoteStreams()[0]; |
| if (event.track == remoteStream.getAudioTracks()[0]) |
| firedForAudioTrack = true; |
| else if (event.track == remoteStream.getVideoTracks()[0]) |
| firedForVideoTrack = true; |
| resolvers.shift().resolve(); |
| }; |
| return Promise.all( |
| Resolver.promises(resolvers).concat( |
| createAndSetRemoteDescription(pc, pc2))); |
| }).then(function() { |
| assert_true(firedForAudioTrack && firedForVideoTrack); |
| }); |
| }, 'ontrack event fires twice for a stream containing two tracks.'); |
| |
| /** |
| * Helper functions. |
| */ |
| |
| function createStreams(constraints, numStreams, streamsSoFar = []) { |
| if (numStreams == 0) { |
| return Promise.resolve(streamsSoFar); |
| } |
| return navigator.mediaDevices.getUserMedia(constraints) |
| .then(function(stream) { |
| return createStreams(constraints, |
| numStreams - 1, |
| streamsSoFar.concat([stream])); |
| }); |
| } |
| |
| /** |
| * Makes the setup step necessary to cause pc_b to emit events. |
| * Note: This does not set up a connection. |
| * Returns the promise resulting from pc_b.setRemoteDescription. |
| */ |
| function createAndSetRemoteDescription(pc_a, pc_b) { |
| return pc_a.createOffer() |
| .then(function(offer) { |
| return pc_b.setRemoteDescription(offer); |
| }) |
| } |
| |
| /** |
| * The resolver has a |promise| that can be resolved or rejected using |resolve| |
| * or |reject|. |
| */ |
| class Resolver { |
| constructor() { |
| let promiseResolve; |
| let promiseReject; |
| this.promise = new Promise(function(resolve, reject) { |
| promiseResolve = resolve; |
| promiseReject = reject; |
| }); |
| this.resolve = promiseResolve; |
| this.reject = promiseReject; |
| } |
| |
| static createResolvers(count) { |
| let result = []; |
| for (let i = 0; i < count; ++i) |
| result.push(new Resolver()); |
| return result; |
| } |
| |
| static promises(resolvers) { |
| let promises = []; |
| for (let i = 0; i < resolvers.length; ++i) { |
| promises.push(resolvers[i].promise); |
| } |
| return promises; |
| } |
| } |
| </script> |
| </body> |
| </html> |