diff --git a/background.js b/background.js index cdf6a9a..91ad747 100644 --- a/background.js +++ b/background.js @@ -1,13 +1,14 @@ -// onBeforeNavigate captures right before navigation to a new page starts; -// onCreatedNavigationTarget captures new tabs/windows; -// onCommitted captures after onBeforeNavigate, used to catch redirects. -chrome.webNavigation.onBeforeNavigate.addListener(event => main(event, 'onBeforeNavigation')); -chrome.webNavigation.onCreatedNavigationTarget.addListener(event => main(event, 'onCreatedNavigationTarget')); -chrome.webNavigation.onCommitted.addListener(event => main(event, 'onCommitted')); +// Capture web requests +chrome.webRequest.onBeforeSendHeaders.addListener( + function(event) { + main(event); + }, + { urls: ['*://*.fandom.com/*', '*://*.wiki.fextralife.com/*'], types: ['main_frame'] } +); // Listen for user turning extension on or off, to update icon chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { - if (msg.action === "updateIcon") { + if (msg.action === 'updateIcon') { setPowerIcon(msg.value); } }); @@ -148,14 +149,17 @@ function redirectToBreezeWiki(storage, eventInfo, url) { function processRedirect(host) { const subdomain = url.hostname.split(".")[0]; const article = url.href.split('fandom.com/wiki/')[1].replaceAll('%20', '_'); + + // Extract article from URL if (article) { chrome.tabs.update(eventInfo.tabId, { url: host + '/' + subdomain + '/wiki/' + article }); } else { chrome.tabs.update(eventInfo.tabId, { url: host + '/' + subdomain }); } - if (eventInfo.frameId === 0) { - chrome.storage.sync.set({ 'countBreezeWiki': (storage.countBreezeWiki ?? 0) + 1 }); - } + + // Increase BreezeWiki stat count + chrome.storage.sync.set({ 'countBreezeWiki': (storage.countBreezeWiki ?? 0) + 1 }); + if ((storage.notifications ?? 'on') === 'on') { // Notify that user is being redirected to BreezeWiki let notifID = 'independent-wiki-redirector-notification-' + Math.floor(Math.random() * 1E16); @@ -165,7 +169,7 @@ function redirectToBreezeWiki(storage, eventInfo, url) { "title": "You've been redirected to BreezeWiki!", "message": "Indie Wiki Buddy has sent you to BreezeWiki for a cleaner, ad-free experience on Fandom." }); - // Self-clear notification after 6 seconds: + // Self-clear notification after 6 seconds setTimeout(function () { chrome.notifications.clear(notifID); }, 6000); } } @@ -210,7 +214,7 @@ function redirectToBreezeWiki(storage, eventInfo, url) { } } -// Load website data: +// Load website data async function getData() { const LANGS = ["DE", "EN", "ES", "FR", "IT", "PL", "TOK"]; let sites = []; @@ -242,114 +246,107 @@ async function getData() { return sites; } -async function main(eventInfo, eventName) { - // Create object prototypes for getting and setting attributes: - Object.prototype.get = function (prop) { - this[prop] = this[prop] || {}; - return this[prop]; - }; - Object.prototype.set = function (prop, value) { - this[prop] = value; - } - - // Store tab URL and remove any search parameters and section anchors: +async function main(eventInfo) { + // Store tab URL and remove any search parameters and section anchors const url = new URL(eventInfo.url.replace(/(\?|#).*/i, '')); - // Check if tabId is > 0 (some background events may have tabId < 0) - // & check for fandom.com in hostname and quit early if it's not: - if (eventInfo.tabId > 0 && (url.hostname.includes('.fandom.com') || url.hostname.includes('wiki.fextralife.com'))) { + // Check for Fandom or Fextralife in hostname and quit early if not + if (eventInfo.documentLifecycle !== 'prerender') { + // Create object prototypes for getting and setting attributes + Object.prototype.get = function (prop) { + this[prop] = this[prop] || {}; + return this[prop]; + }; + Object.prototype.set = function (prop, value) { + this[prop] = value; + } + // Check if tab is actually available // This is mainly to prevent background processes from triggering an event - chrome.tabs.get(eventInfo.tabId, async function (tab) { - if (tab) { - let sites = []; + let sites = []; - sites = await getData(); + sites = await getData(); - chrome.storage.local.get(function (localStorage) { - chrome.storage.sync.get(function (syncStorage) { - const storage = { ...syncStorage, ...localStorage }; - if ((storage.power ?? 'on') === 'on') { - // Check if site is in our list of wikis: - let matchingSites = sites.filter(el => url.href.replace(/^https?:\/\//, '').startsWith(el.origin_base_url)); - if (matchingSites.length > 0) { - // Select match with longest base URL - let closestMatch = ""; - matchingSites.forEach(site => { - if (site.origin_base_url.length > closestMatch.length) { - closestMatch = site.origin_base_url; - } - }); - let site = matchingSites.find(site => site.origin_base_url === closestMatch); - if (site) { - // Get user's settings for the wiki - let settings = storage.siteSettings || {}; - let id = site['id']; - let siteSetting = ''; - if (settings.hasOwnProperty(id) && settings[id].hasOwnProperty('action')) { - siteSetting = settings[id].action; - } else if (storage.defaultActionSettings && storage.defaultActionSettings[site.language]) { - siteSetting = storage.defaultActionSettings[site.language]; - } else { - siteSetting = 'alert'; - } - // Check if redirects are enabled for the site: - if (siteSetting === 'redirect') { - // Get article name from the end of the URL; - // We can't just take the last part of the path due to subpages; - // Instead, we take everything after the wiki's base URL + content path: - let article = url.href.split(site['origin_base_url'] + site['origin_content_path'])[1]; - // Set up URL to redirect user to based on wiki platform: - if (article || (!article && !url.href.split(site['origin_base_url'] + '/')[1])) { - let newURL = ''; - if (article) { - let searchParams = ''; - switch (site['destination_platform']) { - case 'mediawiki': - searchParams = 'Special:Search/' + site['destination_content_prefix'] + article; - break; - case 'doku': - searchParams = 'start?do=search&q=' + article; - break; - } - newURL = 'https://' + site["destination_base_url"] + site["destination_content_path"] + searchParams; - } else { - newURL = 'https://' + site["destination_base_url"]; - } - - // Perform redirect: - chrome.tabs.update(eventInfo.tabId, { url: newURL }); - - // Increase global redirect count: - if (eventInfo.frameId === 0) { - chrome.storage.sync.set({ 'countRedirects': (storage.countRedirects ?? 0) + 1 }); - } - - // Notify if enabled - if ((storage.notifications ?? 'on') === 'on') { - // Notify that user is being redirected - let notifID = 'independent-wiki-redirector-notification-' + Math.floor(Math.random() * 1E16); - chrome.notifications.create(notifID, { - "type": "basic", - "iconUrl": 'images/logo-48.png', - "title": "You've been redirected!", - "message": "Indie Wiki Buddy has sent you from " + site['origin'] + " to " + site['destination'] - }); - // Self-clear notification after 6 seconds: - setTimeout(function () { chrome.notifications.clear(notifID); }, 6000); - } + chrome.storage.local.get(function (localStorage) { + chrome.storage.sync.get(function (syncStorage) { + const storage = { ...syncStorage, ...localStorage }; + if ((storage.power ?? 'on') === 'on') { + // Check if site is in our list of wikis: + let matchingSites = sites.filter(el => url.href.replace(/^https?:\/\//, '').startsWith(el.origin_base_url)); + if (matchingSites.length > 0) { + // Select match with longest base URL + let closestMatch = ""; + matchingSites.forEach(site => { + if (site.origin_base_url.length > closestMatch.length) { + closestMatch = site.origin_base_url; + } + }); + let site = matchingSites.find(site => site.origin_base_url === closestMatch); + if (site) { + // Get user's settings for the wiki + let settings = storage.siteSettings || {}; + let id = site['id']; + let siteSetting = ''; + if (settings.hasOwnProperty(id) && settings[id].hasOwnProperty('action')) { + siteSetting = settings[id].action; + } else if (storage.defaultActionSettings && storage.defaultActionSettings[site.language]) { + siteSetting = storage.defaultActionSettings[site.language]; + } else { + siteSetting = 'alert'; + } + // Check if redirects are enabled for the site + if (siteSetting === 'redirect') { + // Get article name from the end of the URL; + // We can't just take the last part of the path due to subpages; + // Instead, we take everything after the wiki's base URL + content path + let article = url.href.split(site['origin_base_url'] + site['origin_content_path'])[1]; + // Set up URL to redirect user to based on wiki platform + if (article || (!article && !url.href.split(site['origin_base_url'] + '/')[1])) { + let newURL = ''; + if (article) { + let searchParams = ''; + switch (site['destination_platform']) { + case 'mediawiki': + searchParams = 'Special:Search/' + site['destination_content_prefix'] + article; + break; + case 'doku': + searchParams = 'start?do=search&q=' + article; + break; } - } else if ((storage.breezewiki ?? 'off') === 'on') { - redirectToBreezeWiki(storage, eventInfo, url); + newURL = 'https://' + site["destination_base_url"] + site["destination_content_path"] + searchParams; + } else { + newURL = 'https://' + site["destination_base_url"]; + } + + // Perform redirect + chrome.tabs.update(eventInfo.tabId, { url: newURL }); + + // Increase redirect count + chrome.storage.sync.set({ 'countRedirects': (storage.countRedirects ?? 0) + 1 }); + + // Notify if enabled + if ((storage.notifications ?? 'on') === 'on') { + // Notify that user is being redirected + let notifID = 'independent-wiki-redirector-notification-' + Math.floor(Math.random() * 1E16); + chrome.notifications.create(notifID, { + "type": "basic", + "iconUrl": 'images/logo-48.png', + "title": "You've been redirected!", + "message": "Indie Wiki Buddy has sent you from " + site['origin'] + " to " + site['destination'] + }); + // Self-clear notification after 6 seconds + setTimeout(function () { chrome.notifications.clear(notifID); }, 6000); } } } else if ((storage.breezewiki ?? 'off') === 'on') { redirectToBreezeWiki(storage, eventInfo, url); } } - }); - }); - } + } else if ((storage.breezewiki ?? 'off') === 'on') { + redirectToBreezeWiki(storage, eventInfo, url); + } + } + }); }); } } diff --git a/manifest2.json b/manifest2.json index e6435c8..029041b 100644 --- a/manifest2.json +++ b/manifest2.json @@ -4,10 +4,11 @@ "description": "Indie Wiki Buddy helps you discover quality, independent wikis through alerts, redirects, and search filtering.", "permissions": [ "storage", - "webNavigation", "webRequest", "webRequestBlocking", "notifications", + "https://*.fandom.com/*", + "https://*.fextralife.com/*", "https://breezewiki.com/*", "https://antifandom.com/*", "https://bw.projectsegfau.lt/*", diff --git a/manifest3.json b/manifest3.json index 99b8fff..abd28d7 100644 --- a/manifest3.json +++ b/manifest3.json @@ -4,7 +4,7 @@ "description": "Indie Wiki Buddy helps you discover quality, independent wikis through alerts, redirects, and search filtering.", "permissions": [ "storage", - "webNavigation", + "webRequest", "declarativeNetRequest", "notifications" ], @@ -482,6 +482,8 @@ } ], "host_permissions": [ + "https://*.fandom.com/*", + "https://*.fextralife.com/*", "https://breezewiki.com/*", "https://antifandom.com/*", "https://bw.projectsegfau.lt/*",