Bug 1423372 - Move MediaDecoder::BackgroundVideoDecodingPermissionObserver to its own file. r?jwwang draft
authorChris Pearce <cpearce@mozilla.com>
Wed, 06 Dec 2017 11:22:36 +1300
changeset 707898 70264c61a842d1411c73935c119ed31e55dc7ef2
parent 707182 5be384bcf00191f97d32b4ac3ecd1b85ec7b18e1
child 707899 e374de1f022fec755d55d8c39db7b93aa6210158
child 707906 7b890f23ade7b6d3eff132b96cf57d7dd1e97bd6
push id92237
push userbmo:cpearce@mozilla.com
push dateTue, 05 Dec 2017 22:41:42 +0000
reviewersjwwang
bugs1423372
milestone59.0a1
Bug 1423372 - Move MediaDecoder::BackgroundVideoDecodingPermissionObserver to its own file. r?jwwang This class contains a bunch of Gecko DOM specific stuff, and it would make keeping the copy of MediaDecoder in Servo up to date easier if the Gecko DOM stuff wasn't in MediaDecoder (and the other classes we import). MozReview-Commit-ID: 3dP1nrQ7sT3
dom/media/BackgroundVideoDecodingPermissionObserver.cpp
dom/media/BackgroundVideoDecodingPermissionObserver.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/media/BackgroundVideoDecodingPermissionObserver.cpp
@@ -0,0 +1,198 @@
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BackgroundVideoDecodingPermissionObserver.h"
+
+#include "mozilla/AsyncEventDispatcher.h"
+#include "MediaDecoder.h"
+#include "MediaPrefs.h"
+#include "nsContentUtils.h"
+#include "nsIDocument.h"
+
+namespace mozilla {
+
+BackgroundVideoDecodingPermissionObserver::
+  BackgroundVideoDecodingPermissionObserver(MediaDecoder* aDecoder)
+  : mDecoder(aDecoder)
+  , mIsRegisteredForEvent(false)
+{
+  MOZ_ASSERT(mDecoder);
+}
+
+NS_IMETHODIMP
+BackgroundVideoDecodingPermissionObserver::Observe(nsISupports* aSubject,
+                                                   const char* aTopic,
+                                                   const char16_t* aData)
+{
+  if (!MediaPrefs::ResumeVideoDecodingOnTabHover()) {
+    return NS_OK;
+  }
+
+  if (!IsValidEventSender(aSubject)) {
+    return NS_OK;
+  }
+
+  if (strcmp(aTopic, "unselected-tab-hover") == 0) {
+    bool allowed = !NS_strcmp(aData, u"true");
+    mDecoder->SetIsBackgroundVideoDecodingAllowed(allowed);
+  }
+  return NS_OK;
+}
+
+void
+BackgroundVideoDecodingPermissionObserver::RegisterEvent()
+{
+  MOZ_ASSERT(!mIsRegisteredForEvent);
+  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+  if (observerService) {
+    observerService->AddObserver(this, "unselected-tab-hover", false);
+    mIsRegisteredForEvent = true;
+    if (nsContentUtils::IsInStableOrMetaStableState()) {
+      // Events shall not be fired synchronously to prevent anything visible
+      // from the scripts while we are in stable state.
+      if (nsCOMPtr<nsIDocument> doc = GetOwnerDoc()) {
+        doc->Dispatch(
+          TaskCategory::Other,
+          NewRunnableMethod(
+            "BackgroundVideoDecodingPermissionObserver::"
+            "EnableEvent",
+            this,
+            &BackgroundVideoDecodingPermissionObserver::
+              EnableEvent));
+      }
+    } else {
+      EnableEvent();
+    }
+  }
+}
+
+void
+BackgroundVideoDecodingPermissionObserver::UnregisterEvent()
+{
+  MOZ_ASSERT(mIsRegisteredForEvent);
+  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+  if (observerService) {
+    observerService->RemoveObserver(this, "unselected-tab-hover");
+    mIsRegisteredForEvent = false;
+    mDecoder->SetIsBackgroundVideoDecodingAllowed(false);
+    if (nsContentUtils::IsInStableOrMetaStableState()) {
+      // Events shall not be fired synchronously to prevent anything visible
+      // from the scripts while we are in stable state.
+      if (nsCOMPtr<nsIDocument> doc = GetOwnerDoc()) {
+        doc->Dispatch(
+          TaskCategory::Other,
+          NewRunnableMethod(
+            "BackgroundVideoDecodingPermissionObserver::"
+            "DisableEvent",
+            this,
+            &BackgroundVideoDecodingPermissionObserver::
+              DisableEvent));
+      }
+    } else {
+      DisableEvent();
+    }
+  }
+}
+
+BackgroundVideoDecodingPermissionObserver::
+  ~BackgroundVideoDecodingPermissionObserver()
+{
+  MOZ_ASSERT(!mIsRegisteredForEvent);
+}
+
+void
+BackgroundVideoDecodingPermissionObserver::EnableEvent() const
+{
+  nsIDocument* doc = GetOwnerDoc();
+  if (!doc) {
+    return;
+  }
+
+  RefPtr<AsyncEventDispatcher> asyncDispatcher =
+    new AsyncEventDispatcher(doc,
+                             NS_LITERAL_STRING("UnselectedTabHover:Enable"),
+                             /* Bubbles */ true,
+                             /* OnlyChromeDispatch */ true);
+  asyncDispatcher->PostDOMEvent();
+}
+
+void
+BackgroundVideoDecodingPermissionObserver::DisableEvent() const
+{
+  nsIDocument* doc = GetOwnerDoc();
+  if (!doc) {
+    return;
+  }
+
+  RefPtr<AsyncEventDispatcher> asyncDispatcher =
+    new AsyncEventDispatcher(doc,
+                             NS_LITERAL_STRING("UnselectedTabHover:Disable"),
+                             /* Bubbles */ true,
+                             /* OnlyChromeDispatch */ true);
+  asyncDispatcher->PostDOMEvent();
+}
+
+already_AddRefed<nsPIDOMWindowOuter>
+BackgroundVideoDecodingPermissionObserver::GetOwnerWindow() const
+{
+  nsIDocument* doc = GetOwnerDoc();
+  if (!doc) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsPIDOMWindowInner> innerWin = doc->GetInnerWindow();
+  if (!innerWin) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> outerWin = innerWin->GetOuterWindow();
+  if (!outerWin) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> topWin = outerWin->GetTop();
+  return topWin.forget();
+}
+
+nsIDocument*
+BackgroundVideoDecodingPermissionObserver::GetOwnerDoc() const
+{
+  if (!mDecoder->GetOwner()) {
+    return nullptr;
+  }
+
+  return mDecoder->GetOwner()->GetDocument();
+}
+
+bool
+BackgroundVideoDecodingPermissionObserver::IsValidEventSender(
+  nsISupports* aSubject) const
+{
+  nsCOMPtr<nsPIDOMWindowInner> senderInner(do_QueryInterface(aSubject));
+  if (!senderInner) {
+    return false;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> senderOuter = senderInner->GetOuterWindow();
+  if (!senderOuter) {
+    return false;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> senderTop = senderOuter->GetTop();
+  if (!senderTop) {
+    return false;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> ownerTop = GetOwnerWindow();
+  if (!ownerTop) {
+    return false;
+  }
+
+  return ownerTop == senderTop;
+}
+
+NS_IMPL_ISUPPORTS(BackgroundVideoDecodingPermissionObserver, nsIObserver)
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/BackgroundVideoDecodingPermissionObserver.h
@@ -0,0 +1,48 @@
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if !defined(BackgroundVideoDecodingPermissionObserver_h_)
+#define BackgroundVideoDecodingPermissionObserver_h_
+
+#include "nsIObserver.h"
+#include "nsISupportsImpl.h"
+
+class nsIDocument;
+class nsISupports;
+class nsPIDOMWindowOuter;
+
+namespace mozilla {
+
+class MediaDecoder;
+
+class BackgroundVideoDecodingPermissionObserver final
+  : public nsIObserver
+{
+  public:
+    NS_DECL_ISUPPORTS
+
+    explicit BackgroundVideoDecodingPermissionObserver(MediaDecoder* aDecoder);
+
+    NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
+                       const char16_t* aData) override;
+    void RegisterEvent();
+    void UnregisterEvent();
+  private:
+    ~BackgroundVideoDecodingPermissionObserver();
+    void EnableEvent() const;
+    void DisableEvent() const;
+    already_AddRefed<nsPIDOMWindowOuter> GetOwnerWindow() const;
+    nsIDocument* GetOwnerDoc() const;
+    bool IsValidEventSender(nsISupports* aSubject) const;
+
+    // The life cycle of observer would always be shorter than decoder, so we
+    // use raw pointer here.
+    MediaDecoder* mDecoder;
+    bool mIsRegisteredForEvent;
+};
+
+} // namespace mozilla
+
+#endif // BackgroundVideoDecodingPermissionObserver_h_
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -10,17 +10,16 @@
 #include "Layers.h"
 #include "MediaDecoderStateMachine.h"
 #include "MediaFormatReader.h"
 #include "MediaResource.h"
 #include "MediaShutdownManager.h"
 #include "VideoFrameContainer.h"
 #include "VideoUtils.h"
 #include "mozilla/AbstractThread.h"
-#include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/AudioTrack.h"
 #include "mozilla/dom/AudioTrackList.h"
 #include "mozilla/dom/VideoTrack.h"
@@ -118,187 +117,16 @@ public:
     DecodersArray& decoders = Decoders();
     decoders.RemoveElement(aDecoder);
     if (decoders.IsEmpty()) {
       sUniqueInstance = nullptr;
     }
   }
 };
 
-class MediaDecoder::BackgroundVideoDecodingPermissionObserver final :
-  public nsIObserver
-{
-  public:
-    NS_DECL_ISUPPORTS
-
-    explicit BackgroundVideoDecodingPermissionObserver(MediaDecoder* aDecoder)
-      : mDecoder(aDecoder)
-      , mIsRegisteredForEvent(false)
-    {
-      MOZ_ASSERT(mDecoder);
-    }
-
-    NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
-                       const char16_t* aData) override
-    {
-      if (!MediaPrefs::ResumeVideoDecodingOnTabHover()) {
-        return NS_OK;
-      }
-
-      if (!IsValidEventSender(aSubject)) {
-        return NS_OK;
-      }
-
-      if (strcmp(aTopic, "unselected-tab-hover") == 0) {
-        mDecoder->mIsBackgroundVideoDecodingAllowed = !NS_strcmp(aData, u"true");
-        mDecoder->UpdateVideoDecodeMode();
-      }
-      return NS_OK;
-    }
-
-    void RegisterEvent() {
-      MOZ_ASSERT(!mIsRegisteredForEvent);
-      nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
-      if (observerService) {
-        observerService->AddObserver(this, "unselected-tab-hover", false);
-        mIsRegisteredForEvent = true;
-        if (nsContentUtils::IsInStableOrMetaStableState()) {
-          // Events shall not be fired synchronously to prevent anything visible
-          // from the scripts while we are in stable state.
-          if (nsCOMPtr<nsIDocument> doc = GetOwnerDoc()) {
-            doc->Dispatch(TaskCategory::Other,
-              NewRunnableMethod(
-                "MediaDecoder::BackgroundVideoDecodingPermissionObserver::EnableEvent",
-                this, &MediaDecoder::BackgroundVideoDecodingPermissionObserver::EnableEvent));
-          }
-        } else {
-          EnableEvent();
-        }
-      }
-    }
-
-    void UnregisterEvent() {
-      MOZ_ASSERT(mIsRegisteredForEvent);
-      nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
-      if (observerService) {
-        observerService->RemoveObserver(this, "unselected-tab-hover");
-        mIsRegisteredForEvent = false;
-        mDecoder->mIsBackgroundVideoDecodingAllowed = false;
-        mDecoder->UpdateVideoDecodeMode();
-        if (nsContentUtils::IsInStableOrMetaStableState()) {
-          // Events shall not be fired synchronously to prevent anything visible
-          // from the scripts while we are in stable state.
-          if (nsCOMPtr<nsIDocument> doc = GetOwnerDoc()) {
-            doc->Dispatch(TaskCategory::Other,
-              NewRunnableMethod(
-                "MediaDecoder::BackgroundVideoDecodingPermissionObserver::DisableEvent",
-                this, &MediaDecoder::BackgroundVideoDecodingPermissionObserver::DisableEvent));
-          }
-        } else {
-          DisableEvent();
-        }
-      }
-    }
-  private:
-    ~BackgroundVideoDecodingPermissionObserver() {
-      MOZ_ASSERT(!mIsRegisteredForEvent);
-    }
-
-    void EnableEvent() const
-    {
-      nsIDocument* doc = GetOwnerDoc();
-      if (!doc) {
-        return;
-      }
-
-      RefPtr<AsyncEventDispatcher> asyncDispatcher =
-        new AsyncEventDispatcher(doc,
-                                 NS_LITERAL_STRING("UnselectedTabHover:Enable"),
-                                 /* Bubbles */ true,
-                                 /* OnlyChromeDispatch */ true);
-      asyncDispatcher->PostDOMEvent();
-    }
-
-    void DisableEvent() const
-    {
-      nsIDocument* doc = GetOwnerDoc();
-      if (!doc) {
-        return;
-      }
-
-      RefPtr<AsyncEventDispatcher> asyncDispatcher =
-        new AsyncEventDispatcher(doc,
-                                 NS_LITERAL_STRING("UnselectedTabHover:Disable"),
-                                 /* Bubbles */ true,
-                                 /* OnlyChromeDispatch */ true);
-      asyncDispatcher->PostDOMEvent();
-    }
-
-    already_AddRefed<nsPIDOMWindowOuter> GetOwnerWindow() const
-    {
-      nsIDocument* doc = GetOwnerDoc();
-      if (!doc) {
-        return nullptr;
-      }
-
-      nsCOMPtr<nsPIDOMWindowInner> innerWin = doc->GetInnerWindow();
-      if (!innerWin) {
-        return nullptr;
-      }
-
-      nsCOMPtr<nsPIDOMWindowOuter> outerWin = innerWin->GetOuterWindow();
-      if (!outerWin) {
-        return nullptr;
-      }
-
-      nsCOMPtr<nsPIDOMWindowOuter> topWin = outerWin->GetTop();
-      return topWin.forget();
-    }
-
-    nsIDocument* GetOwnerDoc() const
-    {
-      if (!mDecoder->mOwner) {
-        return nullptr;
-      }
-
-      return mDecoder->mOwner->GetDocument();
-    }
-
-    bool IsValidEventSender(nsISupports* aSubject) const
-    {
-      nsCOMPtr<nsPIDOMWindowInner> senderInner(do_QueryInterface(aSubject));
-      if (!senderInner) {
-        return false;
-      }
-
-      nsCOMPtr<nsPIDOMWindowOuter> senderOuter = senderInner->GetOuterWindow();
-      if (!senderOuter) {
-        return false;
-      }
-
-      nsCOMPtr<nsPIDOMWindowOuter> senderTop = senderOuter->GetTop();
-      if (!senderTop) {
-        return false;
-      }
-
-      nsCOMPtr<nsPIDOMWindowOuter> ownerTop = GetOwnerWindow();
-      if (!ownerTop) {
-        return false;
-      }
-
-      return ownerTop == senderTop;
-    }
-    // The life cycle of observer would always be shorter than decoder, so we
-    // use raw pointer here.
-    MediaDecoder* mDecoder;
-    bool mIsRegisteredForEvent;
-};
-
-NS_IMPL_ISUPPORTS(MediaDecoder::BackgroundVideoDecodingPermissionObserver, nsIObserver)
-
 StaticRefPtr<MediaMemoryTracker> MediaMemoryTracker::sUniqueInstance;
 
 LazyLogModule gMediaTimerLog("MediaTimer");
 
 constexpr TimeUnit MediaDecoder::DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED;
 
 void
 MediaDecoder::InitStatics()
@@ -1195,16 +1023,23 @@ MediaDecoder::UpdateVideoDecodeMode()
     LOG("UpdateVideoDecodeMode(), set Normal because the element visible.");
     mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Normal);
   } else {
     LOG("UpdateVideoDecodeMode(), set Suspend because the element is not visible.");
     mDecoderStateMachine->SetVideoDecodeMode(VideoDecodeMode::Suspend);
   }
 }
 
+void
+MediaDecoder::SetIsBackgroundVideoDecodingAllowed(bool aAllowed)
+{
+  mIsBackgroundVideoDecodingAllowed = aAllowed;
+  UpdateVideoDecodeMode();
+}
+
 bool
 MediaDecoder::HasSuspendTaint() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mHasSuspendTaint;
 }
 
 bool
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #if !defined(MediaDecoder_h_)
 #define MediaDecoder_h_
 
+#include "BackgroundVideoDecodingPermissionObserver.h"
 #include "DecoderDoctorDiagnostics.h"
 #include "MediaContainerType.h"
 #include "MediaDecoderOwner.h"
 #include "MediaEventSource.h"
 #include "MediaMetadataManager.h"
 #include "MediaPromiseDefs.h"
 #include "MediaResource.h"
 #include "MediaStatistics.h"
@@ -301,16 +302,18 @@ private:
   // Mark the decoder as tainted, meaning suspend-video-decoder is disabled.
   void SetSuspendTaint(bool aTaint);
 
   // Returns true if the decoder can't participate in suspend-video-decoder.
   bool HasSuspendTaint() const;
 
   void UpdateVideoDecodeMode();
 
+  void SetIsBackgroundVideoDecodingAllowed(bool aAllowed);
+
   /******
    * The following methods must only be called on the main
    * thread.
    ******/
 
   // Change to a new play state. This updates the mState variable and
   // notifies any thread blocking on this object's monitor of the
   // change. Call on the main thread only.
@@ -636,17 +639,16 @@ protected:
 
   // An identifier for the principal of the media. Used to track when
   // main-thread induced principal changes get reflected on MSG thread.
   Canonical<PrincipalHandle> mMediaPrincipalHandle;
 
   // We can allow video decoding in background when we match some special
   // conditions, eg. when the cursor is hovering over the tab. This observer is
   // used to listen the related events.
-  class BackgroundVideoDecodingPermissionObserver;
   RefPtr<BackgroundVideoDecodingPermissionObserver> mVideoDecodingOberver;
 
   // True if we want to resume video decoding even the media element is in the
   // background.
   bool mIsBackgroundVideoDecodingAllowed;
 
 public:
   AbstractCanonical<double>* CanonicalVolume() { return &mVolume; }
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -94,16 +94,17 @@ EXPORTS += [
     'AudioCompactor.h',
     'AudioConverter.h',
     'AudioMixer.h',
     'AudioPacketizer.h',
     'AudioSampleFormat.h',
     'AudioSegment.h',
     'AudioStream.h',
     'AutoplayPolicy.h',
+    'BackgroundVideoDecodingPermissionObserver.h',
     'Benchmark.h',
     'BitReader.h',
     'BufferMediaResource.h',
     'BufferReader.h',
     'ByteWriter.h',
     'ChannelMediaDecoder.h',
     'CubebUtils.h',
     'DecoderTraits.h',
@@ -210,16 +211,17 @@ UNIFIED_SOURCES += [
     'AudioConverter.cpp',
     'AudioDeviceInfo.cpp',
     'AudioSegment.cpp',
     'AudioStream.cpp',
     'AudioStreamTrack.cpp',
     'AudioTrack.cpp',
     'AudioTrackList.cpp',
     'AutoplayPolicy.cpp',
+    'BackgroundVideoDecodingPermissionObserver.cpp',
     'BaseMediaResource.cpp',
     'Benchmark.cpp',
     'BitReader.cpp',
     'CanvasCaptureMediaStream.cpp',
     'ChannelMediaDecoder.cpp',
     'ChannelMediaResource.cpp',
     'CloneableWithRangeMediaResource.cpp',
     'DOMMediaStream.cpp',