Backing out bug 489415 due to Linux test failures

This commit is contained in:
Robert O'Callahan 2009-05-14 12:39:00 +12:00
commit b1b462d25c
8 changed files with 45 additions and 301 deletions

View File

@ -172,15 +172,11 @@ void nsHTMLMediaElement::QueueLoadFromSourceTask()
NS_DispatchToMainThread(event); NS_DispatchToMainThread(event);
} }
class nsHTMLMediaElement::MediaLoadListener : public nsIStreamListener, class nsHTMLMediaElement::MediaLoadListener : public nsIStreamListener
public nsIChannelEventSink,
public nsIInterfaceRequestor
{ {
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER NS_DECL_NSISTREAMLISTENER
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
public: public:
MediaLoadListener(nsHTMLMediaElement* aElement) MediaLoadListener(nsHTMLMediaElement* aElement)
@ -194,9 +190,7 @@ private:
nsCOMPtr<nsIStreamListener> mNextListener; nsCOMPtr<nsIStreamListener> mNextListener;
}; };
NS_IMPL_ISUPPORTS4(nsHTMLMediaElement::MediaLoadListener, nsIRequestObserver, NS_IMPL_ISUPPORTS2(nsHTMLMediaElement::MediaLoadListener, nsIRequestObserver, nsIStreamListener)
nsIStreamListener, nsIChannelEventSink,
nsIInterfaceRequestor)
NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
{ {
@ -258,21 +252,6 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnDataAvailable(nsIRequest*
return mNextListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount); return mNextListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount);
} }
NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
PRUint32 aFlags)
{
nsCOMPtr<nsIChannelEventSink> sink = do_QueryInterface(mNextListener);
if (sink)
return sink->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
return NS_OK;
}
NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::GetInterface(const nsIID & aIID, void **aResult)
{
return QueryInterface(aIID, aResult);
}
NS_IMPL_ADDREF_INHERITED(nsHTMLMediaElement, nsGenericHTMLElement) NS_IMPL_ADDREF_INHERITED(nsHTMLMediaElement, nsGenericHTMLElement)
NS_IMPL_RELEASE_INHERITED(nsHTMLMediaElement, nsGenericHTMLElement) NS_IMPL_RELEASE_INHERITED(nsHTMLMediaElement, nsGenericHTMLElement)
@ -534,10 +513,8 @@ nsresult nsHTMLMediaElement::LoadResource(nsIURI* aURI)
// The listener holds a strong reference to us. This creates a reference // The listener holds a strong reference to us. This creates a reference
// cycle which is manually broken in the listener's OnStartRequest method // cycle which is manually broken in the listener's OnStartRequest method
// after it is finished with the element. // after it is finished with the element.
nsRefPtr<MediaLoadListener> loadListener = new MediaLoadListener(this); nsCOMPtr<nsIStreamListener> loadListener = new MediaLoadListener(this);
if (!loadListener) return NS_ERROR_OUT_OF_MEMORY; if (!loadListener) return NS_ERROR_OUT_OF_MEMORY;
mChannel->SetNotificationCallbacks(loadListener);
nsCOMPtr<nsIStreamListener> listener; nsCOMPtr<nsIStreamListener> listener;
if (ShouldCheckAllowOrigin()) { if (ShouldCheckAllowOrigin()) {

View File

@ -41,8 +41,6 @@
#include "nsTArray.h" #include "nsTArray.h"
#include "nsAutoLock.h" #include "nsAutoLock.h"
#include "nsIPrincipal.h"
#include "nsCOMPtr.h"
/** /**
* Media applications want fast, "on demand" random access to media data, * Media applications want fast, "on demand" random access to media data,
@ -188,13 +186,6 @@
* we must not acquire any nsMediaDecoder locks or nsMediaStream locks * we must not acquire any nsMediaDecoder locks or nsMediaStream locks
* while holding the nsMediaCache lock. But it's OK to hold those locks * while holding the nsMediaCache lock. But it's OK to hold those locks
* and then get the nsMediaCache lock. * and then get the nsMediaCache lock.
*
* nsMediaCache associates a principal with each stream. CacheClientSeek
* can trigger new HTTP requests; due to redirects to other domains,
* each HTTP load can return data with a different principal. This
* principal must be passed to NotifyDataReceived, and nsMediaCache
* will detect when different principals are associated with data in the
* same stream, and replace them with a null principal.
*/ */
class nsMediaCache; class nsMediaCache;
// defined in nsMediaStream.h // defined in nsMediaStream.h
@ -224,8 +215,7 @@ public:
mStreamOffset(0), mStreamLength(-1), mPlaybackBytesPerSecond(10000), mStreamOffset(0), mStreamLength(-1), mPlaybackBytesPerSecond(10000),
mPinCount(0), mCurrentMode(MODE_PLAYBACK), mClosed(PR_FALSE), mPinCount(0), mCurrentMode(MODE_PLAYBACK), mClosed(PR_FALSE),
mIsSeekable(PR_FALSE), mCacheSuspended(PR_FALSE), mIsSeekable(PR_FALSE), mCacheSuspended(PR_FALSE),
mMetadataInPartialBlockBuffer(PR_FALSE), mMetadataInPartialBlockBuffer(PR_FALSE) {}
mUsingNullPrincipal(PR_FALSE) {}
~nsMediaCacheStream(); ~nsMediaCacheStream();
// Set up this stream with the cache. Can fail on OOM. Must be called // Set up this stream with the cache. Can fail on OOM. Must be called
@ -246,8 +236,6 @@ public:
void Close(); void Close();
// This returns true when the stream has been closed // This returns true when the stream has been closed
PRBool IsClosed() const { return mClosed; } PRBool IsClosed() const { return mClosed; }
// Get the principal for this stream.
nsIPrincipal* GetCurrentPrincipal() { return mPrincipal; }
// These callbacks are called on the main thread by the client // These callbacks are called on the main thread by the client
// when data has been received via the channel. // when data has been received via the channel.
@ -275,9 +263,7 @@ public:
// the starting offset is known via NotifyDataStarted or because // the starting offset is known via NotifyDataStarted or because
// the cache requested the offset in // the cache requested the offset in
// nsMediaChannelStream::CacheClientSeek, or because it defaulted to 0. // nsMediaChannelStream::CacheClientSeek, or because it defaulted to 0.
// We pass in the principal that was used to load this data. void NotifyDataReceived(PRInt64 aSize, const char* aData);
void NotifyDataReceived(PRInt64 aSize, const char* aData,
nsIPrincipal* aPrincipal);
// Notifies the cache that the channel has closed with the given status. // Notifies the cache that the channel has closed with the given status.
void NotifyDataEnded(nsresult aStatus); void NotifyDataEnded(nsresult aStatus);
@ -377,12 +363,9 @@ private:
// This is used to NotifyAll to wake up threads that might be // This is used to NotifyAll to wake up threads that might be
// blocked on reading from this stream. // blocked on reading from this stream.
void CloseInternal(nsAutoMonitor* aMonitor); void CloseInternal(nsAutoMonitor* aMonitor);
// Update mPrincipal given that data has been received from aPrincipal
void UpdatePrincipal(nsIPrincipal* aPrincipal);
// These fields are main-thread-only. // This field is main-thread-only.
nsMediaChannelStream* mClient; nsMediaChannelStream* mClient;
nsCOMPtr<nsIPrincipal> mPrincipal;
// All other fields are all protected by the cache's monitor and // All other fields are all protected by the cache's monitor and
// can be accessed by by any thread. // can be accessed by by any thread.
@ -418,9 +401,6 @@ private:
PRPackedBool mCacheSuspended; PRPackedBool mCacheSuspended;
// true if some data in mPartialBlockBuffer has been read as metadata // true if some data in mPartialBlockBuffer has been read as metadata
PRPackedBool mMetadataInPartialBlockBuffer; PRPackedBool mMetadataInPartialBlockBuffer;
// true if mPrincipal is a null principal because we saw data from
// multiple origins
PRPackedBool mUsingNullPrincipal;
// Data received for the block containing mChannelOffset. Data needs // Data received for the block containing mChannelOffset. Data needs
// to wait here so we can write back a complete block. The first // to wait here so we can write back a complete block. The first

View File

@ -44,8 +44,6 @@
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsIStreamListener.h" #include "nsIStreamListener.h"
#include "nsIChannelEventSink.h"
#include "nsIInterfaceRequestor.h"
#include "prlock.h" #include "prlock.h"
#include "nsMediaCache.h" #include "nsMediaCache.h"
#include "nsTimeStamp.h" #include "nsTimeStamp.h"
@ -151,6 +149,8 @@ public:
} }
// The following can be called on the main thread only: // The following can be called on the main thread only:
// Get the current principal for the channel
already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
// Get the decoder // Get the decoder
nsMediaDecoder* Decoder() { return mDecoder; } nsMediaDecoder* Decoder() { return mDecoder; }
// Close the stream, stop any listeners, channels, etc. // Close the stream, stop any listeners, channels, etc.
@ -161,8 +161,6 @@ public:
virtual void Suspend() = 0; virtual void Suspend() = 0;
// Resume any downloads that have been suspended. // Resume any downloads that have been suspended.
virtual void Resume() = 0; virtual void Resume() = 0;
// Get the current principal for the channel
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() = 0;
// These methods are called off the main thread. // These methods are called off the main thread.
// The mode is initially MODE_PLAYBACK. // The mode is initially MODE_PLAYBACK.
@ -319,7 +317,6 @@ public:
virtual nsresult Close(); virtual nsresult Close();
virtual void Suspend(); virtual void Suspend();
virtual void Resume(); virtual void Resume();
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
// Return PR_TRUE if the stream has been closed. // Return PR_TRUE if the stream has been closed.
PRBool IsClosed() const { return mCacheStream.IsClosed(); } PRBool IsClosed() const { return mCacheStream.IsClosed(); }
@ -340,18 +337,13 @@ public:
virtual PRBool IsSuspendedByCache(); virtual PRBool IsSuspendedByCache();
protected: protected:
class Listener : public nsIStreamListener, class Listener : public nsIStreamListener {
public nsIInterfaceRequestor,
public nsIChannelEventSink
{
public: public:
Listener(nsMediaChannelStream* aStream) : mStream(aStream) {} Listener(nsMediaChannelStream* aStream) : mStream(aStream) {}
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER NS_DECL_NSISTREAMLISTENER
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
void Revoke() { mStream = nsnull; } void Revoke() { mStream = nsnull; }
@ -366,12 +358,10 @@ protected:
nsresult OnDataAvailable(nsIRequest* aRequest, nsresult OnDataAvailable(nsIRequest* aRequest,
nsIInputStream* aStream, nsIInputStream* aStream,
PRUint32 aCount); PRUint32 aCount);
nsresult OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew, PRUint32 aFlags);
// Opens the channel, using an HTTP byte range request to start at aOffset // Opens the channel, using an HTTP byte range request to start at aOffset
// if possible. Main thread only. // if possible. Main thread only.
nsresult OpenChannel(nsIStreamListener** aStreamListener, PRInt64 aOffset); nsresult OpenChannel(nsIStreamListener** aStreamListener, PRInt64 aOffset);
void SetupChannelHeaders();
// Closes the channel. Main thread only. // Closes the channel. Main thread only.
void CloseChannel(); void CloseChannel();
@ -383,9 +373,9 @@ protected:
PRUint32 *aWriteCount); PRUint32 *aWriteCount);
// Main thread access only // Main thread access only
PRInt64 mLastSeekOffset;
nsRefPtr<Listener> mListener; nsRefPtr<Listener> mListener;
PRUint32 mSuspendCount; PRUint32 mSuspendCount;
PRPackedBool mSeeking;
// Any thread access // Any thread access
nsMediaCacheStream mCacheStream; nsMediaCacheStream mCacheStream;

View File

@ -1390,47 +1390,10 @@ nsMediaCacheStream::NotifyDataStarted(PRInt64 aOffset)
} }
void void
nsMediaCacheStream::UpdatePrincipal(nsIPrincipal* aPrincipal) nsMediaCacheStream::NotifyDataReceived(PRInt64 aSize, const char* aData)
{
if (!mPrincipal) {
NS_ASSERTION(!mUsingNullPrincipal, "Are we using a null principal or not?");
if (mUsingNullPrincipal) {
// Don't let mPrincipal be set to anything
return;
}
mPrincipal = aPrincipal;
return;
}
if (mPrincipal == aPrincipal) {
// Common case
NS_ASSERTION(!mUsingNullPrincipal, "We can't receive data from a null principal");
return;
}
if (mUsingNullPrincipal) {
// We've already fallen back to a null principal, so nothing more
// to do.
return;
}
PRBool equal;
nsresult rv = mPrincipal->Equals(aPrincipal, &equal);
if (NS_SUCCEEDED(rv) && equal)
return;
// Principals are not equal, so set mPrincipal to a null principal.
mPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1");
mUsingNullPrincipal = PR_TRUE;
}
void
nsMediaCacheStream::NotifyDataReceived(PRInt64 aSize, const char* aData,
nsIPrincipal* aPrincipal)
{ {
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
UpdatePrincipal(aPrincipal);
nsAutoMonitor mon(gMediaCache->Monitor()); nsAutoMonitor mon(gMediaCache->Monitor());
PRInt64 size = aSize; PRInt64 size = aSize;
const char* data = aData; const char* data = aData;

View File

@ -65,7 +65,7 @@ using mozilla::TimeStamp;
nsMediaChannelStream::nsMediaChannelStream(nsMediaDecoder* aDecoder, nsMediaChannelStream::nsMediaChannelStream(nsMediaDecoder* aDecoder,
nsIChannel* aChannel, nsIURI* aURI) nsIChannel* aChannel, nsIURI* aURI)
: nsMediaStream(aDecoder, aChannel, aURI), : nsMediaStream(aDecoder, aChannel, aURI),
mLastSeekOffset(0), mSuspendCount(0), mSuspendCount(0), mSeeking(PR_FALSE),
mCacheStream(this), mCacheStream(this),
mLock(nsAutoLock::NewLock("media.channel.stream")), mLock(nsAutoLock::NewLock("media.channel.stream")),
mCacheSuspendCount(0) mCacheSuspendCount(0)
@ -89,9 +89,7 @@ nsMediaChannelStream::~nsMediaChannelStream()
// disconnect the old listener from the nsMediaChannelStream and hook up // disconnect the old listener from the nsMediaChannelStream and hook up
// a new listener, so notifications from the old channel are discarded // a new listener, so notifications from the old channel are discarded
// and don't confuse us. // and don't confuse us.
NS_IMPL_ISUPPORTS4(nsMediaChannelStream::Listener, NS_IMPL_ISUPPORTS2(nsMediaChannelStream::Listener, nsIRequestObserver, nsIStreamListener)
nsIRequestObserver, nsIStreamListener, nsIChannelEventSink,
nsIInterfaceRequestor)
nsresult nsresult
nsMediaChannelStream::Listener::OnStartRequest(nsIRequest* aRequest, nsMediaChannelStream::Listener::OnStartRequest(nsIRequest* aRequest,
@ -124,22 +122,6 @@ nsMediaChannelStream::Listener::OnDataAvailable(nsIRequest* aRequest,
return mStream->OnDataAvailable(aRequest, aStream, aCount); return mStream->OnDataAvailable(aRequest, aStream, aCount);
} }
nsresult
nsMediaChannelStream::Listener::OnChannelRedirect(nsIChannel* aOldChannel,
nsIChannel* aNewChannel,
PRUint32 aFlags)
{
if (!mStream)
return NS_OK;
return mStream->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
}
nsresult
nsMediaChannelStream::Listener::GetInterface(const nsIID & aIID, void **aResult)
{
return QueryInterface(aIID, aResult);
}
nsresult nsresult
nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest) nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
{ {
@ -166,7 +148,7 @@ nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
ranges); ranges);
PRBool acceptsRanges = ranges.EqualsLiteral("bytes"); PRBool acceptsRanges = ranges.EqualsLiteral("bytes");
if (mLastSeekOffset == 0) { if (!mSeeking) {
// Look for duration headers from known Ogg content systems. In the case // Look for duration headers from known Ogg content systems. In the case
// of multiple options for obtaining the duration the order of precedence is; // of multiple options for obtaining the duration the order of precedence is;
// 1) The Media resource metadata if possible (done by the decoder itself). // 1) The Media resource metadata if possible (done by the decoder itself).
@ -190,12 +172,12 @@ nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
PRUint32 responseStatus = 0; PRUint32 responseStatus = 0;
hc->GetResponseStatus(&responseStatus); hc->GetResponseStatus(&responseStatus);
if (mLastSeekOffset > 0 && responseStatus == HTTP_OK_CODE) { if (mSeeking && responseStatus == HTTP_OK_CODE) {
// If we get an OK response but we were seeking, we have to assume // If we get an OK response but we were seeking, we have to assume
// that seeking doesn't work. We also need to tell the cache that // that seeking doesn't work. We also need to tell the cache that
// it's getting data for the start of the stream. // it's getting data for the start of the stream.
mCacheStream.NotifyDataStarted(0); mCacheStream.NotifyDataStarted(0);
} else if (mLastSeekOffset == 0 && } else if (!mSeeking &&
(responseStatus == HTTP_OK_CODE || (responseStatus == HTTP_OK_CODE ||
responseStatus == HTTP_PARTIAL_RESPONSE_CODE)) { responseStatus == HTTP_PARTIAL_RESPONSE_CODE)) {
// We weren't seeking and got a valid response status, // We weren't seeking and got a valid response status,
@ -261,20 +243,6 @@ nsMediaChannelStream::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
return NS_OK; return NS_OK;
} }
nsresult
nsMediaChannelStream::OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew,
PRUint32 aFlags)
{
mChannel = aNew;
SetupChannelHeaders();
return NS_OK;
}
struct CopySegmentClosure {
nsCOMPtr<nsIPrincipal> mPrincipal;
nsMediaChannelStream* mStream;
};
NS_METHOD NS_METHOD
nsMediaChannelStream::CopySegmentToCache(nsIInputStream *aInStream, nsMediaChannelStream::CopySegmentToCache(nsIInputStream *aInStream,
void *aClosure, void *aClosure,
@ -283,9 +251,8 @@ nsMediaChannelStream::CopySegmentToCache(nsIInputStream *aInStream,
PRUint32 aCount, PRUint32 aCount,
PRUint32 *aWriteCount) PRUint32 *aWriteCount)
{ {
CopySegmentClosure* closure = static_cast<CopySegmentClosure*>(aClosure); nsMediaChannelStream* stream = static_cast<nsMediaChannelStream*>(aClosure);
closure->mStream->mCacheStream.NotifyDataReceived(aCount, aFromSegment, stream->mCacheStream.NotifyDataReceived(aCount, aFromSegment);
closure->mPrincipal);
*aWriteCount = aCount; *aWriteCount = aCount;
return NS_OK; return NS_OK;
} }
@ -302,17 +269,10 @@ nsMediaChannelStream::OnDataAvailable(nsIRequest* aRequest,
mChannelStatistics.AddBytes(aCount); mChannelStatistics.AddBytes(aCount);
} }
CopySegmentClosure closure;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (secMan && mChannel) {
secMan->GetChannelPrincipal(mChannel, getter_AddRefs(closure.mPrincipal));
}
closure.mStream = this;
PRUint32 count = aCount; PRUint32 count = aCount;
while (count > 0) { while (count > 0) {
PRUint32 read; PRUint32 read;
nsresult rv = aStream->ReadSegments(CopySegmentToCache, &closure, count, nsresult rv = aStream->ReadSegments(CopySegmentToCache, this, count,
&read); &read);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
@ -350,7 +310,7 @@ nsresult nsMediaChannelStream::OpenChannel(nsIStreamListener** aStreamListener,
*aStreamListener = nsnull; *aStreamListener = nsnull;
} }
mLastSeekOffset = aOffset; mSeeking = aOffset != 0;
mListener = new Listener(this); mListener = new Listener(this);
NS_ENSURE_TRUE(mListener, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(mListener, NS_ERROR_OUT_OF_MEMORY);
@ -359,8 +319,6 @@ nsresult nsMediaChannelStream::OpenChannel(nsIStreamListener** aStreamListener,
*aStreamListener = mListener; *aStreamListener = mListener;
NS_ADDREF(*aStreamListener); NS_ADDREF(*aStreamListener);
} else { } else {
mChannel->SetNotificationCallbacks(mListener.get());
nsCOMPtr<nsIStreamListener> listener = mListener.get(); nsCOMPtr<nsIStreamListener> listener = mListener.get();
// Ensure that if we're loading cross domain, that the server is sending // Ensure that if we're loading cross domain, that the server is sending
@ -384,7 +342,18 @@ nsresult nsMediaChannelStream::OpenChannel(nsIStreamListener** aStreamListener,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
SetupChannelHeaders(); // Use a byte range request from the start of the resource.
// This enables us to detect if the stream supports byte range
// requests, and therefore seeking, early.
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(mChannel);
if (hc) {
nsCAutoString rangeString("bytes=");
rangeString.AppendInt(aOffset);
rangeString.Append("-");
hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, PR_FALSE);
} else {
NS_ASSERTION(aOffset == 0, "Don't know how to seek on this channel type");
}
nsresult rv = mChannel->AsyncOpen(listener, nsnull); nsresult rv = mChannel->AsyncOpen(listener, nsnull);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -393,23 +362,6 @@ nsresult nsMediaChannelStream::OpenChannel(nsIStreamListener** aStreamListener,
return NS_OK; return NS_OK;
} }
void nsMediaChannelStream::SetupChannelHeaders()
{
// Always use a byte range request even if we're reading from the start
// of the resource.
// This enables us to detect if the stream supports byte range
// requests, and therefore seeking, early.
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(mChannel);
if (hc) {
nsCAutoString rangeString("bytes=");
rangeString.AppendInt(mLastSeekOffset);
rangeString.Append("-");
hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, PR_FALSE);
} else {
NS_ASSERTION(mLastSeekOffset == 0, "Don't know how to seek on this channel type");
}
}
nsresult nsMediaChannelStream::Close() nsresult nsMediaChannelStream::Close()
{ {
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
@ -419,14 +371,6 @@ nsresult nsMediaChannelStream::Close()
return NS_OK; return NS_OK;
} }
already_AddRefed<nsIPrincipal> nsMediaChannelStream::GetCurrentPrincipal()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsCOMPtr<nsIPrincipal> principal = mCacheStream.GetCurrentPrincipal();
return principal.forget();
}
void nsMediaChannelStream::CloseChannel() void nsMediaChannelStream::CloseChannel()
{ {
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
@ -672,7 +616,6 @@ public:
virtual nsresult Close(); virtual nsresult Close();
virtual void Suspend() {} virtual void Suspend() {}
virtual void Resume() {} virtual void Resume() {}
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
// These methods are called off the main thread. // These methods are called off the main thread.
@ -814,18 +757,6 @@ nsresult nsMediaFileStream::Close()
return NS_OK; return NS_OK;
} }
already_AddRefed<nsIPrincipal> nsMediaFileStream::GetCurrentPrincipal()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsCOMPtr<nsIPrincipal> principal;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (!secMan || !mChannel)
return nsnull;
secMan->GetChannelPrincipal(mChannel, getter_AddRefs(principal));
return principal.forget();
}
nsresult nsMediaFileStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes) nsresult nsMediaFileStream::Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes)
{ {
nsAutoLock lock(mLock); nsAutoLock lock(mLock);
@ -900,6 +831,18 @@ nsMediaStream::Open(nsMediaDecoder* aDecoder, nsIURI* aURI,
return NS_OK; return NS_OK;
} }
already_AddRefed<nsIPrincipal> nsMediaStream::GetCurrentPrincipal()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
nsCOMPtr<nsIPrincipal> principal;
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
if (!secMan || !mChannel)
return nsnull;
secMan->GetChannelPrincipal(mChannel, getter_AddRefs(principal));
return principal.forget();
}
void nsMediaStream::MoveLoadsToBackground() { void nsMediaStream::MoveLoadsToBackground() {
NS_ASSERTION(!mLoadInBackground, "Why are you calling this more than once?"); NS_ASSERTION(!mLoadInBackground, "Why are you calling this more than once?");
mLoadInBackground = PR_TRUE; mLoadInBackground = PR_TRUE;

View File

@ -61,7 +61,6 @@ _TEST_FILES = \
ifdef MOZ_OGG ifdef MOZ_OGG
_TEST_FILES += \ _TEST_FILES += \
dynamic_redirect.sjs \
test_access_control.html \ test_access_control.html \
file_access_controls.html \ file_access_controls.html \
test_bug448534.html \ test_bug448534.html \
@ -83,7 +82,6 @@ _TEST_FILES += \
test_info_leak.html \ test_info_leak.html \
test_onloadedmetadata.html \ test_onloadedmetadata.html \
test_load_candidates.html \ test_load_candidates.html \
test_mixed_principals.html \
test_play.html \ test_play.html \
test_progress1.html \ test_progress1.html \
test_progress3.html \ test_progress3.html \

View File

@ -1,39 +0,0 @@
// Return seek.ogv file content for the first request with a given key.
// All subsequent requests return a redirect to a different-origin resource.
function handleRequest(request, response)
{
var key = request.queryString.match(/^key=(.*)$/);
if (getState(key[1]) == "redirect") {
var origin = request.host == "localhost" ? "example.org" : "localhost:8888";
response.setStatusLine(request.httpVersion, 303, "See Other");
response.setHeader("Location", "http://" + origin + "/tests/content/media/video/test/seek.ogv");
response.setHeader("Content-Type", "text/html");
return;
}
setState(key[1], "redirect");
var file = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("CurWorkD", Components.interfaces.nsILocalFile);
var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
createInstance(Components.interfaces.nsIFileInputStream);
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
createInstance(Components.interfaces.nsIBinaryInputStream);
var paths = "tests/content/media/video/test/seek.ogv";
var split = paths.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);
}
fis.init(file, -1, -1, false);
dump("file=" + file + "\n");
bis.setInputStream(fis);
var bytes = bis.readBytes(bis.available());
response.setStatusLine(request.httpVersion, 206, "Partial Content");
response.setHeader("Content-Range", "bytes 0-" + (bytes.length - 1) + "/" + bytes.length);
response.setHeader("Content-Length", ""+bytes.length, false);
response.setHeader("Content-Type", "video/ogg", false);
response.write(bytes, bytes.length);
bis.close();
}

View File

@ -1,68 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=489415
-->
<head>
<title>Test for Bug 489415</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=489415">Mozilla Bug 489415</a>
<p id="display"></p>
<video id="v1" autoplay onended="loaded('v1')"></video>
<video id="v2" autoplay onended="loaded('v2')"></video>
<pre id="test">
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
var v1 = document.getElementById("v1");
var v2 = document.getElementById("v2");
var count = 0;
function loaded(id) {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
var v = document.getElementById(id);
ctx.drawImage(v, 0, 0);
try {
c.toDataURL();
ok(false, "Failed to throw exception in toDataURL for " + id);
} catch (ex) {
ok(true, "Threw exception in toDataURL for " + id);
}
if (++count == 2) {
SimpleTest.finish();
}
}
// Generate a random key. The first load with that key will return
// data, the second and subsequent loads with that key will return a redirect
// to a different origin ('localhost:8888' will be redirected to 'example.org',
// and 'example.org' will be redirected to 'localhost:8888'). We rely on the
// fact that Ogg will do a seek to the end of the resource, triggering a new
// load with the same key which will return a same-origin resource.
// Loading data from two different origins should be detected by the media
// cache and result in a null principal so that the canvas usage above fails.
var key = Math.floor(Math.random()*100000000);
// In v1, try loading from same-origin first and then getting redirected to
// another origin.
v1.src = "http://localhost:8888/tests/content/media/video/test/dynamic_redirect.sjs?key=v1_" + key;
v1.load();
// In v2, try loading cross-origin first and then getting redirected to
// our origin.
v2.src = "http://example.org/tests/content/media/video/test/dynamic_redirect.sjs?key=v2_" + key;
v2.load();
</script>
</pre>
</body>
</html>