In place of manifest.json
Safari extensions use Info.plist
which is typically generated with ExtensionBuilder. As you can see from the provided screenshot, no 'uninstallURL' is available. I suggest testing a beforeUnload listener in the global page but this will probably also be triggered during other events like updates, browser closing etc.
As for Firefox, it all depends on the actual API your add-on is based on. You maybe out of luck if you have used the Addon SDK or created a legacy XUL overlay extension. However, Restartless bootstrapped extensions use low-level APIs and the uninstall
function in bootstrap.js receives a reason parameter:
function uninstall(data, reason) {
if (reason === ADDON_UNINSTALL) {
let win = Services.wm.getMostRecentWindow('navigator:browser');
win.gBrowser.selectedTab = win.gBrowser.addTab(url);
}
}
Good news is a new WebExtensions API is coming to Firefox. It is basically identical to the Chrome API. See the relevant bug