mirror of
https://github.com/fmhy/FMHY-SafeGuard.git
synced 2026-03-11 08:55:40 +00:00
Add files via upload
This commit is contained in:
parent
8171528bfc
commit
43915ee69a
5 changed files with 475 additions and 152 deletions
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 3,
|
||||
"name": "FMHY SafeGuard",
|
||||
"author": "Kenneth Hendricks & contributors",
|
||||
"version": "1.1.9",
|
||||
"version": "1.2.0",
|
||||
"icons": {
|
||||
"128": "res/ext_icon_144.png"
|
||||
},
|
||||
|
|
@ -18,16 +18,68 @@
|
|||
"tabs",
|
||||
"alarms"
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "js/background.js"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"matches": [
|
||||
"*://*.google.com/*",
|
||||
"*://*.google.co.uk/*",
|
||||
"*://*.google.de/*",
|
||||
"*://*.google.fr/*",
|
||||
"*://*.google.it/*",
|
||||
"*://*.google.es/*",
|
||||
"*://*.google.nl/*",
|
||||
"*://*.google.ca/*",
|
||||
"*://*.google.com.au/*",
|
||||
"*://*.google.com.br/*",
|
||||
"*://*.google.co.jp/*",
|
||||
"*://*.google.co.kr/*",
|
||||
"*://*.google.co.in/*",
|
||||
"*://*.google.ru/*",
|
||||
"*://*.google.cn/*",
|
||||
"*://*.bing.com/*",
|
||||
"*://*.duckduckgo.com/*",
|
||||
"*://*.librey.org/*",
|
||||
"*://*.4get.ca/*",
|
||||
"*://*.mojeek.com/*",
|
||||
"*://*.qwant.com/*",
|
||||
"*://*.swisscows.com/*",
|
||||
"*://*.yacy.net/*",
|
||||
"*://*.startpage.com/*",
|
||||
"*://*.search.brave.com/*",
|
||||
"*://*.ekoru.org/*",
|
||||
"*://*.gibiru.com/*",
|
||||
"*://*.searx.org/*",
|
||||
"*://*.metager.org/*",
|
||||
"*://*.ecosia.org/*",
|
||||
"*://*.yandex.com/*",
|
||||
"*://*.yandex.ru/*",
|
||||
"*://*.yandex.ua/*",
|
||||
"*://*.yandex.kz/*",
|
||||
"*://*.yandex.by/*",
|
||||
"*://*.yandex.tr/*",
|
||||
"*://*.yahoo.com/*",
|
||||
"*://*.yahoo.co.jp/*",
|
||||
"*://*.yahoo.co.uk/*",
|
||||
"*://*.yahoo.de/*",
|
||||
"*://*.yahoo.fr/*",
|
||||
"*://*.yahoo.it/*",
|
||||
"*://*.yahoo.es/*",
|
||||
"*://*.yahoo.ca/*",
|
||||
"*://*.yahoo.com.au/*",
|
||||
"*://*.yahoo.com.br/*",
|
||||
"*://*.yahoo.co.kr/*",
|
||||
"*://*.yahoo.co.in/*",
|
||||
"*://*.baidu.com/*",
|
||||
"*://*.naver.com/*",
|
||||
"*://*.seznam.cz/*"
|
||||
],
|
||||
"js": ["js/content.js"],
|
||||
"run_at": "document_idle"
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "js/background.js"
|
||||
},
|
||||
"description": "An extension that detects starred, safe, unsafe or potentially unsafe sites using the FMHY Filterlist.",
|
||||
"minimum_chrome_version": "100"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 3,
|
||||
"name": "FMHY SafeGuard",
|
||||
"author": "Kenneth Hendricks & contributors",
|
||||
"version": "1.1.9",
|
||||
"version": "1.2.0",
|
||||
"icons": {
|
||||
"128": "res/ext_icon_144.png"
|
||||
},
|
||||
|
|
@ -18,16 +18,68 @@
|
|||
"tabs",
|
||||
"alarms"
|
||||
],
|
||||
"background": {
|
||||
"scripts": ["js/background.js"]
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"matches": [
|
||||
"*://*.google.com/*",
|
||||
"*://*.google.co.uk/*",
|
||||
"*://*.google.de/*",
|
||||
"*://*.google.fr/*",
|
||||
"*://*.google.it/*",
|
||||
"*://*.google.es/*",
|
||||
"*://*.google.nl/*",
|
||||
"*://*.google.ca/*",
|
||||
"*://*.google.com.au/*",
|
||||
"*://*.google.com.br/*",
|
||||
"*://*.google.co.jp/*",
|
||||
"*://*.google.co.kr/*",
|
||||
"*://*.google.co.in/*",
|
||||
"*://*.google.ru/*",
|
||||
"*://*.google.cn/*",
|
||||
"*://*.bing.com/*",
|
||||
"*://*.duckduckgo.com/*",
|
||||
"*://*.librey.org/*",
|
||||
"*://*.4get.ca/*",
|
||||
"*://*.mojeek.com/*",
|
||||
"*://*.qwant.com/*",
|
||||
"*://*.swisscows.com/*",
|
||||
"*://*.yacy.net/*",
|
||||
"*://*.startpage.com/*",
|
||||
"*://*.search.brave.com/*",
|
||||
"*://*.ekoru.org/*",
|
||||
"*://*.gibiru.com/*",
|
||||
"*://*.searx.org/*",
|
||||
"*://*.metager.org/*",
|
||||
"*://*.ecosia.org/*",
|
||||
"*://*.yandex.com/*",
|
||||
"*://*.yandex.ru/*",
|
||||
"*://*.yandex.ua/*",
|
||||
"*://*.yandex.kz/*",
|
||||
"*://*.yandex.by/*",
|
||||
"*://*.yandex.tr/*",
|
||||
"*://*.yahoo.com/*",
|
||||
"*://*.yahoo.co.jp/*",
|
||||
"*://*.yahoo.co.uk/*",
|
||||
"*://*.yahoo.de/*",
|
||||
"*://*.yahoo.fr/*",
|
||||
"*://*.yahoo.it/*",
|
||||
"*://*.yahoo.es/*",
|
||||
"*://*.yahoo.ca/*",
|
||||
"*://*.yahoo.com.au/*",
|
||||
"*://*.yahoo.com.br/*",
|
||||
"*://*.yahoo.co.kr/*",
|
||||
"*://*.yahoo.co.in/*",
|
||||
"*://*.baidu.com/*",
|
||||
"*://*.naver.com/*",
|
||||
"*://*.seznam.cz/*"
|
||||
],
|
||||
"js": ["js/content.js"],
|
||||
"run_at": "document_idle"
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"scripts": ["js/background.js"]
|
||||
},
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "{5d554479-7cc4-487f-bd25-d8fc67a42602}"
|
||||
|
|
|
|||
|
|
@ -45,6 +45,37 @@ let safeSites = [];
|
|||
let starredSites = [];
|
||||
const approvedUrls = new Map(); // Map to store approved URLs per tab
|
||||
|
||||
// List of search engines to check against
|
||||
const searchEngines = [
|
||||
"google.com",
|
||||
"google.", // Covers all Google country domains like google.co.uk, google.fr, etc.
|
||||
"bing.com",
|
||||
"duckduckgo.com",
|
||||
"librey.org",
|
||||
"4get.ca",
|
||||
"mojeek.com",
|
||||
"qwant.com",
|
||||
"swisscows.com",
|
||||
"yacy.net",
|
||||
"startpage.com",
|
||||
"search.brave.com",
|
||||
"ekoru.org",
|
||||
"gibiru.com",
|
||||
"searx.org",
|
||||
"searx.", // Covers all SearX instances
|
||||
"searxng.", // Covers all SearXNG instances
|
||||
"whoogle.", // Covers all Whoogle instances
|
||||
"metager.org",
|
||||
"ecosia.org",
|
||||
"yandex.com",
|
||||
"yandex.", // Covers all Yandex country domains
|
||||
"yahoo.com",
|
||||
"yahoo.", // Covers all Yahoo country domains
|
||||
"baidu.com",
|
||||
"naver.com",
|
||||
"seznam.cz",
|
||||
];
|
||||
|
||||
// Helper Functions
|
||||
function extractUrlsFromMarkdown(markdown) {
|
||||
const urlRegex = /https?:\/\/[^\s)]+/g;
|
||||
|
|
@ -141,6 +172,20 @@ function extractUrlsFromFilterList(text) {
|
|||
.filter((url) => url !== null);
|
||||
}
|
||||
|
||||
// Function to check if a URL is a search engine
|
||||
function isSearchEngine(url) {
|
||||
try {
|
||||
const urlObj = new URL(url);
|
||||
return searchEngines.some(
|
||||
(domain) =>
|
||||
urlObj.hostname === domain || urlObj.hostname.endsWith("." + domain)
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Error checking search engine:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch and Update Functions
|
||||
async function fetchFilterLists() {
|
||||
console.log("Fetching filter lists...");
|
||||
|
|
@ -437,6 +482,132 @@ browserAPI.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
sendResponse({ status, matchedUrl });
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message.action === "getSiteStatus") {
|
||||
try {
|
||||
// Get the URL from the message
|
||||
const url = message.url;
|
||||
if (!url) {
|
||||
sendResponse({ status: "no_data", matchedUrl: null });
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log(`getSiteStatus: checking status for ${url}`);
|
||||
|
||||
// Normalize the URL
|
||||
const normalizedUrl = normalizeUrl(url);
|
||||
if (!normalizedUrl) {
|
||||
sendResponse({ status: "no_data", matchedUrl: null });
|
||||
return true;
|
||||
}
|
||||
|
||||
// Extract domain for domain-level checking
|
||||
const urlObj = new URL(normalizedUrl);
|
||||
const domain = urlObj.hostname;
|
||||
|
||||
// First check if it's an extension page
|
||||
if (url.startsWith(browserAPI.runtime.getURL(""))) {
|
||||
sendResponse({ status: "extension_page", matchedUrl: url });
|
||||
return true;
|
||||
}
|
||||
|
||||
// Special handling for repository sites
|
||||
const isRepoSite = ["github.com", "gitlab.com", "sourceforge.net"].some(
|
||||
(domain) =>
|
||||
urlObj.hostname === domain || urlObj.hostname.endsWith("." + domain)
|
||||
);
|
||||
|
||||
// Variables to track status and matched URL
|
||||
let status = "no_data";
|
||||
let matchedUrl = null;
|
||||
|
||||
// Check full URL first
|
||||
if (unsafeSitesRegex?.test(normalizedUrl)) {
|
||||
status = "unsafe";
|
||||
matchedUrl = normalizedUrl;
|
||||
} else if (potentiallyUnsafeSitesRegex?.test(normalizedUrl)) {
|
||||
status = "potentially_unsafe";
|
||||
matchedUrl = normalizedUrl;
|
||||
} else if (fmhySitesRegex?.test(normalizedUrl)) {
|
||||
status = "fmhy";
|
||||
matchedUrl = normalizedUrl;
|
||||
} else if (starredSites.includes(normalizedUrl)) {
|
||||
status = "starred";
|
||||
matchedUrl = normalizedUrl;
|
||||
} else if (safeSites.includes(normalizedUrl)) {
|
||||
status = "safe";
|
||||
matchedUrl = normalizedUrl;
|
||||
}
|
||||
|
||||
// If no match for full URL and it's a repository site, don't try domain matching
|
||||
if (status === "no_data" && isRepoSite) {
|
||||
console.log(`No match for repository URL: ${normalizedUrl}`);
|
||||
sendResponse({ status: "no_data", matchedUrl: normalizedUrl });
|
||||
return true;
|
||||
}
|
||||
|
||||
// If no match for full URL and it's a regular site, try domain-level matching
|
||||
if (status === "no_data" && !isRepoSite) {
|
||||
console.log(`No match for full URL, trying domain: ${domain}`);
|
||||
|
||||
// Check domain against regex patterns
|
||||
if (unsafeSitesRegex?.test(domain)) {
|
||||
status = "unsafe";
|
||||
matchedUrl = `https://${domain}`;
|
||||
} else if (potentiallyUnsafeSitesRegex?.test(domain)) {
|
||||
status = "potentially_unsafe";
|
||||
matchedUrl = `https://${domain}`;
|
||||
} else if (fmhySitesRegex?.test(domain)) {
|
||||
status = "fmhy";
|
||||
matchedUrl = `https://${domain}`;
|
||||
}
|
||||
|
||||
// Check domain against starred and safe lists
|
||||
if (status === "no_data") {
|
||||
for (const starredUrl of starredSites) {
|
||||
try {
|
||||
const starredUrlObj = new URL(starredUrl);
|
||||
if (starredUrlObj.hostname === domain) {
|
||||
status = "starred";
|
||||
matchedUrl = starredUrl;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status === "no_data") {
|
||||
for (const safeUrl of safeSites) {
|
||||
try {
|
||||
const safeUrlObj = new URL(safeUrl);
|
||||
if (safeUrlObj.hostname === domain) {
|
||||
status = "safe";
|
||||
matchedUrl = safeUrl;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`getSiteStatus result for ${url}: ${status}, matched: ${matchedUrl}`
|
||||
);
|
||||
sendResponse({ status: status, matchedUrl: matchedUrl });
|
||||
} catch (error) {
|
||||
console.error("Error in getSiteStatus handler:", error);
|
||||
sendResponse({
|
||||
status: "no_data",
|
||||
matchedUrl: null,
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
return true; // Keep the message channel open for async response
|
||||
}
|
||||
});
|
||||
|
||||
function getStatusFromLists(url) {
|
||||
|
|
@ -446,94 +617,62 @@ function getStatusFromLists(url) {
|
|||
return "no_data";
|
||||
}
|
||||
|
||||
// Create URL variations to check consistently across all lists
|
||||
const originalUrl = url;
|
||||
const urlWithSlash = url.endsWith("/") ? url : url + "/";
|
||||
const urlWithoutSlash = url.endsWith("/") ? url.slice(0, -1) : url;
|
||||
const urlVariations = [originalUrl, urlWithSlash, urlWithoutSlash];
|
||||
try {
|
||||
// Special handling for repository hosting sites
|
||||
const urlObj = new URL(url);
|
||||
const domain = urlObj.hostname;
|
||||
const isRepoSite = ["github.com", "gitlab.com", "sourceforge.net"].some(
|
||||
(domain) =>
|
||||
urlObj.hostname === domain || urlObj.hostname.endsWith("." + domain)
|
||||
);
|
||||
|
||||
// Special handling for repository hosting sites
|
||||
const urlObj = new URL(url);
|
||||
const isRepoSite = ["github.com", "gitlab.com", "sourceforge.net"].some(
|
||||
(domain) =>
|
||||
urlObj.hostname === domain || urlObj.hostname.endsWith("." + domain)
|
||||
);
|
||||
// For repository sites, need exact path matching
|
||||
if (isRepoSite) {
|
||||
// Check unsafe and potentially unsafe first
|
||||
if (unsafeSitesRegex?.test(url)) return "unsafe";
|
||||
if (potentiallyUnsafeSitesRegex?.test(url)) return "potentially_unsafe";
|
||||
if (fmhySitesRegex?.test(url)) return "fmhy";
|
||||
if (starredSites.includes(url)) return "starred";
|
||||
if (safeSites.includes(url)) return "safe";
|
||||
return "no_data"; // No domain-only matches for repos
|
||||
}
|
||||
|
||||
// For repository sites, we need to check the full path, not just the domain
|
||||
if (isRepoSite) {
|
||||
// Check unsafe and potentially unsafe lists first using regex
|
||||
// For normal sites, direct checks first (full URL)
|
||||
if (unsafeSitesRegex?.test(url)) return "unsafe";
|
||||
if (potentiallyUnsafeSitesRegex?.test(url)) return "potentially_unsafe";
|
||||
if (fmhySitesRegex?.test(url)) return "fmhy";
|
||||
if (starredSites.includes(url)) return "starred";
|
||||
if (safeSites.includes(url)) return "safe";
|
||||
|
||||
// For repo sites, check for exact matches in starred and safe lists
|
||||
// Skip domain-only matching which we do later in the function
|
||||
for (const variant of urlVariations) {
|
||||
if (starredSites.includes(variant)) return "starred";
|
||||
}
|
||||
// Then check domain-level
|
||||
if (unsafeSitesRegex?.test(domain)) return "unsafe";
|
||||
if (potentiallyUnsafeSitesRegex?.test(domain)) return "potentially_unsafe";
|
||||
if (fmhySitesRegex?.test(domain)) return "fmhy";
|
||||
|
||||
for (const variant of urlVariations) {
|
||||
if (safeSites.includes(variant)) return "safe";
|
||||
}
|
||||
|
||||
// If no match found for the specific repository, return no_data
|
||||
// We skip the domain-level matching for repository hosting sites
|
||||
return "no_data";
|
||||
}
|
||||
|
||||
// For non-repository sites, continue with standard checks
|
||||
if (unsafeSitesRegex?.test(url)) return "unsafe";
|
||||
if (potentiallyUnsafeSitesRegex?.test(url)) return "potentially_unsafe";
|
||||
if (fmhySitesRegex?.test(url)) return "fmhy";
|
||||
|
||||
// Check for starred status with all URL variations - highest priority after unsafe/fmhy
|
||||
for (const variant of urlVariations) {
|
||||
if (starredSites.includes(variant)) {
|
||||
return "starred";
|
||||
}
|
||||
}
|
||||
|
||||
// Check for safe status with all URL variations - lower priority than starred
|
||||
for (const variant of urlVariations) {
|
||||
if (safeSites.includes(variant)) {
|
||||
return "safe";
|
||||
}
|
||||
}
|
||||
|
||||
// Try matching the domain part only for safe sites
|
||||
try {
|
||||
const domain = urlObj.hostname;
|
||||
|
||||
// First check if domain matches any starred site (priority)
|
||||
// Try domain-level checks for starred and safe
|
||||
for (const starredUrl of starredSites) {
|
||||
try {
|
||||
const starredUrlObj = new URL(starredUrl);
|
||||
if (starredUrlObj.hostname === domain) {
|
||||
return "starred";
|
||||
}
|
||||
if (starredUrlObj.hostname === domain) return "starred";
|
||||
} catch (e) {
|
||||
// Skip invalid URLs in starredSites
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Then check for safe site domain matches
|
||||
for (const safeUrl of safeSites) {
|
||||
try {
|
||||
const safeUrlObj = new URL(safeUrl);
|
||||
if (safeUrlObj.hostname === domain) {
|
||||
return "safe";
|
||||
}
|
||||
if (safeUrlObj.hostname === domain) return "safe";
|
||||
} catch (e) {
|
||||
// Skip invalid URLs in safeSites
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// If URL parsing fails, skip domain matching
|
||||
}
|
||||
|
||||
return "no_data";
|
||||
return "no_data";
|
||||
} catch (e) {
|
||||
console.warn(`Error in getStatusFromLists: ${e.message}`);
|
||||
return "no_data";
|
||||
}
|
||||
}
|
||||
|
||||
async function openWarningPage(tabId, unsafeUrl) {
|
||||
|
|
@ -567,31 +706,6 @@ async function openWarningPage(tabId, unsafeUrl) {
|
|||
browserAPI.tabs.update(tabId, { url: warningPageUrl });
|
||||
}
|
||||
|
||||
// Add listener for approval from the warning page
|
||||
browserAPI.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.action === "approveSite") {
|
||||
const { tabId, url } = message;
|
||||
const rootUrl = extractRootUrl(url);
|
||||
|
||||
// Fetch existing approved URLs from storage
|
||||
browserAPI.storage.local.get("approvedUrls", (result) => {
|
||||
const approvedUrls = result.approvedUrls || [];
|
||||
|
||||
// Add the root URL if not already approved
|
||||
if (!approvedUrls.includes(rootUrl)) {
|
||||
approvedUrls.push(rootUrl);
|
||||
browserAPI.storage.local.set({ approvedUrls });
|
||||
console.log(`approveSite: ${rootUrl} approved globally.`);
|
||||
}
|
||||
|
||||
// Set the toolbar icon to "unsafe" immediately
|
||||
updatePageAction("unsafe", tabId);
|
||||
sendResponse({ status: "approved" });
|
||||
});
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Listen for settings updates from the settings page
|
||||
browserAPI.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.type === "settingsUpdated") {
|
||||
|
|
@ -601,8 +715,10 @@ browserAPI.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||
}
|
||||
});
|
||||
|
||||
browserAPI.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
||||
// Listen for tab updates
|
||||
browserAPI.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
|
||||
if (changeInfo.status === "complete" && tab.url) {
|
||||
// Always check the site status
|
||||
checkSiteAndUpdatePageAction(tabId, tab.url);
|
||||
}
|
||||
});
|
||||
|
|
@ -807,4 +923,29 @@ browserAPI.runtime.onMessage.addListener(
|
|||
}
|
||||
);
|
||||
|
||||
// Add listener for approval from the warning page
|
||||
browserAPI.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.action === "approveSite") {
|
||||
const { tabId, url } = message;
|
||||
const rootUrl = extractRootUrl(url);
|
||||
|
||||
// Fetch existing approved URLs from storage
|
||||
browserAPI.storage.local.get("approvedUrls", (result) => {
|
||||
const approvedUrls = result.approvedUrls || [];
|
||||
|
||||
// Add the root URL if not already approved
|
||||
if (!approvedUrls.includes(rootUrl)) {
|
||||
approvedUrls.push(rootUrl);
|
||||
browserAPI.storage.local.set({ approvedUrls });
|
||||
console.log(`approveSite: ${rootUrl} approved globally.`);
|
||||
}
|
||||
|
||||
// Set the toolbar icon to "unsafe" immediately
|
||||
updatePageAction("unsafe", tabId);
|
||||
sendResponse({ status: "approved" });
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
initializeExtension();
|
||||
|
|
|
|||
|
|
@ -359,14 +359,11 @@ browserAPI.storage.onChanged.addListener((changes, area) => {
|
|||
}
|
||||
});
|
||||
|
||||
// Handle messages from background script
|
||||
// Listen for messages from background script
|
||||
browserAPI.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.action === "refreshSettings") {
|
||||
refreshPage();
|
||||
sendResponse({ status: "success" });
|
||||
return true;
|
||||
if (message.action === "processPage") {
|
||||
processPage();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Function to refresh page highlighting
|
||||
|
|
|
|||
171
src/pub/index.js
171
src/pub/index.js
|
|
@ -11,6 +11,17 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
const settingsPageUrl = browserAPI.runtime.getURL("pub/settings-page.html");
|
||||
const welcomePageUrl = browserAPI.runtime.getURL("pub/welcome-page.html");
|
||||
|
||||
// Apply theme
|
||||
await applyTheme();
|
||||
|
||||
// Check site status immediately
|
||||
await checkSiteStatus();
|
||||
|
||||
// Add settings button listener
|
||||
document.getElementById("settingsButton").addEventListener("click", () => {
|
||||
browserAPI.runtime.openOptionsPage();
|
||||
});
|
||||
|
||||
async function applyTheme() {
|
||||
try {
|
||||
const { theme } = await browserAPI.storage.sync.get("theme");
|
||||
|
|
@ -25,50 +36,124 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
console.error("Error applying theme:", error);
|
||||
}
|
||||
}
|
||||
await applyTheme();
|
||||
|
||||
try {
|
||||
const [activeTab] = await browserAPI.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
});
|
||||
async function checkSiteStatus() {
|
||||
console.log("Checking site status from popup");
|
||||
try {
|
||||
const [activeTab] = await browserAPI.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
});
|
||||
|
||||
if (!activeTab || !activeTab.url) {
|
||||
throw new Error("No active tab found or URL is unavailable.");
|
||||
if (!activeTab || !activeTab.url) {
|
||||
throw new Error("No active tab found or URL is unavailable.");
|
||||
}
|
||||
|
||||
const currentUrl = activeTab.url;
|
||||
const rootUrl = extractRootUrl(currentUrl);
|
||||
console.log("Current URL:", currentUrl);
|
||||
console.log("Root URL:", rootUrl);
|
||||
|
||||
// Handle extension pages
|
||||
if (
|
||||
currentUrl.startsWith(warningPageUrl) ||
|
||||
currentUrl === settingsPageUrl ||
|
||||
currentUrl === welcomePageUrl ||
|
||||
currentUrl.startsWith(browserAPI.runtime.getURL(""))
|
||||
) {
|
||||
handleStatusUpdate("extension_page", currentUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the status from the background script
|
||||
const response = await browserAPI.runtime.sendMessage({
|
||||
action: "getSiteStatus",
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
console.log("Status response:", response);
|
||||
if (!response || !response.status) {
|
||||
throw new Error("Failed to get site status");
|
||||
}
|
||||
|
||||
// Determine what URL to display
|
||||
let displayUrl;
|
||||
|
||||
// If we have a matched URL from the background, format it appropriately
|
||||
if (response.matchedUrl) {
|
||||
try {
|
||||
const matchedUrlObj = new URL(response.matchedUrl);
|
||||
const currentUrlObj = new URL(currentUrl);
|
||||
const isRepoSite = [
|
||||
"github.com",
|
||||
"gitlab.com",
|
||||
"sourceforge.net",
|
||||
].some(
|
||||
(domain) =>
|
||||
matchedUrlObj.hostname === domain ||
|
||||
matchedUrlObj.hostname.endsWith("." + domain)
|
||||
);
|
||||
|
||||
if (isRepoSite) {
|
||||
// For repo sites, extract the domain and path parts that were matched
|
||||
const pathParts = matchedUrlObj.pathname
|
||||
.split("/")
|
||||
.filter((p) => p);
|
||||
if (pathParts.length >= 2) {
|
||||
displayUrl = `${matchedUrlObj.hostname}/${pathParts[0]}/${pathParts[1]}`;
|
||||
} else {
|
||||
// If the matched URL doesn't have enough path parts but current URL does,
|
||||
// use the current URL's path for better display (but only for no_data status)
|
||||
if (response.status === "no_data") {
|
||||
const currentPathParts = currentUrlObj.pathname
|
||||
.split("/")
|
||||
.filter((p) => p);
|
||||
if (currentPathParts.length >= 2) {
|
||||
displayUrl = `${currentUrlObj.hostname}/${currentPathParts[0]}/${currentPathParts[1]}`;
|
||||
} else {
|
||||
displayUrl = matchedUrlObj.hostname + matchedUrlObj.pathname;
|
||||
}
|
||||
} else {
|
||||
displayUrl = matchedUrlObj.hostname + matchedUrlObj.pathname;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For regular sites, just show the hostname from the matched URL
|
||||
displayUrl = matchedUrlObj.hostname;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error formatting matched URL:", e);
|
||||
displayUrl = response.matchedUrl;
|
||||
}
|
||||
} else {
|
||||
// Fallback to current URL if no match
|
||||
const urlObj = new URL(currentUrl);
|
||||
const isRepoSite = ["github.com", "gitlab.com", "sourceforge.net"].some(
|
||||
(domain) =>
|
||||
urlObj.hostname === domain || urlObj.hostname.endsWith("." + domain)
|
||||
);
|
||||
|
||||
if (isRepoSite) {
|
||||
// For repo sites, extract the domain and first two path segments (user/repo)
|
||||
const pathParts = urlObj.pathname.split("/").filter((p) => p);
|
||||
if (pathParts.length >= 2) {
|
||||
displayUrl = `${urlObj.hostname}/${pathParts[0]}/${pathParts[1]}`;
|
||||
} else {
|
||||
displayUrl = urlObj.hostname + urlObj.pathname;
|
||||
}
|
||||
} else {
|
||||
// For regular sites, just show the hostname
|
||||
displayUrl = urlObj.hostname;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the popup with the result
|
||||
handleStatusUpdate(response.status, displayUrl);
|
||||
} catch (error) {
|
||||
console.error("Error checking site status:", error);
|
||||
errorMessage.textContent = `Error: ${error.message}`;
|
||||
updateUI("error", "An error occurred while checking the site status");
|
||||
}
|
||||
|
||||
const currentUrl = activeTab.url;
|
||||
const rootUrl = extractRootUrl(currentUrl);
|
||||
|
||||
if (
|
||||
currentUrl.startsWith(warningPageUrl) ||
|
||||
currentUrl === settingsPageUrl ||
|
||||
currentUrl === welcomePageUrl
|
||||
) {
|
||||
handleStatusUpdate("extension_page", currentUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send both the full URL and root URL to the background for status checking
|
||||
const response = await browserAPI.runtime.sendMessage({
|
||||
action: "checkSiteStatus",
|
||||
url: currentUrl, // full path URL
|
||||
rootUrl: rootUrl, // root domain URL
|
||||
});
|
||||
|
||||
if (!response || !response.status) {
|
||||
throw new Error(
|
||||
"Failed to retrieve site status from the background script."
|
||||
);
|
||||
}
|
||||
|
||||
// Display the appropriate URL in the popup
|
||||
const displayUrl = response.matchedUrl || rootUrl;
|
||||
handleStatusUpdate(response.status, displayUrl);
|
||||
} catch (error) {
|
||||
console.error("Error while checking site status:", error);
|
||||
errorMessage.textContent = `Error: ${error.message}`;
|
||||
updateUI("error", "An error occurred while retrieving the site status.");
|
||||
}
|
||||
|
||||
function handleStatusUpdate(status, displayUrl) {
|
||||
|
|
@ -136,10 +221,6 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
console.log(`UI updated: ${message}`);
|
||||
}
|
||||
|
||||
document.getElementById("settingsButton").addEventListener("click", () => {
|
||||
browserAPI.runtime.openOptionsPage();
|
||||
});
|
||||
|
||||
function extractRootUrl(url) {
|
||||
try {
|
||||
const urlObj = new URL(url);
|
||||
|
|
|
|||
Loading…
Reference in a new issue