From fcdc5cb77aec6f325a97048641c05bd3341d88ec Mon Sep 17 00:00:00 2001 From: Shiba <44804845+DeepDoge@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:31:48 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=8D=99=20opening=20new=20tabs=20handl?= =?UTF-8?q?ed=20by=20the=20background=20now=20-=20because=20firefox=20seem?= =?UTF-8?q?=20to=20block=20content=20script=20from=20openning=20new=20tabs?= =?UTF-8?q?=20in=20some=20cases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manifest.v2.json | 1 + manifest.v3.json | 3 ++- src/scripts/background.ts | 34 +++++++++++++++++++++------------- src/scripts/ytContent.tsx | 22 +++++++++++++++------- 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/manifest.v2.json b/manifest.v2.json index 2258b86..9489f9c 100644 --- a/manifest.v2.json +++ b/manifest.v2.json @@ -18,6 +18,7 @@ "https://odysee.com/", "https://madiator.com/", "https://finder.madiator.com/", + "tabs", "storage" ], "web_accessible_resources": [ diff --git a/manifest.v3.json b/manifest.v3.json index 5e848c5..25dee5b 100644 --- a/manifest.v3.json +++ b/manifest.v3.json @@ -8,7 +8,8 @@ "128": "assets/icons/wol/icon128.png" }, "permissions": [ - "storage" + "storage", + "tabs" ], "host_permissions": [ "https://www.youtube.com/", diff --git a/src/scripts/background.ts b/src/scripts/background.ts index a6e3f30..4bb72bd 100644 --- a/src/scripts/background.ts +++ b/src/scripts/background.ts @@ -2,23 +2,31 @@ import { resolveById } from "../modules/yt/urlResolve" const onGoingLbryPathnameRequest: Record> = {} -chrome.runtime.onMessage.addListener(({ json }, sender, sendResponse) => { +chrome.runtime.onMessage.addListener(({ method, data }, sender, sendResponse) => { function resolve(result: Awaited>) { sendResponse(JSON.stringify(result)) } (async () => { - try { - const params: Parameters = JSON.parse(json) - // Don't create a new Promise for same ID until on going one is over. - const promise = onGoingLbryPathnameRequest[json] ?? (onGoingLbryPathnameRequest[json] = resolveById(...params)) - console.log('lbrypathname request', params, await promise) - resolve(await promise) - } catch (error) { - sendResponse('error') - console.error(error) - } - finally { - delete onGoingLbryPathnameRequest[json] + + switch (method) { + case 'openTab': + chrome.tabs.create({ url: data }) + break + case 'resolveUrl': + try { + const params: Parameters = JSON.parse(data) + // Don't create a new Promise for same ID until on going one is over. + const promise = onGoingLbryPathnameRequest[data] ?? (onGoingLbryPathnameRequest[data] = resolveById(...params)) + console.log('lbrypathname request', params, await promise) + resolve(await promise) + } catch (error) { + sendResponse('error') + console.error(error) + } + finally { + delete onGoingLbryPathnameRequest[data] + } + break } })() diff --git a/src/scripts/ytContent.tsx b/src/scripts/ytContent.tsx index 1277ae1..521eb0d 100644 --- a/src/scripts/ytContent.tsx +++ b/src/scripts/ytContent.tsx @@ -222,7 +222,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa } // We should get this from background, so the caching works and we don't get errors in the future if yt decides to impliment CORS async function requestResolveById(...params: Parameters): ReturnType { - const json = await new Promise((resolve) => chrome.runtime.sendMessage({ json: JSON.stringify(params) }, resolve)) + const json = await new Promise((resolve) => chrome.runtime.sendMessage({ method: 'resolveUrl', data: JSON.stringify(params) }, resolve)) if (json === 'error') { console.error("Background error on:", params) throw new Error("Background error.") @@ -230,6 +230,11 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa return json ? JSON.parse(json) : null } + // Request new tab + async function openNewTab(url: URL) { + chrome.runtime.sendMessage({ method: 'openTab', data: url.href }) + } + function getLbryUrlByTarget(target: Target) { const url = new URL(`${target.platform.domainPrefix}${target.lbryPathname}`) if (target.time) url.searchParams.set('t', target.time.toFixed(0)) @@ -253,11 +258,13 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa const lbryURL = getLbryUrlByTarget(target) - // As soon as video play is ready and start playing, pause it. - findVideoElementAwait(source).then((videoElement) => { - videoElement.addEventListener('play', () => videoElement.pause(), { once: true }) - videoElement.pause() - }) + if (source.type === 'video') { + // As soon as video play is ready and start playing, pause it. + findVideoElementAwait(source).then((videoElement) => { + videoElement.addEventListener('play', () => videoElement.pause(), { once: true }) + videoElement.pause() + }) + } if (target.platform === targetPlatformSettings.app) { if (document.hidden) await new Promise((resolve) => document.addEventListener('visibilitychange', resolve, { once: true })) @@ -266,7 +273,8 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa location.replace(lbryURL) } else { - open(lbryURL, '_blank') + openNewTab(lbryURL) + if (window.history.length === 1) window.close() else window.history.back() } From b26d540a4a944fdf9f6251d5e88223cbda31657f Mon Sep 17 00:00:00 2001 From: Shiba <44804845+DeepDoge@users.noreply.github.com> Date: Tue, 9 Aug 2022 16:42:51 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=8D=A3=20bug=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/scripts/background.ts | 7 +++++-- src/scripts/ytContent.tsx | 25 +++++++++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/scripts/background.ts b/src/scripts/background.ts index 4bb72bd..139b5b4 100644 --- a/src/scripts/background.ts +++ b/src/scripts/background.ts @@ -10,7 +10,10 @@ chrome.runtime.onMessage.addListener(({ method, data }, sender, sendResponse) => switch (method) { case 'openTab': - chrome.tabs.create({ url: data }) + { + const { href, active }: { href: string, active: boolean } = JSON.parse(data) + chrome.tabs.create({ url: href, active }) + } break case 'resolveUrl': try { @@ -20,7 +23,7 @@ chrome.runtime.onMessage.addListener(({ method, data }, sender, sendResponse) => console.log('lbrypathname request', params, await promise) resolve(await promise) } catch (error) { - sendResponse('error') + sendResponse(`error:${(error as any).toString()}`) console.error(error) } finally { diff --git a/src/scripts/ytContent.tsx b/src/scripts/ytContent.tsx index 521eb0d..4b24c2a 100644 --- a/src/scripts/ytContent.tsx +++ b/src/scripts/ytContent.tsx @@ -26,6 +26,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa chrome.storage.onChanged.addListener(async (changes, areaName) => { if (areaName !== 'local') return Object.assign(settings, Object.fromEntries(Object.entries(changes).map(([key, change]) => [key, change.newValue]))) + if (settings.redirect) updateButton(null) }) const buttonMountPoint = document.createElement('div') @@ -222,17 +223,17 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa } // We should get this from background, so the caching works and we don't get errors in the future if yt decides to impliment CORS async function requestResolveById(...params: Parameters): ReturnType { - const json = await new Promise((resolve) => chrome.runtime.sendMessage({ method: 'resolveUrl', data: JSON.stringify(params) }, resolve)) - if (json === 'error') { + const response = await new Promise((resolve) => chrome.runtime.sendMessage({ method: 'resolveUrl', data: JSON.stringify(params) }, resolve)) + if (response?.startsWith('error:')) { console.error("Background error on:", params) - throw new Error("Background error.") + throw new Error(`Background error.${response ?? ''}`) } - return json ? JSON.parse(json) : null + return response ? JSON.parse(response) : null } // Request new tab - async function openNewTab(url: URL) { - chrome.runtime.sendMessage({ method: 'openTab', data: url.href }) + async function openNewTab(url: URL, active: boolean) { + chrome.runtime.sendMessage({ method: 'openTab', data: JSON.stringify({ href: url.href, active }) }) } function getLbryUrlByTarget(target: Target) { @@ -242,11 +243,11 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa return url } - let urlCache: URL | null = null + let urlHrefCache: string | null = null while (true) { await sleep(500) - const url: URL = (urlCache?.href === location.href) ? urlCache : new URL(location.href) + const url: URL = new URL(location.href) const source = await getSourceByUrl(new URL(location.href)) if (!source) continue @@ -254,7 +255,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa if (settings.redirect) { const target = (await getTargetsBySources(source))[source.id] if (!target) continue - if (url === urlCache) continue + if (url.href === urlHrefCache) continue const lbryURL = getLbryUrlByTarget(target) @@ -273,14 +274,14 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa location.replace(lbryURL) } else { - openNewTab(lbryURL) + openNewTab(lbryURL, document.hasFocus()) if (window.history.length === 1) window.close() else window.history.back() } } else { - if (urlCache !== url) updateButton(null) + if (urlHrefCache !== url.href) updateButton(null) let target = (await getTargetsBySources(source))[source.id] // There is no target found via API try to check Video Description for LBRY links. @@ -336,7 +337,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa } catch (error) { console.error(error) } - urlCache = url + urlHrefCache = url.href } })() \ No newline at end of file From 4295dbe1feac598e72cc1c36d7d8cc3700156dd1 Mon Sep 17 00:00:00 2001 From: Shiba <44804845+DeepDoge@users.noreply.github.com> Date: Tue, 9 Aug 2022 16:49:45 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=8D=A3=20bug=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/scripts/ytContent.tsx | 169 ++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 82 deletions(-) diff --git a/src/scripts/ytContent.tsx b/src/scripts/ytContent.tsx index 4b24c2a..3e8cebc 100644 --- a/src/scripts/ytContent.tsx +++ b/src/scripts/ytContent.tsx @@ -246,97 +246,102 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa let urlHrefCache: string | null = null while (true) { await sleep(500) - - const url: URL = new URL(location.href) - const source = await getSourceByUrl(new URL(location.href)) - if (!source) continue - - try { - if (settings.redirect) { - const target = (await getTargetsBySources(source))[source.id] - if (!target) continue - if (url.href === urlHrefCache) continue - - const lbryURL = getLbryUrlByTarget(target) - - if (source.type === 'video') { - // As soon as video play is ready and start playing, pause it. - findVideoElementAwait(source).then((videoElement) => { - videoElement.addEventListener('play', () => videoElement.pause(), { once: true }) - videoElement.pause() - }) - } - - if (target.platform === targetPlatformSettings.app) { - if (document.hidden) await new Promise((resolve) => document.addEventListener('visibilitychange', resolve, { once: true })) - // Replace is being used so browser doesnt start an empty window - // Its not gonna be able to replace anyway, since its a LBRY Uri - location.replace(lbryURL) + const url: URL = new URL(location.href); + + await (async () => { + const source = await getSourceByUrl(new URL(location.href)) + if (!source) return + + try { + if (settings.redirect) { + const target = (await getTargetsBySources(source))[source.id] + if (!target) return + console.log(url.href, urlHrefCache) + if (url.href === urlHrefCache) return + + const lbryURL = getLbryUrlByTarget(target) + + if (source.type === 'video') { + // As soon as video play is ready and start playing, pause it. + findVideoElementAwait(source).then((videoElement) => { + videoElement.addEventListener('play', () => videoElement.pause(), { once: true }) + videoElement.pause() + }) + } + + if (target.platform === targetPlatformSettings.app) { + if (document.hidden) await new Promise((resolve) => document.addEventListener('visibilitychange', resolve, { once: true })) + // Replace is being used so browser doesnt start an empty window + // Its not gonna be able to replace anyway, since its a LBRY Uri + location.replace(lbryURL) + } + else { + console.log('open', lbryURL.href) + openNewTab(lbryURL, document.hasFocus()) + + if (window.history.length === 1) window.close() + else window.history.back() + } } else { - openNewTab(lbryURL, document.hasFocus()) - - if (window.history.length === 1) window.close() - else window.history.back() - } - } - else { - if (urlHrefCache !== url.href) updateButton(null) - let target = (await getTargetsBySources(source))[source.id] - - // There is no target found via API try to check Video Description for LBRY links. - if (!target) { - const linksContainer = - source.type === 'video' ? - document.querySelector(source.platform.htmlQueries.videoDescription) : - source.platform.htmlQueries.channelLinks ? document.querySelector(source.platform.htmlQueries.channelLinks) : null - - if (linksContainer) { - const anchors = Array.from(linksContainer.querySelectorAll('a')) - - for (const anchor of anchors) { - if (!anchor.href) continue - const url = new URL(anchor.href) - let lbryURL: URL | null = null - - // Extract real link from youtube's redirect link - if (source.platform === sourcePlatfromSettings['youtube.com']) { - if (!targetPlatforms.some(([key, platform]) => url.searchParams.get('q')?.startsWith(platform.domainPrefix))) continue - lbryURL = new URL(url.searchParams.get('q')!) - } - // Just directly use the link itself on other platforms - else { - if (!targetPlatforms.some(([key, platform]) => url.href.startsWith(platform.domainPrefix))) continue - lbryURL = new URL(url.href) - } - - if (lbryURL) { - target = { - lbryPathname: lbryURL.pathname.substring(1), - time: null, - type: lbryURL.pathname.substring(1).includes('/') ? 'video' : 'channel', - platform: targetPlatformSettings[settings.targetPlatform] + if (urlHrefCache !== url.href) updateButton(null) + let target = (await getTargetsBySources(source))[source.id] + + // There is no target found via API try to check Video Description for LBRY links. + if (!target) { + const linksContainer = + source.type === 'video' ? + document.querySelector(source.platform.htmlQueries.videoDescription) : + source.platform.htmlQueries.channelLinks ? document.querySelector(source.platform.htmlQueries.channelLinks) : null + + if (linksContainer) { + const anchors = Array.from(linksContainer.querySelectorAll('a')) + + for (const anchor of anchors) { + if (!anchor.href) continue + const url = new URL(anchor.href) + let lbryURL: URL | null = null + + // Extract real link from youtube's redirect link + if (source.platform === sourcePlatfromSettings['youtube.com']) { + if (!targetPlatforms.some(([key, platform]) => url.searchParams.get('q')?.startsWith(platform.domainPrefix))) continue + lbryURL = new URL(url.searchParams.get('q')!) + } + // Just directly use the link itself on other platforms + else { + if (!targetPlatforms.some(([key, platform]) => url.href.startsWith(platform.domainPrefix))) continue + lbryURL = new URL(url.href) + } + + if (lbryURL) { + target = { + lbryPathname: lbryURL.pathname.substring(1), + time: null, + type: lbryURL.pathname.substring(1).includes('/') ? 'video' : 'channel', + platform: targetPlatformSettings[settings.targetPlatform] + } + break } - break } } } - } - - if (!target) updateButton(null) - else { - // If target is a video target add timestampt to it - if (target.type === 'video') { - const videoElement = document.querySelector(source.platform.htmlQueries.videoPlayer) - if (videoElement) target.time = videoElement.currentTime > 3 && videoElement.currentTime < videoElement.duration - 1 ? videoElement.currentTime : null + + if (!target) updateButton(null) + else { + // If target is a video target add timestampt to it + if (target.type === 'video') { + const videoElement = document.querySelector(source.platform.htmlQueries.videoPlayer) + if (videoElement) target.time = videoElement.currentTime > 3 && videoElement.currentTime < videoElement.duration - 1 ? videoElement.currentTime : null + } + + updateButton({ target, source }) } - - updateButton({ target, source }) } + } catch (error) { + console.error(error) } - } catch (error) { - console.error(error) - } + })() + urlHrefCache = url.href }