Bug 856361. Part 2: Block data from a non-same-origin media resource entering a MediaStream from a media element. r=cpearce

--HG--
extra : rebase_source : db895d3d2d91a92d0c8c381940a0e0ccc9d9a8d0
This commit is contained in:
Robert O'Callahan 2013-07-24 21:55:23 +12:00
parent d458f68756
commit 383c6492bc
8 changed files with 66 additions and 31 deletions

View File

@ -2514,12 +2514,21 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
mPausedForInactiveDocumentOrChannel = false;
mEventDeliveryPaused = false;
mPendingEvents.Clear();
// Set mDecoder now so if methods like GetCurrentSrc get called between
// here and Load(), they work.
mDecoder = aDecoder;
// Tell aDecoder about its MediaResource now so things like principals are
// available immediately.
aDecoder->SetResource(aStream);
aDecoder->SetAudioChannelType(mAudioChannelType);
aDecoder->SetAudioCaptured(mAudioCaptured);
aDecoder->SetVolume(mMuted ? 0.0 : mVolume);
aDecoder->SetPreservesPitch(mPreservesPitch);
aDecoder->SetPlaybackRate(mPlaybackRate);
// Update decoder principal before we start decoding, since it
// can affect how we feed data to MediaStreams
NotifyDecoderPrincipalChanged();
for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) {
OutputMediaStream* ms = &mOutputStreams[i];
@ -2527,8 +2536,9 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
ms->mFinishWhenEnded);
}
nsresult rv = aDecoder->Load(aStream, aListener, aCloneDonor);
nsresult rv = aDecoder->Load(aListener, aCloneDonor);
if (NS_FAILED(rv)) {
mDecoder = nullptr;
LOG(PR_LOG_DEBUG, ("%p Failed to load for decoder %p", this, aDecoder));
return rv;
}
@ -2537,9 +2547,7 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
// which owns the channel.
mChannel = nullptr;
mDecoder = aDecoder;
AddMediaElementToURITable();
NotifyDecoderPrincipalChanged();
// We may want to suspend the new stream now.
// This will also do an AddRemoveSelfReference.
@ -3253,9 +3261,14 @@ already_AddRefed<nsIPrincipal> HTMLMediaElement::GetCurrentPrincipal()
void HTMLMediaElement::NotifyDecoderPrincipalChanged()
{
nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
bool subsumes;
mDecoder->UpdateSameOriginStatus(
NS_SUCCEEDED(NodePrincipal()->Subsumes(principal, &subsumes)) && subsumes);
for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) {
OutputMediaStream* ms = &mOutputStreams[i];
nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
ms->mStream->CombineWithPrincipal(principal);
}
}

View File

@ -368,6 +368,7 @@ MediaDecoder::MediaDecoder() :
mDuration(-1),
mTransportSeekable(true),
mMediaSeekable(true),
mSameOriginMedia(false),
mReentrantMonitor("media.decoder"),
mIsDormant(false),
mPlayState(PLAY_STATE_PAUSED),
@ -445,8 +446,7 @@ MediaDecoder::~MediaDecoder()
MOZ_COUNT_DTOR(MediaDecoder);
}
nsresult MediaDecoder::OpenResource(MediaResource* aResource,
nsIStreamListener** aStreamListener)
nsresult MediaDecoder::OpenResource(nsIStreamListener** aStreamListener)
{
MOZ_ASSERT(NS_IsMainThread());
if (aStreamListener) {
@ -459,24 +459,21 @@ nsresult MediaDecoder::OpenResource(MediaResource* aResource,
// should be grabbed before the cache lock
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
nsresult rv = aResource->Open(aStreamListener);
nsresult rv = mResource->Open(aStreamListener);
if (NS_FAILED(rv)) {
LOG(PR_LOG_DEBUG, ("%p Failed to open stream!", this));
return rv;
}
mResource = aResource;
}
return NS_OK;
}
nsresult MediaDecoder::Load(MediaResource* aResource,
nsIStreamListener** aStreamListener,
nsresult MediaDecoder::Load(nsIStreamListener** aStreamListener,
MediaDecoder* aCloneDonor)
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = OpenResource(aResource, aStreamListener);
nsresult rv = OpenResource(aStreamListener);
NS_ENSURE_SUCCESS(rv, rv);
mDecoderStateMachine = CreateStateMachine();
@ -842,6 +839,18 @@ void MediaDecoder::DecodeError()
Shutdown();
}
void MediaDecoder::UpdateSameOriginStatus(bool aSameOrigin)
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mSameOriginMedia = aSameOrigin;
}
bool MediaDecoder::IsSameOriginMedia()
{
GetReentrantMonitor().AssertCurrentThreadIn();
return mSameOriginMedia;
}
bool MediaDecoder::IsSeeking() const
{
MOZ_ASSERT(NS_IsMainThread());

View File

@ -277,16 +277,12 @@ public:
// Start downloading the media. Decode the downloaded data up to the
// point of the first frame of data.
// aResource is the media stream to use. Ownership of aResource passes to
// the decoder, even if Load returns an error.
// This is called at most once per decoder, after Init().
virtual nsresult Load(MediaResource* aResource,
nsIStreamListener** aListener,
virtual nsresult Load(nsIStreamListener** aListener,
MediaDecoder* aCloneDonor);
// Called in |Load| to open the media resource.
nsresult OpenResource(MediaResource* aResource,
nsIStreamListener** aStreamListener);
// Called in |Load| to open mResource.
nsresult OpenResource(nsIStreamListener** aStreamListener);
// Called when the video file has completed downloading.
virtual void ResourceLoaded();
@ -306,6 +302,11 @@ public:
{
return mResource;
}
void SetResource(MediaResource* aResource)
{
NS_ASSERTION(NS_IsMainThread(), "Should only be called on main thread");
mResource = aResource;
}
// Return the principal of the current URI being played or downloaded.
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
@ -640,6 +641,10 @@ public:
// The actual playback rate computation. The monitor must be held.
virtual double ComputePlaybackRate(bool* aReliable);
// Return true when the media is same-origin with the element. The monitor
// must be held.
bool IsSameOriginMedia();
// Returns true if we can play the entire media through without stopping
// to buffer, given the current download and playback rates.
bool CanPlayThrough();
@ -736,6 +741,9 @@ public:
// Notifies the element that decoding has failed.
virtual void DecodeError();
// Indicate whether the media is same-origin with the element.
void UpdateSameOriginStatus(bool aSameOrigin);
MediaDecoderOwner* GetOwner() MOZ_OVERRIDE;
#ifdef MOZ_RAW
@ -958,6 +966,10 @@ public:
// True if the media is seekable (i.e. supports random access).
bool mMediaSeekable;
// True if the media is same-origin with the element. Data can only be
// passed to MediaStreams when this is true.
bool mSameOriginMedia;
/******
* The following member variables can be accessed from any thread.
******/

View File

@ -619,6 +619,11 @@ void MediaDecoderStateMachine::SendStreamData()
if (mState == DECODER_STATE_DECODING_METADATA)
return;
if (!mDecoder->IsSameOriginMedia()) {
printf("MediaDecoderStateMachine::SendStreamData Same-origin check failed (decoder %p)!!!\n", mDecoder.get());
return;
}
// If there's still an audio thread alive, then we can't send any stream
// data yet since both SendStreamData and the audio thread want to be in
// charge of popping the audio queue. We're waiting for the audio thread

View File

@ -195,15 +195,14 @@ DASHDecoder::ReleaseStateMachine()
}
nsresult
DASHDecoder::Load(MediaResource* aResource,
nsIStreamListener** aStreamListener,
DASHDecoder::Load(nsIStreamListener** aStreamListener,
MediaDecoder* aCloneDonor)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
mDASHReader = new DASHReader(this);
nsresult rv = OpenResource(aResource, aStreamListener);
nsresult rv = OpenResource(aStreamListener);
NS_ENSURE_SUCCESS(rv, rv);
mDecoderStateMachine = CreateStateMachine();

View File

@ -57,9 +57,8 @@ public:
// Loads the MPD from the network and subsequently loads the media streams.
// Called from the main thread only.
nsresult Load(MediaResource* aResource,
nsIStreamListener** aListener,
MediaDecoder* aCloneDonor);
virtual nsresult Load(nsIStreamListener** aListener,
MediaDecoder* aCloneDonor) MOZ_OVERRIDE;
// Notifies download of MPD file has ended.
// Called on the main thread only.

View File

@ -73,8 +73,7 @@ DASHRepDecoder::SetReader(WebMReader* aReader)
}
nsresult
DASHRepDecoder::Load(MediaResource* aResource,
nsIStreamListener** aListener,
DASHRepDecoder::Load(nsIStreamListener** aListener,
MediaDecoder* aCloneDonor)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");

View File

@ -73,9 +73,8 @@ public:
void SetMPDRepresentation(Representation const * aRep);
// Called from DASHDecoder on main thread; Starts media stream download.
nsresult Load(MediaResource* aResource = nullptr,
nsIStreamListener** aListener = nullptr,
MediaDecoder* aCloneDonor = nullptr);
virtual nsresult Load(nsIStreamListener** aListener = nullptr,
MediaDecoder* aCloneDonor = nullptr) MOZ_OVERRIDE;
// Loads the next byte range (or first one on first call). Called on the main
// thread only.