about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorHygna <hygna@proton.me>2022-10-02 15:10:36 +0100
committerHygna <hygna@proton.me>2022-10-02 15:10:36 +0100
commite8a67e91729e9ade89bb7f6f9e1c8bf2f4d64ea2 (patch)
tree7072e7544cafd55821f8b8685958129705f96ae3 /src
parentUnify Localstorage (diff)
downloadlibredirect-e8a67e91729e9ade89bb7f6f9e1c8bf2f4d64ea2.zip
Squashed a few bugs
Diffstat (limited to 'src')
-rw-r--r--src/assets/javascripts/init.js118
-rw-r--r--src/assets/javascripts/services.js445
-rw-r--r--src/assets/javascripts/utils.js8
-rw-r--r--src/manifest.json2
-rw-r--r--src/pages/background/background.js47
-rw-r--r--src/pages/options/index.html5
-rw-r--r--src/pages/options/widgets/general.js1
-rw-r--r--src/pages/popup/popup.js43
8 files changed, 419 insertions, 250 deletions
diff --git a/src/assets/javascripts/init.js b/src/assets/javascripts/init.js
index c6758530..568d9cdc 100644
--- a/src/assets/javascripts/init.js
+++ b/src/assets/javascripts/init.js
@@ -1,60 +1,94 @@
-async function getConfig() {
-	return new Promise(resolve => {
-		fetch("/config/config.json")
+async function initDefaults() {
+	return new Promise(async resolve => {
+		fetch("/instances/data.json")
 			.then(response => response.text())
-			.then(data => {
-				config = JSON.parse(data)
-				resolve()
+			.then(async data => {
+				fetch("/config/config.json")
+					.then(response => response.text())
+					.then(async config => {
+						browser.storage.local.get(["options", "blacklists"], async r => {
+							let redirects = JSON.parse(data)
+							let options = r.options
+							let targets = {}
+							const localstorage = {}
+							const latency = {}
+							for (const service in config.services) {
+								options[service] = {}
+								if (config.services[service].targets == "datajson") {
+									targets[service] = redirects[service]
+								}
+								for (const defaultOption in config.services[service].options) {
+									options[service][defaultOption] = config.services[service].options[defaultOption]
+								}
+								for (const frontend in config.services[service].frontends) {
+									if (config.services[service].frontends[frontend].instanceList) {
+										options[frontend] = {}
+										for (const network in config.networks) {
+											options[frontend][network] = {}
+											options[frontend][network].enabled = JSON.parse(data)[frontend][network]
+											options[frontend][network].custom = []
+										}
+										for (const blacklist in r.blacklists) {
+											for (const instance of r.blacklists[blacklist]) {
+												let i = options[frontend].clearnet.enabled.indexOf(instance)
+												if (i > -1) options[frontend].clearnet.enabled.splice(i, 1)
+											}
+										}
+									}
+								}
+							}
+							browser.storage.local.set({ redirects, options, targets, latency, localstorage })
+							resolve()
+						})
+					})
 			})
 	})
 }
 
-let config
-await getConfig()
-
-async function initDefaults() {
+async function upgradeOptions() {
 	return new Promise(async resolve => {
-		fetch("/instances/data.json")
+		fetch("/config/config.json")
 			.then(response => response.text())
-			.then(async data => {
-				browser.storage.local.get(["options", "blacklists"], async r => {
-					let redirects = JSON.parse(data)
-					let options = r.options
-					let targets = {}
-					const localstorage = {}
-					const latency = {}
-					for (const service in config.services) {
-						options[service] = {}
-						if (config.services[service].targets == "datajson") {
-							targets[service] = redirects[service]
-						}
-						for (const defaultOption in config.services[service].options) {
-							options[service][defaultOption] = config.services[service].options[defaultOption]
-						}
-						for (const frontend in config.services[service].frontends) {
-							if (config.services[service].frontends[frontend].instanceList) {
-								options[frontend] = {}
-								for (const network in config.networks) {
-									options[frontend][network] = {}
-									options[frontend][network].enabled = JSON.parse(data)[frontend][network]
-									options[frontend][network].custom = []
+			.then(async config => {
+				initDefaults().then(
+					browser.storage.local.get(["options", "exceptions", "theme", "popupFrontends"], r => {
+						let options = r.options
+						let latency = {}
+						options.exceptions = r.exceptions
+						if (r.theme != "DEFAULT") options.theme = r.theme
+						for (const service in config.services) {
+							browser.storage.local.get([`disable${utils.camelCase(service)}`, `${service}RedirectType`, `${service}Frontend`, `${service}Latency`, `${service}EmbedFrontend`], r => {
+								if (r) {
+									options[service].enabled = r["disable" + utils.camelCase(service)]
+									if (r[service + "Frontend"]) options[service].frontend = r[service + "Frontend"]
+									if (r[service + "RedirectType"]) options[service].redirectType = r[service + "RedirectType"]
+									if (r[service + "EmbedFrontend"] && (service != "youtube" || r[service + "EmbedFrontend"] == ("invidious" || "piped"))) options[service].EmbedFrontend = r[service + "EmbedFrontend"]
+									if (r[service + "Latency"]) latency[frontend] = r[service + "Latency"]
 								}
-								for (const blacklist in r.blacklists) {
-									for (const instance of r.blacklists[blacklist]) {
-										let i = options[frontend].clearnet.enabled.indexOf(instance)
-										if (i > -1) options[frontend].clearnet.enabled.splice(i, 1)
-									}
+							})
+							for (const frontend in config.services[service].frontends) {
+								for (const network in config.networks) {
+									let protocol
+									if (network == "clearnet") protocol == "normal"
+									else protocol == network
+									browser.storage.local.get([`${frontend}${utils.camelCase(network)}RedirectsChecks`, `${frontend}${utils.camelCase(protocol)}CustomRedirects`], r => {
+										if (r) {
+											options[frontend][network].checks = r[frontend + utils.camelCase(protocol) + "RedirectsChecks"]
+											options[frontend][network].custom = r[frontend + utils.camelCase(protocol) + "CustomRedirects"]
+										}
+									})
 								}
 							}
 						}
-					}
-					browser.storage.local.set({ redirects, options, targets, latency, localstorage })
-					resolve()
-				})
+						browser.storage.local.set({ options, latency })
+						resolve()
+					})
+				)
 			})
 	})
 }
 
 export default {
 	initDefaults,
+	upgradeOptions,
 }
diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js
index 718b3f5e..d84db4fe 100644
--- a/src/assets/javascripts/services.js
+++ b/src/assets/javascripts/services.js
@@ -2,58 +2,49 @@ window.browser = window.browser || window.chrome
 

 import utils from "./utils.js"

 

-let config, redirects, options, blacklists

-

-async function getConfig() {

-	return new Promise(resolve => {

-		fetch("/config/config.json")

-			.then(response => response.text())

-			.then(data => {

-				config = JSON.parse(data)

-				resolve()

-			})

-	})

-}

+let config, options, redirects

 

 function init() {

 	return new Promise(async resolve => {

-		browser.storage.local.get(["options", "redirects", "blacklists"], r => {

-			if (r.options) {

-				blacklists = r.blacklists

-				redirects = r.redirects

-				options = r.options

-			}

-			resolve()

+		browser.storage.local.get(["options", "redirects"], r => {

+			options = r.options

+			redirects = r.redirects

+			fetch("/config/config.json")

+				.then(response => response.text())

+				.then(configData => {

+					config = JSON.parse(configData)

+					resolve()

+				})

 		})

 	})

 }

 

-await getConfig()

-await init()

+init()

+browser.storage.onChanged.addListener(init)

 

-function fetchFrontendInstanceList(service, frontend) {

+function fetchFrontendInstanceList(service, frontend, redirects, options, config) {

 	let tmp = []

 	if (config.services[service].frontends[frontend].instanceList) {

 		for (const network in config.networks) {

-			tmp.push(...redirects[frontend][network], ...options[frontend][network].custom)

+			tmp.push(...redirects[network], ...options[frontend][network].custom)

 		}

 	} else if (config.services[service].frontends[frontend].singleInstance) tmp = config.services[service].frontends[frontend].singleInstance

 	return tmp

 }

 

-function all(service, frontend) {

+function all(service, frontend, options, config, redirects) {

 	let instances = []

 	if (!frontend) {

 		for (const frontend in config.services[service].frontends) {

-			instances.push(...fetchFrontendInstanceList(service, frontend))

+			instances.push(...fetchFrontendInstanceList(service, frontend, redirects[frontend], options, config))

 		}

 	} else {

-		instances.push(...fetchFrontendInstanceList(service, frontend))

+		instances.push(...fetchFrontendInstanceList(service, frontend, redirects[frontend], options, config))

 	}

 	return instances

 }

 

-function regexArray(service, url) {

+function regexArray(service, url, config) {

 	let targets

 	if (config.services[service].targets == "datajson") {

 		browser.storage.local.get("targets", r => {

@@ -69,20 +60,20 @@ function regexArray(service, url) {
 	return false

 }

 

-browser.storage.onChanged.addListener(init)

-

 function redirect(url, type, initiator) {

 	let randomInstance

 	let frontend

-	let network = options.network

 	for (const service in config.services) {

 		if (!options[service].enabled) continue

 		if (config.services[service].embeddable && type != options[service].redirectType && options[service].redirectType != "both") continue

 		if (!config.services[service].embeddable && type != "main_frame") continue

 		let targets = new RegExp(config.services[service].targets.join("|"), "i")

 

-		if (initiator && (all(service).includes(initiator.origin) || targets.test(initiator.host))) continue

-		if (!regexArray(service, url)) continue

+		if (!regexArray(service, url, config)) continue

+		if (initiator) {

+			if (targets.test(initiator.host)) continue

+			if (all(service, null, options, config, redirects).includes(initiator.origin)) return "BYPASSTAB"

+		}

 

 		if (Object.keys(config.services[service].frontends).length > 1) {

 			if (type == "sub_frame") frontend = options[service].embedFrontend

@@ -90,7 +81,7 @@ function redirect(url, type, initiator) {
 		} else frontend = Object.keys(config.services[service].frontends)[0]

 

 		if (config.services[service].frontends[frontend].instanceList) {

-			let instanceList = [...options[frontend][network].enabled, ...options[frontend][network].custom]

+			let instanceList = [...options[frontend][options.network].enabled, ...options[frontend][options.network].custom]

 			if (instanceList.length === 0 && options.networkFallback) instanceList = [...options[frontend].clearnet.enabled, ...options[frontend].clearnet.custom]

 			if (instanceList.length === 0) return

 			randomInstance = utils.getRandomInstance(instanceList)

@@ -385,152 +376,276 @@ function redirect(url, type, initiator) {
 	}

 }

 

-function computeService(url, returnFrontend) {

-	for (const service in config.services) {

-		if (regexArray(service, url)) {

-			if (returnFrontend) return [service, null]

-			else return service

-		} else {

-			for (const frontend in config.services[service].frontends) {

-				if (all(service, frontend).includes(utils.protocolHost(url))) {

-					if (returnFrontend) return [service, frontend]

-					else return service

+async function computeService(url, returnFrontend) {

+	fetch("/config/config.json")

+		.then(response => response.text())

+		.then(configData => {

+			const config = JSON.parse(configData)

+			browser.storage.local.get(["redirects", "options"], r => {

+				const redirects = r.redirects

+				const options = r.options

+				for (const service in config.services) {

+					if (regexArray(service, url, config)) {

+						if (returnFrontend) return [service, null]

+						else return service

+					} else {

+						for (const frontend in config.services[service].frontends) {

+							if (all(service, frontend, options, config, redirects).includes(utils.protocolHost(url))) {

+								if (returnFrontend) {

+									return [service, frontend]

+								} else return service

+							}

+						}

+					}

 				}

-			}

-		}

-	}

-	if (returnFrontend) return [null, null]

-	else return null

+				// if (returnFrontend) return [null, null]

+				// else return null

+			})

+		})

 }

 

-function switchInstance(url) {

-	return new Promise(async resolve => {

-		const protocolHost = utils.protocolHost(url)

-		for (const service in config.services) {

-			if (!options[service].enabled) continue

-			if (!all(service).includes(protocolHost)) continue

-

-			let instancesList = [...options[options[service].frontend][options.network].enabled, ...options[options[service].frontend][options.network].custom]

-			if (instancesList.length === 0 && options.networkFallback) instancesList = [...options[options[service].frontend].clearnet.enabled, ...options[options[service].frontend].clearnet.custom]

-

-			let oldInstance

-			const i = instancesList.indexOf(protocolHost)

-			if (i > -1) {

-				oldInstance = instancesList[i]

-				instancesList.splice(i, 1)

-			}

-			if (instancesList.length === 0) {

-				resolve()

-				return

-			}

-			const randomInstance = utils.getRandomInstance(instancesList)

-			const oldUrl = `${oldInstance}${url.pathname}${url.search}`

-			// This is to make instance switching work when the instance depends on the pathname, eg https://darmarit.org/searx

-			// Doesn't work because of .includes array method, not a top priotiry atm

-			resolve(oldUrl.replace(oldInstance, randomInstance))

-			return

-		}

-		resolve()

-	})

+async function switchInstance(url) {

+	fetch("/config/config.json")

+		.then(response => response.text())

+		.then(configData => {

+			const config = JSON.parse(configData)

+			browser.storage.local.get(["redirects", "options"], r => {

+				const redirects = r.redirects

+				const options = r.options

+				const protocolHost = utils.protocolHost(url)

+				for (const service in config.services) {

+					if (!options[service].enabled) continue

+					if (!all(service, null, options, config, redirects).includes(protocolHost)) continue

+

+					let instancesList = [...options[options[service].frontend][options.network].enabled, ...options[options[service].frontend][options.network].custom]

+					if (instancesList.length === 0 && options.networkFallback) instancesList = [...options[options[service].frontend].clearnet.enabled, ...options[options[service].frontend].clearnet.custom]

+

+					let oldInstance

+					const i = instancesList.indexOf(protocolHost)

+					if (i > -1) {

+						oldInstance = instancesList[i]

+						instancesList.splice(i, 1)

+					}

+					if (instancesList.length === 0) return

+					const randomInstance = utils.getRandomInstance(instancesList)

+					const oldUrl = `${oldInstance}${url.pathname}${url.search}`

+					// This is to make instance switching work when the instance depends on the pathname, eg https://darmarit.org/searx

+					// Doesn't work because of .includes array method, not a top priotiry atm

+					return oldUrl.replace(oldInstance, randomInstance)

+				}

+			})

+		})

 }

 

-function reverse(url) {

-	return new Promise(async resolve => {

-		let protocolHost = utils.protocolHost(url)

-		let currentService

-		for (const service in config.services) {

-			if (!all(service).includes(protocolHost)) continue

-			currentService = service

-		}

-		switch (currentService) {

-			case "instagram":

-				if (url.pathname.startsWith("/p")) resolve(`https://instagram.com${url.pathname.replace("/p", "")}${url.search}`)

-				if (url.pathname.startsWith("/u")) resolve(`https://instagram.com${url.pathname.replace("/u", "")}${url.search}`)

-				resolve(config.services[currentService].url + url.pathname + url.search)

-				return

-			case "youtube":

-			case "imdb":

-			case "imgur":

-			case "tiktok":

-			case "twitter":

-				resolve(config.services[currentService].url + url.pathname + url.search)

-				return

-			default:

-				resolve()

-				return

-		}

-	})

+async function reverse(url) {

+	fetch("/config/config.json")

+		.then(response => response.text())

+		.then(configData => {

+			const config = JSON.parse(configData)

+			browser.storage.local.get(["redirects", "options"], r => {

+				const redirects = r.redirects

+				const options = r.options

+				let protocolHost = utils.protocolHost(url)

+				for (const service in config.services) {

+					if (!all(service, null, options, config, redirects).includes(protocolHost)) continue

+

+					switch (service) {

+						case "instagram":

+							if (url.pathname.startsWith("/p")) return `https://instagram.com${url.pathname.replace("/p", "")}${url.search}`

+							if (url.pathname.startsWith("/u")) return `https://instagram.com${url.pathname.replace("/u", "")}${url.search}`

+							return config.services[service].url + url.pathname + url.search

+						case "youtube":

+						case "imdb":

+						case "imgur":

+						case "tiktok":

+						case "twitter":

+						case "reddit":

+							return config.services[service].url + url.pathname + url.search

+						default:

+							return

+					}

+				}

+			})

+		})

 }

 

-function unifyPreferences(url, tabId) {

-	return new Promise(async resolve => {

-		const protocolHost = utils.protocolHost(url)

-		let currentFrontend, currentService

-		serviceloop: for (const service in config.services) {

-			for (const frontend in config.services[service].frontends) {

-				if (all(service, frontend).includes(protocolHost)) {

-					currentFrontend = frontend

-					currentService = service

-					break serviceloop

+async function unifyPreferences(url, tabId) {

+	fetch("/config/config.json")

+		.then(response => response.text())

+		.then(configData => {

+			const config = JSON.parse(configData)

+			browser.storage.local.get(["options", "reidrects"], r => {

+				const redirects = r.redirects

+				const options = r.options

+				const protocolHost = utils.protocolHost(url)

+				for (const service in config.services) {

+					for (const frontend in config.services[service].frontends) {

+						if (all(service, frontend, options, config, redirects).includes(protocolHost)) {

+							let instancesList = [...options[frontend][options.network].enabled, ...options[frontend][options.network].custom]

+							if (options.networkFallback && options.network != "clearnet") instancesList.push(...options[frontend].clearnet.enabled, ...options[frontend].clearnet.custom)

+

+							const frontend = config.services[service].frontends[frontend]

+							if ("cookies" in frontend.preferences) {

+								for (const cookie of frontend.preferences.cookies) {

+									utils.copyCookie(frontend, url, instancesList, cookie)

+								}

+							}

+							if ("localstorage" in frontend.preferences) {

+								browser.storage.local.set({ tmp: [frontend, frontend.preferences.localstorage] })

+								browser.tabs.executeScript(tabId, {

+									file: "/assets/javascripts/get-localstorage.js",

+									runAt: "document_start",

+								})

+								for (const instance of instancesList)

+									browser.tabs.create({ url: instance }, tab =>

+										browser.tabs.executeScript(tab.id, {

+											file: "/assets/javascripts/set-localstorage.js",

+											runAt: "document_start",

+										})

+									)

+							}

+							if ("indexeddb" in frontend.preferences) {

+							}

+							if ("token" in frontend.preferences) {

+							}

+							return true

+						}

+					}

 				}

-			}

-		}

-		let instancesList = [...options[currentFrontend][options.network].enabled, ...options[currentFrontend][options.network].custom]

-		if (options.networkFallback && options.network != "clearnet") instancesList.push(...options[currentFrontend].clearnet.enabled, ...options[currentFrontend].clearnet.custom)

+			})

+		})

+}

 

-		const frontend = config.services[currentService].frontends[currentFrontend]

-		if ("cookies" in frontend.preferences) {

-			for (const cookie of frontend.preferences.cookies) {

-				await utils.copyCookie(currentFrontend, url, instancesList, cookie)

+async function setRedirects(redirects) {

+	fetch("/config/config.json")

+		.then(response => response.text())

+		.then(configData => {

+			//browser.storage.local.get(["options", "blacklists"], async r => {

+			//const options = r.options

+			const config = JSON.parse(configData)

+			let targets = {}

+			for (const service in config.services) {

+				if (config.services[service].targets == "datajson") {

+					targets[service] = redirects[service]

+				}

+				/*

+					for (const frontend in config.services[service].frontends) {

+						if (config.services[service].frontends[frontend].instanceList) {

+							for (const network in config.networks) {

+								options[frontend][network].enabled = redirects[frontend][network]

+							}

+							for (const blacklist in r.blacklists) {

+								for (const instance of blacklist) {

+									let i = options[frontend].clearnet.enabled.indexOf(instance)

+									if (i > -1) options[frontend].clearnet.enabled.splice(i, 1)

+								}

+							}

+						}

+					}

+					*/

+				// The above will be implemented with https://github.com/libredirect/libredirect/issues/334

 			}

-		}

-		if ("localstorage" in frontend.preferences) {

-			browser.storage.local.set({ tmp: [currentFrontend, frontend.preferences.localstorage] })

-			browser.tabs.executeScript(tabId, {

-				file: "/assets/javascripts/get-localstorage.js",

-				runAt: "document_start",

-			})

-			for (const instance of instancesList)

-				browser.tabs.create({ url: instance }, tab =>

-					browser.tabs.executeScript(tab.id, {

-						file: "/assets/javascripts/set-localstorage.js",

-						runAt: "document_start",

+			browser.storage.local.set({ redirects, targets /*, options*/ })

+			//})

+		})

+}

+

+function initDefaults() {

+	return new Promise(resolve => {

+		fetch("/instances/data.json")

+			.then(response => response.text())

+			.then(data => {

+				fetch("/config/config.json")

+					.then(response => response.text())

+					.then(configData => {

+						browser.storage.local.get(["options", "blacklists"], r => {

+							let redirects = JSON.parse(data)

+							let options = r.options

+							let targets = {}

+							let config = JSON.parse(configData)

+							const localstorage = {}

+							const latency = {}

+							for (const service in config.services) {

+								options[service] = {}

+								if (config.services[service].targets == "datajson") {

+									targets[service] = redirects[service]

+								}

+								for (const defaultOption in config.services[service].options) {

+									options[service][defaultOption] = config.services[service].options[defaultOption]

+								}

+								for (const frontend in config.services[service].frontends) {

+									if (config.services[service].frontends[frontend].instanceList) {

+										options[frontend] = {}

+										for (const network in config.networks) {

+											options[frontend][network] = {}

+											options[frontend][network].enabled = JSON.parse(data)[frontend][network]

+											options[frontend][network].custom = []

+										}

+										for (const blacklist in r.blacklists) {

+											for (const instance of r.blacklists[blacklist]) {

+												let i = options[frontend].clearnet.enabled.indexOf(instance)

+												if (i > -1) options[frontend].clearnet.enabled.splice(i, 1)

+											}

+										}

+									}

+								}

+							}

+							browser.storage.local.set({ redirects, options, targets, latency, localstorage })

+							resolve()

+						})

 					})

-				)

-		}

-		if ("indexeddb" in frontend.preferences) {

-		}

-		if ("token" in frontend.preferences) {

-		}

-		resolve(true)

+			})

 	})

 }

 

-function setRedirects(redirects) {

-	//browser.storage.local.get(["options", "blacklists"], async r => {

-	//let options = r.options

-	let targets = {}

-	for (const service in config.services) {

-		if (config.services[service].targets == "datajson") {

-			targets[service] = redirects[service]

-		}

-		for (const frontend in config.services[service].frontends) {

-			if (config.services[service].frontends[frontend].instanceList) {

-				for (const network in config.networks) {

-					options[frontend][network].enabled = redirects[frontend][network]

-				}

-				for (const blacklist in blacklists) {

-					for (const instance of blacklist) {

-						let i = options[frontend].clearnet.enabled.indexOf(instance)

-						if (i > -1) options[frontend].clearnet.enabled.splice(i, 1)

+function upgradeOptions() {

+	return new Promise(resolve => {

+		fetch("/config/config.json")

+			.then(response => response.text())

+			.then(configData => {

+				browser.storage.local.get(["options", "exceptions", "theme", "popupFrontends", "autoRedirect", "firstPartyIsolate"], r => {

+					let options = r.options

+					let latency = {}

+					const config = JSON.parse(configData)

+					options.exceptions = r.exceptions

+					if (r.theme != "DEFAULT") options.theme = r.theme

+					options.popupServices = r.popupFrontends

+					options.firstPartyIsolate = r.firstPartyIsolate

+					options.autoRedirect = r.autoRedirect

+					for (const service in config.services) {

+						browser.storage.local.get([`disable${utils.camelCase(service)}`, `${service}RedirectType`, `${service}Frontend`, `${service}Latency`, `${service}EmbedFrontend`], r => {

+							if (r) {

+								options[service].enabled = !r["disable" + utils.camelCase(service)]

+								if (r[service + "Frontend"]) {

+									if (r[service + "Frontend"] == "yatte") options[service].frontend = "yattee"

+									else options[service].frontend = r[service + "Frontend"]

+								}

+								if (r[service + "RedirectType"]) options[service].redirectType = r[service + "RedirectType"]

+								if (r[service + "EmbedFrontend"] && (service != "youtube" || r[service + "EmbedFrontend"] == "invidious" || "piped")) options[service].embedFrontend = r[service + "EmbedFrontend"]

+								for (const frontend in config.services[service].frontends) {

+									browser.local.storage.get(`${frontend}Latency`, r => {

+										if (r) latency[frontend] = r[frontend + "Latency"]

+										for (const network in config.networks) {

+											let protocol

+											if (network == "clearnet") protocol = "normal"

+											else protocol = network

+											browser.storage.local.get([`${frontend}${utils.camelCase(protocol)}RedirectsChecks`, `${frontend}${utils.camelCase(protocol)}CustomRedirects`], r => {

+												if (r) {

+													options[frontend][network].checks = r[frontend + utils.camelCase(protocol) + "RedirectsChecks"]

+													options[frontend][network].custom = r[frontend + utils.camelCase(protocol) + "CustomRedirects"]

+												}

+											})

+										}

+									})

+								}

+							}

+						})

 					}

-				}

-			}

-		}

-	}

-	console.log(redirects)

-	browser.storage.local.set({ redirects, targets, options })

-	//})

+					browser.storage.local.set({ options, latency })

+					resolve()

+				})

+			})

+	})

 }

 

 export default {

@@ -540,4 +655,6 @@ export default {
 	reverse,

 	unifyPreferences,

 	setRedirects,

+	initDefaults,

+	upgradeOptions,

 }

diff --git a/src/assets/javascripts/utils.js b/src/assets/javascripts/utils.js
index aaa52955..26fe11d6 100644
--- a/src/assets/javascripts/utils.js
+++ b/src/assets/javascripts/utils.js
@@ -342,7 +342,7 @@ function getPreferencesFromToken(frontend, targetUrl, urls, name, endpoint) {
 	})
 }
 
-function copyRaw(test, copyRawElement) {
+function copyRaw(test, copyRawElement, config) {
 	return new Promise(resolve => {
 		browser.tabs.query({ active: true, currentWindow: true }, async tabs => {
 			let currTab = tabs[0]
@@ -355,7 +355,7 @@ function copyRaw(test, copyRawElement) {
 					return
 				}
 
-				let newUrl = await servicesHelper.reverse(url)
+				let newUrl = servicesHelper.reverse(url, config)
 
 				if (newUrl) {
 					resolve(newUrl)
@@ -387,7 +387,7 @@ function unify() {
 					return
 				}
 
-				let result = await servicesHelper.unifyPreferences(url, currTab.id)
+				const result = await servicesHelper.unifyPreferences(url, currTab.id)
 
 				resolve(result)
 			}
@@ -407,7 +407,7 @@ function switchInstance(test) {
 					resolve()
 					return
 				}
-				let newUrl = await servicesHelper.switchInstance(url)
+				const newUrl = await servicesHelper.switchInstance(url)
 
 				if (newUrl) {
 					if (!test) browser.tabs.update({ url: newUrl })
diff --git a/src/manifest.json b/src/manifest.json
index cc804f9d..5674b8f6 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -1,7 +1,7 @@
 {
 	"name": "__MSG_extensionName__",
 	"description": "__MSG_extensionDescription__",
-	"version": "2.2.1",
+	"version": "2.3.0",
 	"manifest_version": 2,
 	"browser_specific_settings": {
 		"gecko": {
diff --git a/src/pages/background/background.js b/src/pages/background/background.js
index 5e164d58..eba436cb 100644
--- a/src/pages/background/background.js
+++ b/src/pages/background/background.js
@@ -3,11 +3,23 @@
 import generalHelper from "../../assets/javascripts/general.js"

 import utils from "../../assets/javascripts/utils.js"

 import servicesHelper from "../../assets/javascripts/services.js"

-import initHelper from "../../assets/javascripts/init.js"

 

 window.browser = window.browser || window.chrome

 

-browser.runtime.onInstalled.addListener(async details => {

+function initDefaults() {

+	browser.storage.local.clear(() => {

+		fetch("/instances/blacklist.json")

+			.then(response => response.text())

+			.then(async data => {

+				browser.storage.local.set({ blacklists: JSON.parse(data) }, async () => {

+					await generalHelper.initDefaults()

+					await servicesHelper.initDefaults()

+				})

+			})

+	})

+}

+

+browser.runtime.onInstalled.addListener(details => {

 	// if (details.reason == 'install' || (details.reason == "update" && details.previousVersion != browser.runtime.getManifest().version)) {

 	//   if (details.reason == "update")

 	//     browser.storage.local.get(null, r => {

@@ -24,27 +36,22 @@ browser.runtime.onInstalled.addListener(async details => {
 			initDefaults()

 			break

 		case "update":

-			switch (details.previousVersion) {

-				case "2.2.1":

-					initDefaults()

-					break

-			}

+			fetch("/instances/blacklist.json")

+				.then(response => response.text())

+				.then(async data => {

+					browser.storage.local.set({ blacklists: JSON.parse(data) }, async () => {

+						switch (details.previousVersion) {

+							case "2.2.1":

+								await generalHelper.initDefaults()

+								await servicesHelper.initDefaults()

+								await servicesHelper.upgradeOptions()

+								break

+						}

+					})

+				})

 	}

 })

 

-function initDefaults() {

-	browser.storage.local.clear(() => {

-		fetch("/instances/blacklist.json")

-			.then(response => response.text())

-			.then(async data => {

-				browser.storage.local.set({ blacklists: JSON.parse(data) }, async () => {

-					await generalHelper.initDefaults()

-					await initHelper.initDefaults()

-				})

-			})

-	})

-}

-

 let BYPASSTABs = []

 browser.webRequest.onBeforeRequest.addListener(

 	details => {

diff --git a/src/pages/options/index.html b/src/pages/options/index.html
index 384b32bd..2549566c 100644
--- a/src/pages/options/index.html
+++ b/src/pages/options/index.html
@@ -150,6 +150,11 @@
       </button>
     </div>
   </form>
+  <div class="buttons buttons-inline"><a class="button button-inline" id="test">
+      <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
+        <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path>
+      </svg>
+      Test Test Yes Yes</a>&nbsp; &nbsp;</div>
   <div class="checklist" id="exceptions-custom-checklist"></div>
   <div class="buttons buttons-inline"><a class="button button-inline" id="update-instances">
       <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
diff --git a/src/pages/options/widgets/general.js b/src/pages/options/widgets/general.js
index cd5cfb47..1a2f44c6 100644
--- a/src/pages/options/widgets/general.js
+++ b/src/pages/options/widgets/general.js
@@ -58,6 +58,7 @@ function exportSettings() {
 exportSettings()
 
 document.getElementById("general_page").addEventListener("click", exportSettings)
+document.getElementById("test").addEventListener("click", servicesHelper.upgradeOptions)
 
 let importSettingsElement = document.getElementById("import-settings")
 let importSettingsElementText = document.getElementById("import_settings_text")
diff --git a/src/pages/popup/popup.js b/src/pages/popup/popup.js
index 5a5ccb53..9899e79e 100644
--- a/src/pages/popup/popup.js
+++ b/src/pages/popup/popup.js
@@ -2,25 +2,11 @@
 window.browser = window.browser || window.chrome
 
 import utils from "../../assets/javascripts/utils.js"
-import generalHelper from "../../assets/javascripts/general.js"
+// import generalHelper from "../../assets/javascripts/general.js"
 import serviceHelper from "../../assets/javascripts/services.js"
 
-utils.switchInstance(true).then(r => {
-	if (!r) document.getElementById("change_instance_div").style.display = "none"
-	else document.getElementById("change_instance").addEventListener("click", () => utils.switchInstance(false))
-})
-
-utils.copyRaw(true).then(r => {
-	if (!r) document.getElementById("copy_raw_div").style.display = "none"
-	else {
-		const copy_raw = document.getElementById("copy_raw")
-		copy_raw.addEventListener("click", () => utils.copyRaw(false, copy_raw))
-	}
-})
-document.getElementById("more-options").addEventListener("click", () => browser.runtime.openOptionsPage())
-
-let config
-let divs = {}
+let config,
+	divs = {}
 
 async function getConfig() {
 	return new Promise(resolve => {
@@ -35,6 +21,20 @@ async function getConfig() {
 
 await getConfig()
 
+utils.switchInstance(true).then(r => {
+	if (!r) document.getElementById("change_instance_div").style.display = "none"
+	else document.getElementById("change_instance").addEventListener("click", () => utils.switchInstance(false))
+})
+
+utils.copyRaw(true, null, config).then(r => {
+	if (!r) document.getElementById("copy_raw_div").style.display = "none"
+	else {
+		const copy_raw = document.getElementById("copy_raw")
+		copy_raw.addEventListener("click", () => utils.copyRaw(false, copy_raw))
+	}
+})
+document.getElementById("more-options").addEventListener("click", () => browser.runtime.openOptionsPage())
+
 const allSites = document.getElementsByClassName("all_sites")[0]
 const currSite = document.getElementsByClassName("current_site")[0]
 
@@ -78,11 +78,16 @@ browser.storage.local.get("options", r => {
 			return
 		}
 
-		const [service, frontend] = serviceHelper.computeService(url, true)
+		let service = await serviceHelper.computeService(url, true)
+		let frontend
 		if (service) {
+			if (service[1]) {
+				frontend = service[1]
+				service = frontend[0]
+			}
 			divs[service].current.classList.remove("hide")
 			divs[service].all.classList.add("hide")
-			if (config.services[service].frontends[frontend].preferences) {
+			if (config.services[service].frontends[frontend].preferences && !config.services[service].frontends[frontend].preferences.token) {
 				const unify = document.getElementById("unify")
 				const textElement = document.getElementById("unify").getElementsByTagName("h4")[0]
 				unify.addEventListener("click", () => {