diff --git a/mobile/android/geckoview/src/androidTest/assets/www/audio/owl.mp3 b/mobile/android/geckoview/src/androidTest/assets/www/audio/owl.mp3 new file mode 100644 index 000000000000..9fafa32f93b2 Binary files /dev/null and b/mobile/android/geckoview/src/androidTest/assets/www/audio/owl.mp3 differ diff --git a/mobile/android/geckoview/src/androidTest/assets/www/media_session_default1.html b/mobile/android/geckoview/src/androidTest/assets/www/media_session_default1.html new file mode 100644 index 000000000000..34ea6c5b628d --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/assets/www/media_session_default1.html @@ -0,0 +1,13 @@ + + MediaSessionDefaultTest1 + + + + diff --git a/mobile/android/geckoview/src/androidTest/assets/www/media_session_dom1.html b/mobile/android/geckoview/src/androidTest/assets/www/media_session_dom1.html new file mode 100644 index 000000000000..75ea046e5022 --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/assets/www/media_session_dom1.html @@ -0,0 +1,87 @@ + + MediaSessionDOMTest1 + + + + diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt index 49ac424d6588..2ef1ced54688 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt @@ -72,7 +72,8 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) { const val OPEN_WINDOW_TARGET_PATH = "/assets/www/worker/open_window_target.html" const val DATA_URI_PATH = "/assets/www/data_uri.html" const val IFRAME_UNKNOWN_PROTOCOL = "/assets/www/iframe_unknown_protocol.html" - + const val MEDIA_SESSION_DOM1_PATH = "/assets/www/media_session_dom1.html" + const val MEDIA_SESSION_DEFAULT1_PATH = "/assets/www/media_session_default1.html" const val TEST_ENDPOINT = GeckoSessionTestRule.TEST_ENDPOINT } 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 000000000000..deb57a03bf7f --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/MediaSessionTest.kt @@ -0,0 +1,698 @@ +/* -*- 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.filters.MediumTest +import androidx.test.ext.junit.runners.AndroidJUnit4 +import android.util.Log + +import org.hamcrest.Matchers.* +import org.json.JSONObject +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.Assume.assumeThat +import org.junit.Assume.assumeTrue + +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule +import org.mozilla.geckoview.test.util.Callbacks + +import org.mozilla.geckoview.GeckoResult +import org.mozilla.geckoview.GeckoSession +import org.mozilla.geckoview.MediaSession + +class Metadata( + title: String?, + artist: String?, + album: String?) + : MediaSession.Metadata(title, artist, album) {} + +@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.37 + + 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)) + + val DEFAULT_META = arrayOf( + Metadata( + DEFAULT_TEST_TITLE1, + // TODO: enforce null for empty strings? + "", + "")) + } + + @Before + fun setup() { + sessionRule.setPrefsUntilTestEnd(mapOf( + "media.mediacontrol.stopcontrol.aftermediaends" to false, + "dom.media.mediasession.enabled" to true)) + } + + @After + fun teardown() { + } + + @Test + fun domMetadataPlayback() { + val onActivatedCalled = arrayOf(GeckoResult()) + val onMetadataCalled = arrayOf( + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()) + val onPlayCalled = arrayOf(GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()) + val onPauseCalled = arrayOf(GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()) + + // 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]) + + // 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[1], + 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[2], + 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 completedStep8 = GeckoResult.allOf( + onPauseCalled[3], + onMetadataCalled[3], + 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 : Callbacks.MediaSessionDelegate { + @AssertCalled(count = 1) + override fun onActivated( + session: GeckoSession, + mediaSession: MediaSession) { + onActivatedCalled[0].complete(null) + mediaSession1 = 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) + 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))) + + 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) + 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!!.nextTrack() + + sessionRule.waitForResult(completedStep6) + mediaSession1!!.nextTrack() + + sessionRule.waitForResult(completedStep7) + mediaSession1!!.previousTrack() + + sessionRule.waitForResult(completedStep8) + sessionRule.waitForResult(completedStep9) + } + + @Test + fun defaultMetadataPlayback() { + val onActivatedCalled = arrayOf(GeckoResult()) + val onMetadataCalled = arrayOf( + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()) + val onPlayCalled = arrayOf(GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()) + val onPauseCalled = arrayOf(GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()) + + // Test: + // 1. Load Media Session page which contains 1 audio track. + // 2. Track 1 is played on page load. + // a. Ensure onActivated is called. + // a. Ensure onMetadata (1) is called. + // b. 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). + // 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 : Callbacks.MediaSessionDelegate { + @AssertCalled(count = 1) + override fun onActivated( + session: GeckoSession, + mediaSession: MediaSession) { + onActivatedCalled[0].complete(null) + mediaSession1 = mediaSession + } + + /* + TODO: currently not called for non-media-session content. + @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 + + assertThat( + "Core playback constrols should be supported", + play && pause && stop, + equalTo(true)) + } + */ + + @AssertCalled(count = 1) + override fun onMetadata( + session: GeckoSession, + mediaSession: MediaSession, + meta: MediaSession.Metadata) { + assertThat( + "Title should match", + meta.title, + equalTo(DEFAULT_META[0].title)) + assertThat( + "Artist should match", + meta.artist, + equalTo(DEFAULT_META[0].artist)) + assertThat( + "Album should match", + meta.album, + equalTo(DEFAULT_META[0].album)) + + onMetadataCalled[sessionRule.currentCall.counter - 1] + .complete(null) + } + + @AssertCalled(count = 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() { + val onActivatedCalled = arrayOf( + arrayOf(GeckoResult()), + arrayOf(GeckoResult())) + val onMetadataCalled = arrayOf( + arrayOf( + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()), + arrayOf( + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult())) + val onPlayCalled = arrayOf( + arrayOf( + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()), + arrayOf( + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult())) + val onPauseCalled = arrayOf( + arrayOf( + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult()), + arrayOf( + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult(), + GeckoResult())) + + // 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. + // e. Session1: 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 : Callbacks.MediaSessionDelegate { + @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(count = 2) + override fun onMetadata( + session: GeckoSession, + mediaSession: MediaSession, + meta: MediaSession.Metadata) { + onMetadataCalled[0][sessionRule.currentCall.counter - 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))) + } + + @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 : Callbacks.MediaSessionDelegate { + @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(count = 1) + override fun onMetadata( + session: GeckoSession, + mediaSession: MediaSession, + meta: MediaSession.Metadata) { + onMetadataCalled[1][sessionRule.currentCall.counter - 1] + .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!!.nextTrack() + sessionRule.waitForResult(completedStep7) + sessionRule.waitForResult(completedStep8) + } +} diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java index ee356e322aa6..a2631c0828ee 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java @@ -17,6 +17,7 @@ import org.mozilla.geckoview.GeckoResult; import org.mozilla.geckoview.GeckoRuntime; import org.mozilla.geckoview.GeckoSession; import org.mozilla.geckoview.GeckoSessionSettings; +import org.mozilla.geckoview.MediaSession; import org.mozilla.geckoview.RuntimeTelemetry; import org.mozilla.geckoview.SessionTextInput; import org.mozilla.geckoview.WebExtension; @@ -879,6 +880,10 @@ public class GeckoSessionTestRule implements TestRule { return GeckoSession.class.getMethod("setAutofillDelegate", cls) .invoke(session, delegate); } + if (cls == MediaSession.Delegate.class) { + return GeckoSession.class.getMethod("setMediaSessionDelegate", cls) + .invoke(session, delegate); + } return GeckoSession.class.getMethod("set" + cls.getSimpleName(), cls) .invoke(session, delegate); } @@ -898,6 +903,10 @@ public class GeckoSessionTestRule implements TestRule { return GeckoSession.class.getMethod("getAutofillDelegate") .invoke(session); } + if (cls == MediaSession.Delegate.class) { + return GeckoSession.class.getMethod("getMediaSessionDelegate") + .invoke(session); + } return GeckoSession.class.getMethod("get" + cls.getSimpleName()) .invoke(session); } diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/Callbacks.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/Callbacks.kt index 7e726385d99e..636e7d1b1c1b 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/Callbacks.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/util/Callbacks.kt @@ -13,6 +13,7 @@ import org.mozilla.geckoview.GeckoSession import org.mozilla.geckoview.GeckoSession.ContentDelegate.ContextElement import org.mozilla.geckoview.GeckoSession.NavigationDelegate.LoadRequest import org.mozilla.geckoview.MediaElement +import org.mozilla.geckoview.MediaSession import org.mozilla.geckoview.WebRequestError import android.view.inputmethod.CursorAnchorInfo @@ -24,7 +25,7 @@ class Callbacks private constructor() { object Default : All interface All : AutofillDelegate, ContentBlockingDelegate, ContentDelegate, - HistoryDelegate, MediaDelegate, + HistoryDelegate, MediaDelegate, MediaSessionDelegate, NavigationDelegate, PermissionDelegate, ProgressDelegate, PromptDelegate, ScrollDelegate, SelectionActionDelegate, TextInputDelegate @@ -40,6 +41,7 @@ class Callbacks private constructor() { interface SelectionActionDelegate : GeckoSession.SelectionActionDelegate {} interface MediaDelegate: GeckoSession.MediaDelegate {} interface HistoryDelegate : GeckoSession.HistoryDelegate {} + interface MediaSessionDelegate: MediaSession.Delegate {} interface TextInputDelegate : GeckoSession.TextInputDelegate { override fun restartInput(session: GeckoSession, reason: Int) {