Bug 1623715 - [2.4] Add MediaSession API tests. r=geckoview-reviewers,droeh,snorp

Differential Revision: https://phabricator.services.mozilla.com/D84190
This commit is contained in:
Eugen Sawin 2020-08-18 14:37:21 +00:00
Родитель 0c4fd16ae8
Коммит 38e22e79a2
7 изменённых файлов: 812 добавлений и 2 удалений

Двоичные данные
mobile/android/geckoview/src/androidTest/assets/www/audio/owl.mp3 Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,13 @@
<html>
<head><title>MediaSessionDefaultTest1</title></head>
<body>
<script>
const audio1 = document.createElement("audio");
audio1.src = "audio/owl.mp3";
window.onload = () => {
audio1.play();
};
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,87 @@
<html>
<head><title>MediaSessionDOMTest1</title></head>
<body>
<script>
function updatePositionState(event) {
navigator.mediaSession.setPositionState({
duration: parseFloat(event.target.duration),
position: parseFloat(event.target.currentTime),
playbackRate: 1,
});
}
function updateMetadata(event) {
active.removeEventListener("timeupdate", updatePositionState);
active = event.target;
updatePositionState(event);
active.addEventListener("timeupdate", updatePositionState);
navigator.mediaSession.metadata = active.metadata;
}
function getTrack(offset) {
console.log("" + active.id + " " + offset);
const nextId = Math.min(tracks.length - 1,
Math.max(0, parseInt(active.id) + offset));
return tracks[nextId];
}
navigator.mediaSession.setActionHandler("play", () => {
active.play();
});
navigator.mediaSession.setActionHandler("pause", () => {
active.pause();
});
navigator.mediaSession.setActionHandler("previoustrack", () => {
active.pause();
getTrack(-1).play();
});
navigator.mediaSession.setActionHandler("nexttrack", () => {
active.pause();
getTrack(1).play();
});
const audio1 = document.createElement("audio");
audio1.src = "audio/owl.mp3";
audio1.addEventListener("play", updateMetadata);
audio1.metadata = new window.MediaMetadata({
title: "hoot",
artist: "owl",
album: "hoots",
artwork: [{src: "owl.png", type: "image/png", sizes: "16x16 32x32"}]
});
audio1.id = 0;
const audio2 = document.createElement("audio");
audio2.src = "audio/owl.mp3";
audio2.addEventListener("play", updateMetadata);
audio2.metadata = new window.MediaMetadata({
title: "hoot2",
artist: "stillowl",
album: "dahoots",
artwork: [{src: "owl.png", type: "image/png", sizes: "16x16 32x32"}]
});
audio2.id = 1;
const audio3 = document.createElement("audio");
audio3.src = "audio/owl.mp3";
audio3.addEventListener("play", updateMetadata);
audio3.metadata = new window.MediaMetadata({
title: "hoot3",
artist: "immaowl",
album: "mahoots",
artwork: [{src: "owl.png", type: "image/png", sizes: "16x16 32x32"}]
});
audio3.id = 2;
const tracks = [audio1, audio2, audio3];
let active = audio1;
window.onload = () => {
getTrack(0).play();
};
</script>
</body>
</html>

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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<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])
// 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<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 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<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.
// 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)
}
}

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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) {