diff options
Diffstat (limited to 'mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/MediaSessionTest.kt')
-rw-r--r-- | mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/MediaSessionTest.kt | 1031 |
1 files changed, 1031 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/MediaSessionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/MediaSessionTest.kt new file mode 100644 index 0000000000..ac0e69663c --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/MediaSessionTest.kt @@ -0,0 +1,1031 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +package org.mozilla.geckoview.test + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.MediumTest +import org.hamcrest.Matchers.* // ktlint-disable no-wildcard-imports +import org.junit.After +import org.junit.Assume.assumeThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.geckoview.GeckoResult +import org.mozilla.geckoview.GeckoSession +import org.mozilla.geckoview.MediaSession +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled + +class Metadata( + title: String?, + artist: String?, + album: String?, +) : + MediaSession.Metadata(title, artist, album, null) + +@RunWith(AndroidJUnit4::class) +@MediumTest +class MediaSessionTest : BaseSessionTest() { + companion object { + // See MEDIA_SESSION_DOM1_PATH file for details. + const val DOM_TEST_TITLE1 = "hoot" + const val DOM_TEST_TITLE2 = "hoot2" + const val DOM_TEST_TITLE3 = "hoot3" + const val DOM_TEST_ARTIST1 = "owl" + const val DOM_TEST_ARTIST2 = "stillowl" + const val DOM_TEST_ARTIST3 = "immaowl" + const val DOM_TEST_ALBUM1 = "hoots" + const val DOM_TEST_ALBUM2 = "dahoots" + const val DOM_TEST_ALBUM3 = "mahoots" + const val DEFAULT_TEST_TITLE1 = "MediaSessionDefaultTest1" + const val TEST_DURATION1 = 3.34 + const val WEBM_TEST_DURATION = 5.59 + const val WEBM_TEST_WIDTH = 560L + const val WEBM_TEST_HEIGHT = 320L + + val DOM_META = arrayOf( + Metadata( + DOM_TEST_TITLE1, + DOM_TEST_ARTIST1, + DOM_TEST_ALBUM1, + ), + Metadata( + DOM_TEST_TITLE2, + DOM_TEST_ARTIST2, + DOM_TEST_ALBUM2, + ), + Metadata( + DOM_TEST_TITLE3, + DOM_TEST_ARTIST3, + DOM_TEST_ALBUM3, + ), + ) + } + + @Before + fun setup() { + sessionRule.setPrefsUntilTestEnd( + mapOf( + "media.mediacontrol.stopcontrol.aftermediaends" to false, + "dom.media.mediasession.enabled" to true, + ), + ) + } + + @After + fun teardown() { + } + + @Test + fun domMetadataPlayback() { + // TODO: needs bug 1700243 + assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) + + val onActivatedCalled = arrayOf(GeckoResult<Void>()) + val onMetadataCalled = arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ) + val onPlayCalled = arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ) + val onPauseCalled = arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ) + + // Test: + // 1. Load DOM Media Session page which contains 3 audio tracks. + // 2. Track 1 is played on page load. + // a. Ensure onActivated is called. + // b. Ensure onMetadata (1) is called. + // c. Ensure onPlay (1) is called. + val completedStep2 = GeckoResult.allOf( + onActivatedCalled[0], + onMetadataCalled[0], + onPlayCalled[0], + ) + + // 3. Pause playback of track 1. + // a. Ensure onPause (1) is called. + val completedStep3 = GeckoResult.allOf( + onPauseCalled[0], + ) + + // 4. Resume playback (1). + // a. Ensure onMetadata (1) is called. + // b. Ensure onPlay (1) is called. + val completedStep4 = GeckoResult.allOf( + onPlayCalled[1], + onMetadataCalled[1], + ) + + // 5. Wait for track 1 end. + // a. Ensure onPause (1) is called. + val completedStep5 = GeckoResult.allOf( + onPauseCalled[1], + ) + + // 6. Play next track (2). + // a. Ensure onMetadata (2) is called. + // b. Ensure onPlay (2) is called. + val completedStep6 = GeckoResult.allOf( + onMetadataCalled[2], + onPlayCalled[2], + ) + + // 7. Play next track (3). + // a. Ensure onPause (2) is called. + // b. Ensure onMetadata (3) is called. + // c. Ensure onPlay (3) is called. + val completedStep7 = GeckoResult.allOf( + onPauseCalled[2], + onMetadataCalled[3], + onPlayCalled[3], + ) + + // 8. Play previous track (2). + // a. Ensure onPause (3) is called. + // b. Ensure onMetadata (2) is called. + // c. Ensure onPlay (2) is called. + val completedStep8a = GeckoResult.allOf( + onPauseCalled[3], + ) + // Without the split, this seems to race and we don't get the pause event. + val completedStep8b = GeckoResult.allOf( + onMetadataCalled[4], + onPlayCalled[4], + ) + + // 9. Wait for track 2 end. + // a. Ensure onPause (2) is called. + val completedStep9 = GeckoResult.allOf( + onPauseCalled[4], + ) + + val path = MEDIA_SESSION_DOM1_PATH + val session1 = sessionRule.createOpenSession() + + var mediaSession1: MediaSession? = null + // 1. + session1.loadTestPath(path) + + session1.delegateUntilTestEnd(object : MediaSession.Delegate { + @AssertCalled(count = 1, order = [1]) + override fun onActivated( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onActivatedCalled[0].complete(null) + mediaSession1 = mediaSession + } + + @AssertCalled(false) + override fun onDeactivated( + session: GeckoSession, + mediaSession: MediaSession, + ) { + } + + @AssertCalled + override fun onFeatures( + session: GeckoSession, + mediaSession: MediaSession, + features: Long, + ) { + val play = (features and MediaSession.Feature.PLAY) != 0L + val pause = (features and MediaSession.Feature.PAUSE) != 0L + val stop = (features and MediaSession.Feature.PAUSE) != 0L + val next = (features and MediaSession.Feature.PAUSE) != 0L + val prev = (features and MediaSession.Feature.PAUSE) != 0L + + assertThat( + "Playback constrols should be supported", + play && pause && stop && next && prev, + equalTo(true), + ) + } + + @AssertCalled(count = 5, order = [2]) + override fun onMetadata( + session: GeckoSession, + mediaSession: MediaSession, + meta: MediaSession.Metadata, + ) { + assertThat( + "Title should match", + meta.title, + equalTo( + forEachCall( + DOM_META[0].title, + DOM_META[0].title, + DOM_META[1].title, + DOM_META[2].title, + DOM_META[1].title, + ), + ), + ) + assertThat( + "Artist should match", + meta.artist, + equalTo( + forEachCall( + DOM_META[0].artist, + DOM_META[0].artist, + DOM_META[1].artist, + DOM_META[2].artist, + DOM_META[1].artist, + ), + ), + ) + assertThat( + "Album should match", + meta.album, + equalTo( + forEachCall( + DOM_META[0].album, + DOM_META[0].album, + DOM_META[1].album, + DOM_META[2].album, + DOM_META[1].album, + ), + ), + ) + assertThat( + "Artwork image should be non-null", + meta.artwork!!.getBitmap(200), + notNullValue(), + ) + + onMetadataCalled[sessionRule.currentCall.counter - 1] + .complete(null) + } + + @AssertCalled + override fun onPositionState( + session: GeckoSession, + mediaSession: MediaSession, + state: MediaSession.PositionState, + ) { + assertThat( + "Duration should match", + state.duration, + closeTo(TEST_DURATION1, 0.01), + ) + + assertThat( + "Playback rate should match", + state.playbackRate, + closeTo(1.0, 0.01), + ) + + assertThat( + "Position should be >= 0", + state.position, + greaterThanOrEqualTo(0.0), + ) + } + + @AssertCalled(count = 5, order = [2]) + override fun onPlay( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPlayCalled[sessionRule.currentCall.counter - 1] + .complete(null) + } + + @AssertCalled(count = 5) + override fun onPause( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPauseCalled[sessionRule.currentCall.counter - 1] + .complete(null) + } + }) + + sessionRule.waitForResult(completedStep2) + mediaSession1!!.pause() + + sessionRule.waitForResult(completedStep3) + mediaSession1!!.play() + + sessionRule.waitForResult(completedStep4) + sessionRule.waitForResult(completedStep5) + mediaSession1!!.pause() + mediaSession1!!.nextTrack() + mediaSession1!!.play() + + sessionRule.waitForResult(completedStep6) + mediaSession1!!.pause() + mediaSession1!!.nextTrack() + mediaSession1!!.play() + + sessionRule.waitForResult(completedStep7) + mediaSession1!!.pause() + + sessionRule.waitForResult(completedStep8a) + mediaSession1!!.previousTrack() + mediaSession1!!.play() + + sessionRule.waitForResult(completedStep8b) + sessionRule.waitForResult(completedStep9) + } + + @Test + fun defaultMetadataPlayback() { + // TODO: needs bug 1700243 + assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) + + val onActivatedCalled = arrayOf(GeckoResult<Void>()) + val onPlayCalled = arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ) + val onPauseCalled = arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ) + + // Test: + // 1. Load Media Session page which contains 1 audio track. + // 2. Track 1 is played on page load. + // a. Ensure onActivated is called. + // b. Ensure onPlay (1) is called. + val completedStep2 = GeckoResult.allOf( + onActivatedCalled[0], + onPlayCalled[0], + ) + + // 3. Pause playback of track 1. + // a. Ensure onPause (1) is called. + val completedStep3 = GeckoResult.allOf( + onPauseCalled[0], + ) + + // 4. Resume playback (1). + // b. Ensure onPlay (1) is called. + val completedStep4 = GeckoResult.allOf( + onPlayCalled[1], + ) + + // 5. Wait for track 1 end. + // a. Ensure onPause (1) is called. + val completedStep5 = GeckoResult.allOf( + onPauseCalled[1], + ) + + val path = MEDIA_SESSION_DEFAULT1_PATH + val session1 = sessionRule.createOpenSession() + + var mediaSession1: MediaSession? = null + // 1. + session1.loadTestPath(path) + + session1.delegateUntilTestEnd(object : MediaSession.Delegate { + @AssertCalled(count = 1, order = [1]) + override fun onActivated( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onActivatedCalled[0].complete(null) + mediaSession1 = mediaSession + } + + @AssertCalled(count = 2, order = [2]) + override fun onPlay( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPlayCalled[sessionRule.currentCall.counter - 1] + .complete(null) + } + + @AssertCalled(count = 2) + override fun onPause( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPauseCalled[sessionRule.currentCall.counter - 1] + .complete(null) + } + }) + + sessionRule.waitForResult(completedStep2) + mediaSession1!!.pause() + + sessionRule.waitForResult(completedStep3) + mediaSession1!!.play() + + sessionRule.waitForResult(completedStep4) + sessionRule.waitForResult(completedStep5) + } + + @Test + fun domMultiSessions() { + // TODO: needs bug 1700243 + assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) + + val onActivatedCalled = arrayOf( + arrayOf(GeckoResult<Void>()), + arrayOf(GeckoResult<Void>()), + ) + val onMetadataCalled = arrayOf( + arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ), + arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ), + ) + val onPlayCalled = arrayOf( + arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ), + arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ), + ) + val onPauseCalled = arrayOf( + arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ), + arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + GeckoResult<Void>(), + ), + ) + + // Test: + // 1. Session1: Load DOM Media Session page with 3 audio tracks. + // 2. Session1: Track 1 is played on page load. + // a. Session1: Ensure onActivated is called. + // b. Session1: Ensure onMetadata (1) is called. + // c. Session1: Ensure onPlay (1) is called. + // d. Session1: Verify isActive. + val completedStep2 = GeckoResult.allOf( + onActivatedCalled[0][0], + onMetadataCalled[0][0], + onPlayCalled[0][0], + ) + + // 3. Session1: Pause playback of track 1. + // a. Session1: Ensure onPause (1) is called. + val completedStep3 = GeckoResult.allOf( + onPauseCalled[0][0], + ) + + // 4. Session2: Load DOM Media Session page with 3 audio tracks. + // 5. Session2: Track 1 is played on page load. + // a. Session2: Ensure onActivated is called. + // b. Session2: Ensure onMetadata (1) is called. + // c. Session2: Ensure onPlay (1) is called. + // d. Session2: Verify isActive. + val completedStep5 = GeckoResult.allOf( + onActivatedCalled[1][0], + onMetadataCalled[1][0], + onPlayCalled[1][0], + ) + + // 6. Session2: Pause playback of track 1. + // a. Session2: Ensure onPause (1) is called. + val completedStep6 = GeckoResult.allOf( + onPauseCalled[1][0], + ) + + // 7. Session1: Play next track (2). + // a. Session1: Ensure onMetadata (2) is called. + // b. Session1: Ensure onPlay (2) is called. + val completedStep7 = GeckoResult.allOf( + onMetadataCalled[0][1], + onPlayCalled[0][1], + ) + + // 8. Session1: wait for track 1 end. + // a. Ensure onPause (1) is called. + val completedStep8 = GeckoResult.allOf( + onPauseCalled[0][1], + ) + + val path = MEDIA_SESSION_DOM1_PATH + val session1 = sessionRule.createOpenSession() + val session2 = sessionRule.createOpenSession() + var mediaSession1: MediaSession? = null + var mediaSession2: MediaSession? = null + + session1.delegateUntilTestEnd(object : MediaSession.Delegate { + @AssertCalled(count = 1) + override fun onActivated( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onActivatedCalled[0][sessionRule.currentCall.counter - 1] + .complete(null) + mediaSession1 = mediaSession + + assertThat( + "Should be active", + mediaSession1?.isActive, + equalTo(true), + ) + } + + @AssertCalled + override fun onPositionState( + session: GeckoSession, + mediaSession: MediaSession, + state: MediaSession.PositionState, + ) { + assertThat( + "Duration should match", + state.duration, + closeTo(TEST_DURATION1, 0.01), + ) + + assertThat( + "Playback rate should match", + state.playbackRate, + closeTo(1.0, 0.01), + ) + + assertThat( + "Position should be >= 0", + state.position, + greaterThanOrEqualTo(0.0), + ) + } + + @AssertCalled + override fun onFeatures( + session: GeckoSession, + mediaSession: MediaSession, + features: Long, + ) { + val play = (features and MediaSession.Feature.PLAY) != 0L + val pause = (features and MediaSession.Feature.PAUSE) != 0L + val stop = (features and MediaSession.Feature.PAUSE) != 0L + val next = (features and MediaSession.Feature.PAUSE) != 0L + val prev = (features and MediaSession.Feature.PAUSE) != 0L + + assertThat( + "Playback constrols should be supported", + play && pause && stop && next && prev, + equalTo(true), + ) + } + + @AssertCalled + override fun onMetadata( + session: GeckoSession, + mediaSession: MediaSession, + meta: MediaSession.Metadata, + ) { + val count = sessionRule.currentCall.counter + if (count < 3) { + // Ignore redundant calls. + onMetadataCalled[0][count - 1].complete(null) + } + + assertThat( + "Title should match", + meta.title, + equalTo( + forEachCall( + DOM_META[0].title, + DOM_META[1].title, + ), + ), + ) + assertThat( + "Artist should match", + meta.artist, + equalTo( + forEachCall( + DOM_META[0].artist, + DOM_META[1].artist, + ), + ), + ) + assertThat( + "Album should match", + meta.album, + equalTo( + forEachCall( + DOM_META[0].album, + DOM_META[1].album, + ), + ), + ) + assertThat( + "Artwork image should be non-null", + meta.artwork!!.getBitmap(200), + notNullValue(), + ) + } + + @AssertCalled(count = 2) + override fun onPlay( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPlayCalled[0][sessionRule.currentCall.counter - 1] + .complete(null) + } + + @AssertCalled(count = 2) + override fun onPause( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPauseCalled[0][sessionRule.currentCall.counter - 1] + .complete(null) + } + }) + + session2.delegateUntilTestEnd(object : MediaSession.Delegate { + @AssertCalled(count = 1) + override fun onActivated( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onActivatedCalled[1][sessionRule.currentCall.counter - 1] + .complete(null) + mediaSession2 = mediaSession + + assertThat( + "Should be active", + mediaSession1!!.isActive, + equalTo(true), + ) + assertThat( + "Should be active", + mediaSession2!!.isActive, + equalTo(true), + ) + } + + @AssertCalled + override fun onMetadata( + session: GeckoSession, + mediaSession: MediaSession, + meta: MediaSession.Metadata, + ) { + val count = sessionRule.currentCall.counter + if (count < 2) { + // Ignore redundant calls. + onMetadataCalled[1][0].complete(null) + } + + assertThat( + "Title should match", + meta.title, + equalTo( + forEachCall( + DOM_META[0].title, + ), + ), + ) + assertThat( + "Artist should match", + meta.artist, + equalTo( + forEachCall( + DOM_META[0].artist, + ), + ), + ) + assertThat( + "Album should match", + meta.album, + equalTo( + forEachCall( + DOM_META[0].album, + ), + ), + ) + } + + @AssertCalled(count = 1) + override fun onPlay( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPlayCalled[1][sessionRule.currentCall.counter - 1] + .complete(null) + } + + @AssertCalled(count = 1) + override fun onPause( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPauseCalled[1][sessionRule.currentCall.counter - 1] + .complete(null) + } + }) + + session1.loadTestPath(path) + sessionRule.waitForResult(completedStep2) + + mediaSession1!!.pause() + sessionRule.waitForResult(completedStep3) + + session2.loadTestPath(path) + sessionRule.waitForResult(completedStep5) + + mediaSession2!!.pause() + sessionRule.waitForResult(completedStep6) + + mediaSession1!!.pause() + mediaSession1!!.nextTrack() + mediaSession1!!.play() + sessionRule.waitForResult(completedStep7) + sessionRule.waitForResult(completedStep8) + } + + @Test + fun fullscreenVideoElementMetadata() { + // TODO: bug 1810736 + assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) + + sessionRule.setPrefsUntilTestEnd( + mapOf( + "media.autoplay.default" to 0, + "full-screen-api.allow-trusted-requests-only" to false, + ), + ) + + val onActivatedCalled = GeckoResult<Void>() + val onPlayCalled = GeckoResult<Void>() + val onPauseCalled = GeckoResult<Void>() + val onFullscreenCalled = arrayOf( + GeckoResult<Void>(), + GeckoResult<Void>(), + ) + + // Test: + // 1. Load video test page which contains 1 video element. + // a. Ensure page has loaded. + // 2. Play video element. + // a. Ensure onActivated is called. + // b. Ensure onPlay is called. + val completedStep2 = GeckoResult.allOf( + onActivatedCalled, + onPlayCalled, + ) + + // 3. Enter fullscreen of the video. + // a. Ensure onFullscreen is called. + val completedStep3 = GeckoResult.allOf( + onFullscreenCalled[0], + ) + + // 4. Exit fullscreen of the video. + // a. Ensure onFullscreen is called. + val completedStep4 = GeckoResult.allOf( + onFullscreenCalled[1], + ) + + // 5. Pause the video. + // a. Ensure onPause is called. + val completedStep5 = GeckoResult.allOf( + onPauseCalled, + ) + + var mediaSession1: MediaSession? = null + + val path = VIDEO_WEBM_PATH + val session1 = sessionRule.createOpenSession() + + session1.delegateUntilTestEnd(object : MediaSession.Delegate { + @AssertCalled(count = 1, order = [1]) + override fun onActivated( + session: GeckoSession, + mediaSession: MediaSession, + ) { + mediaSession1 = mediaSession + + onActivatedCalled.complete(null) + + assertThat( + "Should be active", + mediaSession.isActive, + equalTo(true), + ) + } + + @AssertCalled(count = 1, order = [2]) + override fun onPlay( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPlayCalled.complete(null) + } + + @AssertCalled(count = 1) + override fun onPause( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPauseCalled.complete(null) + } + + @AssertCalled(count = 2) + override fun onFullscreen( + session: GeckoSession, + mediaSession: MediaSession, + enabled: Boolean, + meta: MediaSession.ElementMetadata?, + ) { + if (sessionRule.currentCall.counter == 1) { + assertThat( + "Fullscreen should be enabled", + enabled, + equalTo(true), + ) + assertThat( + "Element metadata should exist", + meta, + notNullValue(), + ) + assertThat( + "Duration should match", + meta!!.duration, + closeTo(WEBM_TEST_DURATION, 0.01), + ) + assertThat( + "Width should match", + meta.width, + equalTo(WEBM_TEST_WIDTH), + ) + assertThat( + "Height should match", + meta.height, + equalTo(WEBM_TEST_HEIGHT), + ) + assertThat( + "Audio track count should match", + meta.audioTrackCount, + equalTo(1), + ) + assertThat( + "Video track count should match", + meta.videoTrackCount, + equalTo(1), + ) + } else { + assertThat( + "Fullscreen should be disabled", + enabled, + equalTo(false), + ) + } + + onFullscreenCalled[sessionRule.currentCall.counter - 1] + .complete(null) + } + }) + + // 1. + session1.loadTestPath(path) + sessionRule.waitForPageStop() + + // 2. + session1.evaluateJS("document.querySelector('video').play()") + sessionRule.waitForResult(completedStep2) + + // 3. + session1.evaluateJS( + "document.querySelector('video').requestFullscreen()", + ) + sessionRule.waitForResult(completedStep3) + + // 4. + session1.evaluateJS("document.exitFullscreen()") + sessionRule.waitForResult(completedStep4) + + // 5. + mediaSession1!!.pause() + sessionRule.waitForResult(completedStep5) + } + + @Test + fun fullscreenVideoWithActivated() { + // TODO: bug 1810736 + assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) + + sessionRule.setPrefsUntilTestEnd( + mapOf( + "media.autoplay.default" to 0, + "full-screen-api.allow-trusted-requests-only" to false, + ), + ) + + val path = VIDEO_WEBM_PATH + val session = sessionRule.createOpenSession() + val resultFullscreen = GeckoResult<Void>() + session.loadTestPath(path) + sessionRule.waitForPageStop() + + session.delegateDuringNextWait(object : MediaSession.Delegate { + override fun onFullscreen( + session: GeckoSession, + mediaSession: MediaSession, + enabled: Boolean, + meta: MediaSession.ElementMetadata?, + ) { + assertThat( + "Fullscreen should be enabled", + enabled, + equalTo(true), + ) + assertThat( + "Element metadata should exist", + meta, + notNullValue(), + ) + resultFullscreen.complete(null) + } + }) + + session.evaluateJS("document.querySelector('video').requestFullscreen()") + sessionRule.waitForResult(resultFullscreen) + } + + @Test + fun switchingProcess() { + // TODO: bug 1810736 + assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false)) + + sessionRule.setPrefsUntilTestEnd( + mapOf( + "media.autoplay.default" to 0, + ), + ) + + mainSession.loadUri("about:blank") + sessionRule.waitForPageStop() + + mainSession.loadTestPath(VIDEO_WEBM_PATH) + sessionRule.waitForPageStop() + + val onPlayCalled = GeckoResult<Void>() + mainSession.delegateUntilTestEnd(object : MediaSession.Delegate { + @AssertCalled(count = 1) + override fun onPlay( + session: GeckoSession, + mediaSession: MediaSession, + ) { + onPlayCalled.complete(null) + } + }) + + mainSession.evaluateJS("document.querySelector('video').play()") + sessionRule.waitForResult(onPlayCalled) + } +} |