blob: 1dbcf41118af885c12a9cfeaf04407cc4bf39c06 [file] [log] [blame]
Philipp Hanckeb7014f72017-02-27 13:24:201<!doctype html>
Soares Chenfda87822017-06-05 14:00:302<meta charset=utf-8>
3<title>RTCPeerConnection.prototype.setRemoteDescription</title>
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
6<script src="RTCPeerConnection-helper.js"></script>
7<script>
Soares Chen0f176432017-05-04 04:40:478 'use strict';
9
Soares Chenfda87822017-06-05 14:00:3010 // Test is based on the following editor draft:
Soares Chena01b1e52017-07-07 09:52:0311 // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
Soares Chenfda87822017-06-05 14:00:3012
Rick Waldron1c5c05d2017-06-07 17:54:4213 // The following helper functions are called from RTCPeerConnection-helper.js:
Rick Waldron1c5c05d2017-06-07 17:54:4214 // assert_session_desc_not_equals()
15 // assert_session_desc_equals()
Rick Waldron1c5c05d2017-06-07 17:54:4216
Soares Chenfda87822017-06-05 14:00:3017 /*
Soares Chena01b1e52017-07-07 09:52:0318 4.3.2. Interface Definition
19 [Constructor(optional RTCConfiguration configuration)]
20 interface RTCPeerConnection : EventTarget {
21 Promise<void> setRemoteDescription(
22 RTCSessionDescriptionInit description);
23
24 readonly attribute RTCSessionDescription? remoteDescription;
25 readonly attribute RTCSessionDescription? currentRemoteDescription;
26 readonly attribute RTCSessionDescription? pendingRemoteDescription;
27 ...
28 };
29
30 4.6.2. RTCSessionDescription Class
31 dictionary RTCSessionDescriptionInit {
32 required RTCSdpType type;
33 DOMString sdp = "";
34 };
35
36 4.6.1. RTCSdpType
37 enum RTCSdpType {
38 "offer",
39 "pranswer",
40 "answer",
41 "rollback"
42 };
Soares Chenfda87822017-06-05 14:00:3043 */
44
Soares Chena01b1e52017-07-07 09:52:0345 /*
Soares Chena01b1e52017-07-07 09:52:0346 4.6.1. enum RTCSdpType
Soares Chenfda87822017-06-05 14:00:3047 */
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0648 promise_test(async t => {
Soares Chenfda87822017-06-05 14:00:3049 const pc = new RTCPeerConnection();
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0650 t.add_cleanup(() => pc.close());
Soares Chenfda87822017-06-05 14:00:3051
52 // SDP is validated after WebIDL validation
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0653 try {
54 await pc.setRemoteDescription({ type: 'bogus', sdp: 'bogus' });
55 t.unreached_func("Should have rejected.");
56 } catch (e) {
57 assert_throws(new TypeError(), () => { throw e });
58 }
Soares Chenadb61762017-08-31 07:51:3859 }, 'setRemoteDescription with invalid type and invalid SDP should reject with TypeError');
Soares Chenfda87822017-06-05 14:00:3060
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0661 promise_test(async t => {
Soares Chenfda87822017-06-05 14:00:3062 const pc = new RTCPeerConnection();
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0663 t.add_cleanup(() => pc.close());
Soares Chenfda87822017-06-05 14:00:3064
65 // SDP is validated after validating type
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0666 try {
67 await pc.setRemoteDescription({ type: 'answer', sdp: 'invalid' });
68 t.unreached_func("Should have rejected.");
69 } catch (e) {
70 assert_throws('InvalidStateError', () => { throw e });
71 }
Soares Chenadb61762017-08-31 07:51:3872 }, 'setRemoteDescription() with invalid SDP and stable state should reject with InvalidStateError');
Soares Chenfda87822017-06-05 14:00:3073
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0674 /* Dedicated signalingstate events test. */
75
76 promise_test(async t => {
77 const pc = new RTCPeerConnection();
78 const pc2 = new RTCPeerConnection();
79 t.add_cleanup(() => pc.close());
80 t.add_cleanup(() => pc2.close());
81
82 let eventCount = 0;
83 const states = [
Jan-Ivar Bruaroey75c1b742018-05-17 19:47:1784 'stable', 'have-local-offer', 'stable', 'have-remote-offer',
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0685 ];
Jan-Ivar Bruaroey75c1b742018-05-17 19:47:1786 pc.onsignalingstatechange = t.step_func(() =>
87 assert_equals(pc.signalingState, states[++eventCount]));
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:0688
89 const assert_state = state => {
90 assert_equals(state, pc.signalingState);
91 assert_equals(state, states[eventCount]);
92 };
93
94 const offer = await pc.createOffer({ offerToReceiveAudio: true });
95 assert_state('stable');
96 await pc.setLocalDescription(offer);
97 assert_state('have-local-offer');
98 await pc2.setRemoteDescription(offer);
99 await pc2.setLocalDescription(await pc2.createAnswer());
100 await pc.setRemoteDescription(pc2.localDescription);
101 assert_state('stable');
102 await pc.setRemoteDescription(await pc2.createOffer());
103 assert_state('have-remote-offer');
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06104 }, 'Negotiation should fire signalingsstate events');
105
Soares Chena01b1e52017-07-07 09:52:03106 /* Operations after returning to stable state */
Soares Chenfda87822017-06-05 14:00:30107
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06108 promise_test(async t => {
Soares Chenfda87822017-06-05 14:00:30109 const pc = new RTCPeerConnection();
110 const pc2 = new RTCPeerConnection();
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06111 t.add_cleanup(() => pc.close());
112 t.add_cleanup(() => pc2.close());
Soares Chenfda87822017-06-05 14:00:30113
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06114 const offer1 = await pc2.createOffer({ offerToReceiveAudio: true });
115 await pc.setRemoteDescription(offer1);
116 await pc.setLocalDescription(await pc.createAnswer());
117 const offer2 = await pc2.createOffer({ offerToReceiveVideo: true });
118 await pc.setRemoteDescription(offer2);
119 assert_session_desc_not_equals(offer1, offer2);
120 assert_session_desc_equals(pc.remoteDescription, offer2);
121 assert_session_desc_equals(pc.currentRemoteDescription, offer1);
122 assert_session_desc_equals(pc.pendingRemoteDescription, offer2);
Soares Chenfda87822017-06-05 14:00:30123 }, 'Calling setRemoteDescription() again after one round of remote-offer/local-answer should succeed');
124
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06125 promise_test(async t => {
Soares Chenfda87822017-06-05 14:00:30126 const pc = new RTCPeerConnection();
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06127 const pc2 = new RTCPeerConnection();
128 t.add_cleanup(() => pc.close());
129 t.add_cleanup(() => pc2.close());
Soares Chenfda87822017-06-05 14:00:30130
Jan-Ivar Bruaroey85e0c942018-05-16 14:38:06131 const offer = await pc.createOffer({ offerToReceiveAudio: true });
132 await pc.setLocalDescription(offer);
133 await pc2.setRemoteDescription(offer);
134 const answer = await pc2.createAnswer();
135 await pc2.setLocalDescription(answer);
136 await pc.setRemoteDescription(answer);
137 await pc.setRemoteDescription(await pc2.createOffer());
138 assert_equals(pc.remoteDescription.sdp, pc.pendingRemoteDescription.sdp);
139 assert_session_desc_equals(pc.remoteDescription, offer);
140 assert_session_desc_equals(pc.currentRemoteDescription, answer);
Soares Chenfda87822017-06-05 14:00:30141 }, 'Switching role from offerer to answerer after going back to stable state should succeed');
142
143 /*
Soares Chena01b1e52017-07-07 09:52:03144 TODO
145 4.3.2. setRemoteDescription
146 - If an a=identity attribute is present in the session description, the browser
147 validates the identity assertion.
148 */
Soares Chen0f176432017-05-04 04:40:47149
Philipp Hanckeb7014f72017-02-27 13:24:20150</script>