Commit b5081845 authored by Kai Uwe Broulik's avatar Kai Uwe Broulik 🍇

Add better player tab crash handling

There is unfortunately no dedicated signal for this (the process API is for dev builds only), so we can only do:

* When we detect a tab becoming inaudible, check if it's gone now, and signal player gone.
  This will catch the case of a tab crashing while playing
* When sending a command, check if it failed, and signal player gone.
  Instead of doing nothing, the player will disappear.
  Not really better UX right there but at least the user will go "huh?" rather than "why is it not working?"

There's also no error codes on the error object, just sentences...

BUG: 419699

Differential Revision: https://phabricator.kde.org/D28614
parent b26ddbe9
......@@ -51,6 +51,23 @@ function sendPlayerTabMessage(player, action, payload) {
chrome.tabs.sendMessage(player.tabId, message, {
frameId: player.frameId
}, (resp) => {
const error = chrome.runtime.lastError;
// When player tab crashed, we get this error message.
// There's unfortunately no proper signal for this so we can really only know when we try to send a command
if (error && error.message === "Could not establish connection. Receiving end does not exist.") {
console.warn("Failed to send player command to tab", player.tabId, ", signalling player gone");
playerTabGone(player.tabId);
}
});
}
function playerTabGone(tabId) {
let players = playerIds;
players.forEach((playerId) => {
if (playerId.startsWith(tabId + "-")) {
playerGone(playerId);
}
});
}
......@@ -84,10 +101,26 @@ function playerGone(playerId) {
// which is invoked in the onbeforeunload handler of the page
chrome.tabs.onRemoved.addListener((tabId) => {
// Since we only get the tab id, search for all players from this tab and signal a "gone"
let players = playerIds;
players.forEach((playerId) => {
if (playerId.startsWith(tabId + "-")) {
playerGone(playerId);
playerTabGone(tabId);
});
// There's no signal for when a tab process crashes (only in browser dev builds).
// We watch for the tab becoming inaudible and check if it's still around.
// With this heuristic we can at least mitigate MPRIS remaining stuck in a playing state.
chrome.tabs.onUpdated.addListener((tabId, changes) => {
if (!changes.hasOwnProperty("audible") || changes.audible === true) {
return;
}
// Now check if the tab is actually gone
chrome.tabs.executeScript(tabId, {
code: `true`
}, (response) => {
const error = chrome.runtime.lastError;
// Chrome error in script_executor.cc "kRendererDestroyed"
if (error && error.message === "The tab was closed.") {
console.warn("Player tab", tabId, "became inaudible and was considered crashed, signalling player gone");
playerTabGone(tabId);
}
});
});
......
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