diff --git a/package-lock.json b/package-lock.json index c9e73e0..fd580a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "blue-blocker", - "version": "0.4.12", + "version": "0.4.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "blue-blocker", - "version": "0.4.12", + "version": "0.4.13", "license": "MPL-2.0", "devDependencies": { "@crxjs/vite-plugin": "=2.0.0-beta.26", diff --git a/package.json b/package.json index 9251395..ab0b905 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blue-blocker", - "version": "0.4.12", + "version": "0.4.13", "author": "DanielleMiu", "description": "Blocks all Twitter Blue verified users on twitter.com", "type": "module", diff --git a/src/background/index.ts b/src/background/index.ts index 455e295..9632133 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -67,6 +67,21 @@ api.storage.sync.onChanged.addListener(async items => { ConnectDb(); +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}) + } + } + }) +}) + api.runtime.onMessage.addListener((m, s, r) => { let response: MessageResponse; (async (message: RuntimeMessage, sender) => { diff --git a/src/constants.ts b/src/constants.ts index 0d70e76..b34e802 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,6 +2,8 @@ let _api: { action: typeof chrome.action | typeof browser.browserAction; runtime: typeof chrome.runtime; storage: typeof chrome.storage | typeof browser.storage; + tabs: typeof chrome.tabs | typeof browser.tabs; + management: typeof chrome.management | typeof browser.management; }; try { _api = { diff --git a/src/content/index.ts b/src/content/index.ts index 91fbee4..7767c6a 100644 --- a/src/content/index.ts +++ b/src/content/index.ts @@ -45,7 +45,7 @@ function compileConfig(config: Config): CompiledConfig { } as CompiledConfig; } -document.addEventListener('blue-blocker-event', function (e: CustomEvent) { +function eventHandler(e: CustomEvent) { if (e.detail.status < 300) { SetHeaders(e.detail.request.headers); } else { @@ -122,17 +122,34 @@ document.addEventListener('blue-blocker-event', function (e: CustomEvent { + eventHandler(event) + }, window, {defineAs: 'blueBlockerRequest'}) +} +else { + document.addEventListener('blue-blocker-event', eventHandler); +} // Add support for OldTwitter requests. -window.addEventListener('message', function (ev) { +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); const body_str = JSON.stringify(ev.data.body); - document.dispatchEvent( + eventHandler( new CustomEvent('blue-blocker-event', { detail: { parsedUrl: /(.+)/.exec(ev.data.url)!, // Have to turn the endpoint string into a regex result... diff --git a/src/content/startup.ts b/src/content/startup.ts index 075f94f..3a3b2f1 100644 --- a/src/content/startup.ts +++ b/src/content/startup.ts @@ -4,11 +4,20 @@ import { api, DefaultOptions } from '../constants'; // TODO: see if we can remove this ignore // @ts-ignore import inject from '/src/injected/inject?script&module'; -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); + +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}) + } +}) let l = document.createElement('link'); l.href = api.runtime.getURL('src/injected/style.css'); // MUST BE ABSOLUTE PATH diff --git a/src/injected/inject.ts b/src/injected/inject.ts index 522d882..76625c3 100644 --- a/src/injected/inject.ts +++ b/src/injected/inject.ts @@ -29,19 +29,27 @@ // determine if request is a timeline/tweet-returning request const parsedUrl = RequestRegex.exec(this._url); if (this._url && parsedUrl && parsedUrl.length > 0) { - document.dispatchEvent( - new CustomEvent('blue-blocker-event', { - detail: { - parsedUrl, - url: this._url, - body: this.response, - request: { - headers: this._requestHeaders, - }, - status: this.status, + const event = new CustomEvent('blue-blocker-event', { + detail: { + parsedUrl, + url: this._url, + body: this.response, + request: { + headers: this._requestHeaders, }, - }), - ); + status: this.status, + }, + }); + /** @ts-ignore This feels bad... */ + if (window?.blueBlockerRequest) { + /** @ts-ignore This really feels bad */ + blueBlockerRequest(event); + } + else { + document.dispatchEvent( + event + ); + } } }); // TODO: remove this ignore diff --git a/src/manifest.ts b/src/manifest.ts index 57b4894..fdcbe76 100644 --- a/src/manifest.ts +++ b/src/manifest.ts @@ -3,7 +3,7 @@ import { defineManifest } from '@crxjs/vite-plugin'; export default defineManifest({ name: 'Blue Blocker', description: 'Blocks all Twitter Blue verified users on twitter.com', - version: '0.4.12', + version: '0.4.13', manifest_version: 3, icons: { '128': 'icon/icon-128.png', diff --git a/src/pages/consent/index.html b/src/pages/consent/index.html new file mode 100644 index 0000000..6357907 --- /dev/null +++ b/src/pages/consent/index.html @@ -0,0 +1,47 @@ + + + + Blue Blocker Data Disclosure + + + + + +
+
+

Collection of Data Disclosure

+
+

Really quickly, before you can use Blue Blocker we have to show you this page. Please read it carefully so that you can understand how Blue Blocker collects, uses and transmits your user data.

+
+
+

Blue Blocker collects the following data: +

+

- Cookies and tokens used to make requests to Twitter

+

- The URL of all requests made by the Twitter client

+

- Responses from Twitter servers

+
+

+
+
+

Your data is used to check if Twitter accounts you run into have Twitter Blue, or match other features that you configure, and then automatically blocks them

+
+

All data that is stored by the extension is stored locally on device

+
+

Your data is only (re)transmitted to Twitter's servers and/or extensions that you consent to sending data to

+
+

All data that Blue Blocker collects, stores, uses, and transmits is mandatory for the function of the extension Because the collection, storage, usage, and transmission of personal data is necessary for the function of this extension, refusing will cause the extension to be uninstalled

+
+

To read the full privacy policy visit the Firefox addons page

+
+

Having read the above disclosure, do you consent to Blue Blocker collecting, storing, using, and transmitting your personal data?

+
+ + +
+ +
+
+
+
+ + \ No newline at end of file diff --git a/src/pages/consent/index.ts b/src/pages/consent/index.ts new file mode 100644 index 0000000..6bf3b44 --- /dev/null +++ b/src/pages/consent/index.ts @@ -0,0 +1,15 @@ +import '../style.css'; +import './style.css'; +import { api } from '../../constants'; + +const accept = document.getElementById('accept'); +const refuse = document.getElementById('refuse'); + +accept?.addEventListener('click', async () => { + await api.storage.local.remove('holdUntilConsent'); + window.close(); +}); + +refuse?.addEventListener('click', () => { + api.management.uninstallSelf(); +}) \ No newline at end of file diff --git a/src/pages/consent/style.css b/src/pages/consent/style.css new file mode 100644 index 0000000..e5c5c92 --- /dev/null +++ b/src/pages/consent/style.css @@ -0,0 +1,45 @@ +p { + font-size: 1rem; + width: auto; +} + +.center { + min-width: 50ch; + max-width: 120ch; + padding: 25px; +} + +img { + height: 75px; + width: auto; +} + +.bullet-list { + width: fit-content; + display: block; + margin-left: calc(50% - 21ch); + & p { + text-align: left; + } +} + +button, button:active, button:focus { + font-size: 1.1rem; +} + +.inputs { + margin-top: 1.1em; + + & div { + margin-top: 5px; + } +} + +.main { + height: 100vh; + width: 100vw; + padding: 0; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/vite.config.ts b/vite.config.ts index fe6298a..3c1eba0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -17,6 +17,7 @@ export default defineConfig(() => { safelist: './src/pages/safelist/index.html', history: './src/pages/history/index.html', integrations: './src/pages/integrations/index.html', + consent: './src/pages/consent/index.html' }, output: { chunkFileNames: 'assets/chunk-[hash].js',