Bug 1511235 - part3 : ensure video is visible before starting test r=jya,baku
authorAlastor Wu <alwu@mozilla.com>
Fri, 21 Dec 2018 06:40:10 +0000
changeset 451721 b8a2ab65c479
parent 451720 93ad0a17cde4
child 451722 1d4816ef6e01
push id75169
push useralwu@mozilla.com
push dateFri, 21 Dec 2018 17:32:39 +0000
treeherderautoland@b8a2ab65c479 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, baku
bugs1511235
milestone66.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 1511235 - part3 : ensure video is visible before starting test r=jya,baku Add testing function to know whether video is visible or not. Differential Revision: https://phabricator.services.mozilla.com/D14667
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/test/background_video.js
dom/media/test/test_background_video_cancel_suspend_taint.html
dom/webidl/HTMLMediaElement.webidl
modules/libpref/init/StaticPrefList.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1630,16 +1630,20 @@ void HTMLMediaElement::SetVisible(bool a
     mDecoder->SetForcedHidden(!aVisible);
   }
 }
 
 bool HTMLMediaElement::IsVideoDecodingSuspended() const {
   return mDecoder && mDecoder->IsVideoDecodingSuspended();
 }
 
+bool HTMLMediaElement::IsVisible() const {
+  return mVisibilityState == Visibility::APPROXIMATELY_VISIBLE;
+}
+
 already_AddRefed<layers::Image> HTMLMediaElement::GetCurrentImage() {
   MarkAsTainted();
 
   // TODO: In bug 1345404, handle case when video decoder is already suspended.
   ImageContainer* container = GetImageContainer();
   if (!container) {
     return nullptr;
   }
@@ -6280,16 +6284,19 @@ static const char* VisibilityString(Visi
   return "NAN";
 }
 
 void HTMLMediaElement::OnVisibilityChange(Visibility aNewVisibility) {
   LOG(LogLevel::Debug,
       ("OnVisibilityChange(): %s\n", VisibilityString(aNewVisibility)));
 
   mVisibilityState = aNewVisibility;
+  if (StaticPrefs::MediaTestVideoSuspend()) {
+    DispatchAsyncEvent(NS_LITERAL_STRING("visibilitychanged"));
+  }
 
   if (!mDecoder) {
     return;
   }
 
   switch (aNewVisibility) {
     case Visibility::UNTRACKED: {
       MOZ_ASSERT_UNREACHABLE("Shouldn't notify for untracked visibility");
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -558,16 +558,19 @@ class HTMLMediaElement : public nsGeneri
   void SetVisible(bool aVisible);
 
   // For use by mochitests. Enabling pref "media.test.video-suspend"
   bool HasSuspendTaint() const;
 
   // For use by mochitests.
   bool IsVideoDecodingSuspended() const;
 
+  // For use by mochitests only.
+  bool IsVisible() const;
+
   // Synchronously, return the next video frame and mark the element unable to
   // participate in decode suspending.
   //
   // This function is synchronous for cases where decoding has been suspended
   // and JS needs a frame to use in, eg., nsLayoutUtils::SurfaceFromElement()
   // via drawImage().
   already_AddRefed<layers::Image> GetCurrentImage();
 
--- a/dom/media/test/background_video.js
+++ b/dom/media/test/background_video.js
@@ -43,16 +43,38 @@ function appendVideoToDoc(url, token, wi
   v.token = token;
   v.width = width;
   v.height = height;
   v.src = url;
   document.body.appendChild(v);
   return v;
 }
 
+
+/**
+ * @param {HTMLMediaElement} video Video element with under test.
+ * @returns {Promise} Promise that is resolved when video 'visibilitychanged' event fires.
+ */
+function waitUntilVisible(video) {
+  let videoChrome = SpecialPowers.wrap(video);
+  if (videoChrome.isVisible) {
+    return Promise.resolve();
+  }
+
+  return new Promise(resolve => {
+    videoChrome.addEventListener("visibilitychanged", () => {
+      if (videoChrome.isVisible) {
+        ok(true, `${video.token} is visible.`);
+        videoChrome.removeEventListener("visibilitychanged", this);
+        resolve();
+      }
+    });
+  });
+}
+
 /**
  * @param {HTMLMediaElement} video Video element under test.
  * @returns {Promise} Promise that is resolved when video 'playing' event fires.
  */
 function waitUntilPlaying(video) {
   var p = once(video, 'playing', () => { ok(true, `${video.token} played.`); });
   Log(video.token, "Start playing");
   video.play();
--- a/dom/media/test/test_background_video_cancel_suspend_taint.html
+++ b/dom/media/test/test_background_video_cancel_suspend_taint.html
@@ -55,15 +55,16 @@ startTest({
     [ "media.suspend-bkgnd-video.enabled", true ],
     [ "media.suspend-bkgnd-video.delay-ms", 10000 ]
   ],
   tests: gDecodeSuspendTests,
   runTest: (test, token) => {
     let v = appendVideoToDoc(test.name, token);
     manager.started(token);
 
-    waitUntilPlaying(v)
+    waitUntilVisible(v)
+      .then(() => waitUntilPlaying(v))
       .then(() => testSuspendTimerStartedWhenHidden(v))
       .then(() => testSuspendTimerCanceledWhenTainted(v))
       .then(() => { manager.finished(token); });
   }
 });
-</script>
\ No newline at end of file
+</script>
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -206,26 +206,30 @@ partial interface HTMLMediaElement {
 /*
  * These APIs are testing only, they are used to simulate visibility changes to help debug and write
  * tests about suspend-video-decoding.
  *
  * - SetVisible() is for simulating visibility changes.
  * - HasSuspendTaint() is for querying that the element's decoder cannot suspend
  *   video decoding because it has been tainted by an operation, such as
  *   drawImage().
+ * - isVisible is a boolean value which indicate whether media element is visible.
  * - isVideoDecodingSuspended() is used to know whether video decoding has suspended.
  */
 partial interface HTMLMediaElement {
   [Pref="media.test.video-suspend"]
   void setVisible(boolean aVisible);
 
   [Pref="media.test.video-suspend"]
   boolean hasSuspendTaint();
 
   [ChromeOnly]
+  readonly attribute boolean isVisible;
+
+  [ChromeOnly]
   readonly attribute boolean isVideoDecodingSuspended;
 };
 
 /* Audio Output Devices API */
 partial interface HTMLMediaElement {
   [Pref="media.setsinkid.enabled"]
   readonly attribute DOMString sinkId;
   [Throws, Pref="media.setsinkid.enabled"]
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -1552,16 +1552,22 @@ VARCACHE_PREF(
 )
 
 VARCACHE_PREF(
   "media.benchmark.timeout",
    MediaBenchmarkTimeout,
   RelaxedAtomicUint32, 1000
 )
 
+VARCACHE_PREF(
+  "media.test.video-suspend",
+   MediaTestVideoSuspend,
+  RelaxedAtomicBool, false
+)
+
 //---------------------------------------------------------------------------
 // Network prefs
 //---------------------------------------------------------------------------
 
 // Sub-resources HTTP-authentication:
 //   0 - don't allow sub-resources to open HTTP authentication credentials
 //       dialogs
 //   1 - allow sub-resources to open HTTP authentication credentials dialogs,