Bug 1395017. P4 - CacheClientUpdatePrincipal() should dispatch the runnable to the main thread on which the callback object runs to preserve the ordering.
MozReview-Commit-ID: 4eQuzx21duz
--- a/dom/media/ChannelMediaDecoder.cpp
+++ b/dom/media/ChannelMediaDecoder.cpp
@@ -40,16 +40,22 @@ ChannelMediaDecoder::ResourceCallback::D
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder = nullptr;
mTimer->Cancel();
mTimer = nullptr;
}
}
+AbstractThread*
+ChannelMediaDecoder::ResourceCallback::AbstractMainThread() const
+{
+ return mAbstractMainThread;
+}
+
MediaDecoderOwner*
ChannelMediaDecoder::ResourceCallback::GetMediaOwner() const
{
MOZ_ASSERT(NS_IsMainThread());
return mDecoder ? mDecoder->GetOwner() : nullptr;
}
void
--- a/dom/media/ChannelMediaDecoder.h
+++ b/dom/media/ChannelMediaDecoder.h
@@ -31,16 +31,17 @@ class ChannelMediaDecoder : public Media
explicit ResourceCallback(AbstractThread* aMainThread);
// Start to receive notifications from ResourceCallback.
void Connect(ChannelMediaDecoder* aDecoder);
// Called upon shutdown to stop receiving notifications.
void Disconnect();
private:
/* MediaResourceCallback functions */
+ AbstractThread* AbstractMainThread() const override;
MediaDecoderOwner* GetMediaOwner() const override;
void NotifyNetworkError() override;
void NotifyDataArrived() override;
void NotifyDataEnded(nsresult aStatus) override;
void NotifyPrincipalChanged() override;
void NotifySuspendedStatusChanged(bool aSuspendedByCache) override;
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) override;
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -884,18 +884,22 @@ ChannelMediaResource::UpdatePrincipal()
if (mCacheStream.UpdatePrincipal(principal)) {
mCallback->NotifyPrincipalChanged();
}
}
void
ChannelMediaResource::CacheClientUpdatePrincipal()
{
- SystemGroup::Dispatch(
- TaskCategory::Other,
+ // Note we need to use the main thread provided by the callback object to
+ // preserve the ordering. E.g. the principal must be udpated before the new
+ // data is consumed by the decoder and then dispatch 'firstFrameLoaded' to
+ // the main thread. Otherwise Canvas.drawImage() will fail for the principal
+ // is not updated.
+ mCallback->AbstractMainThread()->Dispatch(
NewRunnableMethod("ChannelMediaResource::UpdatePrincipal",
this,
&ChannelMediaResource::UpdatePrincipal));
}
void
ChannelMediaResource::CacheClientNotifySuspendedStatusChanged()
{
--- a/dom/media/MediaResourceCallback.h
+++ b/dom/media/MediaResourceCallback.h
@@ -7,32 +7,36 @@
#ifndef MediaResourceCallback_h_
#define MediaResourceCallback_h_
#include "nsError.h"
#include "nsISupportsImpl.h"
namespace mozilla {
+class AbstractThread;
class MediaDecoderOwner;
class MediaResource;
/**
* A callback used by MediaResource (sub-classes like FileMediaResource,
* RtspMediaResource, and ChannelMediaResource) to notify various events.
* Currently this is implemented by MediaDecoder only.
*
* Since this class has no pure virtual function, it is convenient to write
* gtests for the readers without using a mock MediaResource when you don't
* care about the events notified by the MediaResource.
*/
class MediaResourceCallback {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaResourceCallback);
+ // Return an abstract thread on which to run main thread runnables.
+ virtual AbstractThread* AbstractMainThread() const { return nullptr; }
+
// Returns a weak reference to the media decoder owner.
virtual MediaDecoderOwner* GetMediaOwner() const { return nullptr; }
// Notify that a network error is encountered.
virtual void NotifyNetworkError() {}
// Notify that data arrives on the stream and is read into the cache.
virtual void NotifyDataArrived() {}