Fri, 16 Jan 2015 04:50:19 +0100
Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef NSDOMMEDIASTREAM_H_
7 #define NSDOMMEDIASTREAM_H_
9 #include "nsIDOMMediaStream.h"
10 #include "nsCycleCollectionParticipant.h"
11 #include "nsWrapperCache.h"
12 #include "StreamBuffer.h"
13 #include "nsIDOMWindow.h"
15 class nsXPCClassInfo;
16 class nsIPrincipal;
18 // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
19 // GetTickCount() and conflicts with NS_DECL_NSIDOMMEDIASTREAM, containing
20 // currentTime getter.
21 #ifdef GetCurrentTime
22 #undef GetCurrentTime
23 #endif
24 // X11 has a #define for CurrentTime. Unbelievable :-(.
25 // See content/media/webaudio/AudioContext.h for more fun!
26 #ifdef CurrentTime
27 #undef CurrentTime
28 #endif
30 namespace mozilla {
32 class MediaStream;
34 namespace dom {
35 class AudioNode;
36 class MediaStreamTrack;
37 class AudioStreamTrack;
38 class VideoStreamTrack;
39 }
41 class MediaStreamDirectListener;
43 /**
44 * DOM wrapper for MediaStreams.
45 */
46 class DOMMediaStream : public nsIDOMMediaStream,
47 public nsWrapperCache
48 {
49 friend class DOMLocalMediaStream;
50 typedef dom::MediaStreamTrack MediaStreamTrack;
51 typedef dom::AudioStreamTrack AudioStreamTrack;
52 typedef dom::VideoStreamTrack VideoStreamTrack;
54 public:
55 typedef uint8_t TrackTypeHints;
57 DOMMediaStream();
58 virtual ~DOMMediaStream();
60 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMMediaStream)
61 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
63 nsIDOMWindow* GetParentObject() const
64 {
65 return mWindow;
66 }
67 virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
69 // WebIDL
70 double CurrentTime();
72 void GetAudioTracks(nsTArray<nsRefPtr<AudioStreamTrack> >& aTracks);
73 void GetVideoTracks(nsTArray<nsRefPtr<VideoStreamTrack> >& aTracks);
75 MediaStream* GetStream() const { return mStream; }
77 /**
78 * Overridden in DOMLocalMediaStreams to allow getUserMedia to pass
79 * data directly to RTCPeerConnection without going through graph queuing.
80 * Returns a bool to let us know if direct data will be delivered.
81 */
82 virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; }
83 virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {}
85 /**
86 * Overridden in DOMLocalMediaStreams to allow getUserMedia to disable
87 * media at the SourceMediaStream.
88 */
89 virtual void SetTrackEnabled(TrackID aTrackID, bool aEnabled);
91 bool IsFinished();
92 /**
93 * Returns a principal indicating who may access this stream. The stream contents
94 * can only be accessed by principals subsuming this principal.
95 */
96 nsIPrincipal* GetPrincipal() { return mPrincipal; }
98 /**
99 * Indicate that data will be contributed to this stream from origin aPrincipal.
100 * If aPrincipal is null, this is ignored. Otherwise, from now on the contents
101 * of this stream can only be accessed by principals that subsume aPrincipal.
102 * Returns true if the stream's principal changed.
103 */
104 bool CombineWithPrincipal(nsIPrincipal* aPrincipal);
106 /**
107 * Called when this stream's MediaStreamGraph has been shut down. Normally
108 * MSGs are only shut down when all streams have been removed, so this
109 * will only be called during a forced shutdown due to application exit.
110 */
111 void NotifyMediaStreamGraphShutdown();
112 /**
113 * Called when the main-thread state of the MediaStream changed.
114 */
115 void NotifyStreamStateChanged();
117 // Indicate what track types we eventually expect to add to this stream
118 enum {
119 HINT_CONTENTS_AUDIO = 1 << 0,
120 HINT_CONTENTS_VIDEO = 1 << 1
121 };
122 TrackTypeHints GetHintContents() const { return mHintContents; }
123 void SetHintContents(TrackTypeHints aHintContents) { mHintContents = aHintContents; }
125 /**
126 * Create an nsDOMMediaStream whose underlying stream is a SourceMediaStream.
127 */
128 static already_AddRefed<DOMMediaStream>
129 CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
131 /**
132 * Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream.
133 */
134 static already_AddRefed<DOMMediaStream>
135 CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
137 void SetLogicalStreamStartTime(StreamTime aTime)
138 {
139 mLogicalStreamStartTime = aTime;
140 }
142 // Notifications from StreamListener.
143 // CreateDOMTrack should only be called when it's safe to run script.
144 MediaStreamTrack* CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType);
145 MediaStreamTrack* GetDOMTrackFor(TrackID aTrackID);
147 class OnTracksAvailableCallback {
148 public:
149 OnTracksAvailableCallback(uint8_t aExpectedTracks = 0)
150 : mExpectedTracks(aExpectedTracks) {}
151 virtual ~OnTracksAvailableCallback() {}
152 virtual void NotifyTracksAvailable(DOMMediaStream* aStream) = 0;
153 TrackTypeHints GetExpectedTracks() { return mExpectedTracks; }
154 void SetExpectedTracks(TrackTypeHints aExpectedTracks) { mExpectedTracks = aExpectedTracks; }
155 private:
156 TrackTypeHints mExpectedTracks;
157 };
158 // When one track of the appropriate type has been added for each bit set
159 // in aCallback->GetExpectedTracks(), run aCallback->NotifyTracksAvailable.
160 // It is allowed to do anything, including run script.
161 // aCallback may run immediately during this call if tracks are already
162 // available!
163 // We only care about track additions, we'll fire the notification even if
164 // some of the tracks have been removed.
165 // Takes ownership of aCallback.
166 // If GetExpectedTracks() returns 0, the callback will be fired as soon as there are any tracks.
167 void OnTracksAvailable(OnTracksAvailableCallback* aCallback);
169 /**
170 * Add an nsISupports object that this stream will keep alive as long as
171 * the stream is not finished.
172 */
173 void AddConsumerToKeepAlive(nsISupports* aConsumer)
174 {
175 if (!IsFinished() && !mNotifiedOfMediaStreamGraphShutdown) {
176 mConsumersToKeepAlive.AppendElement(aConsumer);
177 }
178 }
180 protected:
181 void Destroy();
182 void InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
183 void InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
184 void InitStreamCommon(MediaStream* aStream);
186 void CheckTracksAvailable();
188 class StreamListener;
189 friend class StreamListener;
191 // StreamTime at which the currentTime attribute would return 0.
192 StreamTime mLogicalStreamStartTime;
194 // We need this to track our parent object.
195 nsCOMPtr<nsIDOMWindow> mWindow;
197 // MediaStream is owned by the graph, but we tell it when to die, and it won't
198 // die until we let it.
199 MediaStream* mStream;
200 // Principal identifying who may access the contents of this stream.
201 // If null, this stream can be used by anyone because it has no content yet.
202 nsCOMPtr<nsIPrincipal> mPrincipal;
204 nsAutoTArray<nsRefPtr<MediaStreamTrack>,2> mTracks;
205 nsRefPtr<StreamListener> mListener;
207 nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable;
209 // Keep these alive until the stream finishes
210 nsTArray<nsCOMPtr<nsISupports> > mConsumersToKeepAlive;
212 // Indicate what track types we eventually expect to add to this stream
213 uint8_t mHintContents;
214 // Indicate what track types have been added to this stream
215 uint8_t mTrackTypesAvailable;
216 bool mNotifiedOfMediaStreamGraphShutdown;
217 };
219 class DOMLocalMediaStream : public DOMMediaStream,
220 public nsIDOMLocalMediaStream
221 {
222 public:
223 DOMLocalMediaStream() {}
224 virtual ~DOMLocalMediaStream();
226 NS_DECL_ISUPPORTS_INHERITED
228 virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
230 virtual void Stop();
232 /**
233 * Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
234 */
235 static already_AddRefed<DOMLocalMediaStream>
236 CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
238 /**
239 * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
240 */
241 static already_AddRefed<DOMLocalMediaStream>
242 CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
243 };
245 class DOMAudioNodeMediaStream : public DOMMediaStream
246 {
247 typedef dom::AudioNode AudioNode;
248 public:
249 DOMAudioNodeMediaStream(AudioNode* aNode);
251 NS_DECL_ISUPPORTS_INHERITED
252 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
254 /**
255 * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream.
256 */
257 static already_AddRefed<DOMAudioNodeMediaStream>
258 CreateTrackUnionStream(nsIDOMWindow* aWindow,
259 AudioNode* aNode,
260 TrackTypeHints aHintContents = 0);
262 private:
263 // If this object wraps a stream owned by an AudioNode, we need to ensure that
264 // the node isn't cycle-collected too early.
265 nsRefPtr<AudioNode> mStreamNode;
266 };
268 }
270 #endif /* NSDOMMEDIASTREAM_H_ */