Bug 992568 - Part 2: Refactor RtspChannel to support redirection. r=sworkman

This commit is contained in:
Ethan Tseng 2014-04-03 19:08:34 +08:00
Родитель 2ea30d25e4
Коммит f2d1f8c08a
18 изменённых файлов: 689 добавлений и 87 удалений

Просмотреть файл

@ -15,6 +15,10 @@
#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;
@ -354,21 +358,21 @@ RtspMediaResource::RtspMediaResource(MediaDecoder* aDecoder,
, 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()
@ -634,6 +638,9 @@ RtspMediaResource::OnDisconnected(uint8_t aTrackIdx, nsresult aReason)
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);
@ -647,6 +654,9 @@ void RtspMediaResource::Suspend(bool aCloseImmediately)
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);

Просмотреть файл

@ -175,6 +175,7 @@ LOCAL_INCLUDES += [
'/content/base/src',
'/layout/generic',
'/layout/xul',
'/netwerk/base/src',
]
if CONFIG['MOZ_DIRECTSHOW']:

Просмотреть файл

@ -7,6 +7,7 @@
include protocol PHttpChannel;
include protocol PFTPChannel;
include protocol PRtspChannel;
include URIParams;
include InputStreamParams;
@ -89,5 +90,15 @@ union ChannelDiverterArgs
PFTPChannel;
};
//-----------------------------------------------------------------------------
// RTSP IPDL structs
//-----------------------------------------------------------------------------
struct RtspChannelConnectArgs
{
URIParams uri;
uint32_t channelId;
};
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -22,6 +22,7 @@
#include "mozilla/dom/network/UDPSocketChild.h"
#ifdef NECKO_PROTOCOL_rtsp
#include "mozilla/net/RtspControllerChild.h"
#include "mozilla/net/RtspChannelChild.h"
#endif
#include "SerializedLoadContext.h"
@ -181,6 +182,23 @@ NeckoChild::DeallocPRtspControllerChild(PRtspControllerChild* child)
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()
{

Просмотреть файл

@ -62,6 +62,10 @@ protected:
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

Просмотреть файл

@ -15,6 +15,7 @@
#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"
@ -336,6 +337,42 @@ NeckoParent::DeallocPRtspControllerParent(PRtspControllerParent* actor)
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()
{

Просмотреть файл

@ -144,6 +144,15 @@ protected:
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

Просмотреть файл

@ -22,6 +22,7 @@ include protocol PBlob; //FIXME: bug #792908
include protocol PFileDescriptorSet;
include protocol PRtspController;
include protocol PRtspChannel;
include URIParams;
include InputStreamParams;
include NeckoChannelParams;
@ -47,6 +48,7 @@ sync protocol PNecko
manages PDNSRequest;
manages PRemoteOpenFile;
manages PRtspController;
manages PRtspChannel;
manages PChannelDiverter;
parent:
@ -71,6 +73,7 @@ parent:
HTMLDNSPrefetch(nsString hostname, uint16_t flags);
CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
PRtspController();
PRtspChannel(RtspChannelConnectArgs args);
PChannelDiverter(ChannelDiverterArgs channel);
both:

Просмотреть файл

@ -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

Просмотреть файл

@ -34,6 +34,7 @@ IPDL_SOURCES = [
'PChannelDiverter.ipdl',
'PNecko.ipdl',
'PRemoteOpenFile.ipdl',
'PRtspChannel.ipdl',
'PRtspController.ipdl',
]

Просмотреть файл

@ -5,42 +5,72 @@
* 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::nsIChannel
// RtspChannelChild
//-----------------------------------------------------------------------------
NS_IMETHODIMP
RtspChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
RtspChannelChild::RtspChannelChild(nsIURI *aUri)
: mIPCOpen(false)
, mCanceled(false)
{
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;
nsBaseChannel::SetURI(aUri);
}
RtspChannelChild::~RtspChannelChild()
{
}
nsIStreamingProtocolController*
RtspChannelChild::GetController()
{
return mMediaStreamController;
}
void
RtspChannelChild::ReleaseController()
{
if (mMediaStreamController) {
mMediaStreamController = nullptr;
}
}
//-----------------------------------------------------------------------------
// IPDL
//-----------------------------------------------------------------------------
void
RtspChannelChild::AddIPDLReference()
{
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)
{
@ -48,15 +78,194 @@ RtspChannelChild::GetContentType(nsACString& aContentType)
return NS_OK;
}
NS_IMETHODIMP
RtspChannelChild::Init(nsIURI* aUri)
class CallListenerOnStartRequestEvent : public nsRunnable
{
MOZ_ASSERT(aUri);
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::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
{
// 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);
// 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));
nsBaseChannel::Init();
nsBaseChannel::SetURI(aUri);
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

Просмотреть файл

@ -7,69 +7,82 @@
#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
NS_DECL_NSICHILDCHANNEL
RtspChannelChild() { }
RtspChannelChild(nsIURI *aUri);
~RtspChannelChild();
~RtspChannelChild() { }
// 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".
// nsBaseChannel::nsIChannel
NS_IMETHOD GetContentType(nsACString & aContentType) MOZ_OVERRIDE MOZ_FINAL;
NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
MOZ_OVERRIDE MOZ_FINAL;
NS_IMETHOD OpenContentStream(bool aAsync,
nsIInputStream **aStream,
nsIChannel **aChannel) MOZ_OVERRIDE MOZ_FINAL
{
return NS_ERROR_NOT_IMPLEMENTED;
}
// 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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -5,6 +5,7 @@
* 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"
@ -68,15 +69,19 @@ 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);

Просмотреть файл

@ -78,6 +78,12 @@ RtspControllerChild::~RtspControllerChild()
LOG(("RtspControllerChild::~RtspControllerChild()"));
}
void
RtspControllerChild::ReleaseChannel()
{
static_cast<RtspChannelChild*>(mChannel.get())->ReleaseController();
}
bool
RtspControllerChild::OKToSendIPC()
{
@ -174,6 +180,7 @@ RtspControllerChild::RecvOnDisconnected(
if (mListener) {
mListener->OnDisconnected(index, reason);
}
ReleaseChannel();
return true;
}
@ -185,6 +192,7 @@ RtspControllerChild::RecvAsyncOpenFailed(const nsresult& reason)
if (mListener) {
mListener->OnDisconnected(0, NS_ERROR_CONNECTION_REFUSED);
}
ReleaseChannel();
return true;
}

Просмотреть файл

@ -13,6 +13,7 @@
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsTArray.h"
#include "mozilla/net/RtspChannelChild.h"
namespace mozilla {
namespace net {
@ -70,6 +71,8 @@ class RtspControllerChild : public nsIStreamingProtocolController
uint32_t mTotalTracks;
// Current suspension depth for this channel object
uint32_t mSuspendCount;
// Detach channel-controller relationship.
void ReleaseChannel();
};
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -10,6 +10,7 @@ EXPORTS.mozilla.net += [
'controller/RtspMetaData.h',
'rtsp/RTSPSource.h',
'RtspChannelChild.h',
'RtspChannelParent.h',
'RtspHandler.h',
]
@ -20,6 +21,7 @@ SOURCES += [
'controller/RtspControllerParent.cpp',
'controller/RtspMetaData.cpp',
'RtspChannelChild.cpp',
'RtspChannelParent.cpp',
'RtspHandler.cpp',
]