michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set sw=2 ts=8 et tw=80 : */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "RtspChannelChild.h" michael@0: #include "mozilla/ipc/URIUtils.h" michael@0: michael@0: using namespace mozilla::ipc; michael@0: michael@0: namespace mozilla { michael@0: namespace net { michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // RtspChannelChild michael@0: //----------------------------------------------------------------------------- michael@0: RtspChannelChild::RtspChannelChild(nsIURI *aUri) michael@0: : mIPCOpen(false) michael@0: , mCanceled(false) michael@0: { michael@0: nsBaseChannel::SetURI(aUri); michael@0: } michael@0: michael@0: RtspChannelChild::~RtspChannelChild() michael@0: { michael@0: } michael@0: michael@0: nsIStreamingProtocolController* michael@0: RtspChannelChild::GetController() michael@0: { michael@0: return mMediaStreamController; michael@0: } michael@0: michael@0: void michael@0: RtspChannelChild::ReleaseController() michael@0: { michael@0: if (mMediaStreamController) { michael@0: mMediaStreamController = nullptr; michael@0: } michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // IPDL michael@0: //----------------------------------------------------------------------------- michael@0: void michael@0: RtspChannelChild::AddIPDLReference() michael@0: { michael@0: NS_ABORT_IF_FALSE(!mIPCOpen, michael@0: "Attempt to retain more than one IPDL reference"); michael@0: mIPCOpen = true; michael@0: AddRef(); michael@0: } michael@0: michael@0: void michael@0: RtspChannelChild::ReleaseIPDLReference() michael@0: { michael@0: NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference"); michael@0: mIPCOpen = false; michael@0: Release(); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsISupports michael@0: //----------------------------------------------------------------------------- michael@0: NS_IMPL_ISUPPORTS_INHERITED(RtspChannelChild, michael@0: nsBaseChannel, michael@0: nsIChannel, michael@0: nsIChildChannel) michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsBaseChannel::nsIChannel michael@0: //----------------------------------------------------------------------------- michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::GetContentType(nsACString& aContentType) michael@0: { michael@0: aContentType.AssignLiteral("RTSP"); michael@0: return NS_OK; michael@0: } michael@0: michael@0: class CallListenerOnStartRequestEvent : public nsRunnable michael@0: { michael@0: public: michael@0: CallListenerOnStartRequestEvent(nsIStreamListener *aListener, michael@0: nsIRequest *aRequest, nsISupports *aContext) michael@0: : mListener(aListener) michael@0: , mRequest(aRequest) michael@0: , mContext(aContext) michael@0: { michael@0: MOZ_RELEASE_ASSERT(aListener); michael@0: } michael@0: NS_IMETHOD Run() michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: mListener->OnStartRequest(mRequest, mContext); michael@0: return NS_OK; michael@0: } michael@0: private: michael@0: nsRefPtr mListener; michael@0: nsRefPtr mRequest; michael@0: nsRefPtr mContext; michael@0: }; michael@0: michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) michael@0: { michael@0: // Precondition checks. michael@0: MOZ_ASSERT(aListener); michael@0: nsCOMPtr uri = nsBaseChannel::URI(); michael@0: NS_ENSURE_TRUE(uri, NS_ERROR_ILLEGAL_VALUE); michael@0: michael@0: // Create RtspController. michael@0: nsCOMPtr mediaControllerService = michael@0: do_GetService(MEDIASTREAMCONTROLLERSERVICE_CONTRACTID); michael@0: MOZ_RELEASE_ASSERT(mediaControllerService, michael@0: "Cannot proceed if media controller service is unavailable!"); michael@0: mediaControllerService->Create(this, getter_AddRefs(mMediaStreamController)); michael@0: MOZ_ASSERT(mMediaStreamController); michael@0: michael@0: // Add ourselves to the load group. michael@0: if (mLoadGroup) { michael@0: mLoadGroup->AddRequest(this, nullptr); michael@0: } michael@0: michael@0: // Dispatch mListener's OnStartRequest directly. mListener is expected to michael@0: // create an RtspMediaResource and use the RtspController we just created to michael@0: // manage the control and data streams to and from the network. michael@0: mListener = aListener; michael@0: mListenerContext = aContext; michael@0: NS_DispatchToMainThread( michael@0: new CallListenerOnStartRequestEvent(mListener, this, mListenerContext)); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsBaseChannel::nsIStreamListener::nsIRequestObserver michael@0: //----------------------------------------------------------------------------- michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) michael@0: { michael@0: MOZ_CRASH("Should never be called"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, michael@0: nsresult aStatusCode) michael@0: { michael@0: MOZ_CRASH("Should never be called"); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsBaseChannel::nsIStreamListener michael@0: //----------------------------------------------------------------------------- michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::OnDataAvailable(nsIRequest *aRequest, michael@0: nsISupports *aContext, michael@0: nsIInputStream *aInputStream, michael@0: uint64_t aOffset, michael@0: uint32_t aCount) michael@0: { michael@0: MOZ_CRASH("Should never be called"); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsBaseChannel::nsIChannel::nsIRequest michael@0: //----------------------------------------------------------------------------- michael@0: class CallListenerOnStopRequestEvent : public nsRunnable michael@0: { michael@0: public: michael@0: CallListenerOnStopRequestEvent(nsIStreamListener *aListener, michael@0: nsIRequest *aRequest, michael@0: nsISupports *aContext, nsresult aStatus) michael@0: : mListener(aListener) michael@0: , mRequest(aRequest) michael@0: , mContext(aContext) michael@0: , mStatus(aStatus) michael@0: { michael@0: MOZ_RELEASE_ASSERT(aListener); michael@0: } michael@0: NS_IMETHOD Run() michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: mListener->OnStopRequest(mRequest, mContext, mStatus); michael@0: return NS_OK; michael@0: } michael@0: private: michael@0: nsRefPtr mListener; michael@0: nsRefPtr mRequest; michael@0: nsRefPtr mContext; michael@0: nsresult mStatus; michael@0: }; michael@0: michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::Cancel(nsresult status) michael@0: { michael@0: if (mCanceled) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: mCanceled = true; michael@0: // Stop RtspController. michael@0: if (mMediaStreamController) { michael@0: mMediaStreamController->Stop(); michael@0: } michael@0: michael@0: // Call mListener's OnStopRequest to do clean up. michael@0: NS_DispatchToMainThread( michael@0: new CallListenerOnStopRequestEvent(mListener, this, michael@0: mListenerContext, status)); michael@0: mListener = nullptr; michael@0: mListenerContext = nullptr; michael@0: michael@0: // Remove ourselves from the load group. michael@0: if (mLoadGroup) { michael@0: mLoadGroup->RemoveRequest(this, nullptr, status); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::Suspend() michael@0: { michael@0: MOZ_CRASH("Should never be called"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::Resume() michael@0: { michael@0: MOZ_CRASH("Should never be called"); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsBaseChannel michael@0: //----------------------------------------------------------------------------- michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::OpenContentStream(bool aAsync, michael@0: nsIInputStream **aStream, michael@0: nsIChannel **aChannel) michael@0: { michael@0: MOZ_CRASH("Should never be called"); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // nsIChildChannel michael@0: //----------------------------------------------------------------------------- michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::ConnectParent(uint32_t id) michael@0: { michael@0: // Create RtspChannelParent for redirection. michael@0: AddIPDLReference(); michael@0: RtspChannelConnectArgs connectArgs; michael@0: SerializeURI(nsBaseChannel::URI(), connectArgs.uri()); michael@0: connectArgs.channelId() = id; michael@0: if (!gNeckoChild->SendPRtspChannelConstructor(this, connectArgs)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: RtspChannelChild::CompleteRedirectSetup(nsIStreamListener *aListener, michael@0: nsISupports *aContext) michael@0: { michael@0: return AsyncOpen(aListener, aContext); michael@0: } michael@0: michael@0: } // namespace net michael@0: } // namespace mozilla