From 4a761efaed0d77f3bd1f16cf06a7929abd2147d4 Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Fri, 29 May 2020 22:06:24 +0200 Subject: [PATCH 01/16] Find all blacklisted origins in stack --- src/ext/lib/Logger.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/ext/lib/Logger.js b/src/ext/lib/Logger.js index 345462b..521efab 100644 --- a/src/ext/lib/Logger.js +++ b/src/ext/lib/Logger.js @@ -227,29 +227,21 @@ class Logger { stackInfo['mousemove'] = false; stackInfo['exitLogs'] = false; - // here we check which source triggered the action. We know that only one of these - // functions will appear in the trace at most once (and if more than one of these - // appears — e.g. frameCheck triggered by user toggling autodetection in popup — - // the most recent one will be the correct one 99% of the time) + // here we check which source triggered the action. There can be more + // than one source, too, so we don't break when we find the first one for (const line of stackInfo.stack.trace) { if (line === 'doPeriodicPlayerElementChangeCheck') { stackInfo['periodicPlayerCheck'] = true; - break; } else if (line === 'doPeriodicFallbackChangeDetectionCheck') { stackInfo['periodicVideoStyleChangeCheck'] = true; - break; } else if (line === 'frameCheck') { stackInfo['aard'] = true; - break; } else if (line === 'execAction') { stackInfo['keyboard'] = true; - break; } else if (line === 'processReceivedMessage') { stackInfo['popup'] = true; - break; } else if (line === 'handleMouseMove') { stackInfo['mousemove'] = true; - break; } } From 88a3298cfab54c4f01c74102e7890ffa1e9c3e7a Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Fri, 29 May 2020 22:50:07 +0200 Subject: [PATCH 02/16] fix launch.json --- .vscode/launch.json | 53 ++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 8d96487..bf89a80 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,23 +1,40 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "firefox", + "request": "attach", + "name": "Attach", + "pathMappings": [ { - "name": "Launch addon", - "type": "firefox", - "request": "launch", - "port":6000, - "reAttach": true, - "addonType": "webExtension", - "addonPath": "${workspaceFolder}/dist-ff", + "url": "webpack:///ext", + "path": "${workspaceFolder}/src/ext" } - ], - "firefox": { - "executable": "/usr/bin/firefox-developer-edition", - "firefoxArgs": [ - "--start-debugger-server" - ] + ] + }, + { + "name": "Launch addon", + "type": "firefox", + "request": "launch", + "port": 6000, + "reAttach": true, + "addonType": "webExtension", + "addonPath": "${workspaceFolder}/dist-ff", + "pathMappings": [ + { + "url": "webpack:///ext", + "path": "${workspaceFolder}/src/ext" + }, + ] } + ], + "firefox": { + "executable": "/usr/bin/firefox-developer-edition", + "firefoxArgs": [ + "--start-debugger-server" + ] + } } \ No newline at end of file From ee7d958224c63839a41aefe9e1cef6f3b80e09c3 Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Fri, 29 May 2020 22:50:39 +0200 Subject: [PATCH 03/16] Fix settings --- src/ext/lib/Settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ext/lib/Settings.js b/src/ext/lib/Settings.js index a74a6ce..c9f261a 100644 --- a/src/ext/lib/Settings.js +++ b/src/ext/lib/Settings.js @@ -556,7 +556,7 @@ class Settings { } getDefaultStretchMode(site) { - if (site && this.active.sites[site]?.stretch !== Stretch.Default) { + if (site && (this.active.sites[site]?.stretch ?? Stretch.Default) !== Stretch.Default) { return this.active.sites[site].stretch; } @@ -564,7 +564,7 @@ class Settings { } getDefaultCropPersistenceMode(site) { - if (site && this.active.sites[site]?.cropModePersistence !== Stretch.Default) { + if (site && (this.active.sites[site]?.cropModePersistence ?? Stretch.Default) !== Stretch.Default) { return this.active.sites[site].cropModePersistence; } @@ -573,7 +573,7 @@ class Settings { } getDefaultVideoAlignment(site) { - if (this.active.sites[site]?.videoAlignment !== VideoAlignment.Default) { + if ( (this.active.sites[site]?.videoAlignment ?? VideoAlignment.Default) !== VideoAlignment.Default) { return this.active.sites[site].videoAlignment; } From 95d8d8a8cbe0f33ca547a8f8b0685ef5621fe34d Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Mon, 1 Jun 2020 23:52:29 +0200 Subject: [PATCH 04/16] Fix minor issue --- src/ext/lib/ar-detect/ArDetector.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ext/lib/ar-detect/ArDetector.js b/src/ext/lib/ar-detect/ArDetector.js index 4af5875..b0cac70 100644 --- a/src/ext/lib/ar-detect/ArDetector.js +++ b/src/ext/lib/ar-detect/ArDetector.js @@ -713,7 +713,11 @@ class ArDetector { // the aspect ratio to defaults this.logger.log('error', 'arDetect', `%c[ArDetect::frameCheck] There was a problem setting blackbar. Doing nothing. Error:`, e); - this.guardline.reset(); + try { + this.guardline.reset(); + } catch (e) { + // no guardline, no bigge + } // WE DO NOT RESET ASPECT RATIO HERE IN CASE OF PROBLEMS, CAUSES UNWARRANTED RESETS: // (eg. here: https://www.youtube.com/watch?v=nw5Z93Yt-UQ&t=410) // From fe66c9dfbc4158830b0fd2fdc2764aa1e4296340 Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Mon, 1 Jun 2020 23:53:03 +0200 Subject: [PATCH 05/16] Diversify logging: in addition to console.log, use .warn .info .error as well --- src/ext/lib/Logger.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/ext/lib/Logger.js b/src/ext/lib/Logger.js index 521efab..2e85119 100644 --- a/src/ext/lib/Logger.js +++ b/src/ext/lib/Logger.js @@ -366,9 +366,21 @@ class Logger { }); } - logToConsole(message, stackInfo) { + logToConsole(level, message, stackInfo) { try { - console.log(...message, {stack: stackInfo}); + switch (level) { + case 'error': + console.error(...message, {stack: stackInfo}); + break; + case 'warn': + console.warn(...message, {stack: stackInfo}); + break; + case 'info': + console.info(...message, {stack: stackInfo}); + break; + default: + console.log(...message, {stack: stackInfo}); + } } catch (e) { console.error("Message too big to log. Error:", e, "stackinfo:", stackInfo); } @@ -391,7 +403,7 @@ class Logger { this.logToFile(message, stackInfo); } if (this.conf.consoleOptions?.enabled) { - this.logToConsole(message, stackInfo); + this.logToConsole(level, message, stackInfo); } return; // don't check further — recursion-land ahead! } @@ -412,7 +424,7 @@ class Logger { } if (this.conf.consoleOptions?.enabled) { if (this.canLogConsole(component) || stackInfo.exitLogs) { - this.logToConsole(message, stackInfo); + this.logToConsole(level, message, stackInfo); } } } From 619d89c4f552b19f29b416217fb0779b78533e22 Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Mon, 1 Jun 2020 23:54:10 +0200 Subject: [PATCH 06/16] Break videoData setup into two stages for improved stability --- src/ext/lib/video-data/PageInfo.js | 11 ------ src/ext/lib/video-data/VideoData.js | 61 +++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/ext/lib/video-data/PageInfo.js b/src/ext/lib/video-data/PageInfo.js index 53bc08e..9a9b60f 100644 --- a/src/ext/lib/video-data/PageInfo.js +++ b/src/ext/lib/video-data/PageInfo.js @@ -209,17 +209,6 @@ class PageInfo { try { v = new VideoData(video, this.settings, this); - - if (!this.defaultCrop) { - if (!v.invalid) { - v.initArDetection(); - } else { - this.logger.log('error', 'debug', 'Video is invalid. Aard not started.', video); - } - } else { - this.logger.log('info', 'debug', 'Default crop is specified for this site. Not starting aard.'); - } - this.videos.push(v); } catch (e) { this.logger.log('error', 'debug', "rescan error: failed to initialize videoData. Skipping this video.",e); diff --git a/src/ext/lib/video-data/VideoData.js b/src/ext/lib/video-data/VideoData.js index 3fd84d0..ed97b03 100644 --- a/src/ext/lib/video-data/VideoData.js +++ b/src/ext/lib/video-data/VideoData.js @@ -15,9 +15,46 @@ class VideoData { this.settings = settings; this.pageInfo = pageInfo; this.extensionMode = pageInfo.extensionMode; + this.videoStatusOk = false; this.userCssClassName = `uw-fuck-you-and-do-what-i-tell-you_${this.vdid}`; + this.videoLoaded = false; + + console.log("video*", video) + + this.dimensions = { + width: this.video.offsetWidth, + height: this.video.offsetHeight, + }; + + // this is in case extension loads before the video + video.addEventListener('loadeddata', () => { + this.logger.log('info', 'init', '[VideoData::ctor->video.onloadeddata] Video fired event "loaded data!"'); + this.onVideoLoaded(); + }); + + // this one is in case extension loads after the video is loaded + video.addEventListener('timeupdate', () => { + this.onVideoLoaded() + }); + } + + async onVideoLoaded() { + if (!this.videoLoaded) { + this.logger.log('info', 'init', '%c[VideoData::onVideoLoaded] ——————————— Initiating phase two of videoData setup ———————————', 'color: #0f9'); + + this.videoLoaded = true; + try { + await this.setupStageTwo(); + this.logger.log('info', 'init', '%c[VideoData::onVideoLoaded] ——————————— videoData setup stage two complete ———————————', 'color: #0f9'); + } catch (e) { + this.logger.log('error', 'init', '%c[VideoData::onVideoLoaded] ——————————— Setup stage two failed. ———————————\n', 'color: #f00', e); + } + } + } + + async setupStageTwo() { // We only init observers once player is confirmed valid const observerConf = { attributes: true, @@ -37,14 +74,10 @@ class VideoData { this.resizer = new Resizer(this); - const ths = this; this.observer = new MutationObserver( (m, o) => this.onVideoDimensionsChanged(m, o, ths)); - this.observer.observe(video, observerConf); + this.observer.observe(this.video, observerConf); + - this.dimensions = { - width: this.video.offsetWidth, - height: this.video.offsetHeight, - }; this.arDetector = new ArDetector(this); // this starts Ar detection. needs optional parameter that prevets ardetdctor from starting @@ -63,10 +96,24 @@ class VideoData { // start fallback video/player size detection this.fallbackChangeDetection(); - // force reload last aspect ratio (if default crop ratio exists) + // force reload last aspect ratio (if default crop ratio exists), but only after the video is if (this.pageInfo.defaultCrop) { this.resizer.setAr(this.pageInfo.defaultCrop); } + + try { + if (!this.pageInfo.defaultCrop) { + if (!this.invalid) { + this.initArDetection(); + } else { + this.logger.log('error', 'debug', '[VideoData::secondStageSetup] Video is invalid. Aard not started.', this.video); + } + } else { + this.logger.log('info', 'debug', '[VideoData::secondStageSetup] Default crop is specified for this site. Not starting aard.'); + } + } catch (e) { + this.logger.log('error', 'init', `[VideoData::secondStageSetup] Error with aard initialization (or error with default aspect ratio application)`, e) + } } async fallbackChangeDetection() { From ecc65676f201dc6923b9cb68636c45af62a25492 Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Mon, 1 Jun 2020 23:54:24 +0200 Subject: [PATCH 07/16] cosmetic fix --- src/ext/lib/video-data/VideoData.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ext/lib/video-data/VideoData.js b/src/ext/lib/video-data/VideoData.js index ed97b03..0ccce0f 100644 --- a/src/ext/lib/video-data/VideoData.js +++ b/src/ext/lib/video-data/VideoData.js @@ -128,7 +128,7 @@ class VideoData { } async sleep(timeout) { - return new Promise( (resolve, reject) => setTimeout(() => resolve(), timeout)); + return new Promise( (resolve) => setTimeout(() => resolve(), timeout)); } From 5c73f97c54e2e2f9c9f172bb0899301cb86421b2 Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Mon, 1 Jun 2020 23:54:42 +0200 Subject: [PATCH 08/16] Add player dimension sanity check to resizer --- src/ext/lib/video-transform/Resizer.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/ext/lib/video-transform/Resizer.js b/src/ext/lib/video-transform/Resizer.js index b66821e..03d284b 100644 --- a/src/ext/lib/video-transform/Resizer.js +++ b/src/ext/lib/video-transform/Resizer.js @@ -503,6 +503,26 @@ class Resizer { '\nwdiff, hdiffAfterZoom:', wdiffAfterZoom, 'x', hdiffAfterZoom, '\n\n---- data out ----\n', 'translate:', translate); + + // by the way, let's do a quick sanity check whether video player is doing any fuckies wuckies + // fucky wucky examples: + // + // * video width is bigger than player width AND video height is bigger than player height + // * video width is smaller than player width AND video height is smaller than player height + // + // In both examples, at most one of the two conditions can be true at the same time. If both + // conditions are true at the same time, we need to go 'chiny reckon' and recheck our player + // element. Chances are our video is not getting aligned correctly + if ( + (this.conf.video.offsetWidth > this.conf.player.dimensions.width && this.conf.video.offsetHeight > this.conf.player.dimensions.height) || + (this.conf.video.offsetWidth < this.conf.player.dimensions.width && this.conf.video.offsetHeight < this.conf.player.dimensions.height) + ) { + this.logger.log('warn', ['debugger', 'resizer'], `[Resizer::_res_computeOffsets] We are getting some incredibly funny results here.\n\n`, + `Video seems to be both wider and taller (or shorter and narrower) than player element at the same time. This is super duper not supposed to happen.\n\n`, + `Player element needs to be checked.` + ) + this.player.checkPlayerSizeChange(); + } return translate; } From a271b4d63eaf769abfec219ff0c3afb46114514d Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Tue, 2 Jun 2020 00:52:23 +0200 Subject: [PATCH 09/16] fix observer --- src/ext/lib/video-data/VideoData.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/ext/lib/video-data/VideoData.js b/src/ext/lib/video-data/VideoData.js index 0ccce0f..64e59e0 100644 --- a/src/ext/lib/video-data/VideoData.js +++ b/src/ext/lib/video-data/VideoData.js @@ -21,8 +21,6 @@ class VideoData { this.videoLoaded = false; - console.log("video*", video) - this.dimensions = { width: this.video.offsetWidth, height: this.video.offsetHeight, @@ -55,17 +53,16 @@ class VideoData { } async setupStageTwo() { - // We only init observers once player is confirmed valid + // POZOR: VRSTNI RED JE POMEMBEN (arDetect mora bit zadnji) + // NOTE: ORDERING OF OBJ INITIALIZATIONS IS IMPORTANT (arDetect needs to go last) + + // NOTE: We only init observers once player is confirmed valid const observerConf = { attributes: true, // attributeFilter: ['style', 'class'], attributeOldValue: true, }; - - - // POZOR: VRSTNI RED JE POMEMBEN (arDetect mora bit zadnji) - // NOTE: ORDERING OF OBJ INITIALIZATIONS IS IMPORTANT (arDetect needs to go last) this.player = new PlayerData(this); if (this.player.invalid) { this.invalid = true; @@ -74,12 +71,14 @@ class VideoData { this.resizer = new Resizer(this); - this.observer = new MutationObserver( (m, o) => this.onVideoDimensionsChanged(m, o, ths)); + // INIT OBSERVERS + this.observer = new MutationObserver( (m, o) => { + this.logger.log('info', 'debug', `[VideoData::setupStageTwo->mutationObserver] Mutation observer detected a mutation:`, {m, o}); + this.onVideoDimensionsChanged(m, o, this) + }); this.observer.observe(this.video, observerConf); - - - + // INIT AARD this.arDetector = new ArDetector(this); // this starts Ar detection. needs optional parameter that prevets ardetdctor from starting // player dimensions need to be in: // this.player.dimensions From cc53df59993f4cb98d26a8aac45ee4cdcdbd0174 Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Tue, 2 Jun 2020 01:05:03 +0200 Subject: [PATCH 10/16] Youtube player detection goes back to auto by default --- src/ext/conf/ExtConfPatches.js | 12 ++++++++++++ src/ext/conf/ExtensionConf.js | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ext/conf/ExtConfPatches.js b/src/ext/conf/ExtConfPatches.js index d4ce44e..bacfd76 100644 --- a/src/ext/conf/ExtConfPatches.js +++ b/src/ext/conf/ExtConfPatches.js @@ -378,6 +378,18 @@ const ExtensionConfPatch = [ } } } + }, { + forVersion: '4.4.9', + sites: { + "www.youtube.com": { + override: true, + DOM: { + player: { + manual: true + } + } + } + } } ]; diff --git a/src/ext/conf/ExtensionConf.js b/src/ext/conf/ExtensionConf.js index 30b643b..57d20fe 100644 --- a/src/ext/conf/ExtensionConf.js +++ b/src/ext/conf/ExtensionConf.js @@ -1022,7 +1022,7 @@ var ExtensionConf = { keyboardShortcutsEnabled: ExtensionMode.Default, DOM: { player: { - manual: true, + manual: false, querySelectors: "#movie_player, #player", additionalCss: "", useRelativeAncestor: false, From a4bca8af456665a25c09ebfd60f552aa5623c77c Mon Sep 17 00:00:00 2001 From: Tamius Han Date: Thu, 4 Jun 2020 21:51:22 +0200 Subject: [PATCH 11/16] =?UTF-8?q?Additional=20fixes=20for=20#101=20?= =?UTF-8?q?=E2=80=94=20if=20illegal=20video=20dimensions=20are=20detected,?= =?UTF-8?q?=20tell=20VideoData=20to=20reset/reapply=20aspect=20ratio=20whe?= =?UTF-8?q?n=20video=20starts=20playing=20again?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ext/lib/video-data/VideoData.js | 25 +++++++++++++++++++++++- src/ext/lib/video-transform/Resizer.js | 27 ++++++-------------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/ext/lib/video-data/VideoData.js b/src/ext/lib/video-data/VideoData.js index 64e59e0..9c3f79c 100644 --- a/src/ext/lib/video-data/VideoData.js +++ b/src/ext/lib/video-data/VideoData.js @@ -20,6 +20,7 @@ class VideoData { this.userCssClassName = `uw-fuck-you-and-do-what-i-tell-you_${this.vdid}`; this.videoLoaded = false; + this.videoDimensionsLoaded = true; this.dimensions = { width: this.video.offsetWidth, @@ -34,7 +35,7 @@ class VideoData { // this one is in case extension loads after the video is loaded video.addEventListener('timeupdate', () => { - this.onVideoLoaded() + this.onVideoLoaded(); }); } @@ -43,12 +44,16 @@ class VideoData { this.logger.log('info', 'init', '%c[VideoData::onVideoLoaded] ——————————— Initiating phase two of videoData setup ———————————', 'color: #0f9'); this.videoLoaded = true; + this.videoDimensionsLoaded = true; try { await this.setupStageTwo(); this.logger.log('info', 'init', '%c[VideoData::onVideoLoaded] ——————————— videoData setup stage two complete ———————————', 'color: #0f9'); } catch (e) { this.logger.log('error', 'init', '%c[VideoData::onVideoLoaded] ——————————— Setup stage two failed. ———————————\n', 'color: #f00', e); } + } else if (!this.videoDimensionsLoaded) { + this.restoreCrop(); + this.videoDimensionsLoaded = true; } } @@ -115,6 +120,24 @@ class VideoData { } } + restoreCrop() { + this.logger.log('info', 'debug', "%c[VideoData::restoreCrop] Recovering from illegal video dimensions. Resetting aspect ratio.", {background: '#afd', color: '#132'}); + + // if we have default crop set for this page, apply this. + // otherwise, reset crop + if (this.pageInfo.defaultCrop) { + this.resizer.setAr(this.pageInfo.defaultCrop); + } else { + this.resizer.reset(); + + try { + this.startArDetection(); + } catch (e) { + this.logger.log('warn', 'debug', '[VideoData::restoreCrop] Autodetection not resumed. Reason:', e); + } + } + } + async fallbackChangeDetection() { while (!this.destroyed && !this.invalid) { await this.sleep(500); diff --git a/src/ext/lib/video-transform/Resizer.js b/src/ext/lib/video-transform/Resizer.js index 03d284b..7a5a6c6 100644 --- a/src/ext/lib/video-transform/Resizer.js +++ b/src/ext/lib/video-transform/Resizer.js @@ -267,28 +267,13 @@ class Resizer { return; } - // we could have issued calculate crop too early. Instead of spending 30 minutes trying to fix this the proper way by - // reading documentation, let's fix it in 30 seconds with some brute force code + // we could have issued calculate crop too early. Let's tell VideoData that there's something wrong + // and exit this function. When