RTCPeerConnection-setLocalDescription.html (5583B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>RTCPeerConnection.prototype.setLocalDescription</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="RTCPeerConnection-helper.js"></script> 7 <script> 8 'use strict'; 9 10 // Test is based on the following editor draft: 11 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html 12 13 // The following helper functions are called from RTCPeerConnection-helper.js: 14 // generateDataChannelOffer 15 // assert_session_desc_not_similar 16 // assert_session_desc_similar 17 18 /* 19 4.3.2. Interface Definition 20 [Constructor(optional RTCConfiguration configuration)] 21 interface RTCPeerConnection : EventTarget { 22 Promise<void> setRemoteDescription( 23 RTCSessionDescriptionInit description); 24 25 readonly attribute RTCSessionDescription? remoteDescription; 26 readonly attribute RTCSessionDescription? currentRemoteDescription; 27 readonly attribute RTCSessionDescription? pendingRemoteDescription; 28 ... 29 }; 30 31 4.6.2. RTCSessionDescription Class 32 dictionary RTCSessionDescriptionInit { 33 required RTCSdpType type; 34 DOMString sdp = ""; 35 }; 36 37 4.6.1. RTCSdpType 38 enum RTCSdpType { 39 "offer", 40 "pranswer", 41 "answer", 42 "rollback" 43 }; 44 */ 45 46 promise_test(t => { 47 const pc = new RTCPeerConnection(); 48 t.add_cleanup(() => pc.close()); 49 50 const states = []; 51 pc.addEventListener('signalingstatechange', () => states.push(pc.signalingState)); 52 53 return generateAudioReceiveOnlyOffer(pc) 54 .then(offer1 => 55 pc.setLocalDescription(offer1) 56 .then(() => generateAnswer(offer1)) 57 .then(answer => pc.setRemoteDescription(answer)) 58 .then(() => { 59 pc.createDataChannel('test'); 60 return generateVideoReceiveOnlyOffer(pc); 61 }) 62 .then(offer2 => 63 pc.setLocalDescription(offer2) 64 .then(() => { 65 assert_equals(pc.signalingState, 'have-local-offer'); 66 assert_session_desc_not_similar(offer1, offer2); 67 assert_session_desc_similar(pc.localDescription, offer2); 68 assert_session_desc_similar(pc.currentLocalDescription, offer1); 69 assert_session_desc_similar(pc.pendingLocalDescription, offer2); 70 71 assert_array_equals(states, ['have-local-offer', 'stable', 'have-local-offer']); 72 }))); 73 }, 'Calling createOffer() and setLocalDescription() again after one round of local-offer/remote-answer should succeed'); 74 75 promise_test(async t => { 76 const pc1 = new RTCPeerConnection(); 77 t.add_cleanup(() => pc1.close()); 78 79 const pc2 = new RTCPeerConnection(); 80 t.add_cleanup(() => pc2.close()); 81 82 const states = []; 83 pc1.addEventListener('signalingstatechange', () => states.push(pc1.signalingState)); 84 85 assert_equals(pc1.localDescription, null); 86 assert_equals(pc1.currentLocalDescription, null); 87 assert_equals(pc1.pendingLocalDescription, null); 88 89 pc1.createDataChannel('test'); 90 const offer = await pc1.createOffer(); 91 92 assert_equals(pc1.localDescription, null); 93 assert_equals(pc1.currentLocalDescription, null); 94 assert_equals(pc1.pendingLocalDescription, null); 95 96 await pc1.setLocalDescription(offer); 97 98 assert_session_desc_similar(pc1.localDescription, offer); 99 assert_equals(pc1.currentLocalDescription, null); 100 assert_session_desc_similar(pc1.pendingLocalDescription, offer); 101 102 await pc2.setRemoteDescription(offer); 103 const answer = await pc2.createAnswer(); 104 await pc2.setLocalDescription(answer); 105 await pc1.setRemoteDescription(answer); 106 107 assert_equals(pc1.signalingState, 'stable'); 108 assert_session_desc_similar(pc1.localDescription, offer); 109 assert_session_desc_similar(pc1.currentLocalDescription, offer); 110 assert_equals(pc1.pendingLocalDescription, null); 111 112 const stream = await getNoiseStream({audio:true}); 113 pc2.addTrack(stream.getTracks()[0], stream); 114 115 const reoffer = await pc2.createOffer(); 116 await pc2.setLocalDescription(reoffer); 117 await pc1.setRemoteDescription(reoffer); 118 const reanswer = await pc1.createAnswer(); 119 await pc1.setLocalDescription(reanswer); 120 121 assert_session_desc_similar(pc1.localDescription, reanswer); 122 assert_session_desc_similar(pc1.currentLocalDescription, reanswer); 123 assert_equals(pc1.pendingLocalDescription, null); 124 }, 'Switching role from answerer to offerer after going back to stable state should succeed'); 125 126 promise_test(async t => { 127 const pc = new RTCPeerConnection(); 128 t.add_cleanup(() => pc.close()); 129 const offer = await pc.createOffer(); 130 let eventSequence = ''; 131 const signalingstatechangeResolver = new Resolver(); 132 pc.onsignalingstatechange = () => { 133 eventSequence += 'onsignalingstatechange;'; 134 signalingstatechangeResolver.resolve(); 135 }; 136 await pc.setLocalDescription(offer); 137 eventSequence += 'setLocalDescription;'; 138 await signalingstatechangeResolver; 139 assert_equals(eventSequence, 'onsignalingstatechange;setLocalDescription;'); 140 }, 'onsignalingstatechange fires before setLocalDescription resolves'); 141 142 /* 143 TODO 144 4.3.2. setLocalDescription 145 4. If description.sdp is null and description.type is pranswer, set description.sdp 146 to lastAnswer. 147 7. If description.type is pranswer and description.sdp does not match lastAnswer, 148 reject the promise with a newly created InvalidModificationError and abort these 149 steps. 150 */ 151 152 </script>