diff --git a/src/ext/lib/comms/CommsServer.js b/src/ext/lib/comms/CommsServer.js index 9432340..72c8067 100644 --- a/src/ext/lib/comms/CommsServer.js +++ b/src/ext/lib/comms/CommsServer.js @@ -9,14 +9,12 @@ class CommsServer { this.ports = []; this.popupPort = null; - var ths = this; - if (BrowserDetect.firefox) { browser.runtime.onConnect.addListener(p => this.onConnect(p)); - browser.runtime.onMessage.addListener((m, sender) => ths.processReceivedMessage_nonpersistent(m, sender)); + browser.runtime.onMessage.addListener((m, sender) => this.processReceivedMessage_nonpersistent(m, sender)); } else { chrome.runtime.onConnect.addListener(p => ths.onConnect(p)); - chrome.runtime.onMessage.addListener((m, sender, callback) => ths.processReceivedMessage_nonpersistent(m, sender, callback)); + chrome.runtime.onMessage.addListener((m, sender, callback) => this.processReceivedMessage_nonpersistent(m, sender, callback)); } // commands — functions that handle incoming messages @@ -230,7 +228,6 @@ class CommsServer { for (const frame in this.ports[tabs[0].id]) { this.sendToContentScripts(message, tabs[0].id, frame); - this.ports[tabs[0].id][frame].postMessage(message); } } @@ -238,7 +235,7 @@ class CommsServer { // poseben primer | special case if (port.name === 'popup-port') { this.popupPort = port; - this.popupPort.onMessage.addListener( (m,p) => ths.processReceivedMessage(m,p)); + this.popupPort.onMessage.addListener( (m,p) => this.processReceivedMessage(m,p)); return; } @@ -251,10 +248,14 @@ class CommsServer { this.ports[tabId][frameId] = {}; } this.ports[tabId][frameId][port.name] = port; - this.ports[tabId][frameId][port.name].onMessage.addListener( (m,p) => ths.processReceivedMessage(m, p)); + this.ports[tabId][frameId][port.name].onMessage.addListener( (m,p) => this.processReceivedMessage(m, p)); - this.ports[tabId][frameId][port.name].onDisconnect.addListener( (p) => { - delete this.ports[p.sender.tab.id][p.sender.frameId][port.name]; + this.ports[tabId][frameId][port.name].onDisconnect.addListener( (p) => { + try { + delete this.ports[p.sender.tab.id][p.sender.frameId][port.name]; + } catch (e) { + // no biggie if the thing above doesn't exist. + } if (Object.keys(this.ports[tabId][frameId].length === 0)) { delete this.ports[tabId][frameId]; if(Object.keys(this.ports[p.sender.tab.id]).length === 0) { @@ -273,7 +274,11 @@ class CommsServer { ); if (this.commands[message.cmd]) { for (const c of this.commands[message.cmd]) { - await c(message, portOrSender, sendResponse); + try { + await c(message, portOrSender, sendResponse); + } catch (e) { + this.logger.log('error', 'debug', "[CommsServer.js::execCmd] failed to execute command.", e) + } } } } diff --git a/src/ext/uw-bg.js b/src/ext/uw-bg.js index 0fa8680..22a493f 100644 --- a/src/ext/uw-bg.js +++ b/src/ext/uw-bg.js @@ -4,7 +4,15 @@ import CommsServer from './lib/comms/CommsServer'; import Settings from './lib/Settings'; import Logger from './lib/Logger'; -import sleep from '../common/js/utils'; +import { sleep } from '../common/js/utils'; + +// we need vue in bg script, so we can get vuex. +// and we need vuex so popup will be initialized +// after the first click without resorting to ugly, +// dirty hacks +import Vue from 'vue'; +import Vuex from 'vuex'; +import VuexWebExtensions from 'vuex-webextensions'; var BgVars = { arIsActive: true, @@ -29,6 +37,8 @@ class UWServer { 'siteSettings': undefined, 'videoSettings': undefined, } + + this.uiLoggerInitialized = false; } async setup() { @@ -51,8 +61,9 @@ class UWServer { this.settings = new Settings({logger: this.logger}); await this.settings.init(); this.comms = new CommsServer(this); - this.comms.subscribe('show-logger', async () => await this.initUi()); + 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); var ths = this; @@ -103,6 +114,10 @@ class UWServer { extractHostname(url){ var hostname; + if (!url) { + return ""; + } + // extract hostname if (url.indexOf("://") > -1) { //find & remove protocol (http, ftp, etc.) and get hostname hostname = url.split('/')[2]; @@ -218,11 +233,41 @@ class UWServer { }, () => resolve()) ); } + } catch (e) { this.logger.log('ERROR', 'uwbg', 'UI initialization failed. Reason:', e); } } + async initUiAndShowLogger() { + // this implementation is less than optimal and very hacky, but it should work + // just fine for our use case. + this.uiLoggerInitialized = false; + + await this.initUi(); + + await new Promise( async (resolve, reject) => { + // 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 + // 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 + // promise and off we go + while (!isRejected) { + if (this.uiLoggerInitialized) { + resolve(); + return; // remember the bit about resolve() not breaking the loop? + } + await sleep(100); + } + }) + } + async getCurrentTab() { if (BrowserDetect.firefox) { return (await browser.tabs.query({active: true, currentWindow: true}))[0]; diff --git a/src/ext/uw-ui.js b/src/ext/uw-ui.js index e543b1b..d3607bc 100644 --- a/src/ext/uw-ui.js +++ b/src/ext/uw-ui.js @@ -8,6 +8,7 @@ import LoggerUi from '../csui/LoggerUi'; import Logger from './lib/Logger'; import Settings from './lib/Settings'; import CommsClient from './lib/comms/CommsClient'; +import Comms from './lib/comms/Comms'; class UwUi { @@ -31,8 +32,8 @@ class UwUi { // * if video/player is detected (which can only happen if extension is enabled // for that particular site) - // initialize vuejs, but only once (check handled in initVue()) - this.initVue(); + // NOTE: we need to setup logger and comms _before_ initializing vue (unless we're starting) + // because logger settings say we should // setup logger try { @@ -74,7 +75,7 @@ class UwUi { if (this.logger.isLoggingAllowed()) { console.info("[uw::init] Logging is allowed! Initalizing vue and UI!"); this.initVue(); - this.initUi(); + this.initLoggerUi(); this.logger.setVuexStore(this.vuexStore); } @@ -107,11 +108,17 @@ class UwUi { } this.comms = new CommsClient('content-ui-port', this.logger, this.commsHandlers); + + // initialize vuejs, but only once (check handled in initVue()) + // we need to initialize this _after_ initializing comms. + this.initVue(); } initVue() { // never init twice if (this.vueInitiated) { + // let background script know it can proceed with sending 'show-logger' command. + Comms.sendMessage({cmd: 'uwui-vue-initialized'}); return; } @@ -154,6 +161,9 @@ class UwUi { // make sure we don't init twice this.vueInitiated = true; + + // let background script know it can proceed with sending 'show-logger' command. + Comms.sendMessage({cmd: 'uwui-vue-initialized'}); } async initLoggerUi() { @@ -188,6 +198,7 @@ class UwUi { if (!this.loggerUiInitiated) { await this.initLoggerUi(); } + try { this.vuexStore.dispatch('uw-show-logger'); @@ -215,5 +226,8 @@ if (! document.getElementById(markerId)) { const uwui = new UwUi(); uwui.init(); +} else { + // let background script know it can proceed with sending 'show-logger' command. + Comms.sendMessage({cmd: 'uwui-vue-initialized'}); }