[WTF] Clean up StringStatics.cpp by using LazyNeverDestroyed<> for Atoms
[WebKit-https.git] / Source / WebCore / Modules / mediastream / RTCDataChannel.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  * Copyright (C) 2017 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "RTCDataChannel.h"
28
29 #if ENABLE(WEB_RTC)
30
31 #include "Blob.h"
32 #include "Event.h"
33 #include "EventNames.h"
34 #include "ExceptionCode.h"
35 #include "MessageEvent.h"
36 #include "RTCDataChannelHandler.h"
37 #include "ScriptExecutionContext.h"
38 #include <runtime/ArrayBuffer.h>
39 #include <runtime/ArrayBufferView.h>
40 #include <wtf/NeverDestroyed.h>
41
42 namespace WebCore {
43
44 static const AtomicString& blobKeyword()
45 {
46     static NeverDestroyed<AtomicString> blob("blob", AtomicString::ConstructFromLiteral);
47     return blob;
48 }
49
50 static const AtomicString& arraybufferKeyword()
51 {
52     static NeverDestroyed<AtomicString> arraybuffer("arraybuffer", AtomicString::ConstructFromLiteral);
53     return arraybuffer;
54 }
55
56 Ref<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext& context, std::unique_ptr<RTCDataChannelHandler>&& handler, String&& label, RTCDataChannelInit&& options)
57 {
58     ASSERT(handler);
59     auto channel = adoptRef(*new RTCDataChannel(context, WTFMove(handler), WTFMove(label), WTFMove(options)));
60     channel->suspendIfNeeded();
61     channel->m_handler->setClient(channel.get());
62     channel->setPendingActivity(channel.ptr());
63     return channel;
64 }
65
66 RTCDataChannel::RTCDataChannel(ScriptExecutionContext& context, std::unique_ptr<RTCDataChannelHandler>&& handler, String&& label, RTCDataChannelInit&& options)
67     : ActiveDOMObject(&context)
68     , m_handler(WTFMove(handler))
69     , m_scheduledEventTimer(*this, &RTCDataChannel::scheduledEventTimerFired)
70     , m_label(WTFMove(label))
71     , m_options(WTFMove(options))
72 {
73 }
74
75 size_t RTCDataChannel::bufferedAmount() const
76 {
77     // FIXME: We should compute our own bufferedAmount and not count on m_handler which is made null at closing time.
78     if (m_stopped)
79         return 0;
80     return m_handler->bufferedAmount();
81 }
82
83 const AtomicString& RTCDataChannel::binaryType() const
84 {
85     switch (m_binaryType) {
86     case BinaryType::Blob:
87         return blobKeyword();
88     case BinaryType::ArrayBuffer:
89         return arraybufferKeyword();
90     }
91
92     ASSERT_NOT_REACHED();
93     return emptyAtom();
94 }
95
96 ExceptionOr<void> RTCDataChannel::setBinaryType(const AtomicString& binaryType)
97 {
98     if (binaryType == blobKeyword())
99         return Exception { NOT_SUPPORTED_ERR };
100     if (binaryType == arraybufferKeyword()) {
101         m_binaryType = BinaryType::ArrayBuffer;
102         return { };
103     }
104     return Exception { TYPE_MISMATCH_ERR };
105 }
106
107 ExceptionOr<void> RTCDataChannel::send(const String& data)
108 {
109     // FIXME: We should only throw in Connected state.
110     if (m_readyState != RTCDataChannelState::Open)
111         return Exception { INVALID_STATE_ERR };
112
113     if (!m_handler->sendStringData(data)) {
114         // FIXME: Decide what the right exception here is.
115         return Exception { SYNTAX_ERR };
116     }
117
118     return { };
119 }
120
121 ExceptionOr<void> RTCDataChannel::send(ArrayBuffer& data)
122 {
123     // FIXME: We should only throw in Connected state.
124     if (m_readyState != RTCDataChannelState::Open)
125         return Exception { INVALID_STATE_ERR };
126
127     size_t dataLength = data.byteLength();
128     if (!dataLength)
129         return { };
130
131     const char* dataPointer = static_cast<const char*>(data.data());
132
133     if (!m_handler->sendRawData(dataPointer, dataLength)) {
134         // FIXME: Decide what the right exception here is.
135         return Exception { SYNTAX_ERR };
136     }
137
138     return { };
139 }
140
141 ExceptionOr<void> RTCDataChannel::send(ArrayBufferView& data)
142 {
143     // FIXME: We should only throw in Connected state.
144     return send(*data.unsharedBuffer());
145 }
146
147 ExceptionOr<void> RTCDataChannel::send(Blob&)
148 {
149     // FIXME: Implement.
150     return Exception { NOT_SUPPORTED_ERR };
151 }
152
153 void RTCDataChannel::close()
154 {
155     if (m_stopped)
156         return;
157
158     m_stopped = true;
159     m_readyState = RTCDataChannelState::Closed;
160
161     m_handler->close();
162     m_handler = nullptr;
163     unsetPendingActivity(this);
164 }
165
166 void RTCDataChannel::didChangeReadyState(RTCDataChannelState newState)
167 {
168     if (m_stopped || m_readyState == RTCDataChannelState::Closed || m_readyState == newState)
169         return;
170
171     m_readyState = newState;
172
173     switch (m_readyState) {
174     case RTCDataChannelState::Open:
175         scheduleDispatchEvent(Event::create(eventNames().openEvent, false, false));
176         break;
177     case RTCDataChannelState::Closed:
178         scheduleDispatchEvent(Event::create(eventNames().closeEvent, false, false));
179         break;
180     default:
181         break;
182     }
183 }
184
185 void RTCDataChannel::didReceiveStringData(const String& text)
186 {
187     if (m_stopped)
188         return;
189
190     scheduleDispatchEvent(MessageEvent::create(text));
191 }
192
193 void RTCDataChannel::didReceiveRawData(const char* data, size_t dataLength)
194 {
195     if (m_stopped)
196         return;
197
198     if (m_binaryType == BinaryType::Blob) {
199         // FIXME: Implement.
200         return;
201     }
202
203     if (m_binaryType == BinaryType::ArrayBuffer) {
204         scheduleDispatchEvent(MessageEvent::create(ArrayBuffer::create(data, dataLength)));
205         return;
206     }
207     ASSERT_NOT_REACHED();
208 }
209
210 void RTCDataChannel::didDetectError()
211 {
212     if (m_stopped)
213         return;
214
215     scheduleDispatchEvent(Event::create(eventNames().errorEvent, false, false));
216 }
217
218 void RTCDataChannel::bufferedAmountIsDecreasing(size_t amount)
219 {
220     if (m_stopped)
221         return;
222
223     if (amount <= m_bufferedAmountLowThreshold)
224         scheduleDispatchEvent(Event::create(eventNames().bufferedamountlowEvent, false, false));
225 }
226
227 void RTCDataChannel::stop()
228 {
229     close();
230 }
231
232 void RTCDataChannel::scheduleDispatchEvent(Ref<Event>&& event)
233 {
234     m_scheduledEvents.append(WTFMove(event));
235
236     if (!m_scheduledEventTimer.isActive())
237         m_scheduledEventTimer.startOneShot(0_s);
238 }
239
240 void RTCDataChannel::scheduledEventTimerFired()
241 {
242     if (m_stopped)
243         return;
244
245     Vector<Ref<Event>> events;
246     events.swap(m_scheduledEvents);
247
248     for (auto& event : events)
249         dispatchEvent(event);
250 }
251
252 } // namespace WebCore
253
254 #endif // ENABLE(WEB_RTC)