-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackground.js
88 lines (86 loc) · 4.1 KB
/
background.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
(async () => {
/**
* The browser interface to use
* @type chrome
*/
const browserToUse = typeof chrome === "undefined" ? browser : chrome;
const result = await new Promise((res) => browserToUse.storage.sync.get("urls", res));
/**
* Convert a wildcard to a regex.
* _Made by Claude, since I wouldn't be able to write something like this_
* @param {string} wildcardPattern the pattern
* @returns a Regex to test
*/
function wildcardToRegex(wildcardPattern) {
// Escape special regex characters except * and ?
const escaped = wildcardPattern.replace(/[.+^${}()|[\]\\]/g, '\\$&');
// Replace wildcards with regex equivalents
const converted = escaped
.replace(/\*/g, '.*') // * becomes .*
.replace(/\?/g, '.') // ? becomes .
// Ensure the pattern matches the entire string
return `^${converted}$`;
}
/**
* The Set that contains the ID of the tabs in which the scripts are being injected
*/
let isTabInjectRunning = new Set();
/**
* Check if in the new tab the script should run or not
* @param {chrome.tabs.Tab} tab the tab to check
*/
async function eventTabChange(tab) {
const result = await new Promise((resolve) => browserToUse.storage.sync.get("urls", resolve));
if (result.urls && result.urls.length > 0) {
if (result.urls.some(pattern => { // Check that tab URL is allowed from the extension settings
try {
const regex = wildcardToRegex(pattern).replaceAll("\\.", ".");
const url = tab.url.trim();
return new RegExp(regex).test(url);
} catch (ex) {
return false;
}
})) await tabInject(tab);
}
}
browserToUse.tabs.onUpdated.addListener((_, __, tab) => {
eventTabChange(tab);
});
if (result.urls) { // When the extension is being activated, check the URLs that have been previously stored and run the scripts there
const queryUrl = await new Promise((resolve) => browserToUse.tabs.query({ url: result.urls }, resolve));
for (const tab of queryUrl) await tabInject(tab)
}
/**
* Inject the content scripts in the tab
* @param {chrome.tabs.Tab} tab the Tab in which the scripts will be injected
*/
async function tabInject(tab) {
if (isTabInjectRunning.has(tab.id)) return;
isTabInjectRunning.add(tab.id);
function getPromise() {
return new Promise((resolve) => {
browserToUse.tabs.sendMessage(tab.id, { action: "ping" }).catch(async (ex) => { // We'll try to send a ping to the isolated content script. If it isn't received since there isn't a receiving end, we'll add it.
if (ex.toString() === "Error: Could not establish connection. Receiving end does not exist.") { // The extension isn't running. Let's add the scripts
await browserToUse.scripting.executeScript({
target: { tabId: tab.id },
files: ["bridge.js"]
})
await browserToUse.scripting.executeScript({
target: { tabId: tab.id },
files: ['script.js'],
world: "MAIN"
});
browserToUse.tabs.sendMessage(ids[0].id, { // Update user preferences
action: "updateChoices",
content: await browserToUse.storage.sync.get(["finalize_fs_stream_when_video_finishes", "delete_entries_when_video_finishes", "download_content_when_video_finishes"])
});
await getPromise(); // Check again
resolve();
}
}).then(async (res) => res?.action && resolve());
});
}
await getPromise();
isTabInjectRunning.delete(tab.id); // The script has been added, so we can delete it from the tab injection
}
})()