Skip to content

Commit

Permalink
Merge pull request #4 from Sherly1001/feature/upgrade-to-block-e2e
Browse files Browse the repository at this point in the history
feat: block seen, typing, stories on e2e
  • Loading branch information
Sherly1001 authored Jul 31, 2024
2 parents 4f4bfe6 + 3be5a56 commit d89f2d1
Show file tree
Hide file tree
Showing 14 changed files with 308 additions and 438 deletions.
41 changes: 23 additions & 18 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
{
"manifest_version": 2,
"manifest_version": 3,
"name": "tame",
"version": "1.0",
"version": "1.1",
"description": "Facebook block seen and typing",
"icons": {
"48": "icons/tame-48.png",
"96": "icons/tame-96.png"
},
"incognito": "not_allowed",
"permissions": [
"storage",
"activeTab"
"activeTab",
"scripting",
"declarativeNetRequest",
"webRequest",
"webRequestBlocking"
],
"host_permissions": [
"*://*.facebook.com/*",
"*://*.messenger.com/*"
],
"web_accessible_resources": [
"scripts/dist/*.js"
{
"matches": [
"*://*.facebook.com/*",
"*://*.messenger.com/*"
],
"resources": [
"*"
]
}
],
"browser_action": {
"action": {
"default_icon": "icons/tame-48.png",
"default_title": "Tame",
"default_popup": "popup/dist/index.html"
Expand All @@ -23,17 +40,5 @@
"scripts": [
"scripts/dist/background.js"
]
},
"content_scripts": [
{
"run_at": "document_start",
"all_frames": true,
"matches": [
"*://*.facebook.com/*"
],
"js": [
"scripts/dist/content.js"
]
}
]
}
}
2 changes: 1 addition & 1 deletion popup/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
Expand Down
6 changes: 3 additions & 3 deletions popup/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ export default function App() {
/>
</Flex>
<Switch
label="Fake Message Notification"
isChecked={cfg.fakeMessageNotification}
label="Block Seen on Stories"
isChecked={cfg.blockSeenStory}
onChange={() => {
sendMsg({ toggleFakeMessage: !cfg.fakeMessageNotification });
sendMsg({ toggleBlockSeenStory: !cfg.blockSeenStory });
}}
/>
</Flex>
Expand Down
2 changes: 1 addition & 1 deletion popup/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<ChakraProvider theme={theme}>
<App />
</ChakraProvider>
</React.StrictMode>
</React.StrictMode>,
);
8 changes: 3 additions & 5 deletions scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@
"devDependencies": {
"@browserify/uglifyify": "^6.0.0",
"@types/firefox-webext-browser": "^111.0.1",
"@types/webextension-polyfill": "^0.10.0",
"@types/webextension-polyfill": "^0.10.7",
"browserify": "^17.0.0",
"tsify": "^5.0.4",
"ttypescript": "^1.5.15",
"typescript": "^5.1.3",
"webextension-polyfill": "^0.10.0"
"webextension-polyfill": "^0.12.0"
},
"dependencies": {
"mqtt-packet": "^8.1.2"
}
"dependencies": {}
}
151 changes: 96 additions & 55 deletions scripts/src/background.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,142 @@
import browser from "webextension-polyfill";
import browser, { Scripting } from "webextension-polyfill";

import { Config, Message } from "./config";
import { getCfg, sendCfg, setCfg } from "./utils";
import { getCfg, sendCfg, setThenSendCfg } from "./utils";

const tabs: number[] = [];
const SCRIPTING_MATCHES = [
"https://www.facebook.com/*",
"https://www.messenger.com/*",
];

browser.declarativeNetRequest.getDynamicRules().then((rules) => {
browser.declarativeNetRequest.updateDynamicRules({
removeRuleIds: rules.map((rule) => rule.id),
addRules: SCRIPTING_MATCHES.map((match, idx) => ({
id: idx + 1,
priority: 1,
action: {
type: "modifyHeaders",
responseHeaders: [
{ header: "Content-Security-Policy", operation: "remove" },
{
header: "Content-Security-Policy-Report-Only",
operation: "remove",
},
],
},
condition: {
regexFilter: match,
resourceTypes: ["main_frame", "xmlhttprequest"],
},
})),
});
});

browser.webRequest?.onHeadersReceived?.addListener(
(e) => {
return {
responseHeaders: e.responseHeaders?.filter(
(header) =>
![
"content-security-policy",
"content-security-policy-report-only",
].includes(header.name.toLowerCase()),
),
};
},
{ urls: SCRIPTING_MATCHES, types: ["main_frame", "xmlhttprequest"] },
["blocking", "responseHeaders"],
);

browser.runtime.onInstalled.addListener(async () => {
const cfg = await getCfg();
if (!cfg.blockMode) {
await setCfg(new Config());
await setThenSendCfg(new Config());
}
});

const tabs: number[] = [];
browser.runtime.onConnect.addListener(async (port) => {
try {
const cfg = await getCfg();
if (port.sender?.tab?.id) {
tabs.push(port.sender?.tab?.id);
sendCfg(cfg, port.sender?.tab?.id);
sendCfg(cfg, port.sender.tab.id);
tabs.push(port.sender.tab.id);
}
} catch (err) {
console.error("connect", err);
}
});

async function setThenSendCfgWithTabs(cfg: Partial<Config>) {
await setThenSendCfg(cfg);
return await Promise.all(tabs.map((tab) => setThenSendCfg(cfg, tab)));
}

// handle message from popup
browser.runtime.onMessage.addListener(async (msg, _sender) => {
const data: Message = JSON.parse(msg);

if (data.toggleBlockMode) {
setCfg({ blockMode: data.toggleBlockMode }).then((cfg) => {
sendCfg(cfg);
for (let tab of tabs) {
sendCfg(cfg, tab);
}
});
} else if (typeof data.toggleFakeMessage != "undefined") {
setCfg({ fakeMessageNotification: data.toggleFakeMessage }).then((cfg) => {
sendCfg(cfg);
for (let tab of tabs) {
sendCfg(cfg, tab);
}
});
await setThenSendCfgWithTabs({ blockMode: data.toggleBlockMode });
} else if (typeof data.toggleBlockSeen != "undefined") {
setCfg({ blockSeen: data.toggleBlockSeen }).then((cfg) => {
sendCfg(cfg);
for (let tab of tabs) {
sendCfg(cfg, tab);
}
});
await setThenSendCfgWithTabs({ blockSeen: data.toggleBlockSeen });
} else if (typeof data.toggleBlockTyping != "undefined") {
setCfg({ blockTyping: data.toggleBlockTyping }).then((cfg) => {
sendCfg(cfg);
for (let tab of tabs) {
sendCfg(cfg, tab);
}
});
await setThenSendCfgWithTabs({ blockTyping: data.toggleBlockTyping });
} else if (typeof data.toggleBlockSeenStory != "undefined") {
await setThenSendCfgWithTabs({ blockSeenStory: data.toggleBlockSeenStory });
} else if (data.addToBlacklist) {
const cfg = await getCfg();
if (cfg.blacklist.includes(data.addToBlacklist)) return;
cfg.blacklist.push(data.addToBlacklist);
setCfg({ blacklist: cfg.blacklist }).then((cfg) => {
sendCfg(cfg);
for (let tab of tabs) {
sendCfg(cfg, tab);
}
});
await setThenSendCfgWithTabs({ blacklist: cfg.blacklist });
} else if (data.addToWhitelist) {
const cfg = await getCfg();
if (cfg.whitelist.includes(data.addToWhitelist)) return;
cfg.whitelist.push(data.addToWhitelist);
setCfg({ whitelist: cfg.whitelist }).then((cfg) => {
sendCfg(cfg);
for (let tab of tabs) {
sendCfg(cfg, tab);
}
});
await setThenSendCfgWithTabs({ whitelist: cfg.whitelist });
} else if (data.removeFromBlacklist) {
const cfg = await getCfg();
const idx = cfg.blacklist.indexOf(data.removeFromBlacklist);
if (idx < 0) return;
cfg.blacklist.splice(idx, 1);
setCfg({ blacklist: cfg.blacklist }).then((cfg) => {
sendCfg(cfg);
for (let tab of tabs) {
sendCfg(cfg, tab);
}
});
await setThenSendCfgWithTabs({ blacklist: cfg.blacklist });
} else if (data.removeFromWhitelist) {
const cfg = await getCfg();
const idx = cfg.whitelist.indexOf(data.removeFromWhitelist);
if (idx < 0) return;
cfg.whitelist.splice(idx, 1);
setCfg({ whitelist: cfg.whitelist }).then((cfg) => {
sendCfg(cfg);
for (let tab of tabs) {
sendCfg(cfg, tab);
}
});
await setThenSendCfgWithTabs({ whitelist: cfg.whitelist });
}
});

// inject content script to handle configs
browser.scripting
.getRegisteredContentScripts({ ids: ["tame-content"] })
.then((scripts) => {
if (scripts.length > 0) return;
browser.scripting.registerContentScripts([
{
id: "tame-content",
matches: SCRIPTING_MATCHES,
js: ["scripts/dist/content.js"],
runAt: "document_start",
} as Scripting.RegisteredContentScript,
]);
});

// inject main world script to handle block seen
browser.scripting
.getRegisteredContentScripts({ ids: ["tame-inject"] })
.then((scripts) => {
if (scripts.length > 0) return;
browser.scripting.registerContentScripts([
{
id: "tame-inject",
matches: SCRIPTING_MATCHES,
js: ["scripts/dist/inject.js"],
runAt: "document_start",
world: "MAIN",
} as Scripting.RegisteredContentScript,
]);
});
8 changes: 7 additions & 1 deletion scripts/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,25 @@ export class Config {
whitelist: string[] = [];
blockSeen: boolean = true;
blockTyping: boolean = true;
blockSeenStory: boolean = true;

static keys() {
const cfg = new Config();
return Object.getOwnPropertyNames(cfg);
}
}

/**
* format for message to sends between listeners
* `cfg` property: background -> tabs
* other properties: popup -> background
*/
export interface Message {
cfg?: Config;
toggleFakeMessage?: boolean;
toggleBlockMode?: BLockMode;
toggleBlockSeen?: boolean;
toggleBlockTyping?: boolean;
toggleBlockSeenStory?: boolean;
addToBlacklist?: string;
addToWhitelist?: string;
removeFromBlacklist?: string;
Expand Down
51 changes: 9 additions & 42 deletions scripts/src/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,20 @@ import { Message } from "./config";
browser.runtime.onMessage.addListener(async (msg, _sender) => {
try {
const data: Message = JSON.parse(msg);
if (!data.cfg) return;

if (data.cfg) {
try {
const wrappedJSObject = (window as any).wrappedJSObject;
wrappedJSObject.cfg = cloneInto(data.cfg, window);
} catch (err) {
document.getElementById("inject-cfg")?.remove();
const script = document.createElement("script");
const elm = document.head ?? document.documentElement;

script.id = "inject-cfg";
script.type = "application/json";
script.textContent = JSON.stringify(data.cfg);
document.getElementById("content-cfg")?.remove();
const script = document.createElement("script");
script.id = "content-cfg";
script.type = "application/json";
script.text = JSON.stringify(data.cfg);

document.head.insertBefore(script, document.head.firstChild);
}
}
elm.appendChild(script);
} catch (err) {
console.error("runtime.msg", err);
console.error(err);
}
});

browser.runtime.connect();

function inject() {
console.debug("inject");
document.getElementById("inject-script")?.remove();
const script = document.createElement("script");

script.id = "inject-script";
script.src = browser.runtime.getURL("scripts/dist/inject.js");

document.head.insertBefore(script, document.head.firstChild);
}

var onAppend = function (elem: HTMLElement, f: (nodes: NodeList) => void) {
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (m) {
if (m.addedNodes.length) {
f(m.addedNodes);
}
});
});
observer.observe(elem, { childList: true });
};

onAppend(document.documentElement, (added) => {
if (added[0] == document.head) {
inject();
}
});
Loading

0 comments on commit d89f2d1

Please sign in to comment.