Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "RtspControllerChild.h"
8 #include "RtspMetaData.h"
9 #include "mozilla/dom/TabChild.h"
10 #include "mozilla/net/NeckoChild.h"
11 #include "nsITabChild.h"
12 #include "nsILoadContext.h"
13 #include "nsNetUtil.h"
14 #include "mozilla/ipc/InputStreamUtils.h"
15 #include "mozilla/ipc/URIUtils.h"
16 #include "nsStringStream.h"
17 #include "prlog.h"
19 PRLogModuleInfo* gRtspChildLog = nullptr;
20 #undef LOG
21 #define LOG(args) PR_LOG(gRtspChildLog, PR_LOG_DEBUG, args)
23 const uint32_t kRtspTotalTracks = 2;
24 using namespace mozilla::ipc;
26 namespace mozilla {
27 namespace net {
29 NS_IMPL_ADDREF(RtspControllerChild)
31 NS_IMETHODIMP_(nsrefcnt) RtspControllerChild::Release()
32 {
33 NS_PRECONDITION(0 != mRefCnt, "dup release");
34 // Enable this to find non-threadsafe destructors:
35 // NS_ASSERT_OWNINGTHREAD(RtspControllerChild);
36 --mRefCnt;
37 NS_LOG_RELEASE(this, mRefCnt, "RtspControllerChild");
39 if (mRefCnt == 1 && mIPCOpen) {
40 Send__delete__(this);
41 return mRefCnt;
42 }
44 if (mRefCnt == 0) {
45 mRefCnt = 1; /* stabilize */
46 delete this;
47 return 0;
48 }
49 return mRefCnt;
50 }
52 NS_INTERFACE_MAP_BEGIN(RtspControllerChild)
53 NS_INTERFACE_MAP_ENTRY(nsIStreamingProtocolController)
54 NS_INTERFACE_MAP_ENTRY(nsIStreamingProtocolListener)
55 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamingProtocolController)
56 NS_INTERFACE_MAP_END
58 //-----------------------------------------------------------------------------
59 // RtspControllerChild methods
60 //-----------------------------------------------------------------------------
61 RtspControllerChild::RtspControllerChild(nsIChannel *channel)
62 : mIPCOpen(false)
63 , mIPCAllowed(false)
64 , mChannel(channel)
65 , mTotalTracks(0)
66 , mSuspendCount(0)
67 {
68 #if defined(PR_LOGGING)
69 if (!gRtspChildLog)
70 gRtspChildLog = PR_NewLogModule("nsRtspChild");
71 #endif
72 AddIPDLReference();
73 gNeckoChild->SendPRtspControllerConstructor(this);
74 }
76 RtspControllerChild::~RtspControllerChild()
77 {
78 LOG(("RtspControllerChild::~RtspControllerChild()"));
79 }
81 void
82 RtspControllerChild::ReleaseChannel()
83 {
84 static_cast<RtspChannelChild*>(mChannel.get())->ReleaseController();
85 }
87 bool
88 RtspControllerChild::OKToSendIPC()
89 {
90 MOZ_ASSERT(NS_IsMainThread());
91 if (mIPCOpen == false) {
92 return false;
93 }
94 return mIPCAllowed;
95 }
97 void
98 RtspControllerChild::AllowIPC()
99 {
100 MOZ_ASSERT(NS_IsMainThread());
101 mIPCAllowed = true;
102 }
104 void
105 RtspControllerChild::DisallowIPC()
106 {
107 MOZ_ASSERT(NS_IsMainThread());
108 mIPCAllowed = false;
109 }
111 //-----------------------------------------------------------------------------
112 // RtspControllerChild::PRtspControllerChild
113 //-----------------------------------------------------------------------------
114 bool
115 RtspControllerChild::RecvOnMediaDataAvailable(
116 const uint8_t& index,
117 const nsCString& data,
118 const uint32_t& length,
119 const uint32_t& offset,
120 const InfallibleTArray<RtspMetadataParam>& metaArray)
121 {
122 nsRefPtr<RtspMetaData> meta = new RtspMetaData();
123 nsresult rv = meta->DeserializeRtspMetaData(metaArray);
124 NS_ENSURE_SUCCESS(rv, true);
126 if (mListener) {
127 mListener->OnMediaDataAvailable(index, data, length, offset, meta.get());
128 }
129 return true;
130 }
132 void
133 RtspControllerChild::AddMetaData(
134 already_AddRefed<nsIStreamingProtocolMetaData>&& meta)
135 {
136 nsCOMPtr<nsIStreamingProtocolMetaData> data = meta;
137 mMetaArray.AppendElement(data);
138 }
140 int
141 RtspControllerChild::GetMetaDataLength()
142 {
143 return mMetaArray.Length();
144 }
146 bool
147 RtspControllerChild::RecvOnConnected(
148 const uint8_t& index,
149 const InfallibleTArray<RtspMetadataParam>& metaArray)
150 {
151 // Deserialize meta data.
152 nsRefPtr<RtspMetaData> meta = new RtspMetaData();
153 nsresult rv = meta->DeserializeRtspMetaData(metaArray);
154 NS_ENSURE_SUCCESS(rv, true);
155 meta->GetTotalTracks(&mTotalTracks);
156 if (mTotalTracks <= 0) {
157 LOG(("RtspControllerChild::RecvOnConnected invalid tracks %d", mTotalTracks));
158 // Set the default value.
159 mTotalTracks = kRtspTotalTracks;
160 }
161 AddMetaData(meta.forget().downcast<nsIStreamingProtocolMetaData>());
163 // Notify the listener when meta data of tracks are available.
164 if ((static_cast<uint32_t>(index) + 1) == mTotalTracks) {
165 // The controller provide |GetTrackMetaData| method for his client.
166 if (mListener) {
167 mListener->OnConnected(index, nullptr);
168 }
169 }
170 return true;
171 }
173 bool
174 RtspControllerChild::RecvOnDisconnected(
175 const uint8_t& index,
176 const nsresult& reason)
177 {
178 DisallowIPC();
179 LOG(("RtspControllerChild::RecvOnDisconnected for track %d reason = 0x%x", index, reason));
180 if (mListener) {
181 mListener->OnDisconnected(index, reason);
182 }
183 ReleaseChannel();
184 return true;
185 }
187 bool
188 RtspControllerChild::RecvAsyncOpenFailed(const nsresult& reason)
189 {
190 DisallowIPC();
191 LOG(("RtspControllerChild::RecvAsyncOpenFailed reason = 0x%x", reason));
192 if (mListener) {
193 mListener->OnDisconnected(0, NS_ERROR_CONNECTION_REFUSED);
194 }
195 ReleaseChannel();
196 return true;
197 }
199 void
200 RtspControllerChild::AddIPDLReference()
201 {
202 NS_ABORT_IF_FALSE(!mIPCOpen,
203 "Attempt to retain more than one IPDL reference");
204 mIPCOpen = true;
205 AllowIPC();
206 AddRef();
207 }
209 void
210 RtspControllerChild::ReleaseIPDLReference()
211 {
212 NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference");
213 mIPCOpen = false;
214 DisallowIPC();
215 Release();
216 }
218 NS_IMETHODIMP
219 RtspControllerChild::GetTrackMetaData(
220 uint8_t index,
221 nsIStreamingProtocolMetaData **result)
222 {
223 if (GetMetaDataLength() <= 0 || index >= GetMetaDataLength()) {
224 LOG(("RtspControllerChild:: meta data is not available"));
225 return NS_ERROR_NOT_INITIALIZED;
226 }
227 LOG(("RtspControllerChild::GetTrackMetaData() %d", index));
228 NS_IF_ADDREF(*result = mMetaArray[index]);
229 return NS_OK;
230 }
232 enum IPCEvent
233 {
234 SendNoneEvent = 0,
235 SendPlayEvent,
236 SendPauseEvent,
237 SendSeekEvent,
238 SendResumeEvent,
239 SendSuspendEvent,
240 SendStopEvent
241 };
243 class SendIPCEvent : public nsRunnable
244 {
245 public:
246 SendIPCEvent(RtspControllerChild *aController, IPCEvent aEvent)
247 : mController(aController)
248 , mEvent(aEvent)
249 , mSeekTime(0)
250 {
251 }
253 SendIPCEvent(RtspControllerChild *aController,
254 IPCEvent aEvent,
255 uint64_t aSeekTime)
256 : mController(aController)
257 , mEvent(aEvent)
258 , mSeekTime(aSeekTime)
259 {
260 }
262 NS_IMETHOD Run()
263 {
264 MOZ_ASSERT(NS_IsMainThread());
265 if (mController->OKToSendIPC() == false) {
266 // Don't send any more IPC events; no guarantee that parent objects are
267 // still alive.
268 return NS_ERROR_FAILURE;
269 }
270 bool rv = true;
272 if (mEvent == SendPlayEvent) {
273 rv = mController->SendPlay();
274 } else if (mEvent == SendPauseEvent) {
275 rv = mController->SendPause();
276 } else if (mEvent == SendSeekEvent) {
277 rv = mController->SendSeek(mSeekTime);
278 } else if (mEvent == SendResumeEvent) {
279 rv = mController->SendResume();
280 } else if (mEvent == SendSuspendEvent) {
281 rv = mController->SendSuspend();
282 } else if (mEvent == SendStopEvent) {
283 rv = mController->SendStop();
284 } else {
285 LOG(("RtspControllerChild::SendIPCEvent"));
286 }
287 if (!rv) {
288 return NS_ERROR_FAILURE;
289 }
290 return NS_OK;
291 }
292 private:
293 nsRefPtr<RtspControllerChild> mController;
294 IPCEvent mEvent;
295 uint64_t mSeekTime;
296 };
298 //-----------------------------------------------------------------------------
299 // RtspControllerChild::nsIStreamingProtocolController
300 //-----------------------------------------------------------------------------
301 NS_IMETHODIMP
302 RtspControllerChild::Play(void)
303 {
304 LOG(("RtspControllerChild::Play()"));
306 if (NS_IsMainThread()) {
307 if (!OKToSendIPC() || !SendPlay()) {
308 return NS_ERROR_FAILURE;
309 }
310 } else {
311 nsresult rv = NS_DispatchToMainThread(
312 new SendIPCEvent(this, SendPlayEvent));
313 NS_ENSURE_SUCCESS(rv, rv);
314 }
316 return NS_OK;
317 }
319 NS_IMETHODIMP
320 RtspControllerChild::Pause(void)
321 {
322 LOG(("RtspControllerChild::Pause()"));
324 if (NS_IsMainThread()) {
325 if (!OKToSendIPC() || !SendPause()) {
326 return NS_ERROR_FAILURE;
327 }
328 } else {
329 nsresult rv = NS_DispatchToMainThread(
330 new SendIPCEvent(this, SendPauseEvent));
331 NS_ENSURE_SUCCESS(rv, rv);
332 }
334 return NS_OK;
335 }
337 NS_IMETHODIMP
338 RtspControllerChild::Resume(void)
339 {
340 LOG(("RtspControllerChild::Resume()"));
341 NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
343 if (!--mSuspendCount) {
344 if (NS_IsMainThread()) {
345 if (!OKToSendIPC() || !SendResume()) {
346 return NS_ERROR_FAILURE;
347 }
348 } else {
349 nsresult rv = NS_DispatchToMainThread(
350 new SendIPCEvent(this, SendResumeEvent));
351 NS_ENSURE_SUCCESS(rv, rv);
352 }
353 }
355 return NS_OK;
356 }
358 NS_IMETHODIMP
359 RtspControllerChild::Suspend(void)
360 {
361 LOG(("RtspControllerChild::Suspend()"));
363 if (!mSuspendCount++) {
364 if (NS_IsMainThread()) {
365 if (!OKToSendIPC() || !SendSuspend()) {
366 return NS_ERROR_FAILURE;
367 }
368 } else {
369 nsresult rv = NS_DispatchToMainThread(
370 new SendIPCEvent(this, SendSuspendEvent));
371 NS_ENSURE_SUCCESS(rv, rv);
372 }
373 }
375 return NS_OK;
376 }
378 NS_IMETHODIMP
379 RtspControllerChild::Seek(uint64_t seekTimeUs)
380 {
381 LOG(("RtspControllerChild::Seek() %llu", seekTimeUs));
383 if (NS_IsMainThread()) {
384 if (!OKToSendIPC() || !SendSeek(seekTimeUs)) {
385 return NS_ERROR_FAILURE;
386 }
387 } else {
388 nsresult rv = NS_DispatchToMainThread(
389 new SendIPCEvent(this, SendSeekEvent, seekTimeUs));
390 NS_ENSURE_SUCCESS(rv, rv);
391 }
393 return NS_OK;
394 }
396 NS_IMETHODIMP
397 RtspControllerChild::Stop()
398 {
399 LOG(("RtspControllerChild::Stop()"));
401 if (NS_IsMainThread()) {
402 if (!OKToSendIPC() || !SendStop()) {
403 return NS_ERROR_FAILURE;
404 }
405 DisallowIPC();
406 } else {
407 nsresult rv = NS_DispatchToMainThread(
408 new SendIPCEvent(this, SendStopEvent));
409 NS_ENSURE_SUCCESS(rv, rv);
410 }
412 return NS_OK;
413 }
415 NS_IMETHODIMP
416 RtspControllerChild::GetTotalTracks(uint8_t *aTracks)
417 {
418 NS_ENSURE_ARG_POINTER(aTracks);
419 *aTracks = kRtspTotalTracks;
420 if (mTotalTracks) {
421 *aTracks = mTotalTracks;
422 }
423 LOG(("RtspControllerChild::GetTracks() %d", *aTracks));
424 return NS_OK;
425 }
427 //-----------------------------------------------------------------------------
428 // RtspControllerChild::nsIStreamingProtocolListener
429 //-----------------------------------------------------------------------------
430 NS_IMETHODIMP
431 RtspControllerChild::OnMediaDataAvailable(uint8_t index,
432 const nsACString & data,
433 uint32_t length,
434 uint32_t offset,
435 nsIStreamingProtocolMetaData *meta)
436 {
437 LOG(("RtspControllerChild::OnMediaDataAvailable()"));
438 return NS_ERROR_NOT_IMPLEMENTED;
439 }
441 NS_IMETHODIMP
442 RtspControllerChild::OnConnected(uint8_t index,
443 nsIStreamingProtocolMetaData *meta)
445 {
446 LOG(("RtspControllerChild::OnConnected()"));
447 return NS_ERROR_NOT_IMPLEMENTED;
448 }
450 NS_IMETHODIMP
451 RtspControllerChild::OnDisconnected(uint8_t index,
452 nsresult reason)
453 {
454 LOG(("RtspControllerChild::OnDisconnected() reason = 0x%x", reason));
455 return NS_ERROR_NOT_IMPLEMENTED;
456 }
458 //-----------------------------------------------------------------------------
459 // RtspControllerChild::nsIStreamingProtocoController
460 //-----------------------------------------------------------------------------
461 NS_IMETHODIMP
462 RtspControllerChild::Init(nsIURI *aURI)
463 {
464 nsresult rv;
466 if (!aURI) {
467 LOG(("RtspControllerChild::Init() - invalid URI"));
468 return NS_ERROR_NOT_INITIALIZED;
469 }
471 nsAutoCString host;
472 int32_t port = -1;
474 rv = aURI->GetAsciiHost(host);
475 if (NS_FAILED(rv)) return rv;
477 // Reject the URL if it doesn't specify a host
478 if (host.IsEmpty())
479 return NS_ERROR_MALFORMED_URI;
481 rv = aURI->GetPort(&port);
482 if (NS_FAILED(rv)) return rv;
484 rv = aURI->GetAsciiSpec(mSpec);
485 if (NS_FAILED(rv)) return rv;
487 if (!strncmp(mSpec.get(), "rtsp:", 5) == 0)
488 return NS_ERROR_UNEXPECTED;
490 mURI = aURI;
492 return NS_OK;
493 }
495 NS_IMETHODIMP
496 RtspControllerChild::AsyncOpen(nsIStreamingProtocolListener *aListener)
497 {
498 LOG(("RtspControllerChild::AsyncOpen()"));
499 if (!aListener) {
500 LOG(("RtspControllerChild::AsyncOpen() - invalid listener"));
501 return NS_ERROR_NOT_INITIALIZED;
502 }
503 mListener = aListener;
505 if (!mChannel) {
506 LOG(("RtspControllerChild::AsyncOpen() - invalid URI"));
507 return NS_ERROR_NOT_INITIALIZED;
508 }
510 nsCOMPtr<nsIURI> uri;
511 URIParams uriParams;
512 mChannel->GetURI(getter_AddRefs(uri));
513 if (!uri) {
514 LOG(("RtspControllerChild::AsyncOpen() - invalid URI"));
515 return NS_ERROR_NOT_INITIALIZED;
516 }
517 SerializeURI(uri, uriParams);
519 if (!OKToSendIPC() || !SendAsyncOpen(uriParams)) {
520 return NS_ERROR_FAILURE;
521 }
522 return NS_OK;
523 }
525 } // namespace net
526 } // namespace mozilla