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 {
notes?: string; // any special things related to this site.
enable: ExtensionMode;
enableAard: ExtensionMode;
enableKeyboard: InputHandlingMode;

View File

@ -120,9 +120,12 @@ export default class UWContent {
this.logger.debug('setup', "KeyboardHandler initiated.");
this.globalUi = new UI('ultrawidify-global-ui', {eventBus: this.eventBus, isGlobal: true});
this.globalUi.enable();
this.globalUi.setUiVisibility(false);
if (this.globalUi) {
this.globalUi.destroy();
}
// this.globalUi = new UI('ultrawidify-global-ui', {eventBus: this.eventBus, isGlobal: true});
// this.globalUi.enable();
// this.globalUi.setUiVisibility(false);
} catch (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 { SiteSupportLevel } from '@src/common/enums/SiteSupportLevel.enum';
import SettingsInterface from '@src/common/interfaces/SettingsInterface';
import { _cp } from '@src/common/utils/_cp';
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": {
enable: ExtensionMode.All,
enableAard: ExtensionMode.All,

View File

@ -143,12 +143,21 @@ export default class EventBus {
...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) {
return;
@ -156,52 +165,6 @@ export default class EventBus {
}
//#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
private setupIframeTunnelling() {
// forward messages coming from iframe tunnels

View File

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

View File

@ -39,6 +39,9 @@ class UI {
private extensionMenu: ClientMenu;
private logger: ComponentLogger;
private forwardedCommandIds: string[] = new Array(64);
private lastForwardedCommandIndex = 0;
private uiState = {
lockXY: true,
zoom: { // log2 scale — 100% is 0
@ -121,7 +124,7 @@ class UI {
private initMessaging() {
if (this.messageListener) {
window.removeEventListener('message', this.messageListener);
this.destroyMessaging();
} else {
this.messageListener = (event: MessageEvent) => {
const data = event.data;
@ -133,7 +136,26 @@ class UI {
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
(UwuiWindow as any).instances?.forEach(win => {
@ -154,6 +176,12 @@ class UI {
window.addEventListener('message', this.messageListener);
}
private destroyMessaging() {
if (this.messageListener) {
window.removeEventListener('message', this.messageListener);
}
}
executeCommand(x: CommandInterface) {
this.eventBus.send(x.action, x.arguments);
}
@ -511,10 +539,6 @@ class UI {
});
}
setUiVisibility(visible) {
return;
}
async enable() {
// if root element is not present, we need to init the UI.
// if (!this.rootDiv) {
@ -535,6 +559,7 @@ class UI {
* @param {*} newUiConfig
*/
replace(newUiConfig) {
this.destroy();
this.uiConfig = newUiConfig;
this.init();
}
@ -543,6 +568,7 @@ class UI {
if (this.extensionMenu) {
this.extensionMenu.destroy();
}
this.destroyMessaging();
}

View File

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

View File

@ -298,10 +298,9 @@ class VideoData {
initializeObservers() {
try {
if (BrowserDetect.firefox) {
this.observer = new ResizeObserver(
_.debounce(
this.onVideoDimensionsChanged,
() => this.onVideoDimensionsChanged,
250,
{
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) {
console.error('[VideoData] Observer setup failed:', e);
}
@ -332,11 +315,13 @@ class VideoData {
}
setupMutationObserver() {
if (this.mutationObserver) {
this.mutationObserver.disconnect();
}
try {
if (BrowserDetect.firefox) {
this.mutationObserver = new MutationObserver(
_.debounce(
this.onVideoMutation,
() => this.onVideoMutation(),
250,
{
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) {
console.error('[VideoData] Observer setup failed:', e);
}
@ -372,6 +341,17 @@ class VideoData {
destroy() {
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) {
this.video.classList.remove(this.userCssClassName);
this.video.classList.remove('uw-ultrawidify-base-wide-screen');
@ -381,8 +361,6 @@ class VideoData {
this.video.removeEventListener('ontimeupdate', this.onTimeUpdate);
}
this.eventBus.send('set-run-level', RunLevel.Off);
this.destroyed = true;
this.eventBus.unsubscribeAll(this);
try {
@ -397,9 +375,6 @@ class VideoData {
try {
this.player.destroy();
} catch (e) {}
try {
this.observer.disconnect();
} catch (e) {}
this.player = undefined;
this.video = undefined;
}
@ -463,7 +438,7 @@ class VideoData {
this.runLevel = runLevel;
if (!options?.fromPlayer) {
this.player.setRunLevel(runLevel);
this.player?.setRunLevel(runLevel);
}
}
@ -532,6 +507,10 @@ class VideoData {
}
onVideoMutation(mutationList?: MutationRecord[], observer?) {
if (this.destroyed) {
return;
}
// verify that mutation didn't remove our class. Some pages like to do that.
let confirmAspectRatioRestore = false;