diff --git a/makefile b/makefile index 51e2e6c..ad1ac28 100644 --- a/makefile +++ b/makefile @@ -31,6 +31,10 @@ firefox: jq '.web_accessible_resources = [.web_accessible_resources[].resources[]]' firefox-manifest.json >tmp.json && mv tmp.json firefox-manifest.json # move action to browser_action jq '.["browser_action"] = .action | del(.action)' firefox-manifest.json >tmp.json && mv tmp.json firefox-manifest.json +# remove static content script + jq '.content_scripts = []' firefox-manifest.json >tmp.json && mv tmp.json firefox-manifest.json +# add host permissions + jq '.permissions += ["*://*.twitter.com/*", "*://twitter.com/*", "*://*.x.com/*", "*://x.com/*"]' firefox-manifest.json >tmp.json && mv tmp.json firefox-manifest.json # replace chrome manifest with firefox manifest jq '.browser_specific_settings = {"gecko": {"id": "{119be3f3-597c-4f6a-9caf-627ee431d374}"}}' firefox-manifest.json >tmp.json && mv tmp.json firefox-manifest.json mv firefox-manifest.json build/manifest.json diff --git a/src/background/index.ts b/src/background/index.ts index 9632133..f0c7068 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -15,6 +15,8 @@ import { IntegrationStateSendOnly, EventKey, MessageEvent, + ConsentGranted, + OpenConsentPage, } from '../constants'; import { abbreviate, RefId } from '../utilities'; import { @@ -67,19 +69,80 @@ api.storage.sync.onChanged.addListener(async items => { ConnectDb(); +let ContentScript: {unregister: Function}; +// @ts-ignore +import consent from '../content/consent?script' +async function registerConsentScript() { + const path = new URL(api.runtime.getURL(consent)).pathname; + const consentScript = { + matches: ['*://*.twitter.com/*', '*://twitter.com/*', '*://*.x.com/*', '*://x.com/*'], + js: [{file: path}], + } + // this is a method in MV2, so it's kosher here + // @ts-ignore + api.contentScripts.register(consentScript).then( + (newScript: any) => { + ContentScript = newScript; + } + ); +} + +// @ts-ignore +import content from '../content/index?script' +async function registerContentScript() { + const path = new URL(api.runtime.getURL(content)).pathname; + const contentScript = { + matches: ['*://*.twitter.com/*', '*://twitter.com/*', '*://*.x.com/*', '*://x.com/*'], + js: [{file: path}], + }; + // @ts-ignore see above + api.contentScripts.register(contentScript).then( + (newScript: any) => { + ContentScript = newScript; + api.storage.local.set({canLoad: true}); + } + ) +} + +api.runtime.onStartup.addListener(() => { + try{ + // @ts-ignore + api.runtime?.getBrowserInfo().then(info => { + if(info.name == 'Firefox') { + api.storage.local.get("canLoad").then( val => { + if (!val) { + registerConsentScript(); + } + else { + registerContentScript(); + } + }); + } + }) + } + catch { + console.debug(logstr, "not running on Firefox!"); + } +}) + const consentRequiredVersions = ['0.3.5'] api.runtime.onInstalled.addListener( ({reason, previousVersion}) => { - /** @ts-ignore I hate that I have to use FF specific APIs to detect FF :)))*/ - api.runtime?.getBrowserInfo().then(info => { - if (info.name == 'Firefox') { - api.storage.local.set({holdUntilConsent: true}); - if(reason == 'install' || (reason == 'update' && consentRequiredVersions.includes(previousVersion as string))) { - const url = api.runtime.getURL('pages/consent.index.html'); - api.tabs.create({url}) + try { + /** @ts-ignore I hate that I have to use FF specific APIs to detect FF :)))*/ + api.runtime?.getBrowserInfo().then(info => { + if (info.name == 'Firefox') { + if(reason == 'install' || (reason == 'update' && consentRequiredVersions.includes(previousVersion as string))) { + registerConsentScript(); + const url = api.runtime.getURL('src/pages/consent/index.html'); + api.tabs.create({url}) + } } - } - }) + }) + } + catch { + console.debug(logstr, "not running on Firefox!"); + } }) api.runtime.onMessage.addListener((m, s, r) => { @@ -126,6 +189,18 @@ api.runtime.onMessage.addListener((m, s, r) => { response = { status: SuccessStatus, result: user } as SuccessResponse; break; + case ConsentGranted: + ContentScript?.unregister(); + registerContentScript(); + response = {status: SuccessStatus} as SuccessResponse; + break; + + case OpenConsentPage: + const url = api.runtime.getURL('src/pages/consent/index.html'); + api.tabs.create({url}); + response = {status: SuccessStatus} as SuccessResponse; + break; + default: console.error( logstr, diff --git a/src/constants.ts b/src/constants.ts index b34e802..a841c19 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -11,6 +11,9 @@ try { runtime: browser.runtime, storage: browser.storage, action: browser.browserAction, + contentScripts: browser.contentScripts, + tabs: browser.tabs, + management: browser.management, }; } catch (ReferenceError) { _api = chrome; @@ -109,12 +112,16 @@ export const [ RemoveFromHistoryAction, AddToQueueAction, PopFromQueueAction, + ConsentGranted, + OpenConsentPage, ] = [ 'is_verified', 'add_user_to_history', 'remove_user_from_history', 'add_user_to_queue', 'pop_user_from_queue', + "consent_granted", + "pop_consent", ]; export const SuccessStatus: SuccessStatus = 'SUCCESS'; export const ErrorStatus: ErrorStatus = 'ERROR'; diff --git a/src/content/consent.ts b/src/content/consent.ts new file mode 100644 index 0000000..ee21686 --- /dev/null +++ b/src/content/consent.ts @@ -0,0 +1,5 @@ +import { api, OpenConsentPage } from "../constants"; + +// basically a stub so that nothing happens +// at least it can open the page :) +api.runtime.sendMessage({action: OpenConsentPage}) diff --git a/src/content/index.ts b/src/content/index.ts index 7767c6a..bac0cc3 100644 --- a/src/content/index.ts +++ b/src/content/index.ts @@ -140,10 +140,6 @@ else { // Add support for OldTwitter requests. window.addEventListener('message', async function (ev) { if (ev.data.type !== 'OLDTWITTER_REQUEST_LOAD') return; - if (Object.keys(await api.storage.local.get('holdUntilConsent')).length != 0) { - // if we still need user consent, we leave - return; - } if (!ev.data.url || !ev.data.body || !ev.data.headers) return console.error(logstr, 'OldTwitter sent an invalid payload.', ev.data); diff --git a/src/content/startup.ts b/src/content/startup.ts index 3a3b2f1..3cd8977 100644 --- a/src/content/startup.ts +++ b/src/content/startup.ts @@ -5,19 +5,11 @@ import { api, DefaultOptions } from '../constants'; // @ts-ignore import inject from '/src/injected/inject?script&module'; -api.storage.local.get('holdUntilConsent').then(obj => { - const script = document.createElement('script'); - script.src = api.runtime.getURL(inject); - script.id = 'injected-blue-block-xhr'; - script.type = 'text/javascript'; - if (!obj?.holdUntilConsent) { - document.head.prepend(script); - } - else if (obj.holdUntilConsent == true) { - const url = api.runtime.getURL('pages/consent.index.html'); - api.tabs.create({url}) - } -}) +const script = document.createElement('script'); +script.src = api.runtime.getURL(inject); +script.id = 'injected-blue-block-xhr'; +script.type = 'text/javascript'; +document.head.prepend(script); let l = document.createElement('link'); l.href = api.runtime.getURL('src/injected/style.css'); // MUST BE ABSOLUTE PATH diff --git a/src/manifest.ts b/src/manifest.ts index fdcbe76..b39b1ed 100644 --- a/src/manifest.ts +++ b/src/manifest.ts @@ -29,6 +29,7 @@ export default defineManifest({ // only files that are accessed from web pages need to be listed here. ie: injected files and assets 'src/injected/*', 'icon/*', + 'pages/consent/*' ], matches: ['*://*.twitter.com/*', '*://twitter.com/*', '*://*.x.com/*', '*://x.com/*'], }, diff --git a/src/pages/consent/index.html b/src/pages/consent/index.html index 6357907..64883ab 100644 --- a/src/pages/consent/index.html +++ b/src/pages/consent/index.html @@ -1,3 +1,4 @@ + diff --git a/src/pages/consent/index.ts b/src/pages/consent/index.ts index 6bf3b44..0e6566a 100644 --- a/src/pages/consent/index.ts +++ b/src/pages/consent/index.ts @@ -1,12 +1,14 @@ import '../style.css'; import './style.css'; -import { api } from '../../constants'; +import { api, ConsentGranted } from '../../constants'; const accept = document.getElementById('accept'); const refuse = document.getElementById('refuse'); accept?.addEventListener('click', async () => { - await api.storage.local.remove('holdUntilConsent'); + api.runtime.sendMessage({ + action: ConsentGranted + }) window.close(); });