Skip to content

Commit

Permalink
Mozilla hijinks part 2 (#378)
Browse files Browse the repository at this point in the history
* [feat] add consent page, block all action until consent is given
  • Loading branch information
rougetimelord authored Nov 20, 2024
1 parent 67d1c80 commit 4643ddf
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 28 deletions.
4 changes: 4 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
93 changes: 84 additions & 9 deletions src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
IntegrationStateSendOnly,
EventKey,
MessageEvent,
ConsentGranted,
OpenConsentPage,
} from '../constants';
import { abbreviate, RefId } from '../utilities';
import {
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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';
Expand Down
5 changes: 5 additions & 0 deletions src/content/consent.ts
Original file line number Diff line number Diff line change
@@ -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})
4 changes: 0 additions & 4 deletions src/content/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
18 changes: 5 additions & 13 deletions src/content/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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/*'],
},
Expand Down
1 change: 1 addition & 0 deletions src/pages/consent/index.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
Expand Down
6 changes: 4 additions & 2 deletions src/pages/consent/index.ts
Original file line number Diff line number Diff line change
@@ -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();
});

Expand Down

0 comments on commit 4643ddf

Please sign in to comment.