Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / Modules / mediastream / MediaStream.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  * Copyright (C) 2011, 2012, 2015 Ericsson AB. All rights reserved.
4  * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
5  * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "MediaStream.h"
30
31 #if ENABLE(MEDIA_STREAM)
32
33 #include "Document.h"
34 #include "Event.h"
35 #include "ExceptionCode.h"
36 #include "MediaStreamRegistry.h"
37 #include "MediaStreamTrackEvent.h"
38 #include "RealtimeMediaSource.h"
39 #include "URL.h"
40 #include <wtf/NeverDestroyed.h>
41
42 namespace WebCore {
43
44 Ref<MediaStream> MediaStream::create(ScriptExecutionContext& context)
45 {
46     return MediaStream::create(context, MediaStreamPrivate::create(Vector<RefPtr<MediaStreamTrackPrivate>>()));
47 }
48
49 Ref<MediaStream> MediaStream::create(ScriptExecutionContext& context, MediaStream* stream)
50 {
51     ASSERT(stream);
52
53     return adoptRef(*new MediaStream(context, stream->getTracks()));
54 }
55
56 Ref<MediaStream> MediaStream::create(ScriptExecutionContext& context, const MediaStreamTrackVector& tracks)
57 {
58     return adoptRef(*new MediaStream(context, tracks));
59 }
60
61 Ref<MediaStream> MediaStream::create(ScriptExecutionContext& context, RefPtr<MediaStreamPrivate>&& streamPrivate)
62 {
63     return adoptRef(*new MediaStream(context, WTFMove(streamPrivate)));
64 }
65
66 MediaStream::MediaStream(ScriptExecutionContext& context, const MediaStreamTrackVector& tracks)
67     : ContextDestructionObserver(&context)
68     , m_activityEventTimer(*this, &MediaStream::activityEventTimerFired)
69 {
70     // This constructor preserves MediaStreamTrack instances and must be used by calls originating
71     // from the JavaScript MediaStream constructor.
72     MediaStreamTrackPrivateVector trackPrivates;
73     trackPrivates.reserveCapacity(tracks.size());
74
75     for (auto& track : tracks) {
76         track->addObserver(this);
77         m_trackSet.add(track->id(), track);
78         trackPrivates.append(&track->privateTrack());
79     }
80
81     m_private = MediaStreamPrivate::create(trackPrivates);
82     setIsActive(m_private->active());
83     m_private->addObserver(*this);
84     MediaStreamRegistry::shared().registerStream(*this);
85 }
86
87 MediaStream::MediaStream(ScriptExecutionContext& context, RefPtr<MediaStreamPrivate>&& streamPrivate)
88     : ContextDestructionObserver(&context)
89     , m_private(streamPrivate)
90     , m_activityEventTimer(*this, &MediaStream::activityEventTimerFired)
91 {
92     ASSERT(m_private);
93     setIsActive(m_private->active());
94     m_private->addObserver(*this);
95     MediaStreamRegistry::shared().registerStream(*this);
96
97     for (auto& trackPrivate : m_private->tracks()) {
98         RefPtr<MediaStreamTrack> track = MediaStreamTrack::create(context, *trackPrivate);
99         track->addObserver(this);
100         m_trackSet.add(track->id(), WTFMove(track));
101     }
102 }
103
104 MediaStream::~MediaStream()
105 {
106     MediaStreamRegistry::shared().unregisterStream(*this);
107     m_private->removeObserver(*this);
108     for (auto& track : m_trackSet.values())
109         track->removeObserver(this);
110 }
111
112 RefPtr<MediaStream> MediaStream::clone()
113 {
114     MediaStreamTrackVector clonedTracks;
115     clonedTracks.reserveCapacity(m_trackSet.size());
116
117     for (auto& track : m_trackSet.values())
118         clonedTracks.append(track->clone());
119
120     return MediaStream::create(*scriptExecutionContext(), clonedTracks);
121 }
122
123 void MediaStream::addTrack(RefPtr<MediaStreamTrack>&& track)
124 {
125     if (!internalAddTrack(WTFMove(track), StreamModifier::DomAPI))
126         return;
127
128     for (auto& observer : m_observers)
129         observer->didAddOrRemoveTrack();
130 }
131
132 void MediaStream::removeTrack(MediaStreamTrack* track)
133 {
134     if (!internalRemoveTrack(track, StreamModifier::DomAPI))
135         return;
136
137     for (auto& observer : m_observers)
138         observer->didAddOrRemoveTrack();
139 }
140
141 MediaStreamTrack* MediaStream::getTrackById(String id)
142 {
143     auto it = m_trackSet.find(id);
144     if (it != m_trackSet.end())
145         return it->value.get();
146
147     return nullptr;
148 }
149
150 MediaStreamTrackVector MediaStream::getAudioTracks() const
151 {
152     return trackVectorForType(RealtimeMediaSource::Audio);
153 }
154
155 MediaStreamTrackVector MediaStream::getVideoTracks() const
156 {
157     return trackVectorForType(RealtimeMediaSource::Video);
158 }
159
160 MediaStreamTrackVector MediaStream::getTracks() const
161 {
162     MediaStreamTrackVector tracks;
163     tracks.reserveCapacity(m_trackSet.size());
164     copyValuesToVector(m_trackSet, tracks);
165
166     return tracks;
167 }
168
169 void MediaStream::contextDestroyed()
170 {
171     ContextDestructionObserver::contextDestroyed();
172 }
173
174 void MediaStream::trackDidEnd()
175 {
176     m_private->updateActiveState(MediaStreamPrivate::NotifyClientOption::Notify);
177 }
178
179 void MediaStream::activeStatusChanged()
180 {
181     // Schedule the active state change and event dispatch since this callback may be called
182     // synchronously from the DOM API (e.g. as a result of addTrack()).
183     scheduleActiveStateChange();
184 }
185
186 void MediaStream::didAddTrack(MediaStreamTrackPrivate& trackPrivate)
187 {
188     ScriptExecutionContext* context = scriptExecutionContext();
189     if (!context)
190         return;
191
192     if (!getTrackById(trackPrivate.id()))
193         internalAddTrack(MediaStreamTrack::create(*context, trackPrivate), StreamModifier::Platform);
194 }
195
196 void MediaStream::didRemoveTrack(MediaStreamTrackPrivate& trackPrivate)
197 {
198     RefPtr<MediaStreamTrack> track = getTrackById(trackPrivate.id());
199     ASSERT(track);
200     internalRemoveTrack(WTFMove(track), StreamModifier::Platform);
201 }
202
203 bool MediaStream::internalAddTrack(RefPtr<MediaStreamTrack>&& track, StreamModifier streamModifier)
204 {
205     if (getTrackById(track->id()))
206         return false;
207
208     m_trackSet.add(track->id(), track);
209     track->addObserver(this);
210
211     if (streamModifier == StreamModifier::DomAPI)
212         m_private->addTrack(&track->privateTrack(), MediaStreamPrivate::NotifyClientOption::DontNotify);
213     else
214         dispatchEvent(MediaStreamTrackEvent::create(eventNames().addtrackEvent, false, false, WTFMove(track)));
215
216     return true;
217 }
218
219 bool MediaStream::internalRemoveTrack(RefPtr<MediaStreamTrack>&& track, StreamModifier streamModifier)
220 {
221     if (!m_trackSet.remove(track->id()))
222         return false;
223
224     track->removeObserver(this);
225
226     if (streamModifier == StreamModifier::DomAPI)
227         m_private->removeTrack(track->privateTrack(), MediaStreamPrivate::NotifyClientOption::DontNotify);
228     else
229         dispatchEvent(MediaStreamTrackEvent::create(eventNames().removetrackEvent, false, false, WTFMove(track)));
230
231     return true;
232 }
233
234 void MediaStream::setIsActive(bool active)
235 {
236     m_isActive = active;
237     if (!active)
238         return;
239
240     if (Document* document = downcast<Document>(scriptExecutionContext()))
241         document->setHasActiveMediaStreamTrack();
242 }
243
244 void MediaStream::scheduleActiveStateChange()
245 {
246     bool active = false;
247     for (auto& track : m_trackSet.values()) {
248         if (!track->ended()) {
249             active = true;
250             break;
251         }
252     }
253
254     if (m_isActive == active)
255         return;
256
257     setIsActive(active);
258
259     const AtomicString& eventName = m_isActive ? eventNames().inactiveEvent : eventNames().activeEvent;
260     m_scheduledActivityEvents.append(Event::create(eventName, false, false));
261
262     if (!m_activityEventTimer.isActive())
263         m_activityEventTimer.startOneShot(0);
264 }
265
266 void MediaStream::activityEventTimerFired()
267 {
268     Vector<Ref<Event>> events;
269     events.swap(m_scheduledActivityEvents);
270
271     for (auto& event : events)
272         dispatchEvent(event);
273 }
274
275 URLRegistry& MediaStream::registry() const
276 {
277     return MediaStreamRegistry::shared();
278 }
279
280 MediaStreamTrackVector MediaStream::trackVectorForType(RealtimeMediaSource::Type filterType) const
281 {
282     MediaStreamTrackVector tracks;
283     for (auto& track : m_trackSet.values()) {
284         if (track->source().type() == filterType)
285             tracks.append(track);
286     }
287
288     return tracks;
289 }
290
291 void MediaStream::addObserver(MediaStream::Observer* observer)
292 {
293     if (m_observers.find(observer) == notFound)
294         m_observers.append(observer);
295 }
296
297 void MediaStream::removeObserver(MediaStream::Observer* observer)
298 {
299     size_t pos = m_observers.find(observer);
300     if (pos != notFound)
301         m_observers.remove(pos);
302 }
303
304 } // namespace WebCore
305
306 #endif // ENABLE(MEDIA_STREAM)