Mind that BroadcastChannel contructor can throw in Firefox

BroadcastChannel constructor throws in Firefox when Enhanced
Tracking Protection is set to "strict".

This behavior could cause scriptlet injection to wholly break
when uBO's logger was opened, as BroadcastChannel() is used
by scriptlets to report information to the logger.

This commit ensures that exceptions from BroadcastChannel
constructor are properly handled.

The scriptlets will fall back to report at the console should
they be unable to report to the logger through BroadcastChannel.
This commit is contained in:
Raymond Hill 2024-10-05 12:42:30 -04:00
parent 41693407b2
commit 6d2b3375f8
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
2 changed files with 60 additions and 46 deletions

View File

@ -173,13 +173,11 @@ function safeSelf() {
scriptletGlobals.safeSelf = safe;
if ( scriptletGlobals.bcSecret === undefined ) { return safe; }
// This is executed only when the logger is opened
const bc = new self.BroadcastChannel(scriptletGlobals.bcSecret);
let bcBuffer = [];
safe.logLevel = scriptletGlobals.logLevel || 1;
let lastLogType = '';
let lastLogText = '';
let lastLogTime = 0;
safe.sendToLogger = (type, ...args) => {
safe.toLogText = (type, ...args) => {
if ( args.length === 0 ) { return; }
const text = `[${document.location.hostname || document.location.href}]${args.join(' ')}`;
if ( text === lastLogText && type === lastLogType ) {
@ -188,30 +186,45 @@ function safeSelf() {
lastLogType = type;
lastLogText = text;
lastLogTime = Date.now();
if ( bcBuffer === undefined ) {
return bc.postMessage({ what: 'messageToLogger', type, text });
}
bcBuffer.push({ type, text });
return text;
};
bc.onmessage = ev => {
const msg = ev.data;
switch ( msg ) {
case 'iamready!':
if ( bcBuffer === undefined ) { break; }
bcBuffer.forEach(({ type, text }) =>
bc.postMessage({ what: 'messageToLogger', type, text })
);
bcBuffer = undefined;
break;
case 'setScriptletLogLevelToOne':
safe.logLevel = 1;
break;
case 'setScriptletLogLevelToTwo':
safe.logLevel = 2;
break;
}
};
bc.postMessage('areyouready?');
try {
const bc = new self.BroadcastChannel(scriptletGlobals.bcSecret);
let bcBuffer = [];
safe.sendToLogger = (type, ...args) => {
const text = safe.toLogText(type, ...args);
if ( text === undefined ) { return; }
if ( bcBuffer === undefined ) {
return bc.postMessage({ what: 'messageToLogger', type, text });
}
bcBuffer.push({ type, text });
};
bc.onmessage = ev => {
const msg = ev.data;
switch ( msg ) {
case 'iamready!':
if ( bcBuffer === undefined ) { break; }
bcBuffer.forEach(({ type, text }) =>
bc.postMessage({ what: 'messageToLogger', type, text })
);
bcBuffer = undefined;
break;
case 'setScriptletLogLevelToOne':
safe.logLevel = 1;
break;
case 'setScriptletLogLevelToTwo':
safe.logLevel = 2;
break;
}
};
bc.postMessage('areyouready?');
} catch(_) {
safe.sendToLogger = (type, ...args) => {
const text = safe.toLogText(type, ...args);
if ( text === undefined ) { return; }
console.log(`uBO${text}`);
};
}
return safe;
}
@ -5144,7 +5157,6 @@ function trustedPreventXhr(...args) {
}
/**
*
* @trustedScriptlet trusted-prevent-dom-bypass
*
* @description
@ -5219,7 +5231,6 @@ function trustedPreventDomBypass(
}
/**
*
* @trustedScriptlet trusted-override-element-method
*
* @description

View File

@ -176,25 +176,28 @@ const onScriptletMessageInjector = (( ) => {
'(',
function(name) {
if ( self.uBO_bcSecret ) { return; }
const bcSecret = new self.BroadcastChannel(name);
bcSecret.onmessage = ev => {
const msg = ev.data;
switch ( typeof msg ) {
case 'string':
if ( msg !== 'areyouready?' ) { break; }
bcSecret.postMessage('iamready!');
break;
case 'object':
if ( self.vAPI && self.vAPI.messaging ) {
self.vAPI.messaging.send('contentscript', msg);
} else {
console.log(`[uBO][${msg.type}]${msg.text}`);
try {
const bcSecret = new self.BroadcastChannel(name);
bcSecret.onmessage = ev => {
const msg = ev.data;
switch ( typeof msg ) {
case 'string':
if ( msg !== 'areyouready?' ) { break; }
bcSecret.postMessage('iamready!');
break;
case 'object':
if ( self.vAPI && self.vAPI.messaging ) {
self.vAPI.messaging.send('contentscript', msg);
} else {
console.log(`[uBO][${msg.type}]${msg.text}`);
}
break;
}
break;
}
};
bcSecret.postMessage('iamready!');
self.uBO_bcSecret = bcSecret;
};
bcSecret.postMessage('iamready!');
self.uBO_bcSecret = bcSecret;
} catch(_) {
}
}.toString(),
')(',
'bcSecret-slot',