Bug 1395017. P4 - CacheClientUpdatePrincipal() should dispatch the runnable to the main thread on which the callback object runs to preserve the ordering. draft
authorJW Wang <jwwang@mozilla.com>
Wed, 06 Sep 2017 15:12:34 +0800
changeset 659705 22b362b56f218acb70cc7ce3c0fd0ea113563681
parent 659704 8d0be483ab3f5c8a53d86728810396ab7b6f6301
child 730033 3d34113557f8e81c8337c16f3b1aa8d28aff122e
push id78176
push userjwwang@mozilla.com
push dateWed, 06 Sep 2017 07:18:39 +0000
bugs1395017
milestone57.0a1
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
dom/media/ChannelMediaDecoder.cpp
dom/media/ChannelMediaDecoder.h
dom/media/MediaResource.cpp
dom/media/MediaResourceCallback.h
--- 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() {}