Fix messaging

This commit is contained in:
Tamius Han 2026-01-28 02:02:27 +01:00
parent c9818c92b3
commit fd7b5ec04e
9 changed files with 121 additions and 118 deletions

View File

@ -446,6 +446,8 @@ interface SettingsInterface {
} }
export interface SiteSettingsInterface { export interface SiteSettingsInterface {
notes?: string; // any special things related to this site.
enable: ExtensionMode; enable: ExtensionMode;
enableAard: ExtensionMode; enableAard: ExtensionMode;
enableKeyboard: InputHandlingMode; enableKeyboard: InputHandlingMode;

View File

@ -120,9 +120,12 @@ export default class UWContent {
this.logger.debug('setup', "KeyboardHandler initiated."); this.logger.debug('setup', "KeyboardHandler initiated.");
this.globalUi = new UI('ultrawidify-global-ui', {eventBus: this.eventBus, isGlobal: true}); if (this.globalUi) {
this.globalUi.enable(); this.globalUi.destroy();
this.globalUi.setUiVisibility(false); }
// this.globalUi = new UI('ultrawidify-global-ui', {eventBus: this.eventBus, isGlobal: true});
// this.globalUi.enable();
// this.globalUi.setUiVisibility(false);
} catch (e) { } catch (e) {
console.error('Ultrawidify: failed to start extension. Error:', e) console.error('Ultrawidify: failed to start extension. Error:', e)

View File

@ -9,6 +9,7 @@ import LegacyExtensionMode from '@src/common/enums/LegacyExtensionMode.enum';
import { PlayerDetectionMode } from '@src/common/enums/PlayerDetectionMode.enum'; import { PlayerDetectionMode } from '@src/common/enums/PlayerDetectionMode.enum';
import { SiteSupportLevel } from '@src/common/enums/SiteSupportLevel.enum'; import { SiteSupportLevel } from '@src/common/enums/SiteSupportLevel.enum';
import SettingsInterface from '@src/common/interfaces/SettingsInterface'; import SettingsInterface from '@src/common/interfaces/SettingsInterface';
import { _cp } from '@src/common/utils/_cp';
import { update } from 'lodash'; import { update } from 'lodash';

View File

@ -983,6 +983,29 @@ const ExtensionConf: SettingsInterface = {
} }
} }
}, },
"www.amazon.com": {
enable: ExtensionMode.Default,
enableAard: ExtensionMode.Default,
enableKeyboard: InputHandlingMode.Enabled,
enableUI: ExtensionMode.Default,
applyToEmbeddedContent: EmbeddedContentSettingsOverridePolicy.Default,
overrideWhenEmbedded: EmbeddedContentSettingsOverridePolicy.Default,
type: SiteSupportLevel.CommunitySupport,
defaultType: SiteSupportLevel.CommunitySupport,
persistCSA: CropModePersistence.Default,
activeDOMConfig: "@community",
DOMConfig: {
"@community": {
type: SiteSupportLevel.CommunitySupport,
elements: {
player: {
detectionMode: PlayerDetectionMode.Auto,
allowAutoFallback: true
}
}
},
},
},
"www.twitch.tv": { "www.twitch.tv": {
enable: ExtensionMode.All, enable: ExtensionMode.All,
enableAard: ExtensionMode.All, enableAard: ExtensionMode.All,

View File

@ -143,12 +143,21 @@ export default class EventBus {
...context, ...context,
borderCrossings: { borderCrossings: {
...context?.borderCrossings, ...context?.borderCrossings,
// iframe: true // we actually no longer check this prop, we should instead rely on visitedBusses
} }
} }
); );
} }
this.sendToTunnel(command, commandData, context);
// send to parent iframe
if (!this.disableTunnel && typeof window !== 'undefined') {
window.parent.postMessage(
{
action: 'uw-bus-tunnel',
payload: {command, config: commandData, context} as EventBusMessage
},
'*'
);
}
if (context?.stopPropagation) { if (context?.stopPropagation) {
return; return;
@ -156,52 +165,6 @@ export default class EventBus {
} }
//#endregion //#endregion
/**
* Send, but intended for sending commands from iframe to content scripts
* @param command
* @param config
*/
private sendToTunnel(command: string, config: any, context: EventBusContext = {}) {
if (!context.visitedBusses) {
// this should never trigger on production version of the extension.
console.error('Visited busses is missing from context. This is illegal.');
return;
}
if (!this.disableTunnel && typeof window !== 'undefined') {
window.parent.postMessage(
{
action: 'uw-bus-tunnel',
payload: {command, config, context} as EventBusMessage
},
'*'
);
} else {
// because iframe UI components get reused in the popup, we
// also need to set up a detour because the tunnel is closed
// in the popup
if (this.comms) {
try {
this.comms.sendMessage(
{
command,
config,
context: {
...this.popupContext,
...context
}
},
this.popupContext
);
} catch (e) {
if (command !== 'reload-required') {
this.send('reload-required', {}, context);
}
}
}
}
}
//#region iframe tunnelling //#region iframe tunnelling
private setupIframeTunnelling() { private setupIframeTunnelling() {
// forward messages coming from iframe tunnels // forward messages coming from iframe tunnels

View File

@ -176,7 +176,7 @@ class CommsServer {
if (context?.comms.forwardTo === 'all') { if (context?.comms.forwardTo === 'all') {
return this.sendToAll(message); return this.sendToAll(message);
} }
if (context?.comms.forwardTo === 'active') { if (context?.comms.forwardTo === 'active' || !context?.comms.forwardTo) {
return this.sendToActive(message); return this.sendToActive(message);
} }
if (context?.comms.forwardTo === 'contentScript') { if (context?.comms.forwardTo === 'contentScript') {

View File

@ -39,6 +39,9 @@ class UI {
private extensionMenu: ClientMenu; private extensionMenu: ClientMenu;
private logger: ComponentLogger; private logger: ComponentLogger;
private forwardedCommandIds: string[] = new Array(64);
private lastForwardedCommandIndex = 0;
private uiState = { private uiState = {
lockXY: true, lockXY: true,
zoom: { // log2 scale — 100% is 0 zoom: { // log2 scale — 100% is 0
@ -121,7 +124,7 @@ class UI {
private initMessaging() { private initMessaging() {
if (this.messageListener) { if (this.messageListener) {
window.removeEventListener('message', this.messageListener); this.destroyMessaging();
} else { } else {
this.messageListener = (event: MessageEvent) => { this.messageListener = (event: MessageEvent) => {
const data = event.data; const data = event.data;
@ -133,7 +136,26 @@ class UI {
const payload = data.payload; const payload = data.payload;
console.log('forwarding from tunnel to event bus. payload', payload); /**
* it appears that forwarded commands can be multiplying to ridiculous degree,
* but i didn't find anything that would obviously cause the message forwarding storm
* this means we'll try to avoid that via brute force.
*
* How bad is it?
* can get as bad as 100k messages a minute (!)
*/
if (!payload.context?.commandId) {
// user should never see this log
console.warn('Command context does not contain commandId. This is illegal. Message will not be forwarded.', {payload});
return;
}
if (this.forwardedCommandIds.includes(payload.context.commandId)) {
console.warn('this command was already forwarded, doing nothing:', {payload});
return;
}
const i = this.lastForwardedCommandIndex++ % this.forwardedCommandIds.length;
this.forwardedCommandIds[i] = payload.id;
// Forward to all iframes except the source // Forward to all iframes except the source
(UwuiWindow as any).instances?.forEach(win => { (UwuiWindow as any).instances?.forEach(win => {
@ -154,6 +176,12 @@ class UI {
window.addEventListener('message', this.messageListener); window.addEventListener('message', this.messageListener);
} }
private destroyMessaging() {
if (this.messageListener) {
window.removeEventListener('message', this.messageListener);
}
}
executeCommand(x: CommandInterface) { executeCommand(x: CommandInterface) {
this.eventBus.send(x.action, x.arguments); this.eventBus.send(x.action, x.arguments);
} }
@ -511,10 +539,6 @@ class UI {
}); });
} }
setUiVisibility(visible) {
return;
}
async enable() { async enable() {
// if root element is not present, we need to init the UI. // if root element is not present, we need to init the UI.
// if (!this.rootDiv) { // if (!this.rootDiv) {
@ -535,6 +559,7 @@ class UI {
* @param {*} newUiConfig * @param {*} newUiConfig
*/ */
replace(newUiConfig) { replace(newUiConfig) {
this.destroy();
this.uiConfig = newUiConfig; this.uiConfig = newUiConfig;
this.init(); this.init();
} }
@ -543,6 +568,7 @@ class UI {
if (this.extensionMenu) { if (this.extensionMenu) {
this.extensionMenu.destroy(); this.extensionMenu.destroy();
} }
this.destroyMessaging();
} }

View File

@ -195,6 +195,10 @@ class PlayerData {
//#region lifecycle //#region lifecycle
constructor(videoData) { constructor(videoData) {
if (!(window as any).uiCount) {
(window as any).uiCount = 1;
}
try { try {
// set all our helper objects // set all our helper objects
this.logger = new ComponentLogger(videoData.logAggregator, 'PlayerData', {styles: {}}); this.logger = new ComponentLogger(videoData.logAggregator, 'PlayerData', {styles: {}});
@ -875,7 +879,9 @@ class PlayerData {
bestCandidate.heuristics['qsMatch'] = true; bestCandidate.heuristics['qsMatch'] = true;
} }
if (bestCandidate) {
bestCandidate.heuristics['activePlayer'] = true; bestCandidate.heuristics['activePlayer'] = true;
}
return bestCandidate; return bestCandidate;
} }

View File

@ -298,10 +298,9 @@ class VideoData {
initializeObservers() { initializeObservers() {
try { try {
if (BrowserDetect.firefox) {
this.observer = new ResizeObserver( this.observer = new ResizeObserver(
_.debounce( _.debounce(
this.onVideoDimensionsChanged, () => this.onVideoDimensionsChanged,
250, 250,
{ {
leading: true, leading: true,
@ -309,22 +308,6 @@ class VideoData {
} }
) )
); );
} else {
// Chrome for some reason insists that this.onPlayerDimensionsChanged is not a function
// when it's not wrapped into an anonymous function
this.observer = new ResizeObserver(
_.debounce(
(m, o) => {
this.onVideoDimensionsChanged(m, o)
},
250,
{
leading: true,
trailing: true
}
)
);
}
} catch (e) { } catch (e) {
console.error('[VideoData] Observer setup failed:', e); console.error('[VideoData] Observer setup failed:', e);
} }
@ -332,11 +315,13 @@ class VideoData {
} }
setupMutationObserver() { setupMutationObserver() {
if (this.mutationObserver) {
this.mutationObserver.disconnect();
}
try { try {
if (BrowserDetect.firefox) {
this.mutationObserver = new MutationObserver( this.mutationObserver = new MutationObserver(
_.debounce( _.debounce(
this.onVideoMutation, () => this.onVideoMutation(),
250, 250,
{ {
leading: true, leading: true,
@ -344,22 +329,6 @@ class VideoData {
} }
) )
) )
} else {
// Chrome for some reason insists that this.onPlayerDimensionsChanged is not a function
// when it's not wrapped into an anonymous function
this.mutationObserver = new MutationObserver(
_.debounce(
(m, o) => {
this.onVideoMutation(m, o)
},
250,
{
leading: true,
trailing: true
}
)
)
}
} catch (e) { } catch (e) {
console.error('[VideoData] Observer setup failed:', e); console.error('[VideoData] Observer setup failed:', e);
} }
@ -372,6 +341,17 @@ class VideoData {
destroy() { destroy() {
this.logger.info('destroy', `<vdid:${this.vdid}> received destroy command`); this.logger.info('destroy', `<vdid:${this.vdid}> received destroy command`);
// Disconnect observer and set destroyed to 'true' _before_ removing classes from
// the video element
this.destroyed = true;
try {
this.observer.disconnect();
} catch (e) {}
try {
this.mutationObserver.disconnect();
} catch (e) {}
if (this.video) { if (this.video) {
this.video.classList.remove(this.userCssClassName); this.video.classList.remove(this.userCssClassName);
this.video.classList.remove('uw-ultrawidify-base-wide-screen'); this.video.classList.remove('uw-ultrawidify-base-wide-screen');
@ -381,8 +361,6 @@ class VideoData {
this.video.removeEventListener('ontimeupdate', this.onTimeUpdate); this.video.removeEventListener('ontimeupdate', this.onTimeUpdate);
} }
this.eventBus.send('set-run-level', RunLevel.Off);
this.destroyed = true;
this.eventBus.unsubscribeAll(this); this.eventBus.unsubscribeAll(this);
try { try {
@ -397,9 +375,6 @@ class VideoData {
try { try {
this.player.destroy(); this.player.destroy();
} catch (e) {} } catch (e) {}
try {
this.observer.disconnect();
} catch (e) {}
this.player = undefined; this.player = undefined;
this.video = undefined; this.video = undefined;
} }
@ -463,7 +438,7 @@ class VideoData {
this.runLevel = runLevel; this.runLevel = runLevel;
if (!options?.fromPlayer) { if (!options?.fromPlayer) {
this.player.setRunLevel(runLevel); this.player?.setRunLevel(runLevel);
} }
} }
@ -532,6 +507,10 @@ class VideoData {
} }
onVideoMutation(mutationList?: MutationRecord[], observer?) { onVideoMutation(mutationList?: MutationRecord[], observer?) {
if (this.destroyed) {
return;
}
// verify that mutation didn't remove our class. Some pages like to do that. // verify that mutation didn't remove our class. Some pages like to do that.
let confirmAspectRatioRestore = false; let confirmAspectRatioRestore = false;