зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1819814 - Call MediaSession.Delegate.onFullscreen correctly when entering full screen. r=geckoview-reviewers,calu
This is a race condition of full screen event and activated event of media controller. Media controller will dispatch activated event when full screen button is clicked on controller. But since this depends on full screen event, if GeckoView's media session receives this event before controller fires activated event, `MediaSession.Delegate.onFullscreen` won't be called because MediaSession.isActive() is false at this time. So I would like to retry `GeckoView:MediaSession:Fullscreen` call when entering full screen and controller isn't active yet. Differential Revision: https://phabricator.services.mozilla.com/D173831
This commit is contained in:
Родитель
6b7b637d36
Коммит
f5090d66a1
|
@ -14,6 +14,10 @@ const { XPCOMUtils } = ChromeUtils.importESModule(
|
|||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(lazy, {
|
||||
MediaUtils: "resource://gre/modules/MediaUtils.jsm",
|
||||
});
|
||||
|
@ -27,12 +31,12 @@ class MediaControlDelegateChild extends GeckoViewActorChild {
|
|||
switch (aEvent.type) {
|
||||
case "MozDOMFullscreen:Entered":
|
||||
case "MozDOMFullscreen:Exited":
|
||||
this.handleFullscreenChanged();
|
||||
this.handleFullscreenChanged(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleFullscreenChanged() {
|
||||
async handleFullscreenChanged(retry) {
|
||||
debug`handleFullscreenChanged`;
|
||||
|
||||
const element = this.document.fullscreenElement;
|
||||
|
@ -43,11 +47,23 @@ class MediaControlDelegateChild extends GeckoViewActorChild {
|
|||
debug`No fullscreen media element found.`;
|
||||
}
|
||||
|
||||
this.eventDispatcher.sendRequest({
|
||||
const activated = await this.eventDispatcher.sendRequestForResult({
|
||||
type: "GeckoView:MediaSession:Fullscreen",
|
||||
metadata: lazy.MediaUtils.getMetadata(mediaElement) ?? {},
|
||||
enabled: !!element,
|
||||
});
|
||||
if (activated) {
|
||||
return;
|
||||
}
|
||||
if (retry && element) {
|
||||
// When media session is going to active, we have a race condition of
|
||||
// full screen event because media session will be activated by full
|
||||
// screen event.
|
||||
// So we retry to call media session delegate for this situation.
|
||||
lazy.setTimeout(() => {
|
||||
this.handleFullscreenChanged(false);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -953,4 +953,47 @@ class MediaSessionTest : BaseSessionTest() {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -629,10 +629,18 @@ public class MediaSession {
|
|||
} else if (FEATURES_EVENT.equals(event)) {
|
||||
final long features = Feature.fromBundle(message.getBundle("features"));
|
||||
delegate.onFeatures(mSession, mMediaSession, features);
|
||||
} else if (FULLSCREEN_EVENT.equals(event) && mMediaSession.isActive()) {
|
||||
} else if (FULLSCREEN_EVENT.equals(event)) {
|
||||
final boolean enabled = message.getBoolean("enabled");
|
||||
final ElementMetadata meta = ElementMetadata.fromBundle(message.getBundle("metadata"));
|
||||
if (!mMediaSession.isActive()) {
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "Media session is not active yet");
|
||||
}
|
||||
callback.sendSuccess(false);
|
||||
return;
|
||||
}
|
||||
delegate.onFullscreen(mSession, mMediaSession, enabled, meta);
|
||||
callback.sendSuccess(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -82,6 +83,7 @@ import org.mozilla.geckoview.GeckoSessionSettings;
|
|||
import org.mozilla.geckoview.GeckoView;
|
||||
import org.mozilla.geckoview.GeckoWebExecutor;
|
||||
import org.mozilla.geckoview.Image;
|
||||
import org.mozilla.geckoview.MediaSession;
|
||||
import org.mozilla.geckoview.OrientationController;
|
||||
import org.mozilla.geckoview.RuntimeTelemetry;
|
||||
import org.mozilla.geckoview.SlowScriptResponse;
|
||||
|
@ -1118,6 +1120,8 @@ public class GeckoViewActivity extends AppCompatActivity
|
|||
|
||||
session.setMediaDelegate(new ExampleMediaDelegate(this));
|
||||
|
||||
session.setMediaSessionDelegate(new ExampleMediaSessionDelegate(this));
|
||||
|
||||
session.setSelectionActionDelegate(new BasicSelectionActionDelegate(this));
|
||||
if (sExtensionManager.extension != null) {
|
||||
final WebExtension.SessionController sessionController = session.getWebExtensionController();
|
||||
|
@ -2468,6 +2472,38 @@ public class GeckoViewActivity extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
private class ExampleMediaSessionDelegate implements MediaSession.Delegate {
|
||||
private final Activity mActivity;
|
||||
|
||||
public ExampleMediaSessionDelegate(Activity activity) {
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFullscreen(
|
||||
@NonNull final GeckoSession session,
|
||||
@NonNull final MediaSession mediaSession,
|
||||
final boolean enabled,
|
||||
@Nullable final MediaSession.ElementMetadata meta) {
|
||||
Log.d(LOGTAG, "onFullscreen: Metadata=" + (meta != null ? meta.toString() : "null"));
|
||||
|
||||
if (!enabled) {
|
||||
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
if (meta == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (meta.width > meta.height) {
|
||||
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
||||
} else {
|
||||
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class ExampleTelemetryDelegate implements RuntimeTelemetry.Delegate {
|
||||
@Override
|
||||
public void onHistogram(final @NonNull RuntimeTelemetry.Histogram histogram) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче