2018-12-30 23:41:44 +01:00
|
|
|
import Debug from './conf/Debug.js';
|
|
|
|
import BrowserDetect from './conf/BrowserDetect';
|
|
|
|
import CommsServer from './lib/comms/CommsServer';
|
|
|
|
import Settings from './lib/Settings';
|
2019-09-03 21:30:18 +02:00
|
|
|
import Logger from './lib/Logger';
|
2018-12-30 23:41:44 +01:00
|
|
|
|
2020-03-09 21:29:39 +01:00
|
|
|
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';
|
2020-03-08 18:38:09 +01:00
|
|
|
|
2018-01-26 00:09:08 +01:00
|
|
|
var BgVars = {
|
|
|
|
arIsActive: true,
|
2018-02-02 00:21:29 +01:00
|
|
|
hasVideos: false,
|
|
|
|
currentSite: ""
|
|
|
|
}
|
|
|
|
|
2018-05-26 23:08:49 +02:00
|
|
|
class UWServer {
|
2018-06-27 23:55:37 +02:00
|
|
|
|
2018-05-26 23:08:49 +02:00
|
|
|
constructor() {
|
|
|
|
this.ports = [];
|
2018-06-27 23:55:37 +02:00
|
|
|
this.arIsActive = true;
|
|
|
|
this.hasVideos = false;
|
|
|
|
this.currentSite = "";
|
2018-05-26 23:08:49 +02:00
|
|
|
this.setup();
|
2018-11-07 00:03:06 +01:00
|
|
|
|
|
|
|
this.videoTabs = {};
|
2018-11-08 23:05:47 +01:00
|
|
|
this.currentTabId = 0;
|
2018-11-11 22:35:08 +01:00
|
|
|
this._gctimeout = undefined;
|
2018-11-22 22:55:22 +01:00
|
|
|
|
|
|
|
this.selectedSubitem = {
|
|
|
|
'siteSettings': undefined,
|
|
|
|
'videoSettings': undefined,
|
|
|
|
}
|
2020-03-09 21:29:39 +01:00
|
|
|
|
|
|
|
this.uiLoggerInitialized = false;
|
2018-05-26 23:08:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async setup() {
|
2019-09-03 00:48:18 +02:00
|
|
|
// logger is the first thing that goes up
|
2020-01-27 22:32:38 +01:00
|
|
|
const loggingOptions = {
|
2020-01-30 23:17:43 +01:00
|
|
|
isBackgroundScript: true,
|
2020-01-27 22:32:38 +01:00
|
|
|
allowLogging: true,
|
2020-01-30 23:17:43 +01:00
|
|
|
useConfFromStorage: true,
|
2020-01-27 22:32:38 +01:00
|
|
|
logAll: true,
|
2020-01-30 23:17:43 +01:00
|
|
|
fileOptions: {
|
|
|
|
enabled: true,
|
|
|
|
},
|
|
|
|
consoleOptions: {
|
|
|
|
enabled: true
|
|
|
|
}
|
2020-01-27 22:32:38 +01:00
|
|
|
};
|
|
|
|
this.logger = new Logger();
|
|
|
|
await this.logger.init(loggingOptions);
|
2018-08-07 23:31:28 +02:00
|
|
|
|
2019-09-03 00:48:18 +02:00
|
|
|
this.settings = new Settings({logger: this.logger});
|
2018-08-07 23:31:28 +02:00
|
|
|
await this.settings.init();
|
2018-06-27 23:55:37 +02:00
|
|
|
this.comms = new CommsServer(this);
|
2020-03-09 21:29:39 +01:00
|
|
|
this.comms.subscribe('show-logger', async () => await this.initUiAndShowLogger());
|
2020-03-08 18:38:09 +01:00
|
|
|
this.comms.subscribe('init-vue', async () => await this.initUi());
|
2020-03-09 21:29:39 +01:00
|
|
|
this.comms.subscribe('uwui-vue-initialized', () => this.uiLoggerInitialized = true);
|
2020-03-13 00:28:34 +01:00
|
|
|
this.comms.subscribe('emit-logs', () => {}); // we don't need to do anything, this gets forwarded to UI content script as is
|
2020-03-08 18:38:09 +01:00
|
|
|
|
2018-06-27 23:55:37 +02:00
|
|
|
|
2018-12-30 23:41:44 +01:00
|
|
|
if(BrowserDetect.firefox) {
|
2020-03-09 22:36:17 +01:00
|
|
|
browser.tabs.onActivated.addListener((m) => {this.onTabSwitched(m)});
|
2018-12-30 23:41:44 +01:00
|
|
|
} else if (BrowserDetect.chrome) {
|
2020-03-09 22:36:17 +01:00
|
|
|
chrome.tabs.onActivated.addListener((m) => {this.onTabSwitched(m)});
|
2018-06-27 23:55:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async _promisifyTabsGet(browserObj, tabId){
|
|
|
|
return new Promise( (resolve, reject) => {
|
|
|
|
browserObj.tabs.get(tabId, (tab) => resolve(tab));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-06-14 02:15:24 +02:00
|
|
|
async injectCss(css, sender) {
|
|
|
|
try {
|
|
|
|
if (BrowserDetect.firefox || BrowserDetect.edge) {
|
2019-08-24 00:28:08 +02:00
|
|
|
browser.tabs.insertCSS(sender.tab.id, {code: css, cssOrigin: 'user', frameId: sender.frameId});
|
2019-06-14 02:15:24 +02:00
|
|
|
} else if (BrowserDetect.chrome) {
|
|
|
|
chrome.tabs.insertCSS(sender.tab.id, {code: css, cssOrigin: 'user', frameId: sender.frameId});
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2019-09-03 00:48:18 +02:00
|
|
|
this.logger.log('error','debug', '[UwServer::injectCss] Error while injecting css:', {error: e, css, sender});
|
2019-06-14 02:15:24 +02:00
|
|
|
}
|
|
|
|
}
|
2019-08-24 00:28:08 +02:00
|
|
|
async removeCss(css, sender) {
|
2019-08-24 17:04:53 +02:00
|
|
|
try {
|
|
|
|
if (BrowserDetect.firefox || BrowserDetect.edge) {
|
|
|
|
browser.tabs.removeCSS(sender.tab.id, {code: css, cssOrigin: 'user', frameId: sender.frameId});
|
|
|
|
} else if (BrowserDetect.chrome) {
|
|
|
|
// this doesn't work currently, but hopefully chrome will get this feature in the future
|
|
|
|
chrome.tabs.removeCSS(sender.tab.id, {code: css, cssOrigin: 'user', frameId: sender.frameId});
|
|
|
|
}
|
2019-09-03 00:48:18 +02:00
|
|
|
} catch (e) {
|
|
|
|
this.logger.log('error','debug', '[UwServer::injectCss] Error while removing css:', {error: e, css, sender});
|
|
|
|
}
|
2019-06-14 02:15:24 +02:00
|
|
|
}
|
|
|
|
|
2019-08-24 00:28:08 +02:00
|
|
|
async replaceCss(oldCss, newCss, sender) {
|
2019-08-24 17:04:53 +02:00
|
|
|
if (oldCss !== newCss) {
|
|
|
|
this.injectCss(newCss, sender);
|
|
|
|
this.removeCss(oldCss, sender);
|
|
|
|
}
|
2019-08-24 00:28:08 +02:00
|
|
|
}
|
|
|
|
|
2018-06-27 23:55:37 +02:00
|
|
|
extractHostname(url){
|
|
|
|
var hostname;
|
|
|
|
|
2020-03-09 21:29:39 +01:00
|
|
|
if (!url) {
|
|
|
|
return "<no url>";
|
|
|
|
}
|
|
|
|
|
2018-06-27 23:55:37 +02:00
|
|
|
// 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;
|
2018-05-26 23:08:49 +02:00
|
|
|
}
|
2018-06-27 23:55:37 +02:00
|
|
|
|
|
|
|
async onTabSwitched(activeInfo){
|
|
|
|
this.hasVideos = false;
|
|
|
|
|
|
|
|
try {
|
2018-11-08 23:05:47 +01:00
|
|
|
this.currentTabId = activeInfo.tabId; // just for readability
|
2018-06-27 23:55:37 +02:00
|
|
|
|
2019-09-03 00:48:18 +02:00
|
|
|
let tab;
|
2018-12-30 23:41:44 +01:00
|
|
|
if (BrowserDetect.firefox) {
|
2019-09-03 00:48:18 +02:00
|
|
|
tab = await browser.tabs.get(this.currentTabId);
|
2018-12-30 23:41:44 +01:00
|
|
|
} else if (BrowserDetect.chrome) {
|
2019-09-03 00:48:18 +02:00
|
|
|
tab = await this._promisifyTabsGet(chrome, this.currentTabId);
|
2018-09-13 23:47:20 +02:00
|
|
|
}
|
2018-06-27 23:55:37 +02:00
|
|
|
|
2018-09-13 23:47:20 +02:00
|
|
|
this.currentSite = this.extractHostname(tab.url);
|
2019-09-03 00:48:18 +02:00
|
|
|
this.logger.log('info', 'debug', '[UwServer::onTabSwitched] user switched tab. New site:', this.currentSite);
|
2018-06-27 23:55:37 +02:00
|
|
|
} catch(e) {
|
2019-09-03 00:48:18 +02:00
|
|
|
this.logger.log('error', 'debug', '[UwServer::onTabSwitched] there was a problem getting currnet site:', e)
|
2018-07-15 16:35:08 +02:00
|
|
|
}
|
2018-11-22 22:55:22 +01:00
|
|
|
|
|
|
|
this.selectedSubitem = {
|
|
|
|
'siteSettings': undefined,
|
|
|
|
'videoSettings': undefined,
|
|
|
|
}
|
2018-06-27 23:55:37 +02:00
|
|
|
//TODO: change extension icon based on whether there's any videos on current page
|
|
|
|
}
|
|
|
|
|
2018-11-07 00:03:06 +01:00
|
|
|
registerVideo(sender) {
|
2019-09-03 00:48:18 +02:00
|
|
|
this.logger.log('info', 'comms', '[UWServer::registerVideo] Registering video.\nsender:', sender);
|
2018-11-07 00:03:06 +01:00
|
|
|
|
|
|
|
const tabHostname = this.extractHostname(sender.tab.url);
|
|
|
|
const frameHostname = this.extractHostname(sender.url);
|
|
|
|
|
|
|
|
// preveri za osirotele/zastarele vrednosti ter jih po potrebi izbriši
|
|
|
|
// check for orphaned/outdated values and remove them if neccessary
|
2020-01-28 23:34:36 +01:00
|
|
|
if (this.videoTabs[sender.tab.id]?.host != tabHostname) {
|
|
|
|
delete this.videoTabs[sender.tab.id]
|
|
|
|
} else if(this.videoTabs[sender.tab.id]?.frames[sender.frameId]?.host != frameHostname) {
|
|
|
|
delete this.videoTabs[sender.tab.id].frames[sender.frameId];
|
2018-11-07 00:03:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.videoTabs[sender.tab.id]) {
|
|
|
|
if (this.videoTabs[sender.tab.id].frames[sender.frameId]) {
|
|
|
|
return; // existing value is fine, no need to act
|
|
|
|
} else {
|
|
|
|
this.videoTabs[sender.tab.id].frames[sender.frameId] = {
|
2018-11-09 00:35:18 +01:00
|
|
|
id: sender.frameId,
|
2018-11-07 00:03:06 +01:00
|
|
|
host: frameHostname,
|
|
|
|
url: sender.url
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.videoTabs[sender.tab.id] = {
|
2018-11-09 00:35:18 +01:00
|
|
|
id: sender.tab.id,
|
2018-11-07 00:03:06 +01:00
|
|
|
host: tabHostname,
|
|
|
|
url: sender.tab.url,
|
|
|
|
frames: {}
|
|
|
|
};
|
|
|
|
this.videoTabs[sender.tab.id].frames[sender.frameId] = {
|
2018-11-09 00:35:18 +01:00
|
|
|
id: sender.frameId,
|
2018-11-07 00:03:06 +01:00
|
|
|
host: frameHostname,
|
|
|
|
url: sender.url
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-03 00:48:18 +02:00
|
|
|
this.logger.log('info', 'comms', '[UWServer::registerVideo] Video registered. current videoTabs:', this.videoTabs);
|
2018-11-07 00:03:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
unregisterVideo(sender) {
|
2019-09-03 00:48:18 +02:00
|
|
|
this.logger.log('info', 'comms', '[UwServer::unregisterVideo] Unregistering video.\nsender:', sender);
|
2018-11-07 00:03:06 +01:00
|
|
|
if (this.videoTabs[sender.tab.id]) {
|
|
|
|
if ( Object.keys(this.videoTabs[sender.tab.id].frames).length <= 1) {
|
|
|
|
delete this.videoTabs[sender.tab.id]
|
|
|
|
} else {
|
|
|
|
if(this.videoTabs[sender.tab.id].frames[sender.frameId]) {
|
|
|
|
delete this.videoTabs[sender.tab.id].frames[sender.frameId];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-03 00:48:18 +02:00
|
|
|
this.logger.log('info', 'comms', '[UwServer::unregisterVideo] Video has been unregistered. Current videoTabs:', this.videoTabs);
|
2018-11-07 00:03:06 +01:00
|
|
|
}
|
2018-11-08 23:05:47 +01:00
|
|
|
|
2018-11-22 22:55:22 +01:00
|
|
|
setSelectedTab(menu, subitem) {
|
2019-09-03 00:48:18 +02:00
|
|
|
this.logger.log('info', 'comms', '[UwServer::setSelectedTab] saving selected tab for', menu, ':', subitem);
|
2018-11-22 22:55:22 +01:00
|
|
|
this.selectedSubitem[menu] = subitem;
|
|
|
|
}
|
|
|
|
|
2020-03-08 16:49:20 +01:00
|
|
|
async initUi() {
|
|
|
|
try {
|
|
|
|
if (BrowserDetect.firefox) {
|
2020-03-08 18:38:09 +01:00
|
|
|
await browser.tabs.executeScript({
|
2020-03-08 16:49:20 +01:00
|
|
|
file: '/ext/uw-ui.js',
|
|
|
|
allFrames: true,
|
|
|
|
});
|
|
|
|
} else if (BrowserDetect.chrome) {
|
2020-03-08 18:38:09 +01:00
|
|
|
await new Promise( resolve =>
|
|
|
|
chrome.tabs.executeScript({
|
|
|
|
file: '/ext/uw-ui.js',
|
|
|
|
allFrames: true,
|
|
|
|
}, () => resolve())
|
|
|
|
);
|
2020-03-08 16:49:20 +01:00
|
|
|
}
|
2020-03-09 21:29:39 +01:00
|
|
|
|
2020-03-08 16:49:20 +01:00
|
|
|
} catch (e) {
|
|
|
|
this.logger.log('ERROR', 'uwbg', 'UI initialization failed. Reason:', e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-09 21:29:39 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-01-15 21:20:34 +01:00
|
|
|
async getCurrentTab() {
|
|
|
|
if (BrowserDetect.firefox) {
|
|
|
|
return (await browser.tabs.query({active: true, currentWindow: true}))[0];
|
|
|
|
} else if (BrowserDetect.chrome) {
|
|
|
|
return new Promise((resolve, reject) => chrome.tabs.query({active: true, currentWindow: true}, (x) => resolve(x[0])));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async getVideoTab() {
|
2018-11-08 23:05:47 +01:00
|
|
|
// friendly reminder: if current tab doesn't have a video,
|
|
|
|
// there won't be anything in this.videoTabs[this.currentTabId]
|
2020-01-15 21:20:34 +01:00
|
|
|
|
|
|
|
const ctab = await this.getCurrentTab();
|
|
|
|
|
|
|
|
if (!ctab || !ctab.id) {
|
|
|
|
return {
|
|
|
|
host: 'INVALID SITE',
|
|
|
|
frames: [],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.videoTabs[ctab.id]) {
|
2018-11-23 00:29:13 +01:00
|
|
|
return {
|
2020-01-15 21:20:34 +01:00
|
|
|
...this.videoTabs[ctab.id],
|
|
|
|
host: this.extractHostname(ctab.url),
|
2018-11-23 00:29:13 +01:00
|
|
|
selected: this.selectedSubitem
|
|
|
|
};
|
2018-11-08 23:05:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// return something more or less empty if this tab doesn't have
|
|
|
|
// a video registered for it
|
|
|
|
return {
|
2020-01-15 21:20:34 +01:00
|
|
|
host: this.extractHostname(ctab.url),
|
2018-11-22 22:55:22 +01:00
|
|
|
frames: [],
|
|
|
|
selected: this.selectedSubitem
|
2018-11-08 23:05:47 +01:00
|
|
|
}
|
|
|
|
}
|
2020-05-16 21:35:24 +02:00
|
|
|
|
|
|
|
// chrome shitiness mitigation
|
|
|
|
sendUnmarkPlayer(message) {
|
|
|
|
this.comms.sendUnmarkPlayer(message);
|
|
|
|
}
|
2018-05-26 23:08:49 +02:00
|
|
|
}
|
|
|
|
|
2020-05-16 21:35:24 +02:00
|
|
|
var server = new UWServer();
|
|
|
|
|
|
|
|
window.sendUnmarkPlayer = (message) => {
|
|
|
|
server.sendUnmarkPlayer(message)
|
|
|
|
}
|