Bug 1467350 - Make HTMLMediaElement::mPaused Watchable and update Wakelock status via a watcher. r=jya
authorChris Pearce <cpearce@mozilla.com>
Mon, 21 May 2018 14:19:47 +1200
changeset 475938 765bb540a814f6565484f69cc3de7b8ea28300d2
parent 475937 9e55688e043f1374b259e9844c97d46491506eab
child 475939 2ad747fb382a7ee26512d4d6f9f365f5933a8913
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1467350
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1467350 - Make HTMLMediaElement::mPaused Watchable and update Wakelock status via a watcher. r=jya We currently observe changes to HTMLMediaElement::mPaused via a hand-rolled wrapper class. We can use use mozilla::Watchable<> and avoid rolling our own equivalent here. This also paves the way for using state watching on other observable state in HTMLMediaElement. MozReview-Commit-ID: 4lBlJiV15iG
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3879,29 +3879,32 @@ private:
   Phase mPhase = Phase::Init;
 };
 
 NS_IMPL_ISUPPORTS(HTMLMediaElement::ShutdownObserver, nsIObserver)
 
 HTMLMediaElement::HTMLMediaElement(
   already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
+  , mWatchManager(this, OwnerDoc()->AbstractMainThreadFor(TaskCategory::Other))
   , mMainThreadEventTarget(OwnerDoc()->EventTargetFor(TaskCategory::Other))
   , mAbstractMainThread(OwnerDoc()->AbstractMainThreadFor(TaskCategory::Other))
   , mShutdownObserver(new ShutdownObserver)
   , mPlayed(new TimeRanges(ToSupports(OwnerDoc())))
-  , mPaused(true, *this)
+  , mPaused(true, "HTMLMediaElement::mPaused")
   , mErrorSink(new ErrorSink(this))
   , mAudioChannelWrapper(new AudioChannelAgentCallback(this))
 {
   MOZ_ASSERT(mMainThreadEventTarget);
   MOZ_ASSERT(mAbstractMainThread);
 
   DecoderDoctorLogger::LogConstruction(this);
 
+  mWatchManager.Watch(mPaused, &HTMLMediaElement::UpdateWakeLock);
+
   ErrorResult rv;
 
   double defaultVolume = Preferences::GetFloat("media.default_volume", 1.0);
   SetVolume(defaultVolume, rv);
 
   RegisterActivityObserver();
   NotifyOwnerDocumentActivityChanged();
 
@@ -4175,41 +4178,30 @@ HTMLMediaElement::PlayInternal(ErrorResu
 void
 HTMLMediaElement::MaybeDoLoad()
 {
   if (mNetworkState == NETWORK_EMPTY) {
     DoLoad();
   }
 }
 
-HTMLMediaElement::WakeLockBoolWrapper&
-HTMLMediaElement::WakeLockBoolWrapper::operator=(bool val)
-{
-  if (mValue == val) {
-    return *this;
-  }
-
-  mValue = val;
-  UpdateWakeLock();
-  return *this;
-}
-
-void
-HTMLMediaElement::WakeLockBoolWrapper::UpdateWakeLock()
+void
+HTMLMediaElement::UpdateWakeLock()
 {
   MOZ_ASSERT(NS_IsMainThread());
-
-  bool playing = !mValue;
+  // Ensure we have a wake lock if we're playing audibly. This ensures the
+  // device doesn't sleep while playing.
+  bool playing = !mPaused;
   bool isAudible =
-    mOuter.Volume() > 0.0 && !mOuter.mMuted && mOuter.mIsAudioTrackAudible;
-  // when playing audible media.
+    Volume() > 0.0 && !mMuted && mIsAudioTrackAudible;
+  // WakeLock when playing audible media.
   if (playing && isAudible) {
-    mOuter.WakeLockCreate();
+    WakeLockCreate();
   } else {
-    mOuter.WakeLockRelease();
+    WakeLockRelease();
   }
 }
 
 void
 HTMLMediaElement::WakeLockCreate()
 {
   if (!mWakeLock) {
     RefPtr<power::PowerManagerService> pmService =
@@ -7544,17 +7536,17 @@ HTMLMediaElement::SetAudibleState(bool a
 
 void
 HTMLMediaElement::NotifyAudioPlaybackChanged(AudibleChangedReasons aReason)
 {
   if (mAudioChannelWrapper) {
     mAudioChannelWrapper->NotifyAudioPlaybackChanged(aReason);
   }
   // only request wake lock for audible media.
-  mPaused.UpdateWakeLock();
+  UpdateWakeLock();
 }
 
 bool
 HTMLMediaElement::ShouldElementBePaused()
 {
   // Bfcached page or inactive document.
   if (!IsActive()) {
     return true;
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -834,36 +834,17 @@ protected:
   class StreamListener;
   class StreamSizeListener;
   class ShutdownObserver;
 
   MediaDecoderOwner::NextFrameStatus NextFrameStatus();
 
   void SetDecoder(MediaDecoder* aDecoder);
 
-  class WakeLockBoolWrapper {
-  public:
-    WakeLockBoolWrapper(bool aVal, HTMLMediaElement& aOuter)
-      : mValue(aVal)
-      , mOuter(aOuter)
-    {}
-
-    ~WakeLockBoolWrapper() {};
-
-    MOZ_IMPLICIT operator bool() const { return mValue; }
-
-    WakeLockBoolWrapper& operator=(bool val);
-
-    bool operator !() const { return !mValue; }
-
-    void UpdateWakeLock();
-  private:
-    bool mValue;
-    HTMLMediaElement& mOuter;
-  };
+  void UpdateWakeLock();
 
   // Holds references to the DOM wrappers for the MediaStreams that we're
   // writing to.
   struct OutputMediaStream {
     OutputMediaStream();
     ~OutputMediaStream();
 
     RefPtr<DOMMediaStream> mStream;
@@ -891,18 +872,18 @@ protected:
 
   /**
    * Use this method to change the mNetworkState member, so required
    * actions will be taken during the transition.
    */
   void ChangeNetworkState(nsMediaNetworkState aState);
 
   /**
-   * These two methods are called by the WakeLockBoolWrapper when the wakelock
-   * has to be created or released.
+   * These two methods are called when mPaused is changed to ensure we have
+   * a wake lock active when we're playing audibly.
    */
   virtual void WakeLockCreate();
   virtual void WakeLockRelease();
   RefPtr<WakeLock> mWakeLock;
 
   /**
    * Logs a warning message to the web console to report various failures.
    * aMsg is the localized message identifier, aParams is the parameters to
@@ -1368,16 +1349,18 @@ protected:
   bool AttachNewMediaKeys();
   bool TryMakeAssociationWithCDM(CDMProxy* aProxy);
   void MakeAssociationWithCDMResolved();
   void SetCDMProxyFailure(const MediaResult& aResult);
   void ResetSetMediaKeysTempVariables();
 
   void PauseIfShouldNotBePlaying();
 
+  WatchManager<HTMLMediaElement> mWatchManager;
+
   // The current decoder. Load() has been called on this decoder.
   // At most one of mDecoder and mSrcStream can be non-null.
   RefPtr<MediaDecoder> mDecoder;
 
   // The DocGroup-specific nsISerialEventTarget of this HTML element on the main
   // thread.
   nsCOMPtr<nsISerialEventTarget> mMainThreadEventTarget;
 
@@ -1595,17 +1578,17 @@ protected:
   // start playing when loaded. The 'autoplay' attribute of the object
   // is a mirror of the HTML attribute. These are different from this
   // 'mAutoplaying' flag, which indicates whether the current playback
   // is a result of the autoplay attribute.
   bool mAutoplaying = true;
 
   // Playback of the video is paused either due to calling the
   // 'Pause' method, or playback not yet having started.
-  WakeLockBoolWrapper mPaused;
+  Watchable<bool> mPaused;
 
   // The following two fields are here for the private storage of the builtin
   // video controls, and control 'casting' of the video to external devices
   // (TVs, projectors etc.)
   // True if casting is currently allowed
   bool mAllowCasting = false;
   // True if currently casting this video
   bool mIsCasting = false;