Make some things that return never-null pointers return references instead.
[WebKit-https.git] / Source / WebCore / Modules / mediastream / RTCDataChannel.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #if ENABLE(MEDIA_STREAM)
28
29 #include "RTCDataChannel.h"
30
31 #include "Blob.h"
32 #include "Event.h"
33 #include "ExceptionCode.h"
34 #include "MessageEvent.h"
35 #include "RTCDataChannelHandler.h"
36 #include "RTCPeerConnectionHandler.h"
37 #include "ScriptExecutionContext.h"
38 #include <runtime/ArrayBuffer.h>
39 #include <runtime/ArrayBufferView.h>
40
41 namespace WebCore {
42
43 PassRefPtr<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext* context, RTCPeerConnectionHandler* peerConnectionHandler, const String& label, bool reliable, ExceptionCode& ec)
44 {
45     OwnPtr<RTCDataChannelHandler> handler = peerConnectionHandler->createDataChannel(label, reliable);
46     if (!handler) {
47         ec = NOT_SUPPORTED_ERR;
48         return 0;
49     }
50     return adoptRef(new RTCDataChannel(context, handler.release()));
51 }
52
53 PassRefPtr<RTCDataChannel> RTCDataChannel::create(ScriptExecutionContext* context, PassOwnPtr<RTCDataChannelHandler> handler)
54 {
55     ASSERT(handler);
56     return adoptRef(new RTCDataChannel(context, handler));
57 }
58
59 RTCDataChannel::RTCDataChannel(ScriptExecutionContext* context, PassOwnPtr<RTCDataChannelHandler> handler)
60     : m_scriptExecutionContext(context)
61     , m_handler(handler)
62     , m_stopped(false)
63     , m_readyState(ReadyStateConnecting)
64     , m_binaryType(BinaryTypeArrayBuffer)
65     , m_scheduledEventTimer(this, &RTCDataChannel::scheduledEventTimerFired)
66 {
67     m_handler->setClient(this);
68 }
69
70 RTCDataChannel::~RTCDataChannel()
71 {
72 }
73
74 String RTCDataChannel::label() const
75 {
76     return m_handler->label();
77 }
78
79 bool RTCDataChannel::reliable() const
80 {
81     return m_handler->isReliable();
82 }
83
84 String RTCDataChannel::readyState() const
85 {
86     switch (m_readyState) {
87     case ReadyStateConnecting:
88         return ASCIILiteral("connecting");
89     case ReadyStateOpen:
90         return ASCIILiteral("open");
91     case ReadyStateClosing:
92         return ASCIILiteral("closing");
93     case ReadyStateClosed:
94         return ASCIILiteral("closed");
95     }
96
97     ASSERT_NOT_REACHED();
98     return String();
99 }
100
101 unsigned long RTCDataChannel::bufferedAmount() const
102 {
103     return m_handler->bufferedAmount();
104 }
105
106 String RTCDataChannel::binaryType() const
107 {
108     switch (m_binaryType) {
109     case BinaryTypeBlob:
110         return ASCIILiteral("blob");
111     case BinaryTypeArrayBuffer:
112         return ASCIILiteral("arraybuffer");
113     }
114     ASSERT_NOT_REACHED();
115     return String();
116 }
117
118 void RTCDataChannel::setBinaryType(const String& binaryType, ExceptionCode& ec)
119 {
120     if (binaryType == "blob")
121         ec = NOT_SUPPORTED_ERR;
122     else if (binaryType == "arraybuffer")
123         m_binaryType = BinaryTypeArrayBuffer;
124     else
125         ec = TYPE_MISMATCH_ERR;
126 }
127
128 void RTCDataChannel::send(const String& data, ExceptionCode& ec)
129 {
130     if (m_readyState != ReadyStateOpen) {
131         ec = INVALID_STATE_ERR;
132         return;
133     }
134     if (!m_handler->sendStringData(data)) {
135         // FIXME: Decide what the right exception here is.
136         ec = SYNTAX_ERR;
137     }
138 }
139
140 void RTCDataChannel::send(PassRefPtr<ArrayBuffer> prpData, ExceptionCode& ec)
141 {
142     if (m_readyState != ReadyStateOpen) {
143         ec = INVALID_STATE_ERR;
144         return;
145     }
146
147     RefPtr<ArrayBuffer> data = prpData;
148
149     size_t dataLength = data->byteLength();
150     if (!dataLength)
151         return;
152
153     const char* dataPointer = static_cast<const char*>(data->data());
154
155     if (!m_handler->sendRawData(dataPointer, dataLength)) {
156         // FIXME: Decide what the right exception here is.
157         ec = SYNTAX_ERR;
158     }
159 }
160
161 void RTCDataChannel::send(PassRefPtr<ArrayBufferView> data, ExceptionCode& ec)
162 {
163     RefPtr<ArrayBuffer> arrayBuffer(data->buffer());
164     send(arrayBuffer.release(), ec);
165 }
166
167 void RTCDataChannel::send(PassRefPtr<Blob> data, ExceptionCode& ec)
168 {
169     // FIXME: implement
170     ec = NOT_SUPPORTED_ERR;
171 }
172
173 void RTCDataChannel::close()
174 {
175     if (m_stopped)
176         return;
177
178     m_handler->close();
179 }
180
181 void RTCDataChannel::didChangeReadyState(ReadyState newState)
182 {
183     if (m_stopped || m_readyState == ReadyStateClosed)
184         return;
185
186     m_readyState = newState;
187
188     switch (m_readyState) {
189     case ReadyStateOpen:
190         scheduleDispatchEvent(Event::create(eventNames().openEvent, false, false));
191         break;
192     case ReadyStateClosed:
193         scheduleDispatchEvent(Event::create(eventNames().closeEvent, false, false));
194         break;
195     default:
196         break;
197     }
198 }
199
200 void RTCDataChannel::didReceiveStringData(const String& text)
201 {
202     if (m_stopped)
203         return;
204
205     scheduleDispatchEvent(MessageEvent::create(text));
206 }
207
208 void RTCDataChannel::didReceiveRawData(const char* data, size_t dataLength)
209 {
210     if (m_stopped)
211         return;
212
213     if (m_binaryType == BinaryTypeBlob) {
214         // FIXME: Implement.
215         return;
216     }
217     if (m_binaryType == BinaryTypeArrayBuffer) {
218         RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(data, dataLength);
219         scheduleDispatchEvent(MessageEvent::create(buffer.release()));
220         return;
221     }
222     ASSERT_NOT_REACHED();
223 }
224
225 void RTCDataChannel::didDetectError()
226 {
227     if (m_stopped)
228         return;
229
230     scheduleDispatchEvent(Event::create(eventNames().errorEvent, false, false));
231 }
232
233 const AtomicString& RTCDataChannel::interfaceName() const
234 {
235     return eventNames().interfaceForRTCDataChannel;
236 }
237
238 ScriptExecutionContext* RTCDataChannel::scriptExecutionContext() const
239 {
240     return m_scriptExecutionContext;
241 }
242
243 void RTCDataChannel::stop()
244 {
245     m_stopped = true;
246     m_readyState = ReadyStateClosed;
247     m_handler->setClient(0);
248     m_scriptExecutionContext = 0;
249 }
250
251 EventTargetData* RTCDataChannel::eventTargetData()
252 {
253     return &m_eventTargetData;
254 }
255
256 EventTargetData& RTCDataChannel::ensureEventTargetData()
257 {
258     return m_eventTargetData;
259 }
260
261 void RTCDataChannel::scheduleDispatchEvent(PassRefPtr<Event> event)
262 {
263     m_scheduledEvents.append(event);
264
265     if (!m_scheduledEventTimer.isActive())
266         m_scheduledEventTimer.startOneShot(0);
267 }
268
269 void RTCDataChannel::scheduledEventTimerFired(Timer<RTCDataChannel>*)
270 {
271     if (m_stopped)
272         return;
273
274     Vector<RefPtr<Event> > events;
275     events.swap(m_scheduledEvents);
276
277     Vector<RefPtr<Event> >::iterator it = events.begin();
278     for (; it != events.end(); ++it)
279         dispatchEvent((*it).release());
280
281     events.clear();
282 }
283
284 } // namespace WebCore
285
286 #endif // ENABLE(MEDIA_STREAM)