summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs')
-rw-r--r--mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs234
1 files changed, 234 insertions, 0 deletions
diff --git a/mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs b/mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs
new file mode 100644
index 0000000000..1b39125fce
--- /dev/null
+++ b/mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs
@@ -0,0 +1,234 @@
+/* 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/. */
+
+import { GeckoViewModule } from "resource://gre/modules/GeckoViewModule.sys.mjs";
+
+export class GeckoViewMediaControl extends GeckoViewModule {
+ onInit() {
+ debug`onInit`;
+ }
+
+ onInitBrowser() {
+ debug`onInitBrowser`;
+
+ const options = {
+ mozSystemGroup: true,
+ capture: false,
+ };
+
+ this.controller.addEventListener("activated", this, options);
+ this.controller.addEventListener("deactivated", this, options);
+ this.controller.addEventListener("supportedkeyschange", this, options);
+ this.controller.addEventListener("positionstatechange", this, options);
+ this.controller.addEventListener("metadatachange", this, options);
+ this.controller.addEventListener("playbackstatechange", this, options);
+ }
+
+ onDestroyBrowser() {
+ debug`onDestroyBrowser`;
+
+ this.controller.removeEventListener("activated", this);
+ this.controller.removeEventListener("deactivated", this);
+ this.controller.removeEventListener("supportedkeyschange", this);
+ this.controller.removeEventListener("positionstatechange", this);
+ this.controller.removeEventListener("metadatachange", this);
+ this.controller.removeEventListener("playbackstatechange", this);
+ }
+
+ onEnable() {
+ debug`onEnable`;
+
+ if (this.controller.isActive) {
+ this.handleActivated();
+ }
+
+ this.registerListener([
+ "GeckoView:MediaSession:Play",
+ "GeckoView:MediaSession:Pause",
+ "GeckoView:MediaSession:Stop",
+ "GeckoView:MediaSession:NextTrack",
+ "GeckoView:MediaSession:PrevTrack",
+ "GeckoView:MediaSession:SeekForward",
+ "GeckoView:MediaSession:SeekBackward",
+ "GeckoView:MediaSession:SkipAd",
+ "GeckoView:MediaSession:SeekTo",
+ "GeckoView:MediaSession:MuteAudio",
+ ]);
+ }
+
+ onDisable() {
+ debug`onDisable`;
+
+ this.unregisterListener();
+ }
+
+ get controller() {
+ return this.browser.browsingContext.mediaController;
+ }
+
+ onEvent(aEvent, aData, aCallback) {
+ debug`onEvent: event=${aEvent}, data=${aData}`;
+
+ switch (aEvent) {
+ case "GeckoView:MediaSession:Play":
+ this.controller.play();
+ break;
+ case "GeckoView:MediaSession:Pause":
+ this.controller.pause();
+ break;
+ case "GeckoView:MediaSession:Stop":
+ this.controller.stop();
+ break;
+ case "GeckoView:MediaSession:NextTrack":
+ this.controller.nextTrack();
+ break;
+ case "GeckoView:MediaSession:PrevTrack":
+ this.controller.prevTrack();
+ break;
+ case "GeckoView:MediaSession:SeekForward":
+ this.controller.seekForward();
+ break;
+ case "GeckoView:MediaSession:SeekBackward":
+ this.controller.seekBackward();
+ break;
+ case "GeckoView:MediaSession:SkipAd":
+ this.controller.skipAd();
+ break;
+ case "GeckoView:MediaSession:SeekTo":
+ this.controller.seekTo(aData.time, aData.fast);
+ break;
+ case "GeckoView:MediaSession:MuteAudio":
+ if (aData.mute) {
+ this.browser.mute();
+ } else {
+ this.browser.unmute();
+ }
+ break;
+ }
+ }
+
+ // eslint-disable-next-line complexity
+ handleEvent(aEvent) {
+ debug`handleEvent: ${aEvent.type}`;
+
+ switch (aEvent.type) {
+ case "activated":
+ this.handleActivated();
+ break;
+ case "deactivated":
+ this.handleDeactivated();
+ break;
+ case "supportedkeyschange":
+ this.handleSupportedKeysChanged();
+ break;
+ case "positionstatechange":
+ this.handlePositionStateChanged(aEvent);
+ break;
+ case "metadatachange":
+ this.handleMetadataChanged();
+ break;
+ case "playbackstatechange":
+ this.handlePlaybackStateChanged();
+ break;
+ default:
+ warn`Unknown event type ${aEvent.type}`;
+ break;
+ }
+ }
+
+ handleActivated() {
+ debug`handleActivated`;
+
+ this.eventDispatcher.sendRequest({
+ type: "GeckoView:MediaSession:Activated",
+ });
+ }
+
+ handleDeactivated() {
+ debug`handleDeactivated`;
+
+ this.eventDispatcher.sendRequest({
+ type: "GeckoView:MediaSession:Deactivated",
+ });
+ }
+
+ handlePositionStateChanged(aEvent) {
+ debug`handlePositionStateChanged`;
+
+ this.eventDispatcher.sendRequest({
+ type: "GeckoView:MediaSession:PositionState",
+ state: {
+ duration: aEvent.duration,
+ playbackRate: aEvent.playbackRate,
+ position: aEvent.position,
+ },
+ });
+ }
+
+ handleSupportedKeysChanged() {
+ const supported = this.controller.supportedKeys;
+
+ debug`handleSupportedKeysChanged ${supported}`;
+
+ // Mapping it to a key-value store for compatibility with the JNI
+ // implementation for now.
+ const features = new Map();
+ supported.forEach(key => {
+ features[key] = true;
+ });
+
+ this.eventDispatcher.sendRequest({
+ type: "GeckoView:MediaSession:Features",
+ features,
+ });
+ }
+
+ handleMetadataChanged() {
+ let metadata = null;
+ try {
+ metadata = this.controller.getMetadata();
+ } catch (e) {
+ warn`Metadata not available`;
+ }
+ debug`handleMetadataChanged ${metadata}`;
+
+ if (metadata) {
+ this.eventDispatcher.sendRequest({
+ type: "GeckoView:MediaSession:Metadata",
+ metadata,
+ });
+ }
+ }
+
+ handlePlaybackStateChanged() {
+ const state = this.controller.playbackState;
+ let type = null;
+
+ debug`handlePlaybackStateChanged ${state}`;
+
+ switch (state) {
+ case "none":
+ type = "GeckoView:MediaSession:Playback:None";
+ break;
+ case "paused":
+ type = "GeckoView:MediaSession:Playback:Paused";
+ break;
+ case "playing":
+ type = "GeckoView:MediaSession:Playback:Playing";
+ break;
+ }
+
+ if (!type) {
+ return;
+ }
+
+ this.eventDispatcher.sendRequest({
+ type,
+ });
+ }
+}
+
+const { debug, warn } = GeckoViewMediaControl.initLogging(
+ "GeckoViewMediaControl"
+);