blob: e1607b638366707841d74352d9e9ee10d218504a [file] [log] [blame]
Soares Chen5dbbd5f2017-07-10 09:56:091<!doctype html>
2<meta charset=utf-8>
3<title>RTCPeerConnection.prototype.setLocalDescription rollback</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:
Jan-Ivar Bruaroey6d3fda52018-07-04 13:49:0914 // assert_session_desc_similar
Youenn Fablet27e0acb2018-11-13 19:00:2015 // generateAudioReceiveOnlyOffer
Soares Chen5dbbd5f2017-07-10 09:56:0916
17 /*
18 4.3.2. Interface Definition
19 [Constructor(optional RTCConfiguration configuration)]
20 interface RTCPeerConnection : EventTarget {
21 Promise<void> setLocalDescription(
22 RTCSessionDescriptionInit description);
23
24 readonly attribute RTCSessionDescription? localDescription;
25 readonly attribute RTCSessionDescription? currentLocalDescription;
26 readonly attribute RTCSessionDescription? pendingLocalDescription;
27
28 Promise<void> setRemoteDescription(
29 RTCSessionDescriptionInit description);
30
31 readonly attribute RTCSessionDescription? remoteDescription;
32 readonly attribute RTCSessionDescription? currentRemoteDescription;
33 readonly attribute RTCSessionDescription? pendingRemoteDescription;
34 ...
35 };
36
37 4.6.2. RTCSessionDescription Class
38 dictionary RTCSessionDescriptionInit {
39 required RTCSdpType type;
40 DOMString sdp = "";
41 };
42
43 4.6.1. RTCSdpType
44 enum RTCSdpType {
45 "offer",
46 "pranswer",
47 "answer",
48 "rollback"
49 };
50 */
51
52 /*
53 4.3.1.6. Set the RTCSessionSessionDescription
54 2.2.2. If description is set as a local description, then run one of the
55 following steps:
56 - If description is of type "rollback", then this is a rollback. Set
57 connection.pendingLocalDescription to null and signaling state to stable.
58 */
59 promise_test(t=> {
60 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:5361 t.add_cleanup(() => pc.close());
Soares Chen5dbbd5f2017-07-10 09:56:0962
Philipp Hanckeeb37a992018-05-30 15:55:0263 const states = [];
64 pc.addEventListener('signalingstatechange', () => states.push(pc.signalingState));
Soares Chen5dbbd5f2017-07-10 09:56:0965
66 return pc.createOffer()
67 .then(offer => pc.setLocalDescription(offer))
68 .then(() => {
69 assert_equals(pc.signalingState, 'have-local-offer');
70 assert_not_equals(pc.localDescription, null);
71 assert_not_equals(pc.pendingLocalDescription, null);
72 assert_equals(pc.currentLocalDescription, null);
73
74 return pc.setLocalDescription({ type: 'rollback' });
75 })
76 .then(() => {
77 assert_equals(pc.signalingState, 'stable');
78 assert_equals(pc.localDescription, null);
79 assert_equals(pc.pendingLocalDescription, null);
80 assert_equals(pc.currentLocalDescription, null);
Philipp Hanckeeb37a992018-05-30 15:55:0281
82 assert_array_equals(states, ['have-local-offer', 'stable']);
Soares Chen5dbbd5f2017-07-10 09:56:0983 });
84 }, 'setLocalDescription(rollback) from have-local-offer state should reset back to stable state');
85
Soares Chenc94ef3e2017-07-14 05:20:2086 /*
87 4.3.1.6. Set the RTCSessionSessionDescription
88 2.3. If the description's type is invalid for the current signaling state of
89 connection, then reject p with a newly created InvalidStateError and abort
90 these steps. Note that this implies that once the answerer has performed
91 setLocalDescription with his answer, this cannot be rolled back.
92
93 [jsep]
94 4.1.8.2. Rollback
95 - Rollback can only be used to cancel proposed changes;
96 there is no support for rolling back from a stable state to a
97 previous stable state
98 */
99 promise_test(t => {
100 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53101 t.add_cleanup(() => pc.close());
Boris Zbarskyb7f2dd32020-02-04 21:26:48102 return promise_rejects_dom(t, 'InvalidStateError',
Soares Chenc94ef3e2017-07-14 05:20:20103 pc.setLocalDescription({ type: 'rollback' }));
104 }, `setLocalDescription(rollback) from stable state should reject with InvalidStateError`);
105
106 promise_test(t => {
107 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53108 t.add_cleanup(() => pc.close());
Youenn Fablet27e0acb2018-11-13 19:00:20109 return generateAudioReceiveOnlyOffer(pc)
Soares Chenc94ef3e2017-07-14 05:20:20110 .then(offer =>
111 pc.setRemoteDescription(offer)
112 .then(() => pc.createAnswer()))
113 .then(answer => pc.setLocalDescription(answer))
114 .then(() => {
Boris Zbarskyb7f2dd32020-02-04 21:26:48115 return promise_rejects_dom(t, 'InvalidStateError',
Soares Chenc94ef3e2017-07-14 05:20:20116 pc.setLocalDescription({ type: 'rollback' }));
117 });
118 }, `setLocalDescription(rollback) after setting answer description should reject with InvalidStateError`);
119
120 promise_test(t => {
121 const pc = new RTCPeerConnection();
Philipp Hancke1622a022018-06-11 10:00:53122 t.add_cleanup(() => pc.close());
Soares Chenc94ef3e2017-07-14 05:20:20123 return pc.createOffer()
124 .then(offer => pc.setLocalDescription(offer))
125 .then(() => pc.setLocalDescription({
126 type: 'rollback',
127 sdp: '!<Invalid SDP Content>;'
128 }));
129 }, `setLocalDescription(rollback) should ignore invalid sdp content and succeed`);
Byron Campen [:bwc]dcc39202020-02-06 16:03:59130
131 promise_test(async t => {
132 const pc = new RTCPeerConnection();
133 t.add_cleanup(() => pc.close());
134
135 await pc.setLocalDescription(await pc.createOffer({offerToReceiveAudio: true}));
136 const sldPromise = pc.setLocalDescription({type: "rollback"});
137
138 assert_equals(pc.signalingState, "have-local-offer", "signalingState should not be set synchronously after a call to sLD");
139
140 assert_not_equals(pc.pendingLocalDescription, null, "pendingLocalDescription should not be set synchronously after a call to sLD");
141 assert_equals(pc.pendingLocalDescription.type, "offer");
142 assert_equals(pc.pendingLocalDescription.sdp, pc.localDescription.sdp);
143 assert_equals(pc.pendingRemoteDescription, null, "pendingRemoteDescription should never be set due to sLD(offer)");
144
145 const stablePromise = new Promise(resolve => {
146 pc.onsignalingstatechange = () => {
147 resolve(pc.signalingState);
148 }
149 });
150 const raceValue = await Promise.race([stablePromise, sldPromise]);
151 assert_equals(raceValue, "stable", "signalingstatechange event should fire before sLD resolves");
152 assert_equals(pc.pendingLocalDescription, null, "pendingLocalDescription should be updated before the signalingstatechange event");
153 assert_equals(pc.pendingRemoteDescription, null, "pendingRemoteDescription should never be set due to sLD(offer)");
154
155 await sldPromise;
156 }, "setLocalDescription(rollback) should update internal state with a queued tassk, in the right order");
157
Soares Chen5dbbd5f2017-07-10 09:56:09158</script>