Skip to content

Commit e83716d

Browse files
committed
RTCDataChannel close event does not fire if RTCPeerConnection closes
rdar://165617848 https://bugs.webkit.org/show_bug.cgi?id=303052 Reviewed by Jean-Yves Avenard. Since closing the peer connection backend is severing the state updates of the data channel backend, we add the logic to close the data channel from RTCPeerConnection::close. For that reason, we keep a list of channel identifiers in RTCPeerConnection. We then call RTCDataChannelHandlerClient::peerConnectionIsClosing for each of this identifier. This will do the following: - If the data channel lives in main thread, it will call RTCDataChannel::peerConnectionIsClosing() directly. - If the data channel lives in another process, it will call RTCDataChannel::peerConnectionIsClosing() directly. - If the data channel lives in a worker, it will call RTCDataChannel::peerConnectionIsClosing() after hopping to the service worker thread. - If the data channel is being transferred, it will call RTCDataChannel::peerConnectionIsClosing() which will make the newly transferred data channel moving to closed state. Covered by added test. Canonical link: https://commits.webkit.org/304859@main
1 parent 898e897 commit e83716d

File tree

14 files changed

+334
-29
lines changed

14 files changed

+334
-29
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
PASS Close peerconnection causes close event on local channel
3+
PASS Close peerconnection causes close event on transfered channel
4+
PASS Close peerconnection causes close event on local being transfered channel
5+
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<!doctype html>
2+
<meta charset=utf-8>
3+
<meta name="timeout" content="long">
4+
<title>RTCDataChannel.prototype.close</title>
5+
<script src="/resources/testharness.js"></script>
6+
<script src="/resources/testharnessreport.js"></script>
7+
<script src="RTCPeerConnection-helper.js"></script>
8+
<script>
9+
'use strict';
10+
11+
promise_test(async t => {
12+
const pc1 = new RTCPeerConnection();
13+
t.add_cleanup(() => pc1.close());
14+
const [channel1, channel2] = await createDataChannelPairWithLabel(t, 'local_close', [], pc1);
15+
16+
const haveClosed1 = new Promise((resolve, reject) => {
17+
channel1.addEventListener('close', () => {
18+
assert_true(isClosed);
19+
resolve();
20+
});
21+
t.step_timeout(() => reject('test1 timed out'), 2000);
22+
});
23+
const haveClosed2 = new Promise((resolve, reject) => {
24+
channel2.addEventListener('close', resolve);
25+
t.step_timeout(() => reject('test2 timed out'), 2000);
26+
});
27+
28+
let isClosed = false;
29+
let isClosing1 = false;
30+
let isClosing2 = false;
31+
channel1.onclosing = () => {
32+
isClosing1 = true;
33+
assert_true(isClosed, "isClosed for channel1.onclosing");
34+
}
35+
channel2.onclosing = () => {
36+
isClosing2 = true;
37+
assert_true(isClosed, "isClosed for channel2.onclosing");
38+
}
39+
40+
pc1.close();
41+
isClosed = true;
42+
await haveClosed1;
43+
await haveClosed2;
44+
45+
assert_false(isClosing1, "isClosing1");
46+
assert_true(isClosing2, "isClosing2");
47+
}, `Close peerconnection causes close event on local channel`);
48+
49+
promise_test(async t => {
50+
const pc1 = new RTCPeerConnection();
51+
t.add_cleanup(() => pc1.close());
52+
const channel1 = pc1.createDataChannel("test");
53+
54+
const worker = new Worker(`data:text/javascript,onmessage = e => { e.data.onclose = () => postMessage('CLOSED'); postMessage("OK"); };`);
55+
56+
worker.postMessage(channel1, [channel1]);
57+
const transferResult = await new Promise(resolve => worker.addEventListener('message', e => resolve(e.data)));
58+
assert_equals(transferResult, "OK");
59+
60+
const haveClosed1 = new Promise((resolve, reject) => {
61+
worker.addEventListener('message', e => resolve(e.data));
62+
t.step_timeout(() => reject("test timed out"), 1000);
63+
});
64+
65+
pc1.close();
66+
assert_equals(await haveClosed1, "CLOSED");
67+
}, `Close peerconnection causes close event on transfered channel`);
68+
69+
promise_test(async t => {
70+
const pc1 = new RTCPeerConnection();
71+
t.add_cleanup(() => pc1.close());
72+
const channel1 = pc1.createDataChannel("test");
73+
74+
const worker = new Worker(`data:text/javascript,onmessage = e => { if (e.data.readyState === 'closed') postMessage('CLOSED'); e.data.onclose = () => postMessage('CLOSED'); };`);
75+
const haveClosed1 = new Promise((resolve, reject) => {
76+
worker.onmessage = e => resolve(e.data);
77+
t.step_timeout(() => reject("test timed out"), 1000);
78+
});
79+
80+
worker.postMessage(channel1, [channel1]);
81+
pc1.close();
82+
assert_equals(await haveClosed1, "CLOSED");
83+
}, `Close peerconnection causes close event on local being transfered channel`);
84+
85+
</script>

Source/WebCore/Modules/mediastream/RTCDataChannel.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,9 @@ namespace WebCore {
5353
WTF_MAKE_TZONE_ALLOCATED_IMPL(DetachedRTCDataChannel);
5454
WTF_MAKE_TZONE_ALLOCATED_IMPL(RTCDataChannel);
5555

56-
Ref<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext& context, std::unique_ptr<RTCDataChannelHandler>&& handler, String&& label, RTCDataChannelInit&& options, RTCDataChannelState state)
56+
Ref<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext& context, std::unique_ptr<RTCDataChannelHandler>&& handler, String&& label, RTCDataChannelInit&& options, RTCDataChannelState state, std::optional<RTCDataChannelIdentifier> identifier)
5757
{
58-
ASSERT(handler);
59-
Ref channel = adoptRef(*new RTCDataChannel(context, WTF::move(handler), WTF::move(label), WTF::move(options), state));
58+
Ref channel = adoptRef(*new RTCDataChannel(context, identifier.value_or(RTCDataChannelIdentifier::generate()), WTF::move(handler), WTF::move(label), WTF::move(options), state));
6059
channel->suspendIfNeeded();
6160
queueTaskKeepingObjectAlive(channel.get(), TaskSource::Networking, [](auto& channel) {
6261
if (!channel.m_isDetachable)
@@ -87,10 +86,10 @@ Ref<NetworkSendQueue> RTCDataChannel::createMessageQueue(ScriptExecutionContext&
8786
});
8887
}
8988

90-
RTCDataChannel::RTCDataChannel(ScriptExecutionContext& context, std::unique_ptr<RTCDataChannelHandler>&& handler, String&& label, RTCDataChannelInit&& options, RTCDataChannelState readyState)
89+
RTCDataChannel::RTCDataChannel(ScriptExecutionContext& context, RTCDataChannelIdentifier identifier, std::unique_ptr<RTCDataChannelHandler>&& handler, String&& label, RTCDataChannelInit&& options, RTCDataChannelState readyState)
9190
: ActiveDOMObject(&context)
91+
, RTCDataChannelHandlerClient(context.identifier(), identifier)
9292
, m_handler(WTF::move(handler))
93-
, m_identifier(RTCDataChannelIdentifier::generate())
9493
, m_contextIdentifier(context.isDocument() ? std::nullopt : std::optional { context.identifier() })
9594
, m_readyState(readyState)
9695
, m_label(WTF::move(label))
@@ -284,6 +283,8 @@ std::unique_ptr<DetachedRTCDataChannel> RTCDataChannel::detach()
284283
m_isDetached = true;
285284
m_readyState = RTCDataChannelState::Closed;
286285

286+
willDetach();
287+
287288
Locker locker { s_rtcDataChannelLocalMapLock };
288289
rtcDataChannelLocalMap().add(identifier().object(), WTF::move(m_handler));
289290

@@ -321,18 +322,21 @@ Ref<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext& context, RTCD
321322
{
322323
CheckedPtr<RTCDataChannelRemoteHandler> remoteHandlerPtr;
323324
std::unique_ptr<RTCDataChannelHandler> handler;
324-
if (identifier.processIdentifier() == Process::identifier())
325+
std::optional<RTCDataChannelIdentifier> localIdentifier;
326+
if (identifier.processIdentifier() == Process::identifier()) {
325327
handler = RTCDataChannel::handlerFromIdentifier(identifier.object());
326-
else {
328+
localIdentifier = identifier;
329+
} else {
327330
auto remoteHandler = RTCDataChannelRemoteHandler::create(identifier, context.createRTCDataChannelRemoteHandlerConnection());
328331
remoteHandlerPtr = remoteHandler.get();
329332
handler = WTF::move(remoteHandler);
333+
localIdentifier = RTCDataChannelIdentifier::generate();
330334
}
331335

332336
if (!handler)
333337
return createClosedChannel(context, WTF::move(label), WTF::move(options));
334338

335-
auto channel = RTCDataChannel::create(context, WTF::move(handler), WTF::move(label), WTF::move(options), state);
339+
auto channel = RTCDataChannel::create(context, WTF::move(handler), WTF::move(label), WTF::move(options), state, *localIdentifier);
336340

337341
if (remoteHandlerPtr)
338342
remoteHandlerPtr->setLocalIdentifier(channel->identifier());

Source/WebCore/Modules/mediastream/RTCDataChannel.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ template<typename> class ExceptionOr;
5454
class RTCDataChannel final : public RefCounted<RTCDataChannel>, public ActiveDOMObject, public RTCDataChannelHandlerClient, public EventTarget {
5555
WTF_MAKE_TZONE_ALLOCATED(RTCDataChannel);
5656
public:
57-
static Ref<RTCDataChannel> create(ScriptExecutionContext&, std::unique_ptr<RTCDataChannelHandler>&&, String&&, RTCDataChannelInit&&, RTCDataChannelState);
57+
static Ref<RTCDataChannel> create(ScriptExecutionContext&, std::unique_ptr<RTCDataChannelHandler>&&, String&&, RTCDataChannelInit&&, RTCDataChannelState, std::optional<RTCDataChannelIdentifier> identifier = { });
5858
static Ref<RTCDataChannel> create(ScriptExecutionContext&, RTCDataChannelIdentifier, String&&, RTCDataChannelInit&&, RTCDataChannelState);
5959
WEBCORE_EXPORT virtual ~RTCDataChannel();
6060

@@ -89,15 +89,15 @@ class RTCDataChannel final : public RefCounted<RTCDataChannel>, public ActiveDOM
8989

9090
void close();
9191

92-
RTCDataChannelIdentifier identifier() const { return m_identifier; }
9392
bool canDetach() const;
9493
std::unique_ptr<DetachedRTCDataChannel> detach();
9594

95+
static void removeDetachedRTCDataChannel(RTCDataChannelIdentifier identifer) { handlerFromIdentifier(identifer.object()); }
9696
WEBCORE_EXPORT static std::unique_ptr<RTCDataChannelHandler> handlerFromIdentifier(RTCDataChannelLocalIdentifier);
9797
void fireOpenEventIfNeeded();
9898

9999
private:
100-
RTCDataChannel(ScriptExecutionContext&, std::unique_ptr<RTCDataChannelHandler>&&, String&&, RTCDataChannelInit&&, RTCDataChannelState);
100+
RTCDataChannel(ScriptExecutionContext&, RTCDataChannelIdentifier, std::unique_ptr<RTCDataChannelHandler>&&, String&&, RTCDataChannelInit&&, RTCDataChannelState);
101101

102102
static Ref<NetworkSendQueue> createMessageQueue(ScriptExecutionContext&, RTCDataChannel&);
103103

@@ -121,9 +121,9 @@ class RTCDataChannel final : public RefCounted<RTCDataChannel>, public ActiveDOM
121121
void didReceiveRawData(std::span<const uint8_t>) final;
122122
void didDetectError(Ref<RTCError>&&) final;
123123
void bufferedAmountIsDecreasing(size_t) final;
124+
void peerConnectionIsClosing() final { didChangeReadyState(RTCDataChannelState::Closed); }
124125

125126
std::unique_ptr<RTCDataChannelHandler> m_handler;
126-
RTCDataChannelIdentifier m_identifier;
127127
Markable<ScriptExecutionContextIdentifier> m_contextIdentifier;
128128
// FIXME: m_stopped is probably redundant with m_readyState.
129129
bool m_stopped { false };

Source/WebCore/Modules/mediastream/RTCDataChannelRemoteSource.cpp

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,78 @@ namespace WebCore {
3636

3737
WTF_MAKE_TZONE_ALLOCATED_IMPL(RTCDataChannelRemoteSource);
3838

39-
Ref<RTCDataChannelRemoteSource> RTCDataChannelRemoteSource::create(RTCDataChannelIdentifier identifier, UniqueRef<RTCDataChannelHandler>&& handler, Ref<RTCDataChannelRemoteSourceConnection>&& connection)
39+
Ref<RTCDataChannelRemoteSource> RTCDataChannelRemoteSource::create(RTCDataChannelIdentifier localIdentifier, RTCDataChannelIdentifier remoteIdentifier, UniqueRef<RTCDataChannelHandler>&& handler, Ref<RTCDataChannelRemoteSourceConnection>&& connection)
4040
{
41-
return adoptRef(*new RTCDataChannelRemoteSource(identifier, WTF::move(handler), WTF::move(connection)));
41+
return adoptRef(*new RTCDataChannelRemoteSource(localIdentifier, remoteIdentifier, WTF::move(handler), WTF::move(connection)));
4242
}
4343

44-
RTCDataChannelRemoteSource::RTCDataChannelRemoteSource(RTCDataChannelIdentifier identifier, UniqueRef<RTCDataChannelHandler>&& handler, Ref<RTCDataChannelRemoteSourceConnection>&& connection)
45-
: m_identifier(identifier)
44+
RTCDataChannelRemoteSource::RTCDataChannelRemoteSource(RTCDataChannelIdentifier localIdentifier, RTCDataChannelIdentifier remoteIdentifier, UniqueRef<RTCDataChannelHandler>&& handler, Ref<RTCDataChannelRemoteSourceConnection>&& connection)
45+
: RTCDataChannelHandlerClient(std::nullopt, localIdentifier)
46+
, m_remoteIdentifier(remoteIdentifier)
4647
, m_handler(WTF::move(handler))
4748
, m_connection(WTF::move(connection))
4849
{
50+
ASSERT(isMainThread());
4951
// FIXME: We should ask m_handler to call us on its own background thread.
5052
m_handler->setClient(*this, std::nullopt);
5153
}
5254

5355
RTCDataChannelRemoteSource::~RTCDataChannelRemoteSource() = default;
5456

57+
void RTCDataChannelRemoteSource::didChangeReadyState(RTCDataChannelState state)
58+
{
59+
ASSERT(isMainThread());
60+
if (m_isClosed)
61+
return;
62+
if (state == RTCDataChannelState::Closed)
63+
m_isClosed = true;
64+
m_connection->didChangeReadyState(m_remoteIdentifier, state);
65+
}
66+
67+
void RTCDataChannelRemoteSource::didReceiveStringData(const String& text)
68+
{
69+
ASSERT(isMainThread());
70+
if (m_isClosed)
71+
return;
72+
m_connection->didReceiveStringData(m_remoteIdentifier, text);
73+
}
74+
75+
void RTCDataChannelRemoteSource::didReceiveRawData(std::span<const uint8_t> data)
76+
{
77+
ASSERT(isMainThread());
78+
if (m_isClosed)
79+
return;
80+
m_connection->didReceiveRawData(m_remoteIdentifier, data);
81+
}
82+
83+
void RTCDataChannelRemoteSource::didDetectError(Ref<RTCError>&& error)
84+
{
85+
ASSERT(isMainThread());
86+
if (m_isClosed)
87+
return;
88+
m_connection->didDetectError(m_remoteIdentifier, error->errorDetail(), error->message());
89+
}
90+
91+
void RTCDataChannelRemoteSource::bufferedAmountIsDecreasing(size_t amount)
92+
{
93+
ASSERT(isMainThread());
94+
if (m_isClosed)
95+
return;
96+
m_connection->bufferedAmountIsDecreasing(m_remoteIdentifier, amount);
97+
}
98+
99+
size_t RTCDataChannelRemoteSource::bufferedAmount() const
100+
{
101+
ASSERT(isMainThread());
102+
return 0;
103+
}
104+
105+
void RTCDataChannelRemoteSource::peerConnectionIsClosing()
106+
{
107+
ASSERT(isMainThread());
108+
didChangeReadyState(RTCDataChannelState::Closed);
109+
}
110+
55111
} // namespace WebCore
56112

57113
#endif // ENABLE(WEB_RTC)

Source/WebCore/Modules/mediastream/RTCDataChannelRemoteSource.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace WebCore {
4040
class RTCDataChannelRemoteSource : public RTCDataChannelHandlerClient, public RefCounted<RTCDataChannelRemoteSource> {
4141
WTF_MAKE_TZONE_ALLOCATED_EXPORT(RTCDataChannelRemoteSource, WEBCORE_EXPORT);
4242
public:
43-
WEBCORE_EXPORT static Ref<RTCDataChannelRemoteSource> create(RTCDataChannelIdentifier, UniqueRef<RTCDataChannelHandler>&&, Ref<RTCDataChannelRemoteSourceConnection>&&);
43+
WEBCORE_EXPORT static Ref<RTCDataChannelRemoteSource> create(RTCDataChannelIdentifier localIdentifier, RTCDataChannelIdentifier remoteIdentifier, UniqueRef<RTCDataChannelHandler>&&, Ref<RTCDataChannelRemoteSourceConnection>&&);
4444
~RTCDataChannelRemoteSource();
4545

4646
void ref() const final { RefCounted::ref(); }
@@ -51,17 +51,19 @@ class RTCDataChannelRemoteSource : public RTCDataChannelHandlerClient, public Re
5151
void close() { m_handler->close(); }
5252

5353
private:
54-
WEBCORE_EXPORT RTCDataChannelRemoteSource(RTCDataChannelIdentifier, UniqueRef<RTCDataChannelHandler>&&, Ref<RTCDataChannelRemoteSourceConnection>&&);
54+
WEBCORE_EXPORT RTCDataChannelRemoteSource(RTCDataChannelIdentifier localIdentifier, RTCDataChannelIdentifier remoteIdentifier, UniqueRef<RTCDataChannelHandler>&&, Ref<RTCDataChannelRemoteSourceConnection>&&);
5555

5656
// RTCDataChannelHandlerClient
57-
void didChangeReadyState(RTCDataChannelState state) final { m_connection->didChangeReadyState(m_identifier, state); }
58-
void didReceiveStringData(const String& text) final { m_connection->didReceiveStringData(m_identifier, text); }
59-
void didReceiveRawData(std::span<const uint8_t> data) final { m_connection->didReceiveRawData(m_identifier, data); }
60-
void didDetectError(Ref<RTCError>&& error) final { m_connection->didDetectError(m_identifier, error->errorDetail(), error->message()); }
61-
void bufferedAmountIsDecreasing(size_t amount) final { m_connection->bufferedAmountIsDecreasing(m_identifier, amount); }
62-
size_t bufferedAmount() const final { return 0; }
57+
void didChangeReadyState(RTCDataChannelState) final;
58+
void didReceiveStringData(const String&) final;
59+
void didReceiveRawData(std::span<const uint8_t>) final;
60+
void didDetectError(Ref<RTCError>&&) final;
61+
void bufferedAmountIsDecreasing(size_t) final;
62+
size_t bufferedAmount() const final;
63+
void peerConnectionIsClosing() final;
6364

64-
RTCDataChannelIdentifier m_identifier;
65+
const RTCDataChannelIdentifier m_remoteIdentifier;
66+
bool m_isClosed { false };
6567
const UniqueRef<RTCDataChannelHandler> m_handler;
6668
const Ref<RTCDataChannelRemoteSourceConnection> m_connection;
6769
};

Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,10 @@ ExceptionOr<Ref<RTCDataChannel>> RTCPeerConnection::createDataChannel(String&& l
689689
if (!channelHandler)
690690
return Exception { ExceptionCode::OperationError };
691691

692-
return RTCDataChannel::create(*document(), WTF::move(channelHandler), WTF::move(label), WTF::move(options), RTCDataChannelState::Connecting);
692+
Ref channel = RTCDataChannel::create(*document(), WTF::move(channelHandler), WTF::move(label), WTF::move(options), RTCDataChannelState::Connecting);
693+
694+
m_channels.append(channel->identifier());
695+
return channel;
693696
}
694697

695698
bool RTCPeerConnection::doClose()
@@ -714,6 +717,9 @@ bool RTCPeerConnection::doClose()
714717
}
715718
m_operations.clear();
716719

720+
for (auto identifier : std::exchange(m_channels, { }))
721+
RTCDataChannelHandlerClient::peerConnectionIsClosing(identifier);
722+
717723
for (auto& transport : m_dtlsTransports)
718724
transport->close();
719725

@@ -1004,6 +1010,7 @@ void RTCPeerConnection::dispatchDataChannelEvent(UniqueRef<RTCDataChannelHandler
10041010
return;
10051011

10061012
Ref channel = RTCDataChannel::create(*connection.document(), channelHandler.moveToUniquePtr(), WTF::move(label), WTF::move(channelInit), RTCDataChannelState::Open);
1013+
connection.m_channels.append(channel->identifier());
10071014
ALWAYS_LOG_WITH_THIS(&connection, LOGIDENTIFIER_WITH_THIS(&connection), makeString("Dispatching data-channel event for channel "_s, channel->label()));
10081015
connection.dispatchEvent(RTCDataChannelEvent::create(eventNames().datachannelEvent, Event::CanBubble::No, Event::IsCancelable::No, Ref { channel }));
10091016
channel->fireOpenEventIfNeeded();

Source/WebCore/Modules/mediastream/RTCPeerConnection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ class RTCPeerConnection final
283283
RTCConfiguration m_configuration;
284284
WeakPtr<RTCController> m_controller;
285285
Vector<RefPtr<RTCCertificate>> m_certificates;
286+
Vector<RTCDataChannelIdentifier> m_channels;
286287
bool m_shouldDelayTasks { false };
287288
Deque<std::pair<Ref<DeferredPromise>, Function<void(Ref<DeferredPromise>&&)>>> m_operations;
288289
bool m_hasPendingOperation { false };

Source/WebCore/Sources.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,6 +2717,7 @@ platform/mediastream/MediaEndpointConfiguration.cpp
27172717
platform/mediastream/MediaStreamPrivate.cpp
27182718
platform/mediastream/MediaStreamTrackDataHolder.cpp
27192719
platform/mediastream/MediaStreamTrackPrivate.cpp
2720+
platform/mediastream/RTCDataChannelHandlerClient.cpp
27202721
platform/mediastream/RTCIceCandidateDescriptor.cpp
27212722
platform/mediastream/RTCSessionDescriptionDescriptor.cpp
27222723
platform/mediastream/RealtimeIncomingAudioSource.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10474,6 +10474,7 @@
1047410474
410B3939292F70D50003E515 /* InternalReadableStream.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InternalReadableStream.cpp; sourceTree = "<group>"; };
1047510475
410B393A292F70D60003E515 /* InternalReadableStream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InternalReadableStream.h; sourceTree = "<group>"; };
1047610476
410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMessageEventCustom.cpp; sourceTree = "<group>"; };
10477+
410B7ECE2EF06B19001217C2 /* RTCDataChannelHandlerClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RTCDataChannelHandlerClient.cpp; sourceTree = "<group>"; };
1047710478
410BA1312570FE57002E2F8A /* LibWebRTCRtpTransformableFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCRtpTransformableFrame.cpp; path = libwebrtc/LibWebRTCRtpTransformableFrame.cpp; sourceTree = "<group>"; };
1047810479
410BCF5326F0CD8B0040B124 /* RTCLocalSessionDescriptionInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCLocalSessionDescriptionInit.h; sourceTree = "<group>"; };
1047910480
410BCF5526F0CD8C0040B124 /* RTCLocalSessionDescriptionInit.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCLocalSessionDescriptionInit.idl; sourceTree = "<group>"; };
@@ -23381,6 +23382,7 @@
2338123382
073930D92AC644A000C1D1B1 /* RedEyeReduction.h */,
2338223383
3135910C1E7DDCB600F30630 /* RTCBundlePolicy.h */,
2338323384
07221BA217CF0AD400848E51 /* RTCDataChannelHandler.h */,
23385+
410B7ECE2EF06B19001217C2 /* RTCDataChannelHandlerClient.cpp */,
2338423386
07221BA317CF0AD400848E51 /* RTCDataChannelHandlerClient.h */,
2338523387
416EDBFF2600E78700092675 /* RTCDataChannelIdentifier.h */,
2338623388
861FC9E02992A1F500DFDF6D /* RTCDataChannelLocalIdentifier.h */,

0 commit comments

Comments
 (0)