Integrate comms client/server into eventBus

This commit is contained in:
Tamius Han 2022-07-31 00:15:28 +02:00
parent f0120010fe
commit 8806c8ea0c
8 changed files with 269 additions and 354 deletions

View File

@ -7,6 +7,7 @@ import CommsClient from './lib/comms/CommsClient';
import PageInfo from './lib/video-data/PageInfo';
import Logger, { baseLoggingOptions } from './lib/Logger';
import UWGlobals from './lib/UWGlobals';
import EventBus from './lib/EventBus';
export default class UWContent {
pageInfo: PageInfo;
@ -14,6 +15,7 @@ export default class UWContent {
settings: Settings;
actionHandler: ActionHandler;
logger: Logger;
eventBus: EventBus;
commsHandlers: {
[x: string]: ((a: any, b?: any) => void | Promise<void>)[]
@ -84,16 +86,13 @@ export default class UWContent {
console.error("logger init failed!", e)
}
// second — let's add some globals
if (! (window as any).ultrawidify) {
(window as any).ultrawidify = new UWGlobals();
((window as any).ultrawidify as UWGlobals).importSubscriptionsFromCommsHandlers(this.commsHandlers);
}
// init() is re-run any time settings change
if (this.comms) {
this.comms.destroy();
}
if (this.eventBus) {
this.eventBus.destroy();
}
if (!this.settings) {
this.settings = new Settings({
onSettingsChanged: () => this.reloadSettings(),
@ -102,51 +101,70 @@ export default class UWContent {
await this.settings.init();
}
this.comms = new CommsClient('content-main-port', this.logger, this.commsHandlers);
// če smo razširitev onemogočili v nastavitvah, ne naredimo ničesar
// If extension is soft-disabled, don't do shit
var extensionMode = this.settings.getExtensionMode();
this.logger.log('info', 'debug', "[uw::init] Extension mode:" + (extensionMode < 0 ? "disabled" : extensionMode == '1' ? 'basic' : 'full'));
const isSiteDisabled = extensionMode === ExtensionMode.Disabled
if (isSiteDisabled) {
if (this.settings.getExtensionMode('@global') === ExtensionMode.Disabled) {
this.logger.log('info', 'debug', "[uw::init] EXTENSION DISABLED, THEREFORE WONT BE STARTED")
return;
this.eventBus = new EventBus();
this.eventBus.subscribe(
'uw-restart',
{
function: () => this.initPhase2()
}
}
);
this.comms = new CommsClient('content-main-port', this.logger, this.eventBus);
try {
if (this.pageInfo) {
this.logger.log('info', 'debug', '[uw.js::setup] An instance of pageInfo already exists and will be destroyed.');
this.pageInfo.destroy();
}
this.pageInfo = new PageInfo(this.comms, this.settings, this.logger, extensionMode, isSiteDisabled);
this.logger.log('info', 'debug', "[uw.js::setup] pageInfo initialized.");
this.logger.log('info', 'debug', "[uw.js::setup] will try to initate ActionHandler.");
// start action handler only if extension is enabled for this site
if (!isSiteDisabled) {
if (this.actionHandler) {
this.actionHandler.destroy();
}
this.actionHandler = new ActionHandler(this.pageInfo.eventBus, this.settings, this.logger);
this.actionHandler.init();
this.logger.log('info', 'debug', "[uw.js::setup] ActionHandler initiated.");
}
} catch (e) {
console.error('Ultrawidify: failed to start extension. Error:', e)
this.logger.log('error', 'debug', "[uw::init] FAILED TO START EXTENSION. Error:", e);
}
this.initPhase2();
} catch (e) {
console.error('Ultrawidify initalization failed for some reason:', e);
}
}
initPhase2() {
// If extension is soft-disabled, don't do shit
var extensionMode = this.settings.getExtensionMode();
this.logger.log('info', 'debug', "[uw::init] Extension mode:" + (extensionMode < 0 ? "disabled" : extensionMode == '1' ? 'basic' : 'full'));
const isSiteDisabled = extensionMode === ExtensionMode.Disabled
if (isSiteDisabled) {
this.destroy();
if (this.settings.getExtensionMode('@global') === ExtensionMode.Disabled) {
this.logger.log('info', 'debug', "[uw::init] EXTENSION DISABLED, THEREFORE WONT BE STARTED")
return;
}
}
try {
if (this.pageInfo) {
this.logger.log('info', 'debug', '[uw.js::setup] An instance of pageInfo already exists and will be destroyed.');
this.pageInfo.destroy();
}
this.pageInfo = new PageInfo(this.eventBus, this.settings, this.logger, extensionMode, isSiteDisabled);
this.logger.log('info', 'debug', "[uw.js::setup] pageInfo initialized.");
this.logger.log('info', 'debug', "[uw.js::setup] will try to initate ActionHandler.");
// start action handler only if extension is enabled for this site
if (!isSiteDisabled) {
if (this.actionHandler) {
this.actionHandler.destroy();
}
this.actionHandler = new ActionHandler(this.eventBus, this.settings, this.logger);
this.actionHandler.init();
this.logger.log('info', 'debug', "[uw.js::setup] ActionHandler initiated.");
}
} catch (e) {
console.error('Ultrawidify: failed to start extension. Error:', e)
this.logger.log('error', 'debug', "[uw::init] FAILED TO START EXTENSION. Error:", e);
}
}
destroy() {
if (this.pageInfo) {
this.pageInfo.destroy();
}
if (this.actionHandler) {
this.actionHandler.destroy();
}
}
}

View File

@ -7,11 +7,13 @@ import Logger, { baseLoggingOptions } from './lib/Logger';
import { sleep } from '../common/js/utils';
import { browser } from 'webextension-polyfill-ts';
import EventBus, { EventBusCommand } from './lib/EventBus';
export default class UWServer {
settings: Settings;
logger: Logger;
comms: CommsServer;
eventBus: EventBus;
ports: any[] = [];
hasVideos: boolean;
@ -24,6 +26,26 @@ export default class UWServer {
'videoSettings': undefined,
}
eventBusCommands = {
'popup-set-selected-tab': [{
function: (message) => this.setSelectedTab(message.selectedMenu, message.selectedSubitem)
}],
'has-video': [{
function: (message, context) => this.registerVideo(context.comms.sender)
}],
'noVideo' : [{
function: (message, context) => this.unregisterVideo(context.comms.sender)
}],
'inject-css': [{
function: (message, context) => this.injectCss(message.cssString, context.comms.sender)
}],
'eject-css': [{
function: (message, context) => this.removeCss(message.cssString, context.comms.sender)
}],
'replace-css': [{
function: (message, context) => this.replaceCss(message.oldCssString, message.newCssString, context.comms.sender)
}]
};
private gcTimeout: any;
uiLoggerInitialized: boolean = false;
@ -52,13 +74,13 @@ export default class UWServer {
this.settings = new Settings({logger: this.logger});
await this.settings.init();
this.eventBus = new EventBus();
this.comms = new CommsServer(this);
this.comms.subscribe('show-logger', async () => await this.initUiAndShowLogger());
this.comms.subscribe('init-vue', async () => await this.initUi());
this.comms.subscribe('uwui-vue-initialized', () => this.uiLoggerInitialized = true);
this.comms.subscribe('emit-logs', () => {}); // we don't need to do anything, this gets forwarded to UI content script as is
browser.tabs.onActivated.addListener((m) => {this.onTabSwitched(m)});
browser.tabs.onActivated.addListener((m) => {this.onTabSwitched(m)});
} catch (e) {
console.error(`Ultrawidify [server]: failed to start. Reason:`, e);
}
@ -84,7 +106,7 @@ export default class UWServer {
async removeCss(css, sender) {
try {
browser.tabs.removeCSS(sender.tab.id, {code: css, cssOrigin: 'user', frameId: sender.frameId});
} catch (e) {
} catch (e) {
this.logger.log('error','debug', '[UwServer::injectCss] Error while removing css:', {error: e, css, sender});
}
}
@ -98,22 +120,22 @@ export default class UWServer {
extractHostname(url){
var hostname;
if (!url) {
return "<no url>";
}
// extract hostname
// extract hostname
if (url.indexOf("://") > -1) { //find & remove protocol (http, ftp, etc.) and get hostname
hostname = url.split('/')[2];
}
else {
hostname = url.split('/')[0];
}
hostname = hostname.split(':')[0]; //find & remove port number
hostname = hostname.split('?')[0]; //find & remove "?"
return hostname;
}
@ -209,14 +231,14 @@ export default class UWServer {
allFrames: true,
});
} else if (BrowserDetect.anyChromium) {
await new Promise<void>( resolve =>
await new Promise<void>( resolve =>
chrome.tabs.executeScript({
file: '/ext/uw-ui.js',
allFrames: true,
}, () => resolve())
);
}
} catch (e) {
console.warn('Ultrawidify [server]: UI setup failed. While problematic, this problem shouldn\'t completely crash the extension.');
this.logger.log('ERROR', 'uwbg', 'UI initialization failed. Reason:', e);
@ -232,16 +254,16 @@ export default class UWServer {
await this.initUi();
await new Promise<void>( async (resolve, reject) => {
// if content script doesn't give us a response within 5 seconds, something is
// if content script doesn't give us a response within 5 seconds, something is
// obviously wrong and we stop waiting,
// oh and btw, resolve/reject do not break the loops, so we need to do that
// oh and btw, resolve/reject do not break the loops, so we need to do that
// ourselves:
// https://stackoverflow.com/questions/55207256/will-resolve-in-promise-loop-break-loop-iteration
let isRejected = false;
setTimeout( async () => {isRejected = true; reject()}, 5000);
// check whether UI has been initiated on the FE. If it was, we resolve the
// check whether UI has been initiated on the FE. If it was, we resolve the
// promise and off we go
while (!isRejected) {
if (this.uiLoggerInitialized) {
@ -261,7 +283,7 @@ export default class UWServer {
}
async getVideoTab() {
// friendly reminder: if current tab doesn't have a video,
// friendly reminder: if current tab doesn't have a video,
// there won't be anything in this.videoTabs[this.currentTabId]
const ctab = await this.getCurrentTab();
@ -295,11 +317,11 @@ export default class UWServer {
return {
...this.videoTabs[ctab.id],
host: this.extractHostname(ctab.url),
selected: this.selectedSubitem
selected: this.selectedSubitem
};
}
// return something more or less empty if this tab doesn't have
// return something more or less empty if this tab doesn't have
// a video registered for it
return {
host: this.extractHostname(ctab.url),
@ -308,7 +330,7 @@ export default class UWServer {
}
}
// chrome shitiness mitigation
// chrome shitiness mitigation
sendUnmarkPlayer(message) {
this.comms.sendUnmarkPlayer(message);
}

View File

@ -1,7 +1,21 @@
import CommsClient from './comms/CommsClient';
import CommsServer from './comms/CommsServer';
export interface EventBusCommand {
isGlobal?: boolean,
function: (commandConfig: any) => void | Promise<void>
function: (commandConfig: any, context?: any) => void | Promise<void>
}
export interface EventBusContext {
stopPropagation?: boolean,
// Context stuff added by Comms
fromComms?: boolean,
comms?: {
sender?: any,
port?: any,
forwardTo?: 'all' | 'active' | 'contentScript' | 'sameOrigin',
}
}
export default class EventBus {
@ -9,6 +23,20 @@ export default class EventBus {
private commands: { [x: string]: EventBusCommand[]} = {};
private downstreamBuses: EventBus[] = [];
private upstreamBus?: EventBus;
private comms?: CommsClient;
//#region lifecycle
destroy() {
this.commands = null;
for (const bus of this.downstreamBuses) {
bus.destroy();
}
}
//#endregion
setComms(comms: CommsClient): void {
this.comms = comms;
}
setUpstreamBus(eventBus: EventBus, stopRecursing: boolean = false) {
this.upstreamBus = eventBus;
@ -49,18 +77,18 @@ export default class EventBus {
}
}
send(command: string, config: any, stopPropagation?: boolean) {
send(command: string, config: any, context?: EventBusContext) {
if (!this.commands ||!this.commands[command]) {
// ensure send is not being called for commands that we have no subscriptions for
return;
}
for (const eventBusCommand of this.commands[command]) {
eventBusCommand.function(config);
eventBusCommand.function(config, context);
if (eventBusCommand.isGlobal && !stopPropagation) {
this.sendUpstream(command, config);
this.sendDownstream(command, config);
if (eventBusCommand.isGlobal && !context?.stopPropagation) {
this.sendUpstream(command, config, context);
this.sendDownstream(command, config, context);
}
}
}
@ -81,14 +109,14 @@ export default class EventBus {
}
sendGlobal(command: string, config: any) {
sendGlobal(command: string, config: any, context?: EventBusContext) {
this.send(command, config);
this.sendUpstream(command, config);
this.sendDownstream(command, config);
}
sendDownstream(command: string, config: any, sourceEventBus?: EventBus) {
sendDownstream(command: string, config: any, context?: EventBusContext, sourceEventBus?: EventBus) {
for (const eventBus of this.downstreamBuses) {
if (eventBus !== sourceEventBus) {
eventBus.send(command, config);
@ -97,11 +125,14 @@ export default class EventBus {
}
}
sendUpstream(command: string, config: any) {
sendUpstream(command: string, config: any, context?: EventBusContext) {
if (this.upstreamBus) {
this.upstreamBus.send(command, config);
this.upstreamBus.sendUpstream(command, config);
this.upstreamBus.sendDownstream(command, config, this);
this.upstreamBus.send(command, config, context);
this.upstreamBus.sendUpstream(command, config, context);
this.upstreamBus.sendDownstream(command, config, context, this);
}
if (!this.upstreamBus && this.comms && !context?.fromComms) {
this.comms.sendMessage({command, config});
}
}
}

View File

@ -3,124 +3,111 @@ import BrowserDetect from '../../conf/BrowserDetect';
import Logger from '../Logger';
import { browser } from 'webextension-polyfill-ts';
import Settings from '../Settings';
import EventBus from '../EventBus';
if (process.env.CHANNEL !== 'stable'){
console.info("Loading CommsClient");
}
/**
* Ultrawidify communication spans a few different "domains" that require a few different
* means of communication. The four isolated domains are:
*
* > content script event bus (CS)
* > player UI event bus (UI)
* > UWServer event bus (BG)
* > popup event bus
*
* It is our goal to route messages between various domains. It is our goal that eventBus
* instances in different parts of our script are at least somewhat interoperable between
* each other. As such, scripts sending commands should be unaware that Comms object even
* exists.
*
* EventBus is started first. Other components (including commsClient) follow later.
*
*
* fig 0. ULTRAWIDIFY COMMUNICATION MAP
*
* CS EVENT BUS
* (accessible within tab scripts)
* | NOT EVENT BUS
* PageInfo x (accessible within popup)
* x |
* : : x UWServer
* x CommsClient <---------------x CommsServer x
* | (Connect to popup)
* |
* x eventBus.sendToTunnel()
* <iframe tunnel>
* A
* |
* V
* x <iframe tunnel>
* |
* PlayerUIBase x
* : :
* |
* UI EVENT BUS
* (accessible within player UI)
*/
class CommsClient {
commsId: string;
logger: Logger;
settings: any; // sus?
commands: {[x: string]: any[]};
eventBus: EventBus;
_listener: (m: any) => void;
port: any;
constructor(name, logger, commands) {
//#region lifecycle
constructor(name: string, logger: Logger, eventBus: EventBus) {
try {
this.logger = logger;
this.logger = logger;
this.eventBus = eventBus;
this.eventBus.setComms(this);
this.port = browser.runtime.connect(null, {name: name});
this.port = browser.runtime.connect(null, {name: name});
this.logger.onLogEnd(
(history) => {
this.logger.log('info', 'comms', 'Sending logging-stop-and-save to background script ...');
try {
this.port.postMessage({cmd: 'logging-stop-and-save', host: window.location.hostname, history})
} catch (e) {
this.logger.log('error', 'comms', 'Failed to send message to background script. Error:', e);
this.logger.onLogEnd(
(history) => {
this.logger.log('info', 'comms', 'Sending logging-stop-and-save to background script ...');
try {
this.port.postMessage({cmd: 'logging-stop-and-save', host: window.location.hostname, history})
} catch (e) {
this.logger.log('error', 'comms', 'Failed to send message to background script. Error:', e);
}
}
}
);
);
this._listener = m => this.processReceivedMessage(m);
this.port.onMessage.addListener(this._listener);
this._listener = m => this.processReceivedMessage(m);
this.port.onMessage.addListener(this._listener);
this.commsId = (Math.random() * 20).toFixed(0);
this.commsId = (Math.random() * 20).toFixed(0);
this.commands = commands;
} catch (e) {
console.error("CONSTRUCOTR FAILED:", e)
}
}
destroy() {
if (!BrowserDetect.edge) { // edge is a very special browser made by outright morons.
this.port.onMessage.removeListener(this._listener);
}
}
//#endregion
subscribe(command, callback) {
if (!this.commands[command]) {
this.commands[command] = [callback];
} else {
this.commands[command].push(callback);
}
}
processReceivedMessage(message){
this.logger.log('info', 'comms', `[CommsClient.js::processMessage] <${this.commsId}> Received message from background script!`, message);
if (this.commands[message.cmd]) {
for (const c of this.commands[message.cmd]) {
c(message);
}
}
}
async sendMessage_nonpersistent(message){
async sendMessage(message){
message = JSON.parse(JSON.stringify(message)); // vue quirk. We should really use vue store instead
return browser.runtime.sendMessage(null, message, null);
}
// TODO: sus function — does it get any use?
async requestSettings(){
this.logger.log('info', 'comms', "%c[CommsClient::requestSettings] sending request for congif!", "background: #11D; color: #aad");
var response = await this.sendMessage_nonpersistent({cmd: 'get-config'});
this.logger.log('info', 'comms', "%c[CommsClient::requestSettings] received settings response!", "background: #11D; color: #aad", response);
if(! response || response.extensionConf){
return Promise.resolve(false);
}
this.settings = {active: JSON.parse(response.extensionConf)};
return Promise.resolve(true);
processReceivedMessage(message){
this.eventBus.send(message.command, message.config, {fromComms: true});
}
async sendMessage(message) {
return this.sendMessage_nonpersistent(message);
}
registerVideo(){
this.logger.log('info', 'comms', `[CommsClient::registerVideo] <${this.commsId}>`, "Registering video for current page.");
this.port.postMessage({cmd: "has-video"});
}
sendPerformanceUpdate(message){
this.port.postMessage({cmd: 'performance-update', message: message});
}
unregisterVideo(){
this.logger.log('info', 'comms', `[CommsClient::unregisterVideo] <${this.commsId}>`, "Unregistering video for current page.");
this.port.postMessage({cmd: "noVideo"}); // ayymd
}
announceZoom(scale){
this.port.postMessage({cmd: "announce-zoom", zoom: scale});
this.registerVideo();
}
}
if (process.env.CHANNEL !== 'stable'){

View File

@ -4,12 +4,14 @@ import Logger from '../Logger';
import Settings from '../Settings';
import { browser } from 'webextension-polyfill-ts';
import ExtensionMode from '../../../common/enums/ExtensionMode.enum';
import EventBus from '../EventBus';
class CommsServer {
server: any;
logger: Logger;
settings: Settings;
eventBus: EventBus;
ports: {
@ -21,7 +23,7 @@ class CommsServer {
/**
* commands functions that handle incoming messages
* functions can have the following arguments, which are,
* functions can have the following arguments, which are,
* in this order:
* message the message we received
* port|sender on persistent channels, second argument is port on which the server
@ -30,19 +32,6 @@ class CommsServer {
* sendResponse callback function on messages received via non-persistent channel
*/
commands: {[x: string]: ((a: any, b: any) => void | Promise<void>)[]} = {
'announce-zoom': [
(message) => {
try {
// forward message to the popup
this.popupPort.postMessage({cmd: 'set-current-zoom', zoom: message.zoom});
} catch (e) {
// if popup is closed, this will/may fail. This is okay, so we just ignore this error
}
},
],
'get-current-zoom': [
(message) => this.sendToActive(message),
],
'get-current-site': [
async (message, port) => {
port.postMessage({
@ -52,68 +41,7 @@ class CommsServer {
});
},
],
'popup-set-selected-tab': [
(message) => this.server.setSelectedTab(message.selectedMenu, message.selectedSubitem),
],
'has-video': [
(message, port) => this.server.registerVideo(port.sender),
],
'noVideo': [
(message, port) => this.server.unregisterVideo(port.sender),
],
'inject-css': [
(message, sender) => this.server.injectCss(message.cssString, sender),
],
'eject-css': [
(message, sender) => this.server.removeCss(message.cssString, sender),
],
'replace-css': [
(message, sender) => this.server.replaceCss(message.oldCssString, message.newCssString, sender),
],
// 'get-config': [
// (message, port) => {
// this.logger.log('info', 'comms', "CommsServer: received get-config. Active settings?", this.settings.active, "\n(settings:", this.settings, ")");
// port.postMessage(
// {cmd: "set-config", conf: this.settings.active, site: this.server.currentSite}
// );
// },
// ],
'get-config': [
(message, sender) => {
var ret = {extensionConf: JSON.stringify(this.settings.active)};
this.logger.log('info', 'comms', "%c[CommsServer.js::processMessage_nonpersistent] Returning this:", "background-color: #11D; color: #aad", ret);
Promise.resolve(ret);
}
],
'autoar-enable': [
() => {
this.settings.active.sites['@global'].autoar = ExtensionMode.Enabled;
this.settings.save();
this.logger.log('info', 'comms', "[uw-bg] autoar set to enabled (blacklist). evidenz:", this.settings.active);
}
],
'autoar-disable': [
(message) => {
this.settings.active.sites['@global'].autoar = ExtensionMode.Disabled;
if (message.reason){
this.settings.active.arDetect.disabledReason = message.reason;
} else {
this.settings.active.arDetect.disabledReason = 'User disabled';
}
this.settings.save();
this.logger.log('info', 'comms', "[uw-bg] autoar set to disabled. evidenz:", this.settings.active);
}
],
'autoar-set-interval': [
(message) => {
this.logger.log('info', 'comms', `[uw-bg] trying to set new interval for autoAr. New interval is, ${message.timeout} ms`);
// set fairly liberal limit
var timeout = message.timeout < 4 ? 4 : message.timeout;
this.settings.active.arDetect.timers.playing = timeout;
this.settings.save();
}
],
'logging-stop-and-save': [ // TODO: possibly never used/superseded — check
(message, sender) => {
this.logger.log('info', 'comms', "Received command to stop logging and export the received input");
@ -140,6 +68,7 @@ class CommsServer {
this.server = server;
this.logger = server.logger;
this.settings = server.settings;
this.eventBus = server.eventBus;
browser.runtime.onConnect.addListener(p => this.onConnect(p));
browser.runtime.onMessage.addListener((m, sender) => this.processReceivedMessage_nonpersistent(m, sender));
@ -170,14 +99,26 @@ class CommsServer {
else {
hostname = url.split('/')[0];
}
hostname = hostname.split(':')[0]; //find & remove port number
hostname = hostname.split('?')[0]; //find & remove "?"
return hostname;
}
sendToAll(message){
sendMessage(message, context) {
if (context?.forwardTo === 'all') {
return this.sendToAll(message);
}
if (context?.forwardTo === 'active') {
return this.sendToActive(message);
}
if (context?.forwardTo === 'contentScript') {
return this.sendToFrame(message, context.tab, context.frame, context.port);
}
}
private sendToAll(message){
for(const tab of this.ports){
for(const frame in tab){
for (const port in tab[frame]) {
@ -187,7 +128,6 @@ class CommsServer {
}
}
/**
* Sends a message to addon content scripts.
* @param message message
@ -195,7 +135,7 @@ class CommsServer {
* @param frame the frame within that tab that we want to send the message to
* @param port if defined, message will only be sent to that specific script, otherwise it gets sent to all scripts of a given frame
*/
async sendToFrameContentScripts(message, tab, frame, port?) {
private async sendToFrameContentScripts(message, tab, frame, port?) {
if (port !== undefined) {
this.ports[tab][frame][port].postMessage(message);
return;
@ -205,7 +145,7 @@ class CommsServer {
}
}
async sendToFrame(message, tab, frame, port?) {
private async sendToFrame(message, tab, frame, port?) {
this.logger.log('info', 'comms', `%c[CommsServer::sendToFrame] attempting to send message to tab ${tab}, frame ${frame}`, "background: #dda; color: #11D", message);
if (isNaN(tab)) {
@ -229,13 +169,8 @@ class CommsServer {
}
}
async sendToAllFrames(message, tab, port) {
for (const frame in this.ports[tab]) {
this.sendToFrameContentScripts(message, tab, frame, port);
}
}
async sendToActive(message) {
private async sendToActive(message) {
this.logger.log('info', 'comms', "%c[CommsServer::sendToActive] trying to send a message to active tab. Message:", "background: #dda; color: #11D", message);
const tabs = await this.activeTab;
@ -251,7 +186,7 @@ class CommsServer {
}
onConnect(port){
// poseben primer | special case
// special case
if (port.name === 'popup-port') {
this.popupPort = port;
this.popupPort.onMessage.addListener( (m,p) => this.processReceivedMessage(m,p));
@ -261,7 +196,7 @@ class CommsServer {
var tabId = port.sender.tab.id;
var frameId = port.sender.frameId;
if (! this.ports[tabId]){
this.ports[tabId] = {};
this.ports[tabId] = {};
}
if (! this.ports[tabId][frameId]) {
this.ports[tabId][frameId] = {};
@ -271,9 +206,9 @@ class CommsServer {
this.ports[tabId][frameId][port.name].onDisconnect.addListener( (p) => {
try {
delete this.ports[p.sender.tab.id][p.sender.frameId][port.name];
delete this.ports[p.sender.tab.id][p.sender.frameId][port.name];
} catch (e) {
// no biggie if the thing above doesn't exist.
// no biggie if the thing above doesn't exist.
}
if (Object.keys(this.ports[tabId][frameId].length === 0)) {
delete this.ports[tabId][frameId];
@ -284,57 +219,16 @@ class CommsServer {
});
}
// TODO: sendResponse seems redundant — it used to be a callback for
// chrome-based browsers, but browser polyfill doesn't do callback. Just
// awaits.
async execCmd(message, portOrSender, sendResponse?) {
this.logger.log(
'info', 'comms', '[CommsServer.js::execCmd] Received message', message,
". Port/sender:", portOrSender, "sendResponse:", sendResponse, "\nThere is ", this.commands[message.cmd]?.length ?? 0,
" command(s) for action", message.cmd
);
if (this.commands[message.cmd]) {
for (const c of this.commands[message.cmd]) {
try {
await c(message, portOrSender);
} catch (e) {
this.logger.log('error', 'debug', "[CommsServer.js::execCmd] failed to execute command.", e)
}
}
}
}
async handleMessage(message, portOrSender) {
await this.execCmd(message, portOrSender);
if (message.forwardToSameFramePort) {
this.sendToFrameContentScripts(message, portOrSender.tab.id, portOrSender.frameId, message.port);
}
if (message.forwardToContentScript) {
this.logger.log('info', 'comms', "[CommsServer.js::processReceivedMessage] Message has 'forward to content script' flag set. Forwarding message as is. Message:", message);
this.sendToFrame(message, message.targetTab, message.targetFrame);
}
if (message.forwardToAll) {
this.logger.log('info', 'comms', "[CommsServer.js::processReceivedMessage] Message has 'forward to all' flag set. Forwarding message as is. Message:", message);
this.sendToAll(message);
}
if (message.forwardToActive) {
this.logger.log('info', 'comms', "[CommsServer.js::processReceivedMessage] Message has 'forward to active' flag set. Forwarding message as is. Message:", message);
this.sendToActive(message);
}
}
async processReceivedMessage(message, port){
this.logger.log('info', 'comms', "[CommsServer.js::processReceivedMessage] Received message from popup/content script!", message, "port", port);
this.handleMessage(message, port)
this.eventBus.send(message, {port, fromComms: true});
}
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.handleMessage(message, sender);
this.eventBus.send(message, {sender, fromComms: true});
}
// chrome shitiness mitigation

View File

@ -75,7 +75,6 @@ class PageInfo {
this.extensionMode = extensionMode;
this.readOnly = readOnly;
this.eventBus = new EventBus();
if (comms){
this.comms = comms;
@ -84,10 +83,7 @@ class PageInfo {
try {
// request inject css immediately
const playerStyleString = this.settings.active.sites[window.location.hostname].css.replace('\\n', '');
this.comms.sendMessage({
cmd: 'inject-css',
cssString: playerStyleString
});
this.eventBus.send('inject-css', {cssString: playerStyleString});
} catch (e) {
// do nothing. It's ok if there's no special settings for the player element or crop persistence
}
@ -110,28 +106,6 @@ class PageInfo {
this.scheduleUrlCheck();
}
async injectCss(cssString) {
await this.comms.sendMessage({
cmd: 'inject-css',
cssString: cssString
});
}
async ejectCss(cssString) {
await this.comms.sendMessage({
cmd: 'eject-css',
cssString: cssString
});
}
async replaceCss(oldCssString, newCssString) {
await this.comms.sendMessage({
cmd: 'replace-css',
newCssString,
oldCssString
});
}
destroy() {
this.logger.log('info', ['debug', 'init'], "[PageInfo::destroy] destroying all videos!")
if(this.rescanTimer){
@ -139,7 +113,7 @@ class PageInfo {
}
for (let video of this.videos) {
try {
(this.comms.unregisterVideo as any)(video.videoData.vdid)
this.eventBus.send('noVideo', undefined);
video.videoData.destroy();
} catch (e) {
this.logger.log('error', ['debug', 'init'], '[PageInfo::destroy] unable to destroy video! Error:', e);
@ -148,12 +122,7 @@ class PageInfo {
try {
const playerStyleString = this.settings.active.sites[window.location.hostname].css;
if (playerStyleString) {
this.comms.sendMessage({
cmd: 'eject-css',
cssString: playerStyleString
});
}
this.eventBus.send('eject-css', {cssString: playerStyleString});
} catch (e) {
// do nothing. It's ok if there's no special settings for the player element
}
@ -300,10 +269,10 @@ class PageInfo {
if (this.videos.length > 0) {
// this.comms.registerVideo({host: window.location.hostname, location: window.location});
this.comms.registerVideo();
this.eventBus.send('has-video', null);
} else {
// this.comms.unregisterVideo({host: window.location.hostname, location: window.location});
this.comms.unregisterVideo();
this.eventBus.send('noVideo', null);
}
}
@ -415,15 +384,6 @@ class PageInfo {
}
}
announceZoom(scale) {
if (this.announceZoomTimeout) {
clearTimeout(this.announceZoomTimeout);
}
this.currentZoomScale = scale;
const ths = this;
this.announceZoomTimeout = setTimeout(() => ths.comms.announceZoom(scale), this.settings.active.zoom.announceDebounce);
}
setArPersistence(persistenceMode) {
// name of this function is mildly misleading — we don't really _set_ ar persistence. (Ar persistence
// mode is set and saved via popup or keyboard shortcuts, if user defined them) We just save the current

View File

@ -143,16 +143,19 @@ class VideoData {
if (!this.mutationObserver) {
this.setupMutationObserver();
}
await this.pageInfo.injectCss(`
.uw-ultrawidify-base-wide-screen {
margin: 0px 0px 0px 0px !important;
width: initial !important;
align-self: start !important;
justify-self: start !important;
max-height: initial !important;
max-width: initial !important;
}
`);
this.eventBus.send(
'inject-css',
`
.uw-ultrawidify-base-wide-screen {
margin: 0px 0px 0px 0px !important;
width: initial !important;
align-self: start !important;
justify-self: start !important;
max-height: initial !important;
max-width: initial !important;
}
`
);
} catch (e) {
console.error('Failed to inject base css!', e);
}

View File

@ -132,16 +132,16 @@ class Resizer {
}
}
injectCss(css) {
this.conf.pageInfo.injectCss(css);
injectCss(cssString) {
this.eventBus.send('inject-css', {cssString});
}
ejectCss(css) {
this.conf.pageInfo.ejectCss(css);
ejectCss(cssString) {
this.eventBus.send('eject-css', {cssString});
}
replaceCss(oldCss, newCss) {
this.conf.pageInfo.replaceCss(oldCss, newCss);
replaceCss(oldCssString, newCssString) {
this.eventBus.send('replace-css', {oldCss: oldCssString, newCss: newCssString});
}
prepareCss(css) {