Bug 1401461. P1 - protect access to ChannelMediaResource::Listener::mResource. r=gerald

MozReview-Commit-ID: 6G1x7cXNvAq

--HG--
extra : rebase_source : 2f6a8642930ec314621aab2ce6424e4f9f95e0c2
extra : source : eeb067bc2905dfa6fb5764fd42ebb78e1b71a61d
This commit is contained in:
JW Wang 2017-09-20 14:37:18 +08:00
Родитель e0f16de8d6
Коммит f69d8e8e34
2 изменённых файлов: 27 добавлений и 6 удалений

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

@ -68,6 +68,7 @@ nsresult
ChannelMediaResource::Listener::OnStartRequest(nsIRequest* aRequest, ChannelMediaResource::Listener::OnStartRequest(nsIRequest* aRequest,
nsISupports* aContext) nsISupports* aContext)
{ {
MOZ_ASSERT(NS_IsMainThread());
if (!mResource) if (!mResource)
return NS_OK; return NS_OK;
return mResource->OnStartRequest(aRequest, mOffset); return mResource->OnStartRequest(aRequest, mOffset);
@ -78,6 +79,7 @@ ChannelMediaResource::Listener::OnStopRequest(nsIRequest* aRequest,
nsISupports* aContext, nsISupports* aContext,
nsresult aStatus) nsresult aStatus)
{ {
MOZ_ASSERT(NS_IsMainThread());
if (!mResource) if (!mResource)
return NS_OK; return NS_OK;
return mResource->OnStopRequest(aRequest, aStatus); return mResource->OnStopRequest(aRequest, aStatus);
@ -91,8 +93,14 @@ ChannelMediaResource::Listener::OnDataAvailable(nsIRequest* aRequest,
uint32_t aCount) uint32_t aCount)
{ {
// This might happen off the main thread. // This might happen off the main thread.
MOZ_DIAGNOSTIC_ASSERT(mResource); RefPtr<ChannelMediaResource> res;
return mResource->OnDataAvailable(mLoadID, aStream, aCount); {
MutexAutoLock lock(mMutex);
res = mResource;
}
// Note Rekove() might happen at the same time to reset mResource. We check
// the load ID to determine if the data is from an old channel.
return res ? res->OnDataAvailable(mLoadID, aStream, aCount) : NS_OK;
} }
nsresult nsresult
@ -102,6 +110,8 @@ ChannelMediaResource::Listener::AsyncOnChannelRedirect(
uint32_t aFlags, uint32_t aFlags,
nsIAsyncVerifyRedirectCallback* cb) nsIAsyncVerifyRedirectCallback* cb)
{ {
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = NS_OK; nsresult rv = NS_OK;
if (mResource) { if (mResource) {
rv = mResource->OnChannelRedirect(aOld, aNew, aFlags, mOffset); rv = mResource->OnChannelRedirect(aOld, aNew, aFlags, mOffset);
@ -127,6 +137,14 @@ ChannelMediaResource::Listener::GetInterface(const nsIID& aIID, void** aResult)
return QueryInterface(aIID, aResult); return QueryInterface(aIID, aResult);
} }
void
ChannelMediaResource::Listener::Revoke()
{
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(mMutex);
mResource = nullptr;
}
static bool static bool
IsPayloadCompressed(nsIHttpChannel* aChannel) IsPayloadCompressed(nsIHttpChannel* aChannel)
{ {
@ -415,8 +433,6 @@ ChannelMediaResource::OnDataAvailable(uint32_t aLoadID,
uint32_t aCount) uint32_t aCount)
{ {
// This might happen off the main thread. // This might happen off the main thread.
// Don't assert |mChannel.get() == aRequest| since reading mChannel here off
// the main thread is a data race.
RefPtr<ChannelMediaResource> self = this; RefPtr<ChannelMediaResource> self = this;
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(

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

@ -116,7 +116,8 @@ public:
~Listener() {} ~Listener() {}
public: public:
Listener(ChannelMediaResource* aResource, int64_t aOffset, uint32_t aLoadID) Listener(ChannelMediaResource* aResource, int64_t aOffset, uint32_t aLoadID)
: mResource(aResource) : mMutex("Listener.mMutex")
, mResource(aResource)
, mOffset(aOffset) , mOffset(aOffset)
, mLoadID(aLoadID) , mLoadID(aLoadID)
{} {}
@ -128,9 +129,13 @@ public:
NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
void Revoke() { mResource = nullptr; } void Revoke();
private: private:
Mutex mMutex;
// mResource should only be modified on the main thread with the lock.
// So it can be read without lock on the main thread or on other threads
// with the lock.
RefPtr<ChannelMediaResource> mResource; RefPtr<ChannelMediaResource> mResource;
const int64_t mOffset; const int64_t mOffset;
const uint32_t mLoadID; const uint32_t mLoadID;