зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1623715 - [8.2] Move media fullscreen event to JS and extend its metadata. r=geckoview-reviewers,snorp,alwu
Differential Revision: https://phabricator.services.mozilla.com/D86350
This commit is contained in:
Родитель
308a5f3d79
Коммит
7609049ab6
|
@ -0,0 +1,72 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { GeckoViewChildModule } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewChildModule.jsm"
|
||||
);
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
MediaUtils: "resource://gre/modules/MediaUtils.jsm",
|
||||
});
|
||||
|
||||
class GeckoViewMediaControl extends GeckoViewChildModule {
|
||||
onInit() {
|
||||
debug`onEnable`;
|
||||
}
|
||||
|
||||
onEnable() {
|
||||
debug`onEnable`;
|
||||
|
||||
addEventListener("MozDOMFullscreen:Entered", this, false);
|
||||
addEventListener("MozDOMFullscreen:Exited", this, false);
|
||||
}
|
||||
|
||||
onDisable() {
|
||||
debug`onDisable`;
|
||||
|
||||
removeEventListener("MozDOMFullscreen:Entered", this);
|
||||
removeEventListener("MozDOMFullscreen:Exited", this);
|
||||
}
|
||||
|
||||
handleEvent(aEvent) {
|
||||
debug`handleEvent: ${aEvent.type}`;
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "MozDOMFullscreen:Entered":
|
||||
case "MozDOMFullscreen:Exited":
|
||||
this.handleFullscreenChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleFullscreenChanged() {
|
||||
const element = content && content.document.fullscreenElement;
|
||||
const mediaElement = MediaUtils.findMediaElement(element);
|
||||
|
||||
if (element && !mediaElement) {
|
||||
// Non-media element fullscreen.
|
||||
return;
|
||||
}
|
||||
|
||||
const message = {
|
||||
metadata: MediaUtils.getMetadata(mediaElement) ?? {},
|
||||
enabled: !!element,
|
||||
};
|
||||
|
||||
this.messageManager.sendAsyncMessage(
|
||||
"GeckoView:MediaControl:Fullscreen",
|
||||
message
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const { debug } = GeckoViewMediaControl.initLogging("GeckoViewMediaControl");
|
||||
const module = GeckoViewMediaControl.create(this);
|
|
@ -653,6 +653,7 @@ function startup() {
|
|||
name: "GeckoViewMediaControl",
|
||||
onEnable: {
|
||||
resource: "resource://gre/modules/GeckoViewMediaControl.jsm",
|
||||
frameScript: "chrome://geckoview/content/GeckoViewMediaControlChild.js",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -14,6 +14,7 @@ geckoview.jar:
|
|||
content/geckoview.js
|
||||
content/GeckoViewAutofillChild.js
|
||||
content/GeckoViewMediaChild.js
|
||||
content/GeckoViewMediaControlChild.js
|
||||
content/GeckoViewProgressChild.js
|
||||
content/GeckoViewPromptChild.js
|
||||
content/GeckoViewScrollChild.js
|
||||
|
|
|
@ -403,11 +403,13 @@ public class MediaSession {
|
|||
* @param session The associated GeckoSession.
|
||||
* @param mediaSession The media session for the given GeckoSession.
|
||||
* @param enabled True when this media session in in fullscreen mode.
|
||||
* @param meta An instance of {@link ElementMetadata}, if enabled.
|
||||
*/
|
||||
default void onFullscreen(
|
||||
@NonNull GeckoSession session,
|
||||
@NonNull MediaSession mediaSession,
|
||||
boolean enabled) {}
|
||||
boolean enabled,
|
||||
@Nullable ElementMetadata meta) {}
|
||||
|
||||
/**
|
||||
* Notify on changed picture-in-picture mode state.
|
||||
|
@ -424,6 +426,78 @@ public class MediaSession {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* The representation of a media element's metadata.
|
||||
*/
|
||||
public static class ElementMetadata {
|
||||
/**
|
||||
* The media source URI.
|
||||
*/
|
||||
public final @Nullable String source;
|
||||
|
||||
/**
|
||||
* The duration of the media in seconds.
|
||||
*/
|
||||
public final double duration;
|
||||
|
||||
/**
|
||||
* The width of the video in device pixels.
|
||||
*/
|
||||
public final long width;
|
||||
|
||||
/**
|
||||
* The height of the video in device pixels.
|
||||
*/
|
||||
public final long height;
|
||||
|
||||
/**
|
||||
* The number of audio tracks contained in this element.
|
||||
*/
|
||||
public final int audioTrackCount;
|
||||
|
||||
/**
|
||||
* The number of video tracks contained in this element.
|
||||
*/
|
||||
public final int videoTrackCount;
|
||||
|
||||
/**
|
||||
* ElementMetadata constructor.
|
||||
*
|
||||
* @param source The media URI.
|
||||
* @param duration The media duration in seconds.
|
||||
* @param width The video width in device pixels.
|
||||
* @param height The video height in device pixels.
|
||||
* @param audioTrackCount The audio track count.
|
||||
* @param videoTrackCount The video track count.
|
||||
*/
|
||||
public ElementMetadata(
|
||||
@Nullable final String source,
|
||||
final double duration,
|
||||
final long width,
|
||||
final long height,
|
||||
final int audioTrackCount,
|
||||
final int videoTrackCount) {
|
||||
this.source = source;
|
||||
this.duration = duration;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.audioTrackCount = audioTrackCount;
|
||||
this.videoTrackCount = videoTrackCount;
|
||||
}
|
||||
|
||||
/* package */ static @NonNull ElementMetadata fromBundle(
|
||||
final GeckoBundle bundle) {
|
||||
// Sync with MediaUtils.jsm.
|
||||
return new ElementMetadata(
|
||||
bundle.getString("src"),
|
||||
bundle.getDouble("duration", 0.0),
|
||||
bundle.getLong("width", 0),
|
||||
bundle.getLong("height", 0),
|
||||
bundle.getInt("audioTrackCount", 0),
|
||||
bundle.getInt("videoTrackCount", 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The representation of a media session's metadata.
|
||||
*/
|
||||
|
@ -750,7 +824,10 @@ public class MediaSession {
|
|||
delegate.onFeatures(mSession, mMediaSession, features);
|
||||
} else if (FULLSCREEN_EVENT.equals(event)) {
|
||||
final boolean enabled = message.getBoolean("enabled");
|
||||
delegate.onFullscreen(mSession, mMediaSession, enabled);
|
||||
final ElementMetadata meta =
|
||||
ElementMetadata.fromBundle(
|
||||
message.getBundle("metadata"));
|
||||
delegate.onFullscreen(mSession, mMediaSession, enabled, meta);
|
||||
} else if (PICTURE_IN_PICTURE_EVENT.equals(event)) {
|
||||
final boolean enabled = message.getBoolean("enabled");
|
||||
delegate.onPictureInPicture(mSession, mMediaSession, enabled);
|
||||
|
|
|
@ -32,6 +32,11 @@ class GeckoViewMediaControl extends GeckoViewModule {
|
|||
this.controller.addEventListener("supportedkeyschange", this, options);
|
||||
this.controller.addEventListener("positionstatechange", this, options);
|
||||
// TODO: Move other events to webidl once supported.
|
||||
|
||||
this.messageManager.addMessageListener(
|
||||
"GeckoView:MediaControl:Fullscreen",
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
onDisable() {
|
||||
|
@ -41,12 +46,30 @@ class GeckoViewMediaControl extends GeckoViewModule {
|
|||
this.controller.removeEventListener("deactivated", this);
|
||||
this.controller.removeEventListener("supportedkeyschange", this);
|
||||
this.controller.removeEventListener("positionstatechange", this);
|
||||
|
||||
this.messageManager.removeMessageListener(
|
||||
"GeckoView:MediaControl:Fullscreen",
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
get controller() {
|
||||
return this.browser.browsingContext.mediaController;
|
||||
}
|
||||
|
||||
receiveMessage(aMsg) {
|
||||
debug`receiveMessage: name=${aMsg.name}, data=${aMsg.data}`;
|
||||
|
||||
switch (aMsg.name) {
|
||||
case "GeckoView:MediaControl:Fullscreen":
|
||||
this.handleFullscreenChanged(aMsg.data);
|
||||
break;
|
||||
default:
|
||||
warn`Unknown message name ${aMsg.name}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
handleEvent(aEvent) {
|
||||
debug`handleEvent: ${aEvent.type}`;
|
||||
|
@ -70,6 +93,17 @@ class GeckoViewMediaControl extends GeckoViewModule {
|
|||
}
|
||||
}
|
||||
|
||||
handleFullscreenChanged(aData) {
|
||||
debug`handleFullscreenChanged ${aData.enabled}`;
|
||||
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:MediaSession:Fullscreen",
|
||||
id: this.controller.id,
|
||||
enabled: aData.enabled,
|
||||
metadata: aData.metadata,
|
||||
});
|
||||
}
|
||||
|
||||
handleActivated() {
|
||||
debug`handleActivated`;
|
||||
|
||||
|
@ -98,7 +132,7 @@ class GeckoViewMediaControl extends GeckoViewModule {
|
|||
duration: aEvent.duration,
|
||||
playbackRate: aEvent.playbackRate,
|
||||
position: aEvent.position,
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -388,7 +388,6 @@ class nsWindow::MediaSessionSupport final
|
|||
ControllerPtr mMediaController;
|
||||
MediaEventListener mMetadataChangedListener;
|
||||
MediaEventListener mPlaybackChangedListener;
|
||||
MediaEventListener mFullscreenChangedListener;
|
||||
|
||||
public:
|
||||
typedef java::MediaSession::Controller::Natives<MediaSessionSupport> Base;
|
||||
|
@ -536,35 +535,6 @@ class nsWindow::MediaSessionSupport final
|
|||
}
|
||||
}
|
||||
|
||||
void FullscreenChanged(bool aIsEnabled) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
const size_t kBundleSize = 1;
|
||||
|
||||
AutoTArray<jni::String::LocalRef, kBundleSize> keys;
|
||||
AutoTArray<jni::Object::LocalRef, kBundleSize> values;
|
||||
|
||||
keys.AppendElement(
|
||||
jni::StringParam(NS_LITERAL_STRING_FROM_CSTRING("enabled")));
|
||||
values.AppendElement(aIsEnabled ? java::sdk::Boolean::TRUE()
|
||||
: java::sdk::Boolean::FALSE());
|
||||
|
||||
MOZ_ASSERT(kBundleSize == keys.Length());
|
||||
MOZ_ASSERT(kBundleSize == values.Length());
|
||||
|
||||
auto bundleKeys = jni::ObjectArray::New<jni::String>(kBundleSize);
|
||||
auto bundleValues = jni::ObjectArray::New<jni::Object>(kBundleSize);
|
||||
|
||||
for (size_t i = 0; i < kBundleSize; ++i) {
|
||||
bundleKeys->SetElement(i, keys[i]);
|
||||
bundleValues->SetElement(i, values[i]);
|
||||
}
|
||||
auto bundle = java::GeckoBundle::New(bundleKeys, bundleValues);
|
||||
|
||||
const char16_t kFullscreen[] = u"GeckoView:MediaSession:Fullscreen";
|
||||
Dispatch(kFullscreen, bundle);
|
||||
}
|
||||
|
||||
void OnDetach(already_AddRefed<Runnable> aDisposer) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -623,17 +593,11 @@ class nsWindow::MediaSessionSupport final
|
|||
mPlaybackChangedListener = mMediaController->PlaybackChangedEvent().Connect(
|
||||
AbstractThread::MainThread(), this,
|
||||
&MediaSessionSupport::PlaybackChanged);
|
||||
|
||||
mFullscreenChangedListener =
|
||||
mMediaController->FullScreenChangedEvent().Connect(
|
||||
AbstractThread::MainThread(), this,
|
||||
&MediaSessionSupport::FullscreenChanged);
|
||||
}
|
||||
|
||||
void UnregisterControllerListeners() {
|
||||
mMetadataChangedListener.DisconnectIfExists();
|
||||
mPlaybackChangedListener.DisconnectIfExists();
|
||||
mFullscreenChangedListener.DisconnectIfExists();
|
||||
}
|
||||
|
||||
bool IsActive() const {
|
||||
|
|
Загрузка…
Ссылка в новой задаче