<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[282525] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/282525">282525</a></dd>
<dt>Author</dt> <dd>youenn@apple.com</dd>
<dt>Date</dt> <dd>2021-09-16 03:01:25 -0700 (Thu, 16 Sep 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Support RTCPeerConnection lastCreatedOffer/lastCreatedAnswer
https://bugs.webkit.org/show_bug.cgi?id=230260

Reviewed by Eric Carlson.

LayoutTests/imported/w3c:

* web-platform-tests/webrtc/RTCPeerConnection-operations.https-expected.txt:
* web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt:
* web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt:
* web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https-expected.txt:

Source/WebCore:

Update WebIDL to handle optional RTCLocalSessionDescriptionInit.type value.
In case type is missing, compute its value in setLocalDescription as per
https://w3c.github.io/webrtc-pc/#dom-peerconnection-setlocaldescription step 4.1.
If sdp is empty, use local offer/answer as per steps 4.2 and 4.3.
Store local offer and answer as per spec.
Refactor code to let PeerConnectionBackend createOffer and createAnswer take a callback instead of a promise
to store the last offer/answer.

Covered by existing and rebased tests.

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* Modules/mediastream/PeerConnectionBackend.cpp:
(WebCore::PeerConnectionBackend::createOffer):
(WebCore::PeerConnectionBackend::createOfferSucceeded):
(WebCore::PeerConnectionBackend::createOfferFailed):
(WebCore::PeerConnectionBackend::createAnswer):
(WebCore::PeerConnectionBackend::createAnswerSucceeded):
(WebCore::PeerConnectionBackend::createAnswerFailed):
(WebCore::PeerConnectionBackend::stop):
* Modules/mediastream/PeerConnectionBackend.h:
* Modules/mediastream/RTCLocalSessionDescriptionInit.h: Added.
* Modules/mediastream/RTCLocalSessionDescriptionInit.idl: Added.
* Modules/mediastream/RTCPeerConnection.cpp:
(WebCore::RTCPeerConnection::createOffer):
(WebCore::RTCPeerConnection::createAnswer):
(WebCore::typeForSetLocalDescription):
(WebCore::RTCPeerConnection::setLocalDescription):
(WebCore::RTCPeerConnection::setRemoteDescription):
(WebCore::RTCPeerConnection::updateDescriptions):
* Modules/mediastream/RTCPeerConnection.h:
* Modules/mediastream/RTCPeerConnection.idl:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsimportedw3cChangeLog">trunk/LayoutTests/imported/w3c/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionoperationshttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-operations.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionanswerexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionofferexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionparameterlesshttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionrollbackexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionofferexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesinputxcfilelist">trunk/Source/WebCore/DerivedSources-input.xcfilelist</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesoutputxcfilelist">trunk/Source/WebCore/DerivedSources-output.xcfilelist</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesmake">trunk/Source/WebCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamPeerConnectionBackendcpp">trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamPeerConnectionBackendh">trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCPeerConnectioncpp">trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCPeerConnectionh">trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCPeerConnectionidl">trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.idl</a></li>
<li><a href="#trunkSourceWebCoreSourcestxt">trunk/Source/WebCore/Sources.txt</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCLocalSessionDescriptionInith">trunk/Source/WebCore/Modules/mediastream/RTCLocalSessionDescriptionInit.h</a></li>
<li><a href="#trunkSourceWebCoreModulesmediastreamRTCLocalSessionDescriptionInitidl">trunk/Source/WebCore/Modules/mediastream/RTCLocalSessionDescriptionInit.idl</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsimportedw3cChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/ChangeLog (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/ChangeLog 2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/LayoutTests/imported/w3c/ChangeLog    2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2021-09-16  Youenn Fablet  <youenn@apple.com>
+
+        Support RTCPeerConnection lastCreatedOffer/lastCreatedAnswer
+        https://bugs.webkit.org/show_bug.cgi?id=230260
+
+        Reviewed by Eric Carlson.
+
+        * web-platform-tests/webrtc/RTCPeerConnection-operations.https-expected.txt:
+        * web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt:
+        * web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt:
+        * web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https-expected.txt:
+
</ins><span class="cx"> 2021-09-15  Alex Christensen  <achristensen@webkit.org>
</span><span class="cx"> 
</span><span class="cx">         Add IDL skeleton for SharedWorker
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionoperationshttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-operations.https-expected.txt (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-operations.https-expected.txt 2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-operations.https-expected.txt    2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -1,6 +1,4 @@
</span><span class="cx"> 
</span><del>-Harness Error (TIMEOUT), message = null
-
</del><span class="cx"> PASS promiseState helper works
</span><span class="cx"> PASS promiseStateFinal helper works
</span><span class="cx"> PASS createOffer must detect InvalidStateError synchronously when chain is empty (prerequisite)
</span><span class="lines">@@ -27,6 +25,6 @@
</span><span class="cx"> PASS receiver.getStats does NOT use the operations chain
</span><span class="cx"> FAIL addIceCandidate chains onto SRD, fails before assert_equals: expected "InvalidStateError" but got "OperationError"
</span><span class="cx"> PASS Operations queue not vulnerable to recursion by chained negotiationneeded
</span><del>-FAIL Pack operations queue with implicit offer and answer promise_test: Unhandled rejection with value: object "OperationError: Expect line: v="
-TIMEOUT Negotiate solely by operations queue and signaling state Test timed out
</del><ins>+PASS Pack operations queue with implicit offer and answer
+PASS Negotiate solely by operations queue and signaling state
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionanswerexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt       2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt  2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -1,9 +1,9 @@
</span><span class="cx"> 
</span><span class="cx"> PASS setLocalDescription() with valid answer should succeed
</span><del>-FAIL setLocalDescription() with type answer and null sdp should use lastAnswer generated from createAnswer promise_test: Unhandled rejection with value: object "OperationError: Expect line: v="
-FAIL setLocalDescription() with answer not created by own createAnswer() should reject with InvalidModificationError promise_rejects_dom: function "function () { throw e }" threw object "OperationError: Failed to set local answer sdp: Failed to apply the description for m= section with mid='0': Local fingerprint does not match identity. Expected: sha-256 B0:1B:43:87:8A:C5:01:AD:5C:15:79:5B:A1:94:42:53:14:F4:3D:2A:BA:37:D1:5B:45:9C:2F:F9:3E:9D:13:0B Got: sha-256 FB:6E:CE:7C:14:FE:C1:53:6A:95:EB:0E:9F:71:79:46:F1:67:42:90:97:CD:C1:41:5E:7E:C8:BB:C7:44:30:86" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
</del><ins>+PASS setLocalDescription() with type answer and null sdp should use lastAnswer generated from createAnswer
+FAIL setLocalDescription() with answer not created by own createAnswer() should reject with InvalidModificationError promise_rejects_dom: function "function () { throw e }" threw object "OperationError: Failed to set local answer sdp: Failed to apply the description for m= section with mid='0': Local fingerprint does not match identity. Expected: sha-256 E0:10:A4:25:B7:9C:C3:34:17:6B:E8:00:18:CF:06:6A:EE:69:CD:73:98:19:59:50:B0:94:82:E7:5D:1D:8A:9A Got: sha-256 8A:BB:25:66:6B:B6:12:70:27:22:6E:E1:13:A4:5D:5D:50:A9:C0:26:8E:C9:7E:31:37:93:9B:5B:E1:23:2E:8B" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
</ins><span class="cx"> FAIL Calling setLocalDescription(answer) from stable state should reject with InvalidModificationError promise_rejects_dom: function "function () { throw e }" threw object "InvalidStateError: Failed to set local answer sdp: no pending remote description." that is not a DOMException InvalidModificationError: property "code" is equal to 11, expected 13
</span><span class="cx"> FAIL Calling setLocalDescription(answer) from have-local-offer state should reject with InvalidModificationError promise_rejects_dom: function "function () { throw e }" threw object "InvalidStateError: Failed to set local answer sdp: no pending remote description." that is not a DOMException InvalidModificationError: property "code" is equal to 11, expected 13
</span><span class="cx"> PASS Setting previously generated answer after a call to createOffer should work
</span><del>-FAIL setLocalDescription(answer) should update internal state with a queued task, in the right order assert_equals: pendingRemoteDescription should be updated before the signalingstatechange event expected null but got object "[object RTCSessionDescription]"
</del><ins>+PASS setLocalDescription(answer) should update internal state with a queued task, in the right order
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionofferexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt        2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt   2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -1,10 +1,10 @@
</span><span class="cx"> 
</span><span class="cx"> PASS setLocalDescription with valid offer should succeed
</span><del>-FAIL setLocalDescription with type offer and null sdp should use lastOffer generated from createOffer promise_test: Unhandled rejection with value: object "OperationError: Expect line: v="
-FAIL setLocalDescription() with offer not created by own createOffer() should reject with InvalidModificationError promise_rejects_dom: function "function () { throw e }" threw object "OperationError: Failed to set local offer sdp: Failed to apply the description for m= section with mid='0': Local fingerprint does not match identity. Expected: sha-256 88:43:B2:95:49:DE:C2:A7:77:5E:EC:22:6F:D4:3E:B6:D4:FD:96:24:2B:77:6F:18:85:4B:F8:8A:BC:32:46:2F Got: sha-256 14:DC:27:7A:00:73:83:85:21:8B:2A:81:8F:F9:04:01:D3:31:54:68:7D:35:9C:6A:A2:F9:1D:0B:4C:8E:90:2D" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
</del><ins>+PASS setLocalDescription with type offer and null sdp should use lastOffer generated from createOffer
+FAIL setLocalDescription() with offer not created by own createOffer() should reject with InvalidModificationError promise_rejects_dom: function "function () { throw e }" threw object "OperationError: Failed to set local offer sdp: Failed to apply the description for m= section with mid='0': Local fingerprint does not match identity. Expected: sha-256 2E:44:69:5B:86:09:8A:4E:50:8B:E8:D4:CF:C6:38:93:78:A2:D1:0E:91:37:A6:FA:41:6F:CD:9B:94:3D:22:FD Got: sha-256 62:F4:16:A1:2F:35:30:DA:D6:B8:94:CE:1E:5A:70:A0:36:7B:5B:80:05:B3:EE:6D:95:A3:8D:BD:42:38:41:79" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
</ins><span class="cx"> FAIL Set created offer other than last offer should reject with InvalidModificationError assert_unreached: Should have rejected: undefined Reached unreachable code
</span><span class="cx"> PASS Creating and setting offer multiple times should succeed
</span><span class="cx"> PASS Setting previously generated offer after a call to createAnswer should work
</span><span class="cx"> PASS Negotiation works when there has been a repeated setLocalDescription(offer)
</span><del>-FAIL setLocalDescription(offer) should update internal state with a queued task, in the right order assert_not_equals: pendingLocalDescription should be updated before the signalingstatechange event got disallowed value null
</del><ins>+PASS setLocalDescription(offer) should update internal state with a queued task, in the right order
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionparameterlesshttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https-expected.txt (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https-expected.txt  2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-parameterless.https-expected.txt     2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -5,8 +5,8 @@
</span><span class="cx"> PASS Parameterless SLD() in 'have-remote-offer' goes to 'stable'
</span><span class="cx"> PASS Parameterless SLD() in 'have-remote-offer' sets currentLocalDescription
</span><span class="cx"> PASS Parameterless SLD() in 'have-remote-offer' sets transceiver.currentDirection
</span><del>-FAIL Parameterless SLD() uses [[LastCreatedOffer]] if it is still valid assert_true: offerer.pendingLocalDescription.sdp == offer.sdp expected true got false
-FAIL Parameterless SLD() uses [[LastCreatedAnswer]] if it is still valid assert_true: answerer.currentLocalDescription.sdp == answer.sdp expected true got false
</del><ins>+PASS Parameterless SLD() uses [[LastCreatedOffer]] if it is still valid
+PASS Parameterless SLD() uses [[LastCreatedAnswer]] if it is still valid
</ins><span class="cx"> PASS Parameterless SLD() rejects with InvalidStateError if already closed
</span><span class="cx"> PASS Parameterless SLD() never settles if closed while pending
</span><span class="cx"> PASS Parameterless SLD() in a full O/A exchange succeeds
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionrollbackexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback-expected.txt (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback-expected.txt     2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback-expected.txt        2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -3,5 +3,5 @@
</span><span class="cx"> PASS setLocalDescription(rollback) from stable state should reject with InvalidStateError
</span><span class="cx"> PASS setLocalDescription(rollback) after setting answer description should reject with InvalidStateError
</span><span class="cx"> PASS setLocalDescription(rollback) should ignore invalid sdp content and succeed
</span><del>-FAIL setLocalDescription(rollback) should update internal state with a queued tassk, in the right order assert_equals: pendingLocalDescription should be updated before the signalingstatechange event expected null but got object "[object RTCSessionDescription]"
</del><ins>+PASS setLocalDescription(rollback) should update internal state with a queued tassk, in the right order
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionofferexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt       2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt  2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -4,12 +4,12 @@
</span><span class="cx"> PASS setRemoteDescription multiple times with different offer should succeed
</span><span class="cx"> FAIL setRemoteDescription(offer) with invalid SDP should reject with RTCError assert_equals: Expect error detail field to set to sdp-syntax-error expected (string) "sdp-syntax-error" but got (undefined) undefined
</span><span class="cx"> PASS setRemoteDescription(offer) from have-local-offer should roll back and succeed
</span><del>-FAIL setRemoteDescription(offer) from have-local-offer fires signalingstatechange twice assert_equals: expected null but got object "[object RTCSessionDescription]"
-FAIL setRemoteDescription(offer) in stable should update internal state with a queued task, in the right order assert_not_equals: pendingRemoteDescription should be updated before the signalingstatechange event got disallowed value null
-FAIL setRemoteDescription(offer) in have-local-offer should update internal state with a queued task, in the right order assert_equals: pendingLocalDescription should be updated before the signalingstatechange event expected null but got object "[object RTCSessionDescription]"
</del><ins>+PASS setRemoteDescription(offer) from have-local-offer fires signalingstatechange twice
+PASS setRemoteDescription(offer) in stable should update internal state with a queued task, in the right order
+PASS setRemoteDescription(offer) in have-local-offer should update internal state with a queued task, in the right order
</ins><span class="cx"> FAIL Naive rollback approach is not glare-proof (control) assert_unreached: Should have rejected: undefined Reached unreachable code
</span><span class="cx"> PASS setRemoteDescription(offer) from have-local-offer is glare-proof
</span><del>-FAIL setRemoteDescription(invalidOffer) from have-local-offer does not undo rollback assert_equals: expected null but got object "[object RTCSessionDescription]"
</del><ins>+FAIL setRemoteDescription(invalidOffer) from have-local-offer does not undo rollback Test bug: unrecognized DOMException code name or name "RTCError" passed to assert_throws_dom()
</ins><span class="cx"> PASS repeated sRD(offer) works
</span><span class="cx"> PASS sRD(reoffer) with candidates and without trickle works
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt      2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/CMakeLists.txt 2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -410,6 +410,7 @@
</span><span class="cx">     Modules/mediastream/RTCIceTcpCandidateType.idl
</span><span class="cx">     Modules/mediastream/RTCIceTransport.idl
</span><span class="cx">     Modules/mediastream/RTCIceTransportState.idl
</span><ins>+    Modules/mediastream/RTCLocalSessionDescriptionInit.idl
</ins><span class="cx">     Modules/mediastream/RTCOfferAnswerOptions.idl
</span><span class="cx">     Modules/mediastream/RTCOfferOptions.idl
</span><span class="cx">     Modules/mediastream/RTCPeerConnection.idl
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/ChangeLog      2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -1,5 +1,49 @@
</span><span class="cx"> 2021-09-16  Youenn Fablet  <youenn@apple.com>
</span><span class="cx"> 
</span><ins>+        Support RTCPeerConnection lastCreatedOffer/lastCreatedAnswer
+        https://bugs.webkit.org/show_bug.cgi?id=230260
+
+        Reviewed by Eric Carlson.
+
+        Update WebIDL to handle optional RTCLocalSessionDescriptionInit.type value.
+        In case type is missing, compute its value in setLocalDescription as per
+        https://w3c.github.io/webrtc-pc/#dom-peerconnection-setlocaldescription step 4.1.
+        If sdp is empty, use local offer/answer as per steps 4.2 and 4.3.
+        Store local offer and answer as per spec.
+        Refactor code to let PeerConnectionBackend createOffer and createAnswer take a callback instead of a promise
+        to store the last offer/answer.
+
+        Covered by existing and rebased tests.
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * Modules/mediastream/PeerConnectionBackend.cpp:
+        (WebCore::PeerConnectionBackend::createOffer):
+        (WebCore::PeerConnectionBackend::createOfferSucceeded):
+        (WebCore::PeerConnectionBackend::createOfferFailed):
+        (WebCore::PeerConnectionBackend::createAnswer):
+        (WebCore::PeerConnectionBackend::createAnswerSucceeded):
+        (WebCore::PeerConnectionBackend::createAnswerFailed):
+        (WebCore::PeerConnectionBackend::stop):
+        * Modules/mediastream/PeerConnectionBackend.h:
+        * Modules/mediastream/RTCLocalSessionDescriptionInit.h: Added.
+        * Modules/mediastream/RTCLocalSessionDescriptionInit.idl: Added.
+        * Modules/mediastream/RTCPeerConnection.cpp:
+        (WebCore::RTCPeerConnection::createOffer):
+        (WebCore::RTCPeerConnection::createAnswer):
+        (WebCore::typeForSetLocalDescription):
+        (WebCore::RTCPeerConnection::setLocalDescription):
+        (WebCore::RTCPeerConnection::setRemoteDescription):
+        (WebCore::RTCPeerConnection::updateDescriptions):
+        * Modules/mediastream/RTCPeerConnection.h:
+        * Modules/mediastream/RTCPeerConnection.idl:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+2021-09-16  Youenn Fablet  <youenn@apple.com>
+
</ins><span class="cx">         Enable RTCRtpScriptTransform by default
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=230220
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesinputxcfilelist"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources-input.xcfilelist (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources-input.xcfilelist     2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/DerivedSources-input.xcfilelist        2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -242,6 +242,7 @@
</span><span class="cx"> $(PROJECT_DIR)/Modules/mediastream/RTCIceTcpCandidateType.idl
</span><span class="cx"> $(PROJECT_DIR)/Modules/mediastream/RTCIceTransport.idl
</span><span class="cx"> $(PROJECT_DIR)/Modules/mediastream/RTCIceTransportState.idl
</span><ins>+$(PROJECT_DIR)/Modules/mediastream/RTCLocalSessionDescriptionInit.idl
</ins><span class="cx"> $(PROJECT_DIR)/Modules/mediastream/RTCOfferAnswerOptions.idl
</span><span class="cx"> $(PROJECT_DIR)/Modules/mediastream/RTCOfferOptions.idl
</span><span class="cx"> $(PROJECT_DIR)/Modules/mediastream/RTCPeerConnection.idl
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesoutputxcfilelist"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources-output.xcfilelist (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources-output.xcfilelist    2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/DerivedSources-output.xcfilelist       2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -1725,6 +1725,8 @@
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCIceTransport.h
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCIceTransportState.cpp
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCIceTransportState.h
</span><ins>+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCLocalSessionDescriptionInit.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCLocalSessionDescriptionInit.h
</ins><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCOfferAnswerOptions.cpp
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCOfferAnswerOptions.h
</span><span class="cx"> $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCOfferOptions.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.make (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources.make 2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/DerivedSources.make    2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -268,6 +268,7 @@
</span><span class="cx">     $(WebCore)/Modules/mediastream/RTCIceTcpCandidateType.idl \
</span><span class="cx">     $(WebCore)/Modules/mediastream/RTCIceTransport.idl \
</span><span class="cx">     $(WebCore)/Modules/mediastream/RTCIceTransportState.idl \
</span><ins>+    $(WebCore)/Modules/mediastream/RTCLocalSessionDescriptionInit.idl \
</ins><span class="cx">     $(WebCore)/Modules/mediastream/RTCOfferAnswerOptions.idl \
</span><span class="cx">     $(WebCore)/Modules/mediastream/RTCOfferOptions.idl \
</span><span class="cx">     $(WebCore)/Modules/mediastream/RTCPeerConnection.idl \
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamPeerConnectionBackendcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp       2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp  2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -35,8 +35,6 @@
</span><span class="cx"> #if ENABLE(WEB_RTC)
</span><span class="cx"> 
</span><span class="cx"> #include "EventNames.h"
</span><del>-#include "JSDOMPromiseDeferred.h"
-#include "JSRTCSessionDescriptionInit.h"
</del><span class="cx"> #include "LibWebRTCCertificateGenerator.h"
</span><span class="cx"> #include "Logging.h"
</span><span class="cx"> #include "Page.h"
</span><span class="lines">@@ -92,12 +90,12 @@
</span><span class="cx"> 
</span><span class="cx"> PeerConnectionBackend::~PeerConnectionBackend() = default;
</span><span class="cx"> 
</span><del>-void PeerConnectionBackend::createOffer(RTCOfferOptions&& options, PeerConnection::SessionDescriptionPromise&& promise)
</del><ins>+void PeerConnectionBackend::createOffer(RTCOfferOptions&& options, CreateCallback&& callback)
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_offerAnswerPromise);
</del><ins>+    ASSERT(!m_offerAnswerCallback);
</ins><span class="cx">     ASSERT(!m_peerConnection.isClosed());
</span><span class="cx"> 
</span><del>-    m_offerAnswerPromise = WTF::makeUnique<PeerConnection::SessionDescriptionPromise>(WTFMove(promise));
</del><ins>+    m_offerAnswerCallback = WTFMove(callback);
</ins><span class="cx">     doCreateOffer(WTFMove(options));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -106,13 +104,10 @@
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     ALWAYS_LOG(LOGIDENTIFIER, "Create offer succeeded:\n", sdp);
</span><span class="cx"> 
</span><del>-    ASSERT(m_offerAnswerPromise);
</del><ins>+    ASSERT(m_offerAnswerCallback);
</ins><span class="cx">     validateSDP(sdp);
</span><del>-    m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [this, promise = WTFMove(m_offerAnswerPromise), sdp = WTFMove(sdp)]() mutable {
-        if (m_peerConnection.isClosed())
-            return;
-
-        promise->resolve(RTCSessionDescriptionInit { RTCSdpType::Offer, sdp });
</del><ins>+    m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [callback = WTFMove(m_offerAnswerCallback), sdp = WTFMove(sdp)]() mutable {
+        callback(RTCSessionDescriptionInit { RTCSdpType::Offer, sdp });
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -121,21 +116,18 @@
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     ALWAYS_LOG(LOGIDENTIFIER, "Create offer failed:", exception.message());
</span><span class="cx"> 
</span><del>-    ASSERT(m_offerAnswerPromise);
-    m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [this, promise = WTFMove(m_offerAnswerPromise), exception = WTFMove(exception)]() mutable {
-        if (m_peerConnection.isClosed())
-            return;
-
-        promise->reject(WTFMove(exception));
</del><ins>+    ASSERT(m_offerAnswerCallback);
+    m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [callback = WTFMove(m_offerAnswerCallback), exception = WTFMove(exception)]() mutable {
+        callback(WTFMove(exception));
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void PeerConnectionBackend::createAnswer(RTCAnswerOptions&& options, PeerConnection::SessionDescriptionPromise&& promise)
</del><ins>+void PeerConnectionBackend::createAnswer(RTCAnswerOptions&& options, CreateCallback&& callback)
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_offerAnswerPromise);
</del><ins>+    ASSERT(!m_offerAnswerCallback);
</ins><span class="cx">     ASSERT(!m_peerConnection.isClosed());
</span><span class="cx"> 
</span><del>-    m_offerAnswerPromise = WTF::makeUnique<PeerConnection::SessionDescriptionPromise>(WTFMove(promise));
</del><ins>+    m_offerAnswerCallback = WTFMove(callback);
</ins><span class="cx">     doCreateAnswer(WTFMove(options));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -144,12 +136,9 @@
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     ALWAYS_LOG(LOGIDENTIFIER, "Create answer succeeded:\n", sdp);
</span><span class="cx"> 
</span><del>-    ASSERT(m_offerAnswerPromise);
-    m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [this, promise = WTFMove(m_offerAnswerPromise), sdp = WTFMove(sdp)]() mutable {
-        if (m_peerConnection.isClosed())
-            return;
-
-        promise->resolve(RTCSessionDescriptionInit { RTCSdpType::Answer, sdp });
</del><ins>+    ASSERT(m_offerAnswerCallback);
+    m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [callback = WTFMove(m_offerAnswerCallback), sdp = WTFMove(sdp)]() mutable {
+        callback(RTCSessionDescriptionInit { RTCSdpType::Answer, sdp });
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -158,12 +147,9 @@
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     ALWAYS_LOG(LOGIDENTIFIER, "Create answer failed:", exception.message());
</span><span class="cx"> 
</span><del>-    ASSERT(m_offerAnswerPromise);
-    m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [this, promise = WTFMove(m_offerAnswerPromise), exception = WTFMove(exception)]() mutable {
-        if (m_peerConnection.isClosed())
-            return;
-
-        promise->reject(WTFMove(exception));
</del><ins>+    ASSERT(m_offerAnswerCallback);
+    m_peerConnection.queueTaskKeepingObjectAlive(m_peerConnection, TaskSource::Networking, [callback = WTFMove(m_offerAnswerCallback), exception = WTFMove(exception)]() mutable {
+        callback(WTFMove(exception));
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -407,7 +393,7 @@
</span><span class="cx"> 
</span><span class="cx"> void PeerConnectionBackend::stop()
</span><span class="cx"> {
</span><del>-    m_offerAnswerPromise = nullptr;
</del><ins>+    m_offerAnswerCallback = nullptr;
</ins><span class="cx">     m_setDescriptionCallback = nullptr;
</span><span class="cx"> 
</span><span class="cx">     m_pendingTrackEvents.clear();
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamPeerConnectionBackendh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h 2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/Modules/mediastream/PeerConnectionBackend.h    2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -93,8 +93,9 @@
</span><span class="cx">     explicit PeerConnectionBackend(RTCPeerConnection&);
</span><span class="cx">     virtual ~PeerConnectionBackend();
</span><span class="cx"> 
</span><del>-    void createOffer(RTCOfferOptions&&, PeerConnection::SessionDescriptionPromise&&);
-    void createAnswer(RTCAnswerOptions&&, PeerConnection::SessionDescriptionPromise&&);
</del><ins>+    using CreateCallback = Function<void(ExceptionOr<RTCSessionDescriptionInit>&&)>;
+    void createOffer(RTCOfferOptions&&, CreateCallback&&);
+    void createAnswer(RTCAnswerOptions&&, CreateCallback&&);
</ins><span class="cx">     void setLocalDescription(const RTCSessionDescription*, Function<void(ExceptionOr<void>&&)>&&);
</span><span class="cx">     void setRemoteDescription(const RTCSessionDescription&, Function<void(ExceptionOr<void>&&)>&&);
</span><span class="cx">     void addIceCandidate(RTCIceCandidate*, DOMPromiseDeferred<void>&&);
</span><span class="lines">@@ -235,7 +236,7 @@
</span><span class="cx">     RTCPeerConnection& m_peerConnection;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    std::unique_ptr<PeerConnection::SessionDescriptionPromise> m_offerAnswerPromise;
</del><ins>+    CreateCallback m_offerAnswerCallback;
</ins><span class="cx">     Function<void(ExceptionOr<void>&&)> m_setDescriptionCallback;
</span><span class="cx"> 
</span><span class="cx">     bool m_shouldFilterICECandidates { true };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCLocalSessionDescriptionInith"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediastream/RTCLocalSessionDescriptionInit.h (0 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCLocalSessionDescriptionInit.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/RTCLocalSessionDescriptionInit.h   2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEB_RTC)
+
+#include "RTCSdpType.h"
+
+namespace WebCore {
+
+struct RTCLocalSessionDescriptionInit {
+    std::optional<RTCSdpType> type;
+    String sdp;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_RTC)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCLocalSessionDescriptionInitidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/mediastream/RTCLocalSessionDescriptionInit.idl (0 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCLocalSessionDescriptionInit.idl                              (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/RTCLocalSessionDescriptionInit.idl 2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=WEB_RTC
+] dictionary RTCLocalSessionDescriptionInit {
+    RTCSdpType type;
+    DOMString sdp = "";
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCPeerConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp   2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp      2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #include "Frame.h"
</span><span class="cx"> #include "JSDOMPromiseDeferred.h"
</span><span class="cx"> #include "JSRTCPeerConnection.h"
</span><ins>+#include "JSRTCSessionDescriptionInit.h"
</ins><span class="cx"> #include "Logging.h"
</span><span class="cx"> #include "MediaEndpointConfiguration.h"
</span><span class="cx"> #include "MediaStream.h"
</span><span class="lines">@@ -212,7 +213,17 @@
</span><span class="cx">             promise->reject(InvalidStateError);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-        m_backend->createOffer(WTFMove(options), WTFMove(promise));
</del><ins>+        m_backend->createOffer(WTFMove(options), [this, protectedThis = makeRef(*this), promise = PeerConnection::SessionDescriptionPromise(WTFMove(promise))](auto&& result) mutable {
+            if (isClosed())
+                return;
+            if (result.hasException()) {
+                promise.reject(result.releaseException());
+                return;
+            }
+            // https://w3c.github.io/webrtc-pc/#dfn-final-steps-to-create-an-offer steps 4,5 and 6.
+            m_lastCreatedOffer = result.returnValue().sdp;
+            promise.resolve(result.releaseReturnValue());
+        });
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -229,66 +240,87 @@
</span><span class="cx">             promise->reject(InvalidStateError);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-        m_backend->createAnswer(WTFMove(options), WTFMove(promise));
</del><ins>+        m_backend->createAnswer(WTFMove(options), [this, protectedThis = makeRef(*this), promise = PeerConnection::SessionDescriptionPromise(WTFMove(promise))](auto&& result) mutable {
+            if (isClosed())
+                return;
+            if (result.hasException()) {
+                promise.reject(result.releaseException());
+                return;
+            }
+            // https://w3c.github.io/webrtc-pc/#dfn-final-steps-to-create-an-answer steps 4,5 and 6.
+            m_lastCreatedAnswer = result.returnValue().sdp;
+            promise.resolve(result.releaseReturnValue());
+        });
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RTCPeerConnection::setLocalDescription(std::optional<Description>&& localDescription, Ref<DeferredPromise>&& promise)
</del><ins>+static RTCSdpType typeForSetLocalDescription(const std::optional<RTCLocalSessionDescriptionInit>& description, RTCSignalingState signalingState)
</ins><span class="cx"> {
</span><ins>+    std::optional<RTCSdpType> type;
+    if (description)
+        type = description->type;
+
+    // https://w3c.github.io/webrtc-pc/#dom-peerconnection-setlocaldescription step 4.1.
+    if (!type) {
+        bool shouldBeOffer = signalingState == RTCSignalingState::Stable || signalingState == RTCSignalingState::HaveLocalOffer || signalingState == RTCSignalingState::HaveRemotePranswer;
+        return shouldBeOffer ? RTCSdpType::Offer : RTCSdpType::Answer;
+    }
+    return *type;
+}
+
+void RTCPeerConnection::setLocalDescription(std::optional<RTCLocalSessionDescriptionInit>&& localDescription, Ref<DeferredPromise>&& promise)
+{
</ins><span class="cx">     if (isClosed()) {
</span><span class="cx">         promise->reject(InvalidStateError);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    RefPtr<RTCSessionDescription> description;
-    if (localDescription) {
-        description = switchOn(*localDescription, [](RTCSessionDescriptionInit& init) -> RefPtr<RTCSessionDescription> {
-            return RTCSessionDescription::create(WTFMove(init));
-        }, [](RefPtr<RTCSessionDescription>& description) {
-            return WTFMove(description);
-        });
-    }
</del><ins>+    ALWAYS_LOG(LOGIDENTIFIER, "Setting local description to:\n", localDescription ? localDescription->sdp : "''");
+    chainOperation(WTFMove(promise), [this, localDescription = WTFMove(localDescription)](auto&& promise) mutable {
+        auto type = typeForSetLocalDescription(localDescription, m_signalingState);
+        String sdp;
+        if (localDescription)
+            sdp = localDescription->sdp;
+        if (type == RTCSdpType::Offer && sdp.isEmpty())
+            sdp = m_lastCreatedOffer;
+        else if (type == RTCSdpType::Answer && sdp.isEmpty())
+            sdp = m_lastCreatedAnswer;
</ins><span class="cx"> 
</span><del>-    ALWAYS_LOG(LOGIDENTIFIER, "Setting local description to:\n", description ? description->sdp() : "''");
-    chainOperation(WTFMove(promise), [this, description = WTFMove(description)](auto&& promise) mutable {
-        m_backend->setLocalDescription(description.get(), [promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
</del><ins>+        RefPtr<RTCSessionDescription> description;
+        if (!sdp.isEmpty() || (type != RTCSdpType::Offer && type != RTCSdpType::Answer))
+            description = RTCSessionDescription::create(type, WTFMove(sdp));
+        m_backend->setLocalDescription(description.get(), [protectedThis = makeRef(*this), promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
+            if (protectedThis->isClosed())
+                return;
</ins><span class="cx">             promise.settle(WTFMove(result));
</span><span class="cx">         });
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RTCPeerConnection::setRemoteDescription(Description&& remoteDescription, Ref<DeferredPromise>&& promise)
</del><ins>+void RTCPeerConnection::setRemoteDescription(RTCSessionDescriptionInit&& remoteDescription, Ref<DeferredPromise>&& promise)
</ins><span class="cx"> {
</span><del>-    RefPtr<RTCSessionDescription> description;
-    description = switchOn(remoteDescription, [](RTCSessionDescriptionInit& init) -> RefPtr<RTCSessionDescription> {
-        return RTCSessionDescription::create(WTFMove(init));
-    }, [](RefPtr<RTCSessionDescription>& description) {
-        return WTFMove(description);
-    });
-    if (!description) {
-        promise->reject(TypeError);
-        return;
-    }
-
</del><span class="cx">     if (isClosed()) {
</span><span class="cx">         promise->reject(InvalidStateError);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ALWAYS_LOG(LOGIDENTIFIER, "Setting remote description to:\n", description->sdp());
-    chainOperation(WTFMove(promise), [this, description = WTFMove(description)](auto&& promise) mutable {
</del><ins>+    ALWAYS_LOG(LOGIDENTIFIER, "Setting remote description to:\n", remoteDescription.sdp);
+    chainOperation(WTFMove(promise), [this, remoteDescription = WTFMove(remoteDescription)](auto&& promise) mutable {
+        auto description = RTCSessionDescription::create(WTFMove(remoteDescription));
</ins><span class="cx">         if (description->type() == RTCSdpType::Offer && m_signalingState != RTCSignalingState::Stable && m_signalingState != RTCSignalingState::HaveRemoteOffer) {
</span><span class="cx">             auto rollbackDescription = RTCSessionDescription::create(RTCSdpType::Rollback, String { emptyString() });
</span><span class="cx">             m_backend->setLocalDescription(rollbackDescription.ptr(), [this, protectedThis = makeRef(*this), description = WTFMove(description), promise = WTFMove(promise)](auto&&) mutable {
</span><span class="cx">                 if (isClosed())
</span><span class="cx">                     return;
</span><del>-                m_backend->setRemoteDescription(*description, [promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
</del><ins>+                m_backend->setRemoteDescription(description.get(), [protectedThis = makeRef(*this), promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
+                    if (protectedThis->isClosed())
+                        return;
</ins><span class="cx">                     promise.settle(WTFMove(result));
</span><span class="cx">                 });
</span><span class="cx">             });
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-        m_backend->setRemoteDescription(*description, [promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
</del><ins>+        m_backend->setRemoteDescription(description.get(), [promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
</ins><span class="cx">             promise.settle(WTFMove(result));
</span><span class="cx">         });
</span><span class="cx">     });
</span><span class="lines">@@ -926,13 +958,18 @@
</span><span class="cx"> 
</span><span class="cx"> void RTCPeerConnection::updateDescriptions(PeerConnectionBackend::DescriptionStates&& states)
</span><span class="cx"> {
</span><del>-    if (states.signalingState)
-        setSignalingState(*states.signalingState);
-
</del><span class="cx">     updateDescription(m_currentLocalDescription, states.currentLocalDescriptionSdpType, WTFMove(states.currentLocalDescriptionSdp));
</span><span class="cx">     updateDescription(m_pendingLocalDescription, states.pendingLocalDescriptionSdpType, WTFMove(states.pendingLocalDescriptionSdp));
</span><span class="cx">     updateDescription(m_currentRemoteDescription, states.currentRemoteDescriptionSdpType, WTFMove(states.currentRemoteDescriptionSdp));
</span><span class="cx">     updateDescription(m_pendingRemoteDescription, states.pendingRemoteDescriptionSdpType, WTFMove(states.pendingRemoteDescriptionSdp));
</span><ins>+
+    if (states.signalingState)
+        setSignalingState(*states.signalingState);
+
+    if (!m_pendingRemoteDescription && !m_pendingLocalDescription) {
+        m_lastCreatedOffer = { };
+        m_lastCreatedAnswer = { };
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RTCPeerConnection::updateTransceiverTransports()
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCPeerConnectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h     2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.h        2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -44,9 +44,11 @@
</span><span class="cx"> #include "RTCDataChannel.h"
</span><span class="cx"> #include "RTCIceConnectionState.h"
</span><span class="cx"> #include "RTCIceGatheringState.h"
</span><ins>+#include "RTCLocalSessionDescriptionInit.h"
</ins><span class="cx"> #include "RTCPeerConnectionState.h"
</span><span class="cx"> #include "RTCRtpEncodingParameters.h"
</span><span class="cx"> #include "RTCRtpTransceiver.h"
</span><ins>+#include "RTCSessionDescriptionInit.h"
</ins><span class="cx"> #include "RTCSignalingState.h"
</span><span class="cx"> #include <JavaScriptCore/Uint8Array.h>
</span><span class="cx"> #include <wtf/LoggerHelper.h>
</span><span class="lines">@@ -110,13 +112,12 @@
</span><span class="cx">     void createOffer(RTCOfferOptions&&, Ref<DeferredPromise>&&);
</span><span class="cx">     void createAnswer(RTCAnswerOptions&&, Ref<DeferredPromise>&&);
</span><span class="cx"> 
</span><del>-    using Description = Variant<RTCSessionDescriptionInit, RefPtr<RTCSessionDescription>>;
-    void setLocalDescription(std::optional<Description>&&, Ref<DeferredPromise>&&);
</del><ins>+    void setLocalDescription(std::optional<RTCLocalSessionDescriptionInit>&&, Ref<DeferredPromise>&&);
</ins><span class="cx">     RefPtr<RTCSessionDescription> localDescription() const { return m_pendingLocalDescription ? m_pendingLocalDescription.get() : m_currentLocalDescription.get(); }
</span><span class="cx">     RefPtr<RTCSessionDescription> currentLocalDescription() const { return m_currentLocalDescription.get(); }
</span><span class="cx">     RefPtr<RTCSessionDescription> pendingLocalDescription() const { return m_pendingLocalDescription.get(); }
</span><span class="cx"> 
</span><del>-    void setRemoteDescription(Description&&, Ref<DeferredPromise>&&);
</del><ins>+    void setRemoteDescription(RTCSessionDescriptionInit&&, Ref<DeferredPromise>&&);
</ins><span class="cx">     RTCSessionDescription* remoteDescription() const { return m_pendingRemoteDescription ? m_pendingRemoteDescription.get() : m_currentRemoteDescription.get(); }
</span><span class="cx">     RTCSessionDescription* currentRemoteDescription() const { return m_currentRemoteDescription.get(); }
</span><span class="cx">     RTCSessionDescription* pendingRemoteDescription() const { return m_pendingRemoteDescription.get(); }
</span><span class="lines">@@ -276,6 +277,9 @@
</span><span class="cx">     RefPtr<RTCSessionDescription> m_pendingLocalDescription;
</span><span class="cx">     RefPtr<RTCSessionDescription> m_currentRemoteDescription;
</span><span class="cx">     RefPtr<RTCSessionDescription> m_pendingRemoteDescription;
</span><ins>+
+    String m_lastCreatedOffer;
+    String m_lastCreatedAnswer;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmediastreamRTCPeerConnectionidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.idl (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.idl   2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/Modules/mediastream/RTCPeerConnection.idl      2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -83,12 +83,12 @@
</span><span class="cx">     Promise<RTCSessionDescriptionInit> createOffer(optional RTCOfferOptions offerOptions);
</span><span class="cx">     Promise<RTCSessionDescriptionInit> createAnswer(optional RTCAnswerOptions answerOptions);
</span><span class="cx"> 
</span><del>-    Promise<undefined> setLocalDescription(optional (RTCSessionDescriptionInit or RTCSessionDescription) description);
</del><ins>+    Promise<undefined> setLocalDescription(optional RTCLocalSessionDescriptionInit description);
</ins><span class="cx">     readonly attribute RTCSessionDescription? localDescription;
</span><span class="cx">     readonly attribute RTCSessionDescription? currentLocalDescription;
</span><span class="cx">     readonly attribute RTCSessionDescription? pendingLocalDescription;
</span><span class="cx"> 
</span><del>-    Promise<undefined> setRemoteDescription((RTCSessionDescriptionInit or RTCSessionDescription) description);
</del><ins>+    Promise<undefined> setRemoteDescription(RTCSessionDescriptionInit description);
</ins><span class="cx">     readonly attribute RTCSessionDescription? remoteDescription;
</span><span class="cx">     readonly attribute RTCSessionDescription? currentRemoteDescription;
</span><span class="cx">     readonly attribute RTCSessionDescription? pendingRemoteDescription;
</span></span></pre></div>
<a id="trunkSourceWebCoreSourcestxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Sources.txt (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Sources.txt 2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/Sources.txt    2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -3354,6 +3354,7 @@
</span><span class="cx"> JSRTCIceTcpCandidateType.cpp
</span><span class="cx"> JSRTCIceTransport.cpp
</span><span class="cx"> JSRTCIceTransportState.cpp
</span><ins>+JSRTCLocalSessionDescriptionInit.cpp
</ins><span class="cx"> JSRTCOfferAnswerOptions.cpp
</span><span class="cx"> JSRTCOfferOptions.cpp
</span><span class="cx"> JSRTCPeerConnection.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (282524 => 282525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj   2021-09-16 10:00:31 UTC (rev 282524)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj      2021-09-16 10:01:25 UTC (rev 282525)
</span><span class="lines">@@ -1063,6 +1063,7 @@
</span><span class="cx">          3FBC4AF4189881560046EE38 /* VideoFullscreenInterfaceAVKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FBC4AF2189881560046EE38 /* VideoFullscreenInterfaceAVKit.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          3FF813A71DBA8640009BF001 /* PointerLockController.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CFC434F192406A900A0D3B5 /* PointerLockController.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          4107908C1FC3F0330061B27A /* ClientOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 4107908A1FC3E4F20061B27A /* ClientOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+               410BCF5626F0CD8C0040B124 /* RTCLocalSessionDescriptionInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 410BCF5326F0CD8B0040B124 /* RTCLocalSessionDescriptionInit.h */; };
</ins><span class="cx">           410E4461234373E9000173D4 /* LibWebRTCSocketIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 410E445F234373AD000173D4 /* LibWebRTCSocketIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          41100C8023F74583001BC33B /* WebSocketChannelInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 41100C7E23F73982001BC33B /* WebSocketChannelInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          41103AAC1E39791000769F03 /* RealtimeOutgoingAudioSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 41103AA81E39790A00769F03 /* RealtimeOutgoingAudioSource.h */; };
</span><span class="lines">@@ -7801,6 +7802,8 @@
</span><span class="cx">          410A8EF924F8F47B004F9070 /* TextEncoderStreamEncoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TextEncoderStreamEncoder.h; sourceTree = "<group>"; };
</span><span class="cx">          410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMessageEventCustom.cpp; sourceTree = "<group>"; };
</span><span class="cx">          410BA1312570FE57002E2F8A /* LibWebRTCRtpTransformableFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCRtpTransformableFrame.cpp; path = libwebrtc/LibWebRTCRtpTransformableFrame.cpp; sourceTree = "<group>"; };
</span><ins>+               410BCF5326F0CD8B0040B124 /* RTCLocalSessionDescriptionInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCLocalSessionDescriptionInit.h; sourceTree = "<group>"; };
+               410BCF5526F0CD8C0040B124 /* RTCLocalSessionDescriptionInit.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCLocalSessionDescriptionInit.idl; sourceTree = "<group>"; };
</ins><span class="cx">           410E445F234373AD000173D4 /* LibWebRTCSocketIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCSocketIdentifier.h; path = libwebrtc/LibWebRTCSocketIdentifier.h; sourceTree = "<group>"; };
</span><span class="cx">          410F565524FCF70500A2E50C /* RTCSessionDescriptionInit.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCSessionDescriptionInit.idl; sourceTree = "<group>"; };
</span><span class="cx">          410F565724FCF7C700A2E50C /* RTCIceCandidateInit.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCIceCandidateInit.idl; sourceTree = "<group>"; };
</span><span class="lines">@@ -17391,6 +17394,8 @@
</span><span class="cx">                          316DCB891E7A6996001B5F87 /* RTCIceTransport.idl */,
</span><span class="cx">                          414516E026CC042100AAABE0 /* RTCIceTransportBackend.h */,
</span><span class="cx">                          316DCB8E1E7A6C79001B5F87 /* RTCIceTransportState.idl */,
</span><ins>+                               410BCF5326F0CD8B0040B124 /* RTCLocalSessionDescriptionInit.h */,
+                               410BCF5526F0CD8C0040B124 /* RTCLocalSessionDescriptionInit.idl */,
</ins><span class="cx">                           41C14BC426DE6DE800685BF5 /* RTCNetworkManager.h */,
</span><span class="cx">                          073794DC19EE2C5200E5A045 /* RTCOfferAnswerOptions.h */,
</span><span class="cx">                          316DCB121E78BE43001B5F87 /* RTCOfferAnswerOptions.idl */,
</span><span class="lines">@@ -33127,6 +33132,7 @@
</span><span class="cx">                          BC6932740D7E293900AE44D1 /* JSDOMWindowBase.h in Headers */,
</span><span class="cx">                          652FBBBC0DE27CB60001D386 /* JSDOMWindowCustom.h in Headers */,
</span><span class="cx">                          460CBF361D4BCD0E0092E88E /* JSDOMWindowProperties.h in Headers */,
</span><ins>+                               410BCF5626F0CD8C0040B124 /* RTCLocalSessionDescriptionInit.h in Headers */,
</ins><span class="cx">                           65E0E9441133C89F00B4CB10 /* JSDOMWrapper.h in Headers */,
</span><span class="cx">                          7C45C9D31E3FCBD700AAB558 /* JSDOMWrapperCache.h in Headers */,
</span><span class="cx">                          93A8061E1E03B585008A1F26 /* JSDoubleRange.h in Headers */,
</span></span></pre>
</div>
</div>

</body>
</html>