const MozillaVPN = { async handleContainerList(identities) { const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); this.handleStatusIndicatorsInContainerLists(mozillaVpnInstalled); const permissionsEnabled = await this.bothPermissionsEnabled(); if (!permissionsEnabled) { return; } const proxies = await this.getProxies(identities); if (Object.keys(proxies).length === 0) { return; } const tooltipProxyWarning = browser.i18n.getMessage("tooltipWarning"); for (const el of document.querySelectorAll("[data-cookie-store-id]")) { const cookieStoreId = el.dataset.cookieStoreId; if (!proxies[cookieStoreId]) { continue; } const { proxy } = proxies[cookieStoreId]; if (typeof(proxy) !== "undefined") { const flag = el.querySelector(".flag-img"); if (proxy.countryCode) { flag.src = `/img/flags/${proxy.countryCode.toUpperCase()}.png`; } if (typeof(proxy.mozProxyEnabled) === "undefined" && typeof(proxy.countryCode) !== "undefined") { flag.classList.add("proxy-disabled"); } if (!mozillaVpnConnected && proxy.mozProxyEnabled) { flag.classList.add("proxy-unavailable"); const menuItemName = el.querySelector(".menu-item-name"); menuItemName.setAttribute("title", tooltipProxyWarning); if (menuItemName) { el.querySelector(".menu-item-name").dataset.mozProxyWarning = "proxy-unavailable"; } } } } }, async setStatusIndicatorIcons(mozillaVpnInstalled) { const statusIconEls = document.querySelectorAll(".moz-vpn-connection-status-indicator"); if (!mozillaVpnInstalled) { statusIconEls.forEach(el => { el.style.backgroundImage = "none"; if (el.querySelector(".tooltip")) { el.querySelector(".tooltip").textContent = ""; } el.textContent = ""; }); return; } const connectedIndicatorSrc = "url(./img/moz-vpn-connected.svg)"; const disconnectedIndicatorSrc = "url(./img/moz-vpn-disconnected.svg)"; const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); const connectionStatusStringId = mozillaVpnConnected ? "moz-vpn-connected" : "moz-vpn-disconnected"; const connectionStatusLocalizedString = browser.i18n.getMessage(connectionStatusStringId); const connectionStatusTooltip = document.querySelector(".vpn-status-container-list"); connectionStatusTooltip.setAttribute("title", connectionStatusLocalizedString); statusIconEls.forEach(el => { el.style.backgroundImage = mozillaVpnConnected ? connectedIndicatorSrc : disconnectedIndicatorSrc; }); }, async handleStatusIndicatorsInContainerLists(mozillaVpnInstalled) { const mozVpnLogotypes = document.querySelectorAll(".moz-vpn-logotype.vpn-status-container-list"); try { if (!mozillaVpnInstalled) { mozVpnLogotypes.forEach(el => { el.style.display = "none"; }); return; } mozVpnLogotypes.forEach(el => { el.style.display = "flex"; el.classList.remove("display-none"); }); this.setStatusIndicatorIcons(mozillaVpnInstalled); } catch (e) { mozVpnLogotypes.forEach(el => { el.style.display = "none"; }); return; } }, handleMozillaCtaClick(buttonIdentifier) { browser.tabs.create({ url: MozillaVPN.attachUtmParameters("https://www.mozilla.org/products/vpn", buttonIdentifier), }); }, getRandomInteger(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }, proxyIsDisabled(proxy) { return ( // Mozilla VPN proxy is disabled, last location data is stored (proxy.mozProxyEnabled === undefined && proxy.countryCode !== undefined && proxy.cityName !== undefined) || // Mozilla VPN proxy is enabled but Mozilla VPN is not connected proxy.mozProxyEnabled !== undefined ); }, attachUtmParameters(baseUrl, utmContent) { const url = new URL(baseUrl); const utmParameters = { utm_source: "multi.account.containers", utm_medium: "mac-browser-addon", utm_content: utmContent, utm_campaign: "vpn-better-together", }; for (const param in utmParameters) { url.searchParams.append(param, utmParameters[param]); } return url.href; }, async getProxies(identities) { const proxies = {}; const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); if (mozillaVpnInstalled) { for (const identity of identities) { try { const proxy = await proxifiedContainers.retrieve(identity.cookieStoreId); proxies[identity.cookieStoreId] = proxy; } catch (e) { proxies[identity.cookieStoreId] = {}; } } } return proxies; }, getMozillaProxyInfoObj() { return { countryCode: undefined, cityName: undefined, mozProxyEnabled: undefined }; }, async bothPermissionsEnabled() { return await browser.permissions.contains({ permissions: ["proxy", "nativeMessaging"] }); }, async getProxyWarnings(proxyObj) { if (!proxyObj) { return ""; } const { proxy } = proxyObj; if (typeof(proxy) === "undefined") { return ""; } const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); if (typeof(proxy.mozProxyEnabled) !== "undefined" && !mozillaVpnConnected) { return "proxy-unavailable"; } }, async getFlag(proxyObj) { const flag = { imgCode: "default", elemClasses: "display-none", imgAlt: "", }; if (!proxyObj) { return flag; } const { proxy } = proxyObj; const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); if (typeof(proxy) === "undefined" || !mozillaVpnInstalled) { return flag; } const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); if (mozillaVpnInstalled && typeof(proxy.cityName) !== "undefined") { flag.imgCode = proxy.countryCode.toUpperCase(); flag.imgAlt = proxy.cityName; flag.elemClasses = typeof(proxy.mozProxyEnabled) === "undefined" || !mozillaVpnConnected ? "proxy-disabled" : ""; } return flag; }, getProxy(countryCode, cityName, mozProxyEnabled, mozillaVpnServers) { const selectedServerCountry = mozillaVpnServers.find(({code}) => code === countryCode); const selectedServerCity = selectedServerCountry.cities.find(({name}) => name === cityName); const proxyServer = this.pickServerBasedOnWeight(selectedServerCity.servers); return proxifiedContainers.parseProxy( this.makeProxyString(proxyServer.socksName), { countryCode: countryCode, cityName: cityName, mozProxyEnabled, } ); }, makeProxyString(socksName) { return `socks://${socksName}.mullvad.net:1080`; }, async pickRandomLocation() { const { mozillaVpnServers } = await browser.storage.local.get("mozillaVpnServers"); const randomInteger = this.getRandomInteger(0, mozillaVpnServers.length - 1); const randomServerCountry = mozillaVpnServers[randomInteger]; return { randomServerCountryCode: randomServerCountry.code, randomServerCityName: randomServerCountry.cities[0].name, }; }, pickServerBasedOnWeight(serverList) { const filteredServerList = serverList.filter(server => typeof(server.socksName) !== "undefined" && server.socksName !== ""); const sumWeight = filteredServerList.reduce((sum, { weight }) => sum + weight, 0); let randomInteger = this.getRandomInteger(0, sumWeight); let nextServer = {}; for (const server of filteredServerList) { if (server.weight >= randomInteger) { return nextServer = server; } randomInteger = (randomInteger - server.weight); } return nextServer; }, }; window.MozillaVPN = MozillaVPN;