Commit 4c5ee86a authored by Kai Uwe Broulik's avatar Kai Uwe Broulik 🍇

Call into native Media Session browser API if available

Since Chrome 73 it also supports Media Session API on the desktop.
The calls are re-arranged since the native setActionHandler throws if passed an
invalid action and in this case we don't want to register the callback either.

Also, there's a new "skipad" action for a "Skip Ad" overlay in picture-in-picture
mode [1] for which to work we need to call the native browser APIs.
Also, since MediaMetadata is a proper class and not an Object, iterate its prototype
rather than just stringifying it and adjust our shim to do the same.

[1] https://www.chromestatus.com/feature/4749278882824192

Differential Revision: https://phabricator.kde.org/D20726
parent eb583434
......@@ -604,20 +604,51 @@ function loadMediaSessionsShim() {
this.callbacks[action]();
};
navigator.mediaSession = {};
if (!navigator.mediaSession) {
navigator.mediaSession = {};
}
var noop = function() { };
var oldSetActionHandler = navigator.mediaSession.setActionHandler || noop;
navigator.mediaSession.setActionHandler = function (name, cb) {
// Call the original native implementation
// "call()" is needed as the real setActionHandler is a class member
// and calling it directly is illegal as it lacks the context
// We'll register the callback for ourself after this since it may
// throw for unsupported callback names.
var ret = oldSetActionHandler.call(navigator.mediaSession, name, cb);
if (cb) {
${mediaSessionsClassName}.callbacks[name] = cb;
} else {
delete ${mediaSessionsClassName}.callbacks[name];
}
${mediaSessionsClassName}.sendMessage("callbacks", Object.keys(${mediaSessionsClassName}.callbacks));
return ret;
};
Object.defineProperty(navigator.mediaSession, "metadata", {
get: function() { return ${mediaSessionsClassName}.metadata; },
set: function(newValue) {
${mediaSessionsClassName}.metadata = newValue;
${mediaSessionsClassName}.sendMessage("metadata", newValue ? newValue.data : null);
// MediaMetadata is not a regular Object so we cannot just JSON.stringify it
var newMetadata = {};
if (newValue) {
var keys = Object.getOwnPropertyNames(Object.getPrototypeOf(newValue));
keys.forEach(function (key) {
var value = newValue[key];
if (typeof value === "function") {
return; // continue
}
newMetadata[key] = newValue[key];
});
}
${mediaSessionsClassName}.sendMessage("metadata", newMetadata);
}
});
Object.defineProperty(navigator.mediaSession, "playbackState", {
......@@ -628,9 +659,15 @@ function loadMediaSessionsShim() {
}
});
window.MediaMetadata = function (data) {
this.data = data;
};
if (!window.MediaMetadata) {
window.MediaMetadata = function (data) {
Object.assign(this, data);
};
window.MediaMetadata.prototype.title = "";
window.MediaMetadata.prototype.artist = "";
window.MediaMetadata.prototype.album = "";
window.MediaMetadata.prototype.artwork = [];
}
}
`);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment