author | Ethan Tseng <ettseng@mozilla.com> |
Thu, 03 Apr 2014 19:08:34 +0800 | |
changeset 199137 | 93cc1760dbbb17537ca5b46fba7a016a6198426a |
parent 199136 | fa91f01d12363cd91b706118c0923e246a594b40 |
child 199138 | 37a543d6ae3764a1ba4d69ee65f5b6b08f26bbf6 |
push id | 486 |
push user | asasaki@mozilla.com |
push date | Mon, 14 Jul 2014 18:39:42 +0000 |
treeherder | mozilla-release@d33428174ff1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sworkman |
bugs | 992568 |
milestone | 31.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/media/RtspMediaResource.cpp +++ b/content/media/RtspMediaResource.cpp @@ -10,16 +10,20 @@ #include "MediaDecoder.h" #include "mozilla/dom/HTMLMediaElement.h" #include "mozilla/Monitor.h" #include "mozilla/Preferences.h" #include "nsIScriptSecurityManager.h" #include "nsIStreamingProtocolService.h" #include "nsServiceManagerUtils.h" +#ifdef NECKO_PROTOCOL_rtsp +#include "mozilla/net/RtspChannelChild.h" +#endif +using namespace mozilla::net; #ifdef PR_LOGGING PRLogModuleInfo* gRtspMediaResourceLog; #define RTSP_LOG(msg, ...) PR_LOG(gRtspMediaResourceLog, PR_LOG_DEBUG, \ (msg, ##__VA_ARGS__)) // Debug logging macro with object pointer and class name. #define RTSPMLOG(msg, ...) \ RTSP_LOG("%p [RtspMediaResource]: " msg, this, ##__VA_ARGS__) @@ -349,31 +353,31 @@ void RtspTrackBuffer::Reset() { } RtspMediaResource::RtspMediaResource(MediaDecoder* aDecoder, nsIChannel* aChannel, nsIURI* aURI, const nsACString& aContentType) : BaseMediaResource(aDecoder, aChannel, aURI, aContentType) , mIsConnected(false) , mRealTime(false) { - nsCOMPtr<nsIStreamingProtocolControllerService> mediaControllerService = - do_GetService(MEDIASTREAMCONTROLLERSERVICE_CONTRACTID); - MOZ_ASSERT(mediaControllerService); - if (mediaControllerService) { - mediaControllerService->Create(mChannel, - getter_AddRefs(mMediaStreamController)); - MOZ_ASSERT(mMediaStreamController); - mListener = new Listener(this); - mMediaStreamController->AsyncOpen(mListener); - } +#ifndef NECKO_PROTOCOL_rtsp + MOZ_CRASH("Should not be called except for B2G platform"); +#else + MOZ_ASSERT(aChannel); + mMediaStreamController = + static_cast<RtspChannelChild*>(aChannel)->GetController(); + MOZ_ASSERT(mMediaStreamController); + mListener = new Listener(this); + mMediaStreamController->AsyncOpen(mListener); #ifdef PR_LOGGING if (!gRtspMediaResourceLog) { gRtspMediaResourceLog = PR_NewLogModule("RtspMediaResource"); } #endif +#endif } RtspMediaResource::~RtspMediaResource() { RTSPMLOG("~RtspMediaResource"); if (mListener) { // Kill its reference to us since we're going away mListener->Revoke(); @@ -629,29 +633,35 @@ RtspMediaResource::OnDisconnected(uint8_ } return NS_OK; } void RtspMediaResource::Suspend(bool aCloseImmediately) { NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread"); + if (NS_WARN_IF(!mDecoder)) { + return; + } MediaDecoderOwner* owner = mDecoder->GetMediaOwner(); NS_ENSURE_TRUE_VOID(owner); dom::HTMLMediaElement* element = owner->GetMediaElement(); NS_ENSURE_TRUE_VOID(element); mMediaStreamController->Suspend(); element->DownloadSuspended(); } void RtspMediaResource::Resume() { NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread"); + if (NS_WARN_IF(!mDecoder)) { + return; + } MediaDecoderOwner* owner = mDecoder->GetMediaOwner(); NS_ENSURE_TRUE_VOID(owner); dom::HTMLMediaElement* element = owner->GetMediaElement(); NS_ENSURE_TRUE_VOID(element); if (mChannel) { element->DownloadResumed();
--- a/content/media/moz.build +++ b/content/media/moz.build @@ -170,16 +170,17 @@ MSVC_ENABLE_PGO = True include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'gklayout' LOCAL_INCLUDES += [ '/content/base/src', '/layout/generic', '/layout/xul', + '/netwerk/base/src', ] if CONFIG['MOZ_DIRECTSHOW']: LOCAL_INCLUDES += [ '/media/webrtc/trunk/webrtc/modules/video_capture/windows', ] DEFINES['MOZILLA_INTERNAL_API'] = True
--- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -2,16 +2,17 @@ /* vim: set sw=2 ts=8 et tw=80 ft=c: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PHttpChannel; include protocol PFTPChannel; +include protocol PRtspChannel; include URIParams; include InputStreamParams; using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h"; using struct nsHttpAtom from "nsHttp.h"; namespace mozilla { @@ -84,10 +85,20 @@ union FTPChannelCreationArgs }; union ChannelDiverterArgs { PHttpChannel; PFTPChannel; }; +//----------------------------------------------------------------------------- +// RTSP IPDL structs +//----------------------------------------------------------------------------- + +struct RtspChannelConnectArgs +{ + URIParams uri; + uint32_t channelId; +}; + } // namespace ipc } // namespace mozilla
--- a/netwerk/ipc/NeckoChild.cpp +++ b/netwerk/ipc/NeckoChild.cpp @@ -17,16 +17,17 @@ #include "mozilla/net/DNSRequestChild.h" #include "mozilla/net/RemoteOpenFileChild.h" #include "mozilla/net/ChannelDiverterChild.h" #include "mozilla/dom/network/TCPSocketChild.h" #include "mozilla/dom/network/TCPServerSocketChild.h" #include "mozilla/dom/network/UDPSocketChild.h" #ifdef NECKO_PROTOCOL_rtsp #include "mozilla/net/RtspControllerChild.h" +#include "mozilla/net/RtspChannelChild.h" #endif #include "SerializedLoadContext.h" using mozilla::dom::TCPSocketChild; using mozilla::dom::TCPServerSocketChild; using mozilla::dom::UDPSocketChild; namespace mozilla { @@ -176,16 +177,33 @@ NeckoChild::DeallocPRtspControllerChild( { #ifdef NECKO_PROTOCOL_rtsp RtspControllerChild* p = static_cast<RtspControllerChild*>(child); p->ReleaseIPDLReference(); #endif return true; } +PRtspChannelChild* +NeckoChild::AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs) +{ + NS_NOTREACHED("AllocPRtspController should not be called"); + return nullptr; +} + +bool +NeckoChild::DeallocPRtspChannelChild(PRtspChannelChild* child) +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspChannelChild* p = static_cast<RtspChannelChild*>(child); + p->ReleaseIPDLReference(); +#endif + return true; +} + PTCPSocketChild* NeckoChild::AllocPTCPSocketChild() { TCPSocketChild* p = new TCPSocketChild(); p->AddIPDLReference(); return p; }
--- a/netwerk/ipc/NeckoChild.h +++ b/netwerk/ipc/NeckoChild.h @@ -57,16 +57,20 @@ protected: const uint32_t& aFlags) MOZ_OVERRIDE; virtual bool DeallocPDNSRequestChild(PDNSRequestChild*) MOZ_OVERRIDE; virtual PRemoteOpenFileChild* AllocPRemoteOpenFileChild(const URIParams&, const OptionalURIParams&) MOZ_OVERRIDE; virtual bool DeallocPRemoteOpenFileChild(PRemoteOpenFileChild*) MOZ_OVERRIDE; virtual PRtspControllerChild* AllocPRtspControllerChild() MOZ_OVERRIDE; virtual bool DeallocPRtspControllerChild(PRtspControllerChild*) MOZ_OVERRIDE; + virtual PRtspChannelChild* + AllocPRtspChannelChild(const RtspChannelConnectArgs& aArgs) + MOZ_OVERRIDE; + virtual bool DeallocPRtspChannelChild(PRtspChannelChild*) MOZ_OVERRIDE; virtual PChannelDiverterChild* AllocPChannelDiverterChild(const ChannelDiverterArgs& channel) MOZ_OVERRIDE; virtual bool DeallocPChannelDiverterChild(PChannelDiverterChild* actor) MOZ_OVERRIDE; }; /** * Reference to the PNecko Child protocol.
--- a/netwerk/ipc/NeckoParent.cpp +++ b/netwerk/ipc/NeckoParent.cpp @@ -10,16 +10,17 @@ #include "mozilla/net/NeckoParent.h" #include "mozilla/net/HttpChannelParent.h" #include "mozilla/net/CookieServiceParent.h" #include "mozilla/net/WyciwygChannelParent.h" #include "mozilla/net/FTPChannelParent.h" #include "mozilla/net/WebSocketChannelParent.h" #ifdef NECKO_PROTOCOL_rtsp #include "mozilla/net/RtspControllerParent.h" +#include "mozilla/net/RtspChannelParent.h" #endif #include "mozilla/net/DNSRequestParent.h" #include "mozilla/net/RemoteOpenFileParent.h" #include "mozilla/net/ChannelDiverterParent.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/network/TCPSocketParent.h" #include "mozilla/dom/network/TCPServerSocketParent.h" @@ -331,16 +332,52 @@ NeckoParent::DeallocPRtspControllerParen { #ifdef NECKO_PROTOCOL_rtsp RtspControllerParent* p = static_cast<RtspControllerParent*>(actor); p->Release(); #endif return true; } +PRtspChannelParent* +NeckoParent::AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs) +{ +#ifdef NECKO_PROTOCOL_rtsp + nsCOMPtr<nsIURI> uri = DeserializeURI(aArgs.uri()); + RtspChannelParent *p = new RtspChannelParent(uri); + p->AddRef(); + return p; +#else + return nullptr; +#endif +} + +bool +NeckoParent::RecvPRtspChannelConstructor( + PRtspChannelParent* aActor, + const RtspChannelConnectArgs& aConnectArgs) +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspChannelParent* p = static_cast<RtspChannelParent*>(aActor); + return p->Init(aConnectArgs); +#else + return nullptr; +#endif +} + +bool +NeckoParent::DeallocPRtspChannelParent(PRtspChannelParent* actor) +{ +#ifdef NECKO_PROTOCOL_rtsp + RtspChannelParent* p = static_cast<RtspChannelParent*>(actor); + p->Release(); +#endif + return true; +} + PTCPSocketParent* NeckoParent::AllocPTCPSocketParent() { TCPSocketParent* p = new TCPSocketParent(); p->AddIPDLReference(); return p; }
--- a/netwerk/ipc/NeckoParent.h +++ b/netwerk/ipc/NeckoParent.h @@ -139,16 +139,25 @@ protected: const nsresult& reason) MOZ_OVERRIDE; virtual mozilla::ipc::IProtocol* CloneProtocol(Channel* aChannel, mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE; virtual PRtspControllerParent* AllocPRtspControllerParent() MOZ_OVERRIDE; virtual bool DeallocPRtspControllerParent(PRtspControllerParent*) MOZ_OVERRIDE; + virtual PRtspChannelParent* + AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs) + MOZ_OVERRIDE; + virtual bool + RecvPRtspChannelConstructor(PRtspChannelParent* aActor, + const RtspChannelConnectArgs& aArgs) + MOZ_OVERRIDE; + virtual bool DeallocPRtspChannelParent(PRtspChannelParent*) MOZ_OVERRIDE; + virtual PChannelDiverterParent* AllocPChannelDiverterParent(const ChannelDiverterArgs& channel) MOZ_OVERRIDE; virtual bool RecvPChannelDiverterConstructor(PChannelDiverterParent* actor, const ChannelDiverterArgs& channel) MOZ_OVERRIDE; virtual bool DeallocPChannelDiverterParent(PChannelDiverterParent* actor) MOZ_OVERRIDE;
--- a/netwerk/ipc/PNecko.ipdl +++ b/netwerk/ipc/PNecko.ipdl @@ -17,16 +17,17 @@ include protocol PTCPServerSocket; include protocol PUDPSocket; include protocol PRemoteOpenFile; include protocol PDNSRequest; include protocol PChannelDiverter; include protocol PBlob; //FIXME: bug #792908 include protocol PFileDescriptorSet; include protocol PRtspController; +include protocol PRtspChannel; include URIParams; include InputStreamParams; include NeckoChannelParams; using class IPC::SerializedLoadContext from "SerializedLoadContext.h"; namespace mozilla { @@ -42,16 +43,17 @@ sync protocol PNecko manages PFTPChannel; manages PWebSocket; manages PTCPSocket; manages PTCPServerSocket; manages PUDPSocket; manages PDNSRequest; manages PRemoteOpenFile; manages PRtspController; + manages PRtspChannel; manages PChannelDiverter; parent: __delete__(); PCookieService(); PHttpChannel(nullable PBrowser browser, SerializedLoadContext loadContext, @@ -66,16 +68,17 @@ parent: PDNSRequest(nsCString hostName, uint32_t flags); PRemoteOpenFile(URIParams fileuri, OptionalURIParams appuri); HTMLDNSPrefetch(nsString hostname, uint16_t flags); CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason); PRtspController(); + PRtspChannel(RtspChannelConnectArgs args); PChannelDiverter(ChannelDiverterArgs channel); both: PTCPSocket(); }; } // namespace net
new file mode 100644 --- /dev/null +++ b/netwerk/ipc/PRtspChannel.ipdl @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +include protocol PNecko; +include URIParams; + +namespace mozilla { +namespace net { + +async protocol PRtspChannel +{ + manager PNecko; + +parent: + // Note: channels are opened during construction, so no open method here: + // see PNecko.ipdl + __delete__(); +}; + +} // namespace net +} // namespace mozilla
--- a/netwerk/ipc/moz.build +++ b/netwerk/ipc/moz.build @@ -29,16 +29,17 @@ UNIFIED_SOURCES += [ 'RemoteOpenFileParent.cpp', ] IPDL_SOURCES = [ 'NeckoChannelParams.ipdlh', 'PChannelDiverter.ipdl', 'PNecko.ipdl', 'PRemoteOpenFile.ipdl', + 'PRtspChannel.ipdl', 'PRtspController.ipdl', ] FAIL_ON_WARNINGS = True include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'necko'
--- a/netwerk/protocol/rtsp/RtspChannelChild.cpp +++ b/netwerk/protocol/rtsp/RtspChannelChild.cpp @@ -1,62 +1,271 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 ts=8 et tw=80 : */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "RtspChannelChild.h" -#include "nsIURI.h" -#include "nsAutoPtr.h" -#include "nsStandardURL.h" +#include "mozilla/ipc/URIUtils.h" + +using namespace mozilla::ipc; namespace mozilla { namespace net { -NS_IMPL_ISUPPORTS_INHERITED1(RtspChannelChild, - nsBaseChannel, - nsIChannel) +//----------------------------------------------------------------------------- +// RtspChannelChild +//----------------------------------------------------------------------------- +RtspChannelChild::RtspChannelChild(nsIURI *aUri) + : mIPCOpen(false) + , mCanceled(false) +{ + nsBaseChannel::SetURI(aUri); +} + +RtspChannelChild::~RtspChannelChild() +{ +} + +nsIStreamingProtocolController* +RtspChannelChild::GetController() +{ + return mMediaStreamController; +} + +void +RtspChannelChild::ReleaseController() +{ + if (mMediaStreamController) { + mMediaStreamController = nullptr; + } +} //----------------------------------------------------------------------------- -// RtspChannelChild::nsIChannel +// IPDL //----------------------------------------------------------------------------- - -NS_IMETHODIMP -RtspChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) +void +RtspChannelChild::AddIPDLReference() { - MOZ_ASSERT(aListener); - - nsCOMPtr<nsIURI> uri = nsBaseChannel::URI(); - NS_ENSURE_TRUE(uri, NS_ERROR_ILLEGAL_VALUE); - - nsAutoCString uriSpec; - uri->GetSpec(uriSpec); - - mListener = aListener; - mListenerContext = aContext; - - // Call OnStartRequest directly. mListener is expected to create/load an - // RtspMediaResource which will create an RtspMediaController. This controller - // manages the control and data streams to and from the network. - mListener->OnStartRequest(this, aContext); - return NS_OK; + NS_ABORT_IF_FALSE(!mIPCOpen, + "Attempt to retain more than one IPDL reference"); + mIPCOpen = true; + AddRef(); } +void +RtspChannelChild::ReleaseIPDLReference() +{ + NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference"); + mIPCOpen = false; + Release(); +} + +//----------------------------------------------------------------------------- +// nsISupports +//----------------------------------------------------------------------------- +NS_IMPL_ISUPPORTS_INHERITED2(RtspChannelChild, + nsBaseChannel, + nsIChannel, + nsIChildChannel) + +//----------------------------------------------------------------------------- +// nsBaseChannel::nsIChannel +//----------------------------------------------------------------------------- NS_IMETHODIMP RtspChannelChild::GetContentType(nsACString& aContentType) { aContentType.AssignLiteral("RTSP"); return NS_OK; } +class CallListenerOnStartRequestEvent : public nsRunnable +{ +public: + CallListenerOnStartRequestEvent(nsIStreamListener *aListener, + nsIRequest *aRequest, nsISupports *aContext) + : mListener(aListener) + , mRequest(aRequest) + , mContext(aContext) + { + MOZ_RELEASE_ASSERT(aListener); + } + NS_IMETHOD Run() + { + MOZ_ASSERT(NS_IsMainThread()); + mListener->OnStartRequest(mRequest, mContext); + return NS_OK; + } +private: + nsRefPtr<nsIStreamListener> mListener; + nsRefPtr<nsIRequest> mRequest; + nsRefPtr<nsISupports> mContext; +}; + NS_IMETHODIMP -RtspChannelChild::Init(nsIURI* aUri) +RtspChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) { - MOZ_ASSERT(aUri); + // Precondition checks. + MOZ_ASSERT(aListener); + nsCOMPtr<nsIURI> uri = nsBaseChannel::URI(); + NS_ENSURE_TRUE(uri, NS_ERROR_ILLEGAL_VALUE); + + // Create RtspController. + nsCOMPtr<nsIStreamingProtocolControllerService> mediaControllerService = + do_GetService(MEDIASTREAMCONTROLLERSERVICE_CONTRACTID); + MOZ_RELEASE_ASSERT(mediaControllerService, + "Cannot proceed if media controller service is unavailable!"); + mediaControllerService->Create(this, getter_AddRefs(mMediaStreamController)); + MOZ_ASSERT(mMediaStreamController); - nsBaseChannel::Init(); - nsBaseChannel::SetURI(aUri); + // Add ourselves to the load group. + if (mLoadGroup) { + mLoadGroup->AddRequest(this, nullptr); + } + + // Dispatch mListener's OnStartRequest directly. mListener is expected to + // create an RtspMediaResource and use the RtspController we just created to + // manage the control and data streams to and from the network. + mListener = aListener; + mListenerContext = aContext; + NS_DispatchToMainThread( + new CallListenerOnStartRequestEvent(mListener, this, mListenerContext)); + return NS_OK; } -} // namespace mozilla::net +//----------------------------------------------------------------------------- +// nsBaseChannel::nsIStreamListener::nsIRequestObserver +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelChild::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) +{ + MOZ_CRASH("Should never be called"); +} + +NS_IMETHODIMP +RtspChannelChild::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, + nsresult aStatusCode) +{ + MOZ_CRASH("Should never be called"); +} + +//----------------------------------------------------------------------------- +// nsBaseChannel::nsIStreamListener +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelChild::OnDataAvailable(nsIRequest *aRequest, + nsISupports *aContext, + nsIInputStream *aInputStream, + uint64_t aOffset, + uint32_t aCount) +{ + MOZ_CRASH("Should never be called"); +} + +//----------------------------------------------------------------------------- +// nsBaseChannel::nsIChannel::nsIRequest +//----------------------------------------------------------------------------- +class CallListenerOnStopRequestEvent : public nsRunnable +{ +public: + CallListenerOnStopRequestEvent(nsIStreamListener *aListener, + nsIRequest *aRequest, + nsISupports *aContext, nsresult aStatus) + : mListener(aListener) + , mRequest(aRequest) + , mContext(aContext) + , mStatus(aStatus) + { + MOZ_RELEASE_ASSERT(aListener); + } + NS_IMETHOD Run() + { + MOZ_ASSERT(NS_IsMainThread()); + mListener->OnStopRequest(mRequest, mContext, mStatus); + return NS_OK; + } +private: + nsRefPtr<nsIStreamListener> mListener; + nsRefPtr<nsIRequest> mRequest; + nsRefPtr<nsISupports> mContext; + nsresult mStatus; +}; + +NS_IMETHODIMP +RtspChannelChild::Cancel(nsresult status) +{ + if (mCanceled) { + return NS_OK; + } + + mCanceled = true; + // Stop RtspController. + if (mMediaStreamController) { + mMediaStreamController->Stop(); + } + + // Call mListener's OnStopRequest to do clean up. + NS_DispatchToMainThread( + new CallListenerOnStopRequestEvent(mListener, this, + mListenerContext, status)); + mListener = nullptr; + mListenerContext = nullptr; + + // Remove ourselves from the load group. + if (mLoadGroup) { + mLoadGroup->RemoveRequest(this, nullptr, status); + } + + return NS_OK; +} + +NS_IMETHODIMP +RtspChannelChild::Suspend() +{ + MOZ_CRASH("Should never be called"); +} + +NS_IMETHODIMP +RtspChannelChild::Resume() +{ + MOZ_CRASH("Should never be called"); +} + +//----------------------------------------------------------------------------- +// nsBaseChannel +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelChild::OpenContentStream(bool aAsync, + nsIInputStream **aStream, + nsIChannel **aChannel) +{ + MOZ_CRASH("Should never be called"); +} + +//----------------------------------------------------------------------------- +// nsIChildChannel +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelChild::ConnectParent(uint32_t id) +{ + // Create RtspChannelParent for redirection. + AddIPDLReference(); + RtspChannelConnectArgs connectArgs; + SerializeURI(nsBaseChannel::URI(), connectArgs.uri()); + connectArgs.channelId() = id; + if (!gNeckoChild->SendPRtspChannelConstructor(this, connectArgs)) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +NS_IMETHODIMP +RtspChannelChild::CompleteRedirectSetup(nsIStreamListener *aListener, + nsISupports *aContext) +{ + return AsyncOpen(aListener, aContext); +} + +} // namespace net } // namespace mozilla
--- a/netwerk/protocol/rtsp/RtspChannelChild.h +++ b/netwerk/protocol/rtsp/RtspChannelChild.h @@ -2,74 +2,87 @@ /* vim: set sw=2 ts=8 et tw=80 : */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef RtspChannelChild_h #define RtspChannelChild_h +#include "mozilla/net/PRtspChannelChild.h" +#include "mozilla/net/NeckoChild.h" #include "nsBaseChannel.h" +#include "nsIChildChannel.h" +#include "nsIStreamingProtocolController.h" +#include "nsIStreamingProtocolService.h" namespace mozilla { namespace net { //----------------------------------------------------------------------------- // RtspChannelChild is a dummy channel used to aid MediaResource creation in -// HTMLMediaElement. Actual network control and data flows are managed by an -// RtspController object created and owned by RtspMediaResource. -// Therefore, when RtspChannelChild::AsyncOpen is called, mListener->OnStartRequest -// will be called immediately. It is expected that an RtspMediaResource object -// will be created in that calling context or after; the RtspController object -// will be created internally by RtspMediaResource." +// HTMLMediaElement. Network control and data flows are managed by an +// RtspController object, which is created by us and manipulated by +// RtspMediaResource. This object is also responsible for inter-process +// communication with the parent process. +// When RtspChannelChild::AsyncOpen is called, it should create an +// RtspController object, dispatch an OnStartRequest and immediately return. +// We expect an RtspMediaResource object will be created in the calling context +// and it will use the RtpController we create. -class RtspChannelChild : public nsBaseChannel +class RtspChannelChild : public PRtspChannelChild + , public nsBaseChannel + , public nsIChildChannel { public: NS_DECL_ISUPPORTS - - RtspChannelChild() { } - - ~RtspChannelChild() { } + NS_DECL_NSICHILDCHANNEL - // Overrides nsBaseChannel::AsyncOpen and call listener's OnStartRequest immediately. - NS_IMETHOD AsyncOpen(nsIStreamListener *listener, - nsISupports *aContext) MOZ_OVERRIDE MOZ_FINAL; - // Set Rtsp URL. - NS_IMETHOD Init(nsIURI* uri); - // Overrides nsBaseChannel::GetContentType, return streaming protocol type "RTSP". - NS_IMETHOD GetContentType(nsACString & aContentType) MOZ_OVERRIDE MOZ_FINAL; + RtspChannelChild(nsIURI *aUri); + ~RtspChannelChild(); - NS_IMETHOD OpenContentStream(bool aAsync, - nsIInputStream **aStream, - nsIChannel **aChannel) MOZ_OVERRIDE MOZ_FINAL - { - return NS_ERROR_NOT_IMPLEMENTED; - } + // nsBaseChannel::nsIChannel + NS_IMETHOD GetContentType(nsACString & aContentType) MOZ_OVERRIDE MOZ_FINAL; + NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) + MOZ_OVERRIDE MOZ_FINAL; - // nsIRequestObserver - NS_IMETHOD OnStartRequest(nsIRequest *aRequest, - nsISupports *aContext) MOZ_OVERRIDE MOZ_FINAL - { - return NS_ERROR_NOT_IMPLEMENTED; - } - + // nsBaseChannel::nsIStreamListener::nsIRequestObserver + NS_IMETHOD OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) + MOZ_OVERRIDE MOZ_FINAL; NS_IMETHOD OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, - nsresult aStatusCode) MOZ_OVERRIDE MOZ_FINAL - { - return NS_ERROR_NOT_IMPLEMENTED; - } + nsresult aStatusCode) MOZ_OVERRIDE MOZ_FINAL; - // nsIStreamListener + // nsBaseChannel::nsIStreamListener NS_IMETHOD OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, uint64_t aOffset, - uint32_t aCount) MOZ_OVERRIDE MOZ_FINAL - { - return NS_ERROR_NOT_IMPLEMENTED; - } + uint32_t aCount) MOZ_OVERRIDE MOZ_FINAL; + + // nsBaseChannel::nsIChannel::nsIRequest + NS_IMETHOD Cancel(nsresult status) MOZ_OVERRIDE MOZ_FINAL; + NS_IMETHOD Suspend() MOZ_OVERRIDE MOZ_FINAL; + NS_IMETHOD Resume() MOZ_OVERRIDE MOZ_FINAL; + + // nsBaseChannel + NS_IMETHOD OpenContentStream(bool aAsync, + nsIInputStream **aStream, + nsIChannel **aChannel) MOZ_OVERRIDE MOZ_FINAL; + + // IPDL + void AddIPDLReference(); + void ReleaseIPDLReference(); + + // RtspChannelChild + nsIStreamingProtocolController* GetController(); + void ReleaseController(); + +private: + bool mIPCOpen; + bool mCanceled; + nsCOMPtr<nsIStreamingProtocolController> mMediaStreamController; }; -} -} // namespace mozilla::net +} // namespace net +} // namespace mozilla + #endif // RtspChannelChild_h
new file mode 100644 --- /dev/null +++ b/netwerk/protocol/rtsp/RtspChannelParent.cpp @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "RtspChannelParent.h" + +using namespace mozilla::ipc; + +namespace mozilla { +namespace net { + +//----------------------------------------------------------------------------- +// RtspChannelParent +//----------------------------------------------------------------------------- +RtspChannelParent::RtspChannelParent(nsIURI *aUri) + : mIPCClosed(false) +{ + nsBaseChannel::SetURI(aUri); +} + +RtspChannelParent::~RtspChannelParent() +{ +} + +void +RtspChannelParent::ActorDestroy(ActorDestroyReason why) +{ + mIPCClosed = true; +} + +//----------------------------------------------------------------------------- +// nsISupports +//----------------------------------------------------------------------------- +NS_IMPL_ISUPPORTS_INHERITED1(RtspChannelParent, + nsBaseChannel, + nsIParentChannel) + +//----------------------------------------------------------------------------- +// RtspChannelParent methods +//----------------------------------------------------------------------------- +bool +RtspChannelParent::Init(const RtspChannelConnectArgs& aArgs) +{ + return ConnectChannel(aArgs.channelId()); +} + +bool +RtspChannelParent::ConnectChannel(const uint32_t& channelId) +{ + nsresult rv; + nsCOMPtr<nsIChannel> channel; + rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel)); + + return true; +} + +//----------------------------------------------------------------------------- +// nsBaseChannel::nsIChannel +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelParent::GetContentType(nsACString& aContentType) +{ + aContentType.AssignLiteral("RTSP"); + return NS_OK; +} + +NS_IMETHODIMP +RtspChannelParent::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) +{ + return NS_OK; +} + +//----------------------------------------------------------------------------- +// nsBaseChannel::nsIStreamListener::nsIRequestObserver +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelParent::OnStartRequest(nsIRequest *aRequest, + nsISupports *aContext) +{ + MOZ_CRASH("Should never be called"); +} + +NS_IMETHODIMP +RtspChannelParent::OnStopRequest(nsIRequest *aRequest, + nsISupports *aContext, + nsresult aStatusCode) +{ + MOZ_CRASH("Should never be called"); +} + +//----------------------------------------------------------------------------- +// nsBaseChannel::nsIStreamListener +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelParent::OnDataAvailable(nsIRequest *aRequest, + nsISupports *aContext, + nsIInputStream *aInputStream, + uint64_t aOffset, + uint32_t aCount) +{ + MOZ_CRASH("Should never be called"); +} + +//----------------------------------------------------------------------------- +// nsBaseChannel::nsIChannel::nsIRequeset +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelParent::Cancel(nsresult status) +{ + // FIXME: This method will be called by + // nsXMLHttpRequest::CloseRequestWithError while closing the browser app. + // However, the root cause is RtspChannelParent will be created by + // nsXMLHttpRequest::Open when we navigate away from an RTSP web page. + // We should find out why it happens and decide how to fix it. + return NS_OK; +} + +NS_IMETHODIMP +RtspChannelParent::Suspend() +{ + MOZ_CRASH("Should never be called"); +} + +NS_IMETHODIMP +RtspChannelParent::Resume() +{ + MOZ_CRASH("Should never be called"); +} + +//----------------------------------------------------------------------------- +// nsBaseChannel +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelParent::OpenContentStream(bool aAsync, + nsIInputStream **aStream, + nsIChannel **aChannel) +{ + MOZ_CRASH("Should never be called"); +} + +//----------------------------------------------------------------------------- +// nsIParentChannel +//----------------------------------------------------------------------------- +NS_IMETHODIMP +RtspChannelParent::SetParentListener(HttpChannelParentListener *aListener) +{ + return NS_OK; +} + +NS_IMETHODIMP +RtspChannelParent::Delete() +{ + return NS_OK; +} + +} // namespace net +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/netwerk/protocol/rtsp/RtspChannelParent.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef RtspChannelParent_h +#define RtspChannelParent_h + +#include "mozilla/net/PRtspChannelParent.h" +#include "mozilla/net/NeckoParent.h" +#include "nsBaseChannel.h" +#include "nsIParentChannel.h" + +namespace mozilla { +namespace net { + +//----------------------------------------------------------------------------- +// Note: RtspChannel doesn't transport streams as normal channel does. +// (See RtspChannelChild.h for detail). +// The reason for the existence of RtspChannelParent is to support HTTP->RTSP +// redirection. +// When redirection happens, two instances of RtspChannelParent will be created: +// - One will be created when HTTP creates the new channel for redirects, and +// will be registered as an nsIChannel. +// - The other will be created via IPDL by RtspChannelChild, and will be +// registered as an nsIParentChannel. +class RtspChannelParent : public PRtspChannelParent + , public nsBaseChannel + , public nsIParentChannel +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPARENTCHANNEL + + RtspChannelParent(nsIURI *aUri); + ~RtspChannelParent(); + + // nsBaseChannel::nsIChannel + NS_IMETHOD GetContentType(nsACString & aContentType) MOZ_OVERRIDE MOZ_FINAL; + NS_IMETHOD AsyncOpen(nsIStreamListener *listener, + nsISupports *aContext) MOZ_OVERRIDE MOZ_FINAL; + + // nsBaseChannel::nsIStreamListener::nsIRequestObserver + NS_IMETHOD OnStartRequest(nsIRequest *aRequest, + nsISupports *aContext) MOZ_OVERRIDE MOZ_FINAL; + NS_IMETHOD OnStopRequest(nsIRequest *aRequest, + nsISupports *aContext, + nsresult aStatusCode) MOZ_OVERRIDE MOZ_FINAL; + + // nsBaseChannel::nsIStreamListener + NS_IMETHOD OnDataAvailable(nsIRequest *aRequest, + nsISupports *aContext, + nsIInputStream *aInputStream, + uint64_t aOffset, + uint32_t aCount) MOZ_OVERRIDE MOZ_FINAL; + + // nsBaseChannel::nsIChannel::nsIRequest + NS_IMETHOD Cancel(nsresult status) MOZ_OVERRIDE MOZ_FINAL; + NS_IMETHOD Suspend() MOZ_OVERRIDE MOZ_FINAL; + NS_IMETHOD Resume() MOZ_OVERRIDE MOZ_FINAL; + + // nsBaseChannel + NS_IMETHOD OpenContentStream(bool aAsync, + nsIInputStream **aStream, + nsIChannel **aChannel) MOZ_OVERRIDE MOZ_FINAL; + + // RtspChannelParent + bool Init(const RtspChannelConnectArgs& aArgs); + +protected: + // Used to connect redirected-to channel in parent with just created + // ChildChannel. Used during HTTP->RTSP redirection. + bool ConnectChannel(const uint32_t& channelId); + +private: + bool mIPCClosed; + virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; +}; + +} // namespace net +} // namespace mozilla + +#endif // RtspChannelParent_h
--- a/netwerk/protocol/rtsp/RtspHandler.cpp +++ b/netwerk/protocol/rtsp/RtspHandler.cpp @@ -1,15 +1,16 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 ts=8 et tw=80 : */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "RtspChannelChild.h" +#include "RtspChannelParent.h" #include "RtspHandler.h" #include "nsILoadGroup.h" #include "nsIInterfaceRequestor.h" #include "nsIURI.h" #include "nsAutoPtr.h" #include "nsStandardURL.h" #include "mozilla/net/NeckoChild.h" @@ -63,25 +64,29 @@ RtspHandler::NewURI(const nsACString & a url.forget(aResult); return NS_OK; } NS_IMETHODIMP RtspHandler::NewChannel(nsIURI *aURI, nsIChannel **aResult) { bool isRtsp = false; - nsRefPtr<RtspChannelChild> rtspChannel; + nsRefPtr<nsBaseChannel> rtspChannel; nsresult rv = aURI->SchemeIs("rtsp", &isRtsp); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(isRtsp, NS_ERROR_UNEXPECTED); - rtspChannel = new RtspChannelChild(); + if (IsNeckoChild()) { + rtspChannel = new RtspChannelChild(aURI); + } else { + rtspChannel = new RtspChannelParent(aURI); + } - rv = rtspChannel->Init(aURI); + rv = rtspChannel->Init(); NS_ENSURE_SUCCESS(rv, rv); rtspChannel.forget(aResult); return NS_OK; } NS_IMETHODIMP RtspHandler::AllowPort(int32_t port, const char *scheme, bool *aResult)
--- a/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp +++ b/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp @@ -73,16 +73,22 @@ RtspControllerChild::RtspControllerChild gNeckoChild->SendPRtspControllerConstructor(this); } RtspControllerChild::~RtspControllerChild() { LOG(("RtspControllerChild::~RtspControllerChild()")); } +void +RtspControllerChild::ReleaseChannel() +{ + static_cast<RtspChannelChild*>(mChannel.get())->ReleaseController(); +} + bool RtspControllerChild::OKToSendIPC() { MOZ_ASSERT(NS_IsMainThread()); if (mIPCOpen == false) { return false; } return mIPCAllowed; @@ -169,27 +175,29 @@ RtspControllerChild::RecvOnDisconnected( const uint8_t& index, const nsresult& reason) { DisallowIPC(); LOG(("RtspControllerChild::RecvOnDisconnected for track %d reason = 0x%x", index, reason)); if (mListener) { mListener->OnDisconnected(index, reason); } + ReleaseChannel(); return true; } bool RtspControllerChild::RecvAsyncOpenFailed(const nsresult& reason) { DisallowIPC(); LOG(("RtspControllerChild::RecvAsyncOpenFailed reason = 0x%x", reason)); if (mListener) { mListener->OnDisconnected(0, NS_ERROR_CONNECTION_REFUSED); } + ReleaseChannel(); return true; } void RtspControllerChild::AddIPDLReference() { NS_ABORT_IF_FALSE(!mIPCOpen, "Attempt to retain more than one IPDL reference");
--- a/netwerk/protocol/rtsp/controller/RtspControllerChild.h +++ b/netwerk/protocol/rtsp/controller/RtspControllerChild.h @@ -8,16 +8,17 @@ #define RtspControllerChild_h #include "mozilla/net/PRtspControllerChild.h" #include "nsIStreamingProtocolController.h" #include "nsIChannel.h" #include "nsCOMPtr.h" #include "nsString.h" #include "nsTArray.h" +#include "mozilla/net/RtspChannelChild.h" namespace mozilla { namespace net { class RtspControllerChild : public nsIStreamingProtocolController , public nsIStreamingProtocolListener , public PRtspControllerChild { @@ -65,13 +66,15 @@ class RtspControllerChild : public nsISt // Array refer to metadata of the media stream. nsTArray<nsCOMPtr<nsIStreamingProtocolMetaData>> mMetaArray; // ASCII encoded URL spec nsCString mSpec; // The total tracks for the given media stream session. uint32_t mTotalTracks; // Current suspension depth for this channel object uint32_t mSuspendCount; + // Detach channel-controller relationship. + void ReleaseChannel(); }; } // namespace net } // namespace mozilla #endif // RtspControllerChild_h
--- a/netwerk/protocol/rtsp/moz.build +++ b/netwerk/protocol/rtsp/moz.build @@ -5,26 +5,28 @@ EXPORTS.mozilla.net += [ 'controller/RtspController.h', 'controller/RtspControllerChild.h', 'controller/RtspControllerParent.h', 'controller/RtspMetaData.h', 'rtsp/RTSPSource.h', 'RtspChannelChild.h', + 'RtspChannelParent.h', 'RtspHandler.h', ] # These files cannot be built in unified mode because they force NSPR logging. SOURCES += [ 'controller/RtspController.cpp', 'controller/RtspControllerChild.cpp', 'controller/RtspControllerParent.cpp', 'controller/RtspMetaData.cpp', 'RtspChannelChild.cpp', + 'RtspChannelParent.cpp', 'RtspHandler.cpp', ] # Android sources SOURCES += [ 'rtsp/AAMRAssembler.cpp', 'rtsp/AAVCAssembler.cpp', 'rtsp/AH263Assembler.cpp',