fix forwarding data between server, content script, and popup

This commit is contained in:
Tamius Han 2022-09-20 01:34:59 +02:00
parent a0388689cf
commit 740f2e8f6f
6 changed files with 130 additions and 50 deletions

View File

@ -84,6 +84,7 @@ export default class UWServer {
this.settings = new Settings({logger: this.logger}); this.settings = new Settings({logger: this.logger});
await this.settings.init(); await this.settings.init();
this.eventBus = new EventBus(); this.eventBus = new EventBus();
for (const action in this.eventBusCommands) { for (const action in this.eventBusCommands) {
@ -93,6 +94,7 @@ export default class UWServer {
} }
this.comms = new CommsServer(this); this.comms = new CommsServer(this);
this.eventBus.setComms(this.comms);
browser.tabs.onActivated.addListener((m) => {this.onTabSwitched(m)}); browser.tabs.onActivated.addListener((m) => {this.onTabSwitched(m)});
} catch (e) { } catch (e) {

View File

@ -1,4 +1,4 @@
import CommsClient from './comms/CommsClient'; import CommsClient, { CommsOrigin } from './comms/CommsClient';
import CommsServer from './comms/CommsServer'; import CommsServer from './comms/CommsServer';
export interface EventBusCommand { export interface EventBusCommand {
@ -10,7 +10,7 @@ export interface EventBusContext {
stopPropagation?: boolean, stopPropagation?: boolean,
// Context stuff added by Comms // Context stuff added by Comms
fromComms?: boolean, origin?: CommsOrigin,
comms?: { comms?: {
sender?: any, sender?: any,
port?: any, port?: any,
@ -86,8 +86,10 @@ export default class EventBus {
} }
} }
if (this.comms && !context?.fromComms) { // preventing messages from flowing back to their original senders is
this.comms.sendMessage({command, config}, context); // CommsServer's job. EventBus does not have enough data for this decision.
if (this.comms) {
this.comms.sendMessage({command, config, context}, context);
} }
if (context?.stopPropagation) { if (context?.stopPropagation) {

View File

@ -3,7 +3,7 @@ import BrowserDetect from '../../conf/BrowserDetect';
import Logger from '../Logger'; import Logger from '../Logger';
import { browser } from 'webextension-polyfill-ts'; import { browser } from 'webextension-polyfill-ts';
import Settings from '../Settings'; import Settings from '../Settings';
import EventBus from '../EventBus'; import EventBus, { EventBusContext } from '../EventBus';
if (process.env.CHANNEL !== 'stable'){ if (process.env.CHANNEL !== 'stable'){
console.info("Loading CommsClient"); console.info("Loading CommsClient");
@ -50,7 +50,7 @@ if (process.env.CHANNEL !== 'stable'){
* | (Connect to popup) X POPUP EVENT BUS * | (Connect to popup) X POPUP EVENT BUS
* | A (accessible within popup) /todo * | A (accessible within popup) /todo
* x eventBus.sendToTunnel() | | * x eventBus.sendToTunnel() | |
* <iframe tunnel> \----------------> ??? X * <iframe tunnel> \--------> CommsClient X
* A | * A |
* | X App.vue * | X App.vue
* V * V
@ -63,9 +63,15 @@ if (process.env.CHANNEL !== 'stable'){
* (accessible within player UI) * (accessible within player UI)
*/ */
export enum CommsOrigin {
ContentScript = 1,
Popup = 2,
Server = 3
}
class CommsClient { class CommsClient {
commsId: string; commsId: string;
origin: CommsOrigin;
logger: Logger; logger: Logger;
settings: any; // sus? settings: any; // sus?
@ -81,6 +87,12 @@ class CommsClient {
this.logger = logger; this.logger = logger;
this.eventBus = eventBus; this.eventBus = eventBus;
if (name === 'popup-port') {
this.origin = CommsOrigin.Popup;
} else {
this.origin = CommsOrigin.ContentScript;
}
this.port = browser.runtime.connect(null, {name: name}); this.port = browser.runtime.connect(null, {name: name});
this.logger.onLogEnd( this.logger.onLogEnd(
@ -111,13 +123,18 @@ class CommsClient {
} }
//#endregion //#endregion
async sendMessage(message, context?){ async sendMessage(message, context?: EventBusContext){
message = JSON.parse(JSON.stringify(message)); // vue quirk. We should really use vue store instead message = JSON.parse(JSON.stringify(message)); // vue quirk. We should really use vue store instead
// content script client and popup client differ in this one thing
if (this.origin === CommsOrigin.Popup) {
return this.port.postMessage(message, context);
}
return browser.runtime.sendMessage(null, message, null); return browser.runtime.sendMessage(null, message, null);
} }
processReceivedMessage(message){ processReceivedMessage(message){
this.eventBus.send(message.command, message.config, {fromComms: true}); this.eventBus.send(message.command, message.config, {origin: CommsOrigin.Server});
} }
} }

View File

@ -5,6 +5,7 @@ import Settings from '../Settings';
import { browser } from 'webextension-polyfill-ts'; import { browser } from 'webextension-polyfill-ts';
import ExtensionMode from '../../../common/enums/ExtensionMode.enum'; import ExtensionMode from '../../../common/enums/ExtensionMode.enum';
import EventBus from '../EventBus'; import EventBus from '../EventBus';
import { CommsOrigin } from './CommsClient';
class CommsServer { class CommsServer {
@ -76,17 +77,29 @@ class CommsServer {
//#endregion //#endregion
sendMessage(message, context?) { sendMessage(message, context?) {
if (context?.comms.forwardTo === 'all') { // stop messages from returning where they came from, and prevent
return this.sendToAll(message); // cross-pollination between content scripts running in different
// tabs.
console.log('sendmessage of comms server. Received message:', message, 'and context:', context);
if (context?.origin !== CommsOrigin.ContentScript) {
console.log('origin is NOT content script. This means forwarding to content scripts is okay!');
if (context?.comms.forwardTo === 'all') {
return this.sendToAll(message);
}
if (context?.comms.forwardTo === 'active') {
console.log('forwarding message to active tab:', message);
return this.sendToActive(message);
}
if (context?.comms.forwardTo === 'contentScript') {
return this.sendToFrame(message, context.tab, context.frame, context.port);
}
} }
if (context?.comms.forwardTo === 'active') { if (context?.origin !== CommsOrigin.Popup) {
return this.sendToActive(message); if (context?.comms.forwardTo === 'popup') {
} return this.sendToPopup(message);
if (context?.comms.forwardTo === 'contentScript') { }
return this.sendToFrame(message, context.tab, context.frame, context.port);
}
if (context?.comms.forwardTo === 'popup') {
return this.sendToPopup(message);
} }
} }
@ -169,7 +182,7 @@ class CommsServer {
} }
private async processReceivedMessage(message, port){ private async processReceivedMessage(message, port){
this.logger.log('info', 'comms', "[CommsServer.js::processReceivedMessage] Received message from popup/content script!", message, "port", port); console.log('processing received message!', {message, portName: port.name, port})
// this triggers events // this triggers events
this.eventBus.send( this.eventBus.send(
@ -177,8 +190,14 @@ class CommsServer {
message.config, message.config,
{ {
...message.context, ...message.context,
comms: {port}, comms: {
fromComms: true ...message.context?.comms,
port
},
// origin is required to stop cross-pollination between content scripts, while still
// preserving the ability to send messages directly between popup and content scripts
origin: port.name === 'popup-port' ? CommsOrigin.Popup : CommsOrigin.ContentScript
} }
); );
} }
@ -186,7 +205,17 @@ class CommsServer {
private processReceivedMessage_nonpersistent(message, sender){ private processReceivedMessage_nonpersistent(message, sender){
this.logger.log('info', 'comms', "%c[CommsServer.js::processMessage_nonpersistent] Received message from background script!", "background-color: #11D; color: #aad", message, sender); this.logger.log('info', 'comms', "%c[CommsServer.js::processMessage_nonpersistent] Received message from background script!", "background-color: #11D; color: #aad", message, sender);
this.eventBus.send(message.command, message.config, {comms: {sender}, fromComms: true}); this.eventBus.send(
message.command,
message.config, {
...message.context,
comms: {
...message.context?.comms,
sender
},
origin: CommsOrigin.Server
}
);
} }
} }

View File

@ -10,55 +10,52 @@
--> -->
<div v-if="settingsInitialized" <div v-if="settingsInitialized"
class="popup flex flex-column no-overflow" class="popup flex flex-column no-overflow"
:class="{'popup-chrome': ! BrowserDetect.firefox}" :class="{'popup-chrome': ! BrowserDetect?.firefox}"
> >
<div class="flex-row flex-nogrow flex-noshrink relative" <div class="flex-row flex-nogrow flex-noshrink relative"
:class="{'header': !narrowPopup, 'header-small': narrowPopup}" :class="{'header': !narrowPopup, 'header-small': narrowPopup}"
> >
<span class="smallcaps">Ultrawidify</span>: <small>Quick settings</small> <span class="smallcaps">Ultrawidify</span>: <small>Quick settings</small>
<div class="absolute channel-info" v-if="BrowserDetect.processEnvChannel !== 'stable'"> <div class="absolute channel-info" v-if="BrowserDetect?.processEnvChannel !== 'stable'">
Build channel: {{BrowserDetect.processEnvChannel}} Build channel: {{BrowserDetect?.processEnvChannel}}
</div> </div>
</div> </div>
<div class="flex flex-row body no-overflow flex-grow"> <div class="flex flex-row body no-overflow flex-grow">
<pre>
---- site:
{{site}}
----
</pre>
</div> </div>
</div> </div>
<pre>
---- site:
{{site}}
----
</pre>
</template> </template>
<script> <script>
import WhatsNewPanel from './panels/WhatsNewPanel.vue';
import SiteDetailsPanel from './panels/SiteDetailsPanel.vue';
import Donate from '../common/misc/Donate.vue';
import Debug from '../ext/conf/Debug'; import Debug from '../ext/conf/Debug';
import BrowserDetect from '../ext/conf/BrowserDetect'; import BrowserDetect from '../ext/conf/BrowserDetect';
import Comms from '../ext/lib/comms/Comms'; import Comms from '../ext/lib/comms/Comms';
import VideoPanel from './panels/VideoPanel'; import CommsClient from '../ext/lib/comms/CommsClient';
import PerformancePanel from './panels/PerformancePanel';
import Settings from '../ext/lib/Settings'; import Settings from '../ext/lib/Settings';
import ExecAction from './js/ExecAction';
import DefaultSettingsPanel from './panels/DefaultSettingsPanel';
import AboutPanel from './panels/AboutPanel';
import ExtensionMode from '../common/enums/ExtensionMode.enum';
import Logger from '../ext/lib/Logger'; import Logger from '../ext/lib/Logger';
import EventBus from '../ext/lib/EventBus';
import {ChromeShittinessMitigations as CSM} from '../common/js/ChromeShittinessMitigations'; import {ChromeShittinessMitigations as CSM} from '../common/js/ChromeShittinessMitigations';
import { browser } from 'webextension-polyfill-ts'; import { browser } from 'webextension-polyfill-ts';
export default { export default {
data () { data () {
return { return {
comms: new Comms(), comms: undefined,
eventBus: new EventBus(),
settings: {}, settings: {},
settingsInitialized: false, settingsInitialized: false,
narrowPopup: null, narrowPopup: null,
sideMenuVisible: null, sideMenuVisible: null,
logger: undefined, logger: undefined,
site: undefined site: undefined,
} }
}, },
async created() { async created() {
@ -71,9 +68,31 @@ export default {
await this.settings.init(); await this.settings.init();
this.settingsInitialized = true; this.settingsInitialized = true;
const port = browser.runtime.connect({name: 'popup-port'}); // const port = browser.runtime.connect({name: 'popup-port'});
port.onMessage.addListener( (m,p) => this.processReceivedMessage(m,p)); // port.onMessage.addListener( (m,p) => this.processReceivedMessage(m,p));
CSM.setProperty('port', port); // CSM.setProperty('port', port);
this.eventBus = new EventBus();
this.eventBus.subscribe(
'set-current-site',
{
function: (config, context) => {
if (this.site) {
if (!this.site.host) {
// dunno why this fix is needed, but sometimes it is
this.site.host = config.site.host;
}
}
this.site = config.site;
this.selectedSite = this.selectedSite || config.site.host;
this.loadFrames(this.site);
}
}
);
this.comms = new CommsClient('popup-port', this.logger, this.eventBus);
this.eventBus.setComms(this.comms);
// ensure we'll clean player markings on popup close // ensure we'll clean player markings on popup close
@ -94,8 +113,7 @@ export default {
while (true) { while (true) {
try { try {
console.log('trying to get site ...'); console.log('trying to get site ...');
this.getSite(); this.requestSite();
console.log('site gottne');
} catch (e) { } catch (e) {
console.warn('failed to load site:', e); console.warn('failed to load site:', e);
} }
@ -129,13 +147,24 @@ export default {
toObject(obj) { toObject(obj) {
return JSON.parse(JSON.stringify(obj)); return JSON.parse(JSON.stringify(obj));
}, },
getSite() { requestSite() {
try { try {
this.logger.log('info','popup', '[popup::getSite] Requesting current site ...') this.logger.log('info','popup', '[popup::getSite] Requesting current site ...')
CSM.port.postMessage({cmd: 'get-current-site'}); console.info('requesting current site')
// CSM.port.postMessage({command: 'get-current-site'});
this.eventBus.send(
'get-current-site',
undefined,
{
comms: {forwardTo: 'active'}
}
);
} catch (e) { } catch (e) {
this.logger.log('error','popup','[popup::getSite] sending get-current-site failed for some reason. Reason:', e); this.logger.log('error','popup','[popup::getSite] sending get-current-site failed for some reason. Reason:', e);
} }
},
setSite(data) {
}, },
getRandomColor() { getRandomColor() {
return `rgb(${Math.floor(Math.random() * 128)}, ${Math.floor(Math.random() * 128)}, ${Math.floor(Math.random() * 128)})`; return `rgb(${Math.floor(Math.random() * 128)}, ${Math.floor(Math.random() * 128)}, ${Math.floor(Math.random() * 128)})`;
@ -143,8 +172,9 @@ export default {
processReceivedMessage(message, port) { processReceivedMessage(message, port) {
this.logger.log('info', 'popup', '[popup::processReceivedMessage] received message:', message) this.logger.log('info', 'popup', '[popup::processReceivedMessage] received message:', message)
console.info('[popup::processReceivedMessage] got message:', message);
if (message.cmd === 'set-current-site'){ if (message.command === 'set-current-site'){
if (this.site) { if (this.site) {
if (!this.site.host) { if (!this.site.host) {
// dunno why this fix is needed, but sometimes it is // dunno why this fix is needed, but sometimes it is

View File

@ -3,4 +3,4 @@ import App from './App';
import mdiVue from 'mdi-vue/v3'; import mdiVue from 'mdi-vue/v3';
import * as mdijs from '@mdi/js'; import * as mdijs from '@mdi/js';
createApp(App).mount('#app').use(mdiVue, {icons: mdijs}); createApp(App).mount('#app') //.use(mdiVue, {icons: mdijs});