Refactor in scrub.js, reformat in the rest of the javascript

This commit is contained in:
eyedeekay
2025-01-14 18:23:17 -05:00
parent 57eeef643e
commit c027a3d2ca
9 changed files with 2112 additions and 1540 deletions

View File

@ -15,6 +15,7 @@ function control_host() {
console.info("(config)Got i2p:", getFuncName());
return getFromStorageControlHost();
}
function control_port() {
console.info("(config)Got i2p:", getFuncName());
return getFromStorageControlPort();

View File

@ -1,46 +1,193 @@
document.addEventListener("DOMContentLoaded", consoleStatus, false);
/**
* @fileoverview I2P Router Console Status Manager
* Handles router console connectivity checking and UI updates
*/
function consoleStatus() {
let recv = fetch("http://127.0.0.1:7657/welcome");
recv.then(routerConsoleSuccess, routerConsoleError);
}
// Constants
const CONSOLE_CONFIG = {
ROUTER_URL: "http://127.0.0.1:7657",
WELCOME_PATH: "/welcome",
FETCH_OPTIONS: {
method: "GET",
cache: "no-store",
redirect: "follow",
},
};
function routerConsoleSuccess(myJson) {
console.warn("(consoleinfo)", myJson);
contentUpdateById("router-check", "consoleSuccessStatus");
let routerness = document.querySelectorAll(".routerness");
if (routerness !== null) {
unhide(routerness);
}
}
const UI_ELEMENTS = {
ROUTER_STATUS: "router-check",
ROUTER_CLASS: ".routerness",
HIDDEN_CLASS: "hidden",
};
function routerConsoleError(error) {
console.error("(consoleinfo)", error);
contentUpdateById("router-check", "consoleFailedStatus");
let routerness = document.querySelectorAll(".routerness");
if (routerness !== null) {
hide(routerness);
}
}
const MESSAGE_KEYS = {
SUCCESS: "consoleSuccessStatus",
FAILURE: "consoleFailedStatus",
};
function hide(elementsToHide) {
const elements = Array.isArray(elementsToHide)
? elementsToHide
: [elementsToHide];
elements.forEach((element) => {
console.log("(consoleinfo) hiding");
el.classList.add("hidden");
});
}
/**
* UI Manager for handling element visibility
*/
class UIManager {
/**
* Toggle element visibility
* @param {Element|NodeList} elements - Elements to modify
* @param {boolean} show - Whether to show or hide
*/
static toggleVisibility(elements, show) {
try {
if (!elements) {
throw new Error("Elements parameter is null or undefined");
}
function unhide(elementsToShow) {
const elements = Array.isArray(elementsToShow)
? elementsToShow
: [elementsToShow];
elements.forEach((element) => {
if (element.style) {
console.log("(consoleinfo) unhiding");
el.classList.remove("hidden");
const elementArray =
elements instanceof NodeList ? Array.from(elements) : [elements];
elementArray.forEach((element) => {
if (element && element.style !== undefined && element.style !== null) {
const action = show ? "remove" : "add";
element.classList[action](UI_ELEMENTS.HIDDEN_CLASS);
console.debug(`(consoleinfo) ${show ? "showing" : "hiding"} element`);
} else {
console.warn(
"(consoleinfo) Invalid element encountered during visibility toggle"
);
}
});
} catch (error) {
console.error("Visibility toggle failed:", error);
throw error;
}
});
}
/**
* Update element content by ID
* @param {string} elementId - Target element ID
* @param {string} messageKey - i18n message key
*/
static updateContent(elementId, messageKey) {
try {
const element = document.getElementById(elementId);
if (!element) {
throw new Error(`Element not found : ${elementId}`);
}
element.textContent = chrome.i18n.getMessage(messageKey);
} catch (error) {
console.error("Content update failed:", error);
}
}
/**
* Get elements by selector
* @param {string} selector - CSS selector
* @return {?NodeList}
*/
static getElements(selector) {
try {
return document.querySelectorAll(selector);
} catch (error) {
console.error("Element selection failed:", error);
return null;
}
}
}
/**
* Router Console Manager
*/
class RouterConsoleManager {
/**
* Check router console connectivity
* @return {Promise<void>}
*/
static async checkConsoleStatus() {
console.info("(consoleinfo) Checking router console status");
try {
const response = await fetch(
`${CONSOLE_CONFIG.ROUTER_URL}${CONSOLE_CONFIG.WELCOME_PATH}`,
CONSOLE_CONFIG.FETCH_OPTIONS
);
if (!response.ok) {
throw new Error(`Console response not OK : ${response.status}`);
}
await this.handleConsoleSuccess(response);
} catch (error) {
await this.handleConsoleError(error);
}
}
/**
* Handle successful console connection
* @param {Response} response - Fetch response
*/
static async handleConsoleSuccess(response) {
console.info("(consoleinfo) Router console check successful");
try {
UIManager.updateContent(UI_ELEMENTS.ROUTER_STATUS, MESSAGE_KEYS.SUCCESS);
const routerElements = UIManager.getElements(UI_ELEMENTS.ROUTER_CLASS);
if (routerElements) {
UIManager.toggleVisibility(routerElements, true);
}
} catch (error) {
console.error("Console success handling failed:", error);
}
}
/**
* Handle console connection failure
* @param {Error} error - Connection error
*/
static async handleConsoleError(error) {
console.error("(consoleinfo) Router console check failed:", error);
try {
UIManager.updateContent(UI_ELEMENTS.ROUTER_STATUS, MESSAGE_KEYS.FAILURE);
const routerElements = UIManager.getElements(UI_ELEMENTS.ROUTER_CLASS);
if (routerElements) {
UIManager.toggleVisibility(routerElements, false);
}
} catch (additionalError) {
console.error("Console error handling failed:", additionalError);
}
}
/**
* Initialize console monitoring
*/
static initialize() {
try {
this.checkConsoleStatus();
console.info("(consoleinfo) Router console monitoring initialized");
} catch (error) {
console.error("Console initialization failed:", error);
}
}
}
// Event Listeners
document.addEventListener(
"DOMContentLoaded",
() => {
RouterConsoleManager.initialize();
},
{
passive: true,
capture: false,
}
);
// Export for testing
if (typeof module !== "undefined" && module.exports) {
module.exports = {
RouterConsoleManager,
UIManager,
CONSOLE_CONFIG,
UI_ELEMENTS,
MESSAGE_KEYS,
};
}

12
info.js
View File

@ -29,7 +29,7 @@ const UI_ELEMENTS = {
/**
* Privacy Manager for handling browser privacy settings
*/
class PrivacyManager {
class PrivacyManagerInfo {
/**
* Check WebRTC peer connection status
*/
@ -291,10 +291,10 @@ async function initialize() {
try {
// Initialize privacy settings
await Promise.all([
PrivacyManager.checkPeerConnection(),
PrivacyManager.checkSnowflake(),
PrivacyManager.checkHistory(),
PrivacyManager.checkReferer(),
PrivacyManagerInfo.checkPeerConnection(),
PrivacyManagerInfo.checkSnowflake(),
PrivacyManagerInfo.checkHistory(),
PrivacyManagerInfo.checkReferer(),
]);
// Initialize UI
@ -323,7 +323,7 @@ if (browser?.windows) {
// Export for testing
if (typeof module !== "undefined" && module.exports) {
module.exports = {
PrivacyManager,
PrivacyManager: PrivacyManagerInfo,
TabManager,
RouterManager,
UIManager,

View File

@ -66,8 +66,6 @@
"scripts": [
"options/options.js",
"config.js",
"torrent/common.js",
"torrent/background.js",
"host.js",
"privacy.js",
"platform.js",

View File

@ -1,26 +1,132 @@
var android = false;
/**
* @fileoverview I2P Platform Detection Manager
* Handles platform detection and feature support for Firefox WebExtensions
*/
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then((got) => {
if (got.os == "android") {
console.log("Running in Android detected");
android = true;
return true;
} else {
console.log("Running in Desktop detected");
android = false;
return false;
}
});
// Platform configuration constants
const PLATFORM_CONFIG = {
PLATFORMS: {
ANDROID: "android",
DESKTOP: "desktop",
},
FEATURES: {
CLOSABLE: "closable",
CONTAINER_TABS: "containerTabs",
SIDEBAR: "sidebar",
},
};
function isDroid() {
console.log("android?", android);
if (android == undefined) {
return false;
/**
* Platform Manager for handling platform-specific functionality
*/
class PlatformManager {
constructor() {
// Platform state
this.platformState = {
isAndroid: false,
isInitialized: false,
};
// Initialize platform detection
this.initialize();
}
/**
* Initialize platform detection
* @private
* @return {Promise<void>}
*/
async initialize() {
try {
const platformInfo = await browser.runtime.getPlatformInfo();
this.platformState.isAndroid =
platformInfo.os === PLATFORM_CONFIG.PLATFORMS.ANDROID;
this.platformState.isInitialized = true;
console.info(
`(platform) Running in ${
this.platformState.isAndroid ? "Android" : "Desktop"
} detected`
);
} catch (error) {
console.error("Platform detection failed:", error);
this.platformState.isAndroid = false;
this.platformState.isInitialized = true;
}
}
/**
* Check if running on Android
* @return {boolean}
*/
isAndroid() {
if (!this.platformState.isInitialized) {
console.warn("Platform detection not yet initialized");
return false;
}
return this.platformState.isAndroid;
}
/**
* Check if running on Desktop
* @return {boolean}
*/
isDesktop() {
return !this.isAndroid();
}
/**
* Check if windows are closable
* @return {boolean}
*/
isClosable() {
return this.isDesktop();
}
/**
* Get current platform state
* @return {Object}
*/
getPlatformState() {
return { ...this.platformState };
}
return android;
}
function notClosable() {
return false;
// Create singleton instance
const platformManager = new PlatformManager();
/**
* Legacy API compatibility layer
*/
const PlatformAPI = {
/**
* Check if running on Android (legacy support)
* @return {boolean}
*/
isDroid() {
const isAndroid = platformManager.isAndroid();
console.log("(platform) android?", isAndroid);
return isAndroid;
},
/**
* Check if windows are not closable (legacy support)
* @return {boolean}
*/
notClosable() {
return !platformManager.isClosable();
},
};
// Export legacy API functions to window
window.isDroid = PlatformAPI.isDroid;
window.notClosable = PlatformAPI.notClosable;
// Export for testing
if (typeof module !== "undefined" && module.exports) {
module.exports = {
platformManager,
PLATFORM_CONFIG,
PlatformAPI,
};
}

View File

@ -1,541 +1,364 @@
var titlepref = chrome.i18n.getMessage("titlePreface");
/**
* @fileoverview I2P Privacy Manager
* Handles Firefox privacy settings and data cleanup for I2P container tabs
*/
function onSet(result) {
if (result) {
console.log("->: Value was updated");
} else {
console.log("-X: Value was not updated");
}
}
/* This disables queries to centralized databases of bad URLs to screen for
risky sites in your browser */
function disableHyperlinkAuditing() {
var setting = browser.privacy.websites.hyperlinkAuditingEnabled.set({
value: false,
});
console.log("Disabling hyperlink auditing/val=", {
value: false,
});
setting.then(onSet);
}
// UNINSTALL ONLY
function enableHyperlinkAuditing() {
var setting = browser.privacy.websites.hyperlinkAuditingEnabled.clear();
console.log("Disabling hyperlink auditing/val=", {
value: false,
});
setting.then(onSet);
}
// This enables first-party isolation
function enableFirstPartyIsolation() {
var setting = browser.privacy.websites.firstPartyIsolate.set({
value: true,
});
console.log("Enabling first party isolation/val=", {
value: true,
});
setting.then(onSet);
}
// UNINSTALL ONLY
function disableFirstPartyIsolation() {
var setting = browser.privacy.websites.firstPartyIsolate.clear();
console.log("Enabling first party isolation/val=", {
value: true,
});
setting.then(onSet);
}
/* This rejects tracking cookies and third-party cookies but it
LEAVES "Persistent" Cookies unmodified in favor of an option in the content
interface for now */
function disableEvilCookies() {
var getting = browser.privacy.websites.cookieConfig.get({});
getting.then((got) => {
var setting = browser.privacy.websites.cookieConfig.set({
value: {
behavior: "reject_third_party",
nonPersistentCookies: got.value.nonPersistentCookies,
},
});
console.log("Setting cookie behavior/val=", {
value: {
behavior: "reject_third_party",
nonPersistentCookies: got.value.nonPersistentCookies,
},
});
setting.then(onSet);
});
}
function enableEvilCookies() {
var getting = browser.privacy.websites.cookieConfig.clear();
}
// Make sure that they're gone
/*function disableBadCookies(){
var setting = browser.privacy.websites.thirdPartyCookiesAllowed.set({
value: false
});
console.log("Disabling third party cookies/val=", {
value: false
})
setting.then(onSet);
}*/
// this disables the use of referrer headers
function disableReferrers() {
var setting = browser.privacy.websites.referrersEnabled.set({
value: false,
});
console.log("Disabling referrer headers/val=", {
value: false,
});
setting.then(onSet);
}
// UNINSATALL ONLY
function enableReferrers() {
var setting = browser.privacy.websites.referrersEnabled.clear();
console.log("Disabling referrer headers/val=", {
value: false,
});
setting.then(onSet);
}
// enable fingerprinting resistent features(letterboxing and stuff)
function enableResistFingerprinting() {
var setting = browser.privacy.websites.resistFingerprinting.set({
value: true,
});
console.log("Enabling resist fingerprinting/val=", {
value: true,
});
setting.then(onSet);
}
// UNINSTALL ONLY
function disableResistFingerprinting() {
var setting = browser.privacy.websites.resistFingerprinting.clear();
console.log("Enabling resist fingerprinting/val=", {
value: false,
});
setting.then(onSet);
}
// This is essentially a blocklist of clearnet web-sites known to do bad tracking
function enableTrackingProtection() {
var setting = browser.privacy.websites.trackingProtectionMode.set({
value: "always",
});
console.log("Enabling tracking protection/val=", {
value: "always",
});
setting.then(onSet);
}
// UNINSTALL ONLY
function disableTrackingProtection() {
var setting = browser.privacy.websites.trackingProtectionMode.clear();
console.log("Enabling tracking protection/val=", {
value: "always",
});
setting.then(onSet);
}
/* This disables protected content, which is a form of digital restrictions
management dependent on identifying information */
function disableDigitalRestrictionsManagement() {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then((got) => {
if (got.os == "win") {
var setting = browser.privacy.websites.protectedContentEnabled.set({
value: false,
});
console.log(
"Setting Protected Content(Digital Restrictions Management) false/val=",
{
value: false,
}
);
setting.then(onSet);
}
});
}
// UNINSTALL ONLY
function disableDigitalRestrictionsManagement() {
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then((got) => {
if (got.os == "win") {
var setting = browser.privacy.websites.protectedContentEnabled.clear();
console.log(
"Setting Protected Content(Digital Restrictions Management) false/val=",
{
value: true,
}
);
setting.then(onSet);
}
});
}
function unsetAllPrivacy() {
enableHyperlinkAuditing();
disableFirstPartyIsolation();
enableEvilCookies();
enableReferrers();
disableTrackingProtection();
disableResistFingerprinting();
enableDigitalRestrictionsManagement();
UnsetPeerConnection();
EnableSavePasswords();
}
browser.management.onUninstalled.addListener((info) => {
function gotSelf(selfinfo) {
if (info.name == selfinfo.name) {
unsetAllPrivacy();
}
}
var gettingSelf = browser.management.getSelf();
gettingSelf.then(gotSelf);
});
function setAllPrivacy() {
disableHyperlinkAuditing();
enableFirstPartyIsolation();
disableEvilCookies();
//disableReferrers();
enableTrackingProtection();
enableResistFingerprinting();
disableDigitalRestrictionsManagement();
}
setAllPrivacy();
function ResetPeerConnection() {
function reset(snowflake) {
var webrtc = true;
console.log("No snowflake plugin found, pre-disabled WebRTC");
var rtc = browser.privacy.network.peerConnectionEnabled.set({
value: webrtc,
});
rtc.then(AssurePeerConnection);
}
function snowflake(snowflake) {
console.log("snowflake plugin found, leaving WebRTC alone", snowflake);
AssurePeerConnection();
}
var snowflakeInfo = browser.management.get(
"{b11bea1f-a888-4332-8d8a-cec2be7d24b9}" // string
);
snowflakeInfo.then(snowflake, reset);
}
function AssurePeerConnection() {
function assure(webrtc) {
browser.privacy.network.peerConnectionEnabled.set({
value: true,
});
chrome.privacy.network.webRTCIPHandlingPolicy.set({
value: "disable_non_proxied_udp",
});
}
let rtc = browser.privacy.network.peerConnectionEnabled.get({});
rtc.then(assure);
}
// UNINSTALL ONLY
function UnsetPeerConnection() {
function assure(webrtc) {
browser.privacy.network.peerConnectionEnabled.set({
value: true,
});
chrome.privacy.network.webRTCIPHandlingPolicy.set({
value: "default",
});
}
let rtc = browser.privacy.network.peerConnectionEnabled.get({});
rtc.then(assure);
}
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then((got) => {
if (got.os == "android") {
browser.tabs.onCreated.addListener(ResetPeerConnection);
} else {
browser.windows.onCreated.addListener(ResetPeerConnection);
}
});
//AssurePeerConnection();
function ResetDisableSavePasswords() {
browser.privacy.services.passwordSavingEnabled.set({
value: false,
});
console.log("Re-disabled saved passwords");
}
function EnableSavePasswords() {
browser.privacy.services.passwordSavingEnabled.clear();
console.log("Enabled saved passwords");
}
//ResetDisableSavePasswords()
var defaultSettings = {
since: "forever",
dataTypes: ["downloads", "passwords", "formData", "localStorage", "history"],
const PRIVACY_CONFIG = {
TITLE_PREFACE: chrome.i18n.getMessage("titlePreface"),
SNOWFLAKE_ID: "{b11bea1f-a888-4332-8d8a-cec2be7d24b9}",
WINDOWS: {
OS: "win",
},
BROWSING_DATA: {
SINCE: "forever",
TYPES: ["downloads", "passwords", "formData", "localStorage", "history"],
},
};
function onError(therror) {
console.error(therror);
/**
* Privacy Manager for handling browser privacy settings
*/
class PrivacyManager {
/**
* Set browser privacy settings
* @param {Object} settings Privacy setting configuration
* @return {Promise<boolean>}
*/
static async setSetting(setting, value) {
try {
const result = await setting.set({ value });
console.info(`Privacy setting updated : ${value}`);
return true;
} catch (error) {
console.error("Privacy setting failed:", error);
return false;
}
}
/**
* Configure hyperlink auditing
* @param {boolean} enabled Whether to enable auditing
*/
static async configureHyperlinkAuditing(enabled = false) {
await this.setSetting(
browser.privacy.websites.hyperlinkAuditingEnabled,
enabled
);
}
/**
* Configure first party isolation
* @param {boolean} enabled Whether to enable isolation
*/
static async configureFirstPartyIsolation(enabled = true) {
await this.setSetting(browser.privacy.websites.firstPartyIsolate, enabled);
}
/**
* Configure cookie behavior
* @param {boolean} allowThirdParty Whether to allow third party cookies
*/
static async configureCookies(allowThirdParty = false) {
try {
const cookieConfig = await browser.privacy.websites.cookieConfig.get({});
await browser.privacy.websites.cookieConfig.set({
value: {
behavior: allowThirdParty ? "allow_all" : "reject_third_party",
nonPersistentCookies: cookieConfig.value.nonPersistentCookies,
},
});
} catch (error) {
console.error("Cookie configuration failed:", error);
}
}
/**
* Configure referrer policy
* @param {boolean} enabled Whether to enable referrers
*/
static async configureReferrers(enabled = false) {
await this.setSetting(browser.privacy.websites.referrersEnabled, enabled);
}
/**
* Configure fingerprinting resistance
* @param {boolean} enabled Whether to enable resistance
*/
static async configureFingerprinting(enabled = true) {
await this.setSetting(
browser.privacy.websites.resistFingerprinting,
enabled
);
}
/**
* Configure tracking protection
* @param {boolean} enabled Whether to enable protection
*/
static async configureTrackingProtection(enabled = true) {
await this.setSetting(
browser.privacy.websites.trackingProtectionMode,
enabled ? "always" : "never"
);
}
/**
* Configure DRM content
* @param {boolean} enabled Whether to enable DRM
*/
static async configureDRM(enabled = false) {
const platformInfo = await browser.runtime.getPlatformInfo();
if (platformInfo.os === PRIVACY_CONFIG.WINDOWS.OS) {
await this.setSetting(
browser.privacy.websites.protectedContentEnabled,
enabled
);
}
}
/**
* Configure WebRTC
* @param {boolean} enabled Whether to enable WebRTC
*/
static async configureWebRTC(enabled = false) {
try {
const snowflake = await browser.management.get(
PRIVACY_CONFIG.SNOWFLAKE_ID
);
console.info("Snowflake detected, preserving WebRTC");
return;
} catch {
await this.setSetting(
browser.privacy.network.peerConnectionEnabled,
enabled
);
await this.setSetting(
chrome.privacy.network.webRTCIPHandlingPolicy,
enabled ? "disable_non_proxied_udp" : "default"
);
}
}
/**
* Configure password saving
* @param {boolean} enabled Whether to enable password saving
*/
static async configurePasswordSaving(enabled = false) {
await this.setSetting(
browser.privacy.services.passwordSavingEnabled,
enabled
);
}
/**
* Apply recommended privacy settings
*/
static async applyRecommendedSettings() {
await Promise.all([
this.configureHyperlinkAuditing(false),
this.configureFirstPartyIsolation(true),
this.configureCookies(false),
this.configureFingerprinting(true),
this.configureTrackingProtection(true),
this.configureDRM(false),
this.configureWebRTC(false),
this.configurePasswordSaving(false),
]);
}
/**
* Reset all privacy settings to defaults
*/
static async resetAllSettings() {
await Promise.all([
browser.privacy.websites.hyperlinkAuditingEnabled.clear(),
browser.privacy.websites.firstPartyIsolate.clear(),
browser.privacy.websites.cookieConfig.clear(),
browser.privacy.websites.referrersEnabled.clear(),
browser.privacy.websites.resistFingerprinting.clear(),
browser.privacy.websites.trackingProtectionMode.clear(),
browser.privacy.websites.protectedContentEnabled.clear(),
browser.privacy.network.peerConnectionEnabled.clear(),
browser.privacy.services.passwordSavingEnabled.clear(),
]);
}
}
function forgetBrowsingData(storedSettings) {
function getSince(selectedSince) {
if (selectedSince === "forever") {
return 0;
}
/**
* Data Cleanup Manager for handling browsing data
*/
class DataCleanupManager {
/**
* Clean browsing data for I2P domains
* @param {Object} options Cleanup options
*/
static async cleanBrowsingData(options = {}) {
const since = this.calculateCleanupTime(
options.since || PRIVACY_CONFIG.BROWSING_DATA.SINCE
);
try {
const i2pHistory = await browser.history.search({
text: "i2p",
startTime: 0,
});
for (const item of i2pHistory) {
if (this.isI2PUrl(item.url)) {
await this.cleanupForDomain(item.url, since);
}
}
await this.notifyCleanup();
} catch (error) {
console.error("Data cleanup failed:", error);
}
}
/**
* Calculate cleanup timestamp
* @param {string} timeframe Cleanup timeframe
* @returns {number} Timestamp
*/
static calculateCleanupTime(timeframe) {
const times = {
hour: () => 1000 * 60 * 60,
day: () => 1000 * 60 * 60 * 24,
week: () => 1000 * 60 * 60 * 24 * 7,
forever: () => 0,
};
const sinceMilliseconds = times[selectedSince].call();
return Date.now() - sinceMilliseconds;
return timeframe === "forever"
? 0
: Date.now() - (times[timeframe] || times.forever)();
}
function getTypes(selectedTypes) {
let dataTypes = {};
for (let item of selectedTypes) {
dataTypes[item] = true;
/**
* Clean up data for specific domain
* @param {string} url Domain URL
* @param {number} since Timestamp
*/
static async cleanupForDomain(url, since) {
const hostname = this.extractI2PHostname(url);
await Promise.all([
browser.history.deleteUrl({ url }),
browser.browsingData.removeCache({}),
browser.browsingData.removePasswords({ hostnames: [hostname], since }),
browser.browsingData.removeDownloads({ hostnames: [hostname], since }),
browser.browsingData.removeFormData({ hostnames: [hostname], since }),
browser.browsingData.removeLocalStorage({ hostnames: [hostname], since }),
]);
await this.cleanupContainerCookies(url);
}
/**
* Clean up container cookies
* @param {string} url Domain URL
*/
static async cleanupContainerCookies(url) {
const containers = await browser.contextualIdentities.query({
name: PRIVACY_CONFIG.TITLE_PREFACE,
});
for (const container of containers) {
const cookies = await browser.cookies.getAll({
firstPartyDomain: null,
storeId: container.cookieStoreId,
});
for (const cookie of cookies) {
await browser.cookies.remove({
firstPartyDomain: cookie.firstPartyDomain,
name: cookie.name,
url: url,
});
}
}
return dataTypes;
}
const since = getSince(defaultSettings.since);
const dataTypes = getTypes(defaultSettings.dataTypes);
/**
* Extract I2P hostname from URL
* @param {string} url URL to parse
* @returns {string} I2P hostname
*/
static extractI2PHostname(url) {
try {
const urlObj = new URL(url);
if (urlObj.host.endsWith(".i2p")) {
return urlObj.host;
}
function notify() {
let dataTypesString = Object.keys(dataTypes).join(", ");
let sinceString = new Date(since).toLocaleString();
browser.notifications.create({
if (url.includes(".i2p")) {
const parts = url.split("=");
for (const part of parts) {
const items = part.split("%");
for (const item of items) {
if (item.includes(".i2p")) {
return item.replace("3D", "");
}
}
}
}
return url.split("/")[2] || url.split("/")[0];
} catch (error) {
console.error("Hostname extraction failed:", error);
return "";
}
}
/**
* Check if URL is I2P
* @param {string} url URL to check
* @returns {boolean}
*/
static isI2PUrl(url) {
const hostname = this.extractI2PHostname(url);
return hostname.split(":")[0].endsWith(".i2p");
}
/**
* Send cleanup notification
*/
static async notifyCleanup() {
await browser.notifications.create({
type: "basic",
title: "Removed browsing data",
message: `Removed ${dataTypesString}\n for I2P Browsing`,
message: "Cleaned I2P browsing data and history",
});
}
function deepCleanHistory(historyItems) {
console.log("Deep cleaning history");
for (let item of historyItems) {
if (i2pCheck(item.url)) {
browser.history.deleteUrl({
url: item.url,
});
browser.browsingData.removeCache({});
console.log("cleared Cache");
browser.browsingData
.removePasswords({
hostnames: [i2pHostName(item.url)],
since,
})
.then(onContextGotLog);
console.log("cleared Passwords");
browser.browsingData
.removeDownloads({
hostnames: [i2pHostName(item.url)],
since,
})
.then(onContextGotLog);
console.log("cleared Downloads");
browser.browsingData
.removeFormData({
hostnames: [i2pHostName(item.url)],
since,
})
.then(onContextGotLog);
console.log("cleared Form Data");
browser.browsingData
.removeLocalStorage({
hostnames: [i2pHostName(item.url)],
since,
})
.then(onContextGotLog);
console.log("cleared Local Storage");
let contexts = browser.contextualIdentities.query({
name: titlepref,
});
function deepCleanCookies(cookies) {
for (let cookie of cookies) {
var removing = browser.cookies.remove({
firstPartyDomain: cookie.firstPartyDomain,
name: cookie.name,
url: item.url,
});
removing.then(onContextGotLog, onError);
}
console.log("Cleared cookies");
}
function deepCleanContext(cookieStoreIds) {
for (let cookieStoreId of cookieStoreIds) {
var removing = browser.cookies.getAll({
firstPartyDomain: null,
storeId: cookieStoreId.cookieStoreId,
});
removing.then(deepCleanCookies, onError);
}
}
contexts.then(deepCleanContext, onError);
}
}
notify();
}
var searching = browser.history.search({
text: "i2p",
startTime: 0,
});
searching.then(deepCleanHistory);
setAllPrivacy();
ResetPeerConnection();
}
function i2pHostName(url) {
let hostname = "";
console.log("(hosts)", url);
let u = new URL(url);
if (u.host.endsWith(".i2p")) {
hostname = u.host;
} else if (url.includes("=")) {
if (url.includes(".i2p")) {
lsit = url.split("=");
for (let item in lsit) {
var items = lsit[item].split(`\ % `); //"\%")
for (let p in items) {
if (items[p].includes(".i2p")) {
hostname = items[p].replace("3D", 1);
}
break;
}
if (hostname != "") {
break;
}
}
}
} else if (url.indexOf("://") > -1) {
hostname = url.split("/")[2];
} else {
hostname = url.split("/")[0];
}
return hostname;
}
function i2pCheck(url) {
let hostname = i2pHostName(url);
let postname = hostname.split(":")[0];
if (postname.endsWith(".i2p")) {
console.log("(hostname) i2p", postname);
}
return postname.endsWith(".i2p");
}
function onContextGotLog(contexts) {
if (contexts != null) {
console.log(contexts);
}
}
browser.runtime.onMessage.addListener(message);
function enableHistory() {
function checkStoredSettings(storedSettings) {
storedSettings["disable_history"] = false;
console.log(storedSettings);
function enablehistory(settings) {
console.log("Store History:", settings);
}
let setting = browser.storage.local.set(storedSettings);
setting.then(enablehistory);
}
const gettingStoredSettings = browser.storage.local.get();
gettingStoredSettings.then(checkStoredSettings, onError);
}
function disableHistory() {
function checkStoredSettings(storedSettings) {
storedSettings["disable_history"] = true;
console.log(storedSettings);
function enablehistory(settings) {
console.log("Store History:", settings);
}
var setting = browser.storage.local.set(storedSettings);
setting.then(enablehistory);
}
const gettingStoredSettings = browser.storage.local.get();
gettingStoredSettings.then(checkStoredSettings, onError);
}
function enableReferer() {
function checkStoredSettings(storedSettings) {
storedSettings["disable_referer"] = false;
console.log(storedSettings);
function enablereferer(settings) {
console.log("Store Referer:", settings);
}
let setting = browser.storage.local.set(storedSettings);
setting.then(enablereferer);
}
const gettingStoredSettings = browser.storage.local.get();
gettingStoredSettings.then(checkStoredSettings, onError);
}
function disableReferer() {
function checkStoredSettings(storedSettings) {
storedSettings["disable_referer"] = true;
console.log(storedSettings);
function enablereferer(settings) {
console.log("Store Referer:", settings);
}
var setting = browser.storage.local.set(storedSettings);
setting.then(enablereferer);
}
const gettingStoredSettings = browser.storage.local.get();
gettingStoredSettings.then(checkStoredSettings, onError);
}
function message(recieved) {
console.log(recieved);
if (recieved.rtc === "enableWebRTC") {
console.log("enableWebRTC");
AssurePeerConnection();
} else if (recieved.rtc === "disableWebRTC") {
console.log("disableWebRTC");
ResetPeerConnection();
}
if (recieved.history === "enableHistory") {
console.log("enableHistory");
enableHistory();
} else if (recieved.history === "disableHistory") {
console.log("disableHistory");
disableHistory();
// Initialize privacy settings
PrivacyManager.applyRecommendedSettings();
// Listen for uninstall
browser.management.onUninstalled.addListener(async (info) => {
const selfInfo = await browser.management.getSelf();
if (info.name === selfInfo.name) {
await PrivacyManager.resetAllSettings();
}
});
// Listen for messages
browser.runtime.onMessage.addListener(async (message) => {
switch (message.type) {
case "cleanupData":
await DataCleanupManager.cleanBrowsingData(message.options);
break;
case "updatePrivacy":
await PrivacyManager.applyRecommendedSettings();
break;
}
});
// Export for testing
if (typeof module !== "undefined" && module.exports) {
module.exports = {
PrivacyManager,
DataCleanupManager,
PRIVACY_CONFIG,
};
}

740
proxy.js
View File

@ -1,357 +1,405 @@
var titlepref = chrome.i18n.getMessage("titlePreface");
var webpref = chrome.i18n.getMessage("webPreface");
var routerpref = chrome.i18n.getMessage("routerPreface");
var mailpref = chrome.i18n.getMessage("mailPreface");
var torrentpref = chrome.i18n.getMessage("torrentPreface");
var tunnelpref = chrome.i18n.getMessage("i2ptunnelPreface");
var ircpref = chrome.i18n.getMessage("ircPreface");
var extensionpref = chrome.i18n.getMessage("extensionPreface");
var muwirepref = chrome.i18n.getMessage("muwirePreface");
var botepref = chrome.i18n.getMessage("botePreface");
var blogpref = chrome.i18n.getMessage("blogPreface");
var blogprefpriv = chrome.i18n.getMessage("blogPrefacePrivate");
var torpref = chrome.i18n.getMessage("torPreface");
var torprefpriv = chrome.i18n.getMessage("torPreface");
/**
* @fileoverview I2P Proxy Manager
* Handles proxy configuration and routing for I2P container tabs
*/
browser.privacy.network.peerConnectionEnabled.set({
value: true,
});
chrome.privacy.network.networkPredictionEnabled.set({
value: false,
});
chrome.privacy.network.webRTCIPHandlingPolicy.set({
value: "disable_non_proxied_udp",
});
console.log("Disabled unproxied UDP.");
function shouldProxyRequest(requestInfo) {
return requestInfo.parentFrameId != -1;
}
var handleContextProxyRequest = async function (requestDetails) {
if (isProxyHost(requestDetails)) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
return proxy;
}
function ircProxy() {
if (!requestDetails.url.includes("7669")) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
return proxy;
}
if (requestDetails.url.includes(":7669")) {
proxy = null;
return proxy;
}
}
/* This is **NOT** the tor SOCKS5 proxy.
These are the rules for visiting the SOCKS5 proxy manager.
*/
function torProxy() {
if (!requestDetails.url.includes("7695")) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
return proxy;
}
if (requestDetails.url.includes(":7695")) {
proxy = null;
return proxy;
}
}
function blogProxy() {
if (!requestDetails.url.includes("8084")) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
return proxy;
}
if (requestDetails.url.includes(":8084")) {
proxy = null;
return proxy;
}
}
function btProxy() {
proxy = routerProxy();
if (requestDetails.url.includes(":7662")) {
proxy = null;
return proxy;
}
console.log("(bt proxy)", proxy);
return proxy;
}
function mainProxy() {
console.log("(proxy) mainproxy 0");
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
let url = new URL(requestDetails.url);
if (
requestDetails.url.startsWith(
"http://" + proxy_host() + ":" + control_port() + "/i2psnark/"
)
) {
//+url.host)) {
console.log("(proxy) mainproxy 2", url);
proxy = null;
}
return proxy;
}
function routerProxy() {
if (isRouterHost(requestDetails.url)) {
proxy = null;
return proxy;
} else if (!isRouterHost(requestDetails.url)) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
return proxy;
}
}
try {
var handleProxyRequest = function (context) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
if (context == "firefox-default" || context == "firefox-private") {
if (!i2pHost(requestDetails.URL))
if (!isProxyHost(requestDetails.URL)) proxy = null;
return proxy;
}
// eslint-disable-next-line no-negated-condition
if (context != undefined) {
console.log("(proxy), context", context);
if (context.name == ircpref) {
proxy = ircProxy();
return proxy;
} else if (context.name == torpref) {
proxy = torProxy();
return proxy;
} else if (context.name == blogpref) {
proxy = blogProxy();
return proxy;
} else if (context.name == titlepref) {
proxy = mainProxy();
return proxy;
} else if (context.name == routerpref) {
proxy = routerProxy();
return proxy;
} else if (context.name == torrentpref) {
proxy = btProxy();
return proxy;
} else if (context.name == mailpref) {
proxy = routerProxy();
return proxy;
} else if (context.name == tunnelpref) {
proxy = routerProxy();
return proxy;
} else if (context.name == muwirepref) {
proxy = routerProxy();
return proxy;
} else if (context.name == botepref) {
proxy = routerProxy();
return proxy;
}
} else {
if (!isRouterHost(requestDetails.url)) {
if (isLocalHost(requestDetails.url)) {
if (requestDetails.url.includes(":7669")) {
proxy = null;
} else if (requestDetails.url.includes(":7662")) {
proxy = null;
} else if (requestDetails.url.includes(":7695")) {
proxy = null;
} else {
console.log(
"(proxy) non-routerconsole localhost url, will not interfere",
requestDetails.url
);
}
}
}
if (i2pHost(requestDetails)) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
} else if (isProxyHost(requestDetails)) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
} else {
proxy = null;
}
if (requestDetails.url.includes("rpc")) {
console.log("(proxy for rpc url)", rpc);
}
/* var tab = tabGet(requestDetails.tabId);
tab.then(handleTabRequest,) */
return proxy;
}
};
var contextGet = async function (tabInfo) {
try {
context = await browser.contextualIdentities.get(tabInfo.cookieStoreId);
return context;
} catch (error) {
console.warn(error);
return "firefox-default";
}
};
var tabGet = async function (tabId) {
try {
let tabInfo = await browser.tabs.get(tabId);
return tabInfo;
} catch (error) {
console.log("(proxy)Tab error", error);
}
};
if (isProxyHost(requestDetails)) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
return proxy;
}
if (requestDetails.originUrl == browser.runtime.getURL("security.html")) {
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
return proxy;
}
if (
requestDetails.cookieStoreId == "firefox-default" ||
requestDetails.cookieStoreId == "firefox-private"
) {
if (browser.windows != undefined) {
return browser.proxy.settings.get({});
}
}
if (requestDetails.tabId > 0) {
if (requestDetails.url.includes("MuWire")) {
console.debug("(proxy) test is muwire host:", requestDetails);
return;
}
if (isProxyHost(requestDetails)) {
console.debug("(proxy) test is proxy host:", requestDetails);
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
return proxy;
} else if (i2pHost(requestDetails)) {
console.debug("(proxy) test I2P host:", requestDetails);
var tab = tabGet(requestDetails.tabId);
requestDetails.tabId = tab;
var context = tab.then(contextGet);
var proxy = await context.then(handleProxyRequest);
//console.log('(proxy)Returning I2P Proxy', proxy);
return proxy;
} else if (isExtensionHost(requestDetails)) {
console.debug("(proxy) test extension host:", requestDetails);
return;
} else {
console.debug("(proxy) test else in:", requestDetails);
var tab = tabGet(requestDetails.tabId);
var context = tab.then(contextGet);
var proxy = await context.then(handleProxyRequest);
//console.log("(proxy)Returning I2P Proxy", proxy);
return proxy;
}
/*proxy = {};
console.log("(proxy)Returning unset Proxy", proxy);
return proxy;*/
} else {
console.debug("(proxy) test else:", requestDetails);
proxy = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
//console.log('(proxy for rpc url)', rpc);
return proxy;
}
} catch (error) {
console.log("(proxy)Not using I2P Proxy.", error);
}
return { type: "direct" };
// Configuration constants
const PROXY_CONFIG = {
MESSAGES: {
TITLE: chrome.i18n.getMessage("titlePreface"),
WEB: chrome.i18n.getMessage("webPreface"),
ROUTER: chrome.i18n.getMessage("routerPreface"),
MAIL: chrome.i18n.getMessage("mailPreface"),
TORRENT: chrome.i18n.getMessage("torrentPreface"),
TUNNEL: chrome.i18n.getMessage("i2ptunnelPreface"),
IRC: chrome.i18n.getMessage("ircPreface"),
EXTENSION: chrome.i18n.getMessage("extensionPreface"),
MUWIRE: chrome.i18n.getMessage("muwirePreface"),
BOTE: chrome.i18n.getMessage("botePreface"),
BLOG: chrome.i18n.getMessage("blogPreface"),
BLOG_PRIVATE: chrome.i18n.getMessage("blogPrefacePrivate"),
TOR: chrome.i18n.getMessage("torPreface"),
},
PORTS: {
IRC: "7669",
TOR: "7695",
BLOG: "8084",
TORRENT: "7662",
},
};
function setupProxy() {
console.log("Setting up Firefox WebExtension proxy");
browser.proxy.onRequest.addListener(handleContextProxyRequest, {
urls: ["<all_urls>"],
});
console.log("i2p settings created for WebExtension Proxy");
browser.proxy.onError.addListener(handleContextProxyError);
}
function handleContextProxyError(err) {
if (err == 'ProxyInfoData: Invalid proxy server type: "undefined"') {
console.warn("(proxy) Invalid proxy server type: ", err);
/**
* Network Manager for handling WebRTC and network prediction
*/
class NetworkManager {
/**
* Initialize network settings
*/
static async initialize() {
try {
await Promise.all([
browser.privacy.network.peerConnectionEnabled.set({ value: true }),
chrome.privacy.network.networkPredictionEnabled.set({ value: false }),
chrome.privacy.network.webRTCIPHandlingPolicy.set({
value: "disable_non_proxied_udp",
}),
]);
console.info("Network settings initialized");
} catch (error) {
console.error("Network initialization failed:", error);
}
}
console.error("(proxy) test Context Proxy Error: ", err);
}
function update() {
console.log("(proxy) restoring proxy scheme:", proxy_scheme());
console.log("(proxy) restoring proxy host:", proxy_host());
console.log("(proxy) restoring proxy port:", proxy_port());
console.log("(proxy) restoring control host:", control_host());
console.log("(proxy) restoring control port:", control_port());
}
/**
* Proxy Manager for handling proxy configuration
*/
class ProxyManager {
constructor() {
this.proxyConfig = {
type: proxy_scheme(),
host: proxy_host(),
port: proxy_port(),
};
function updateFromStorage() {
console.log("updating settings from storage");
chrome.storage.local.get(function () {
update();
setupProxy();
});
}
this.initialize();
}
//updateFromStorage();
browser.storage.onChanged.addListener(updateFromStorage);
setupProxy();
/**
* Initialize proxy settings
*/
async initialize() {
try {
await this.setupProxyListener();
await this.setupStorageListener();
await this.setupWindowListener();
console.info("Proxy manager initialized");
} catch (error) {
console.error("Proxy initialization failed:", error);
}
}
var gettingListenerInfo = browser.runtime.getPlatformInfo();
gettingListenerInfo.then((got) => {
if (browser.windows != undefined) {
browser.windows.onCreated.addListener(() => {
chrome.storage.local.get(function () {
setupProxy();
});
/**
* Setup proxy request listener
*/
async setupProxyListener() {
browser.proxy.onRequest.addListener(this.handleProxyRequest.bind(this), {
urls: ["<all_urls>"],
});
browser.proxy.onError.addListener(this.handleProxyError.bind(this));
}
});
/**
* Setup storage change listener
*/
async setupStorageListener() {
browser.storage.onChanged.addListener(this.handleStorageChange.bind(this));
}
/**
* Setup window creation listener
*/
async setupWindowListener() {
const platformInfo = await browser.runtime.getPlatformInfo();
if (browser.windows) {
browser.windows.onCreated.addListener(
this.handleWindowCreation.bind(this)
);
}
}
/**
* Handle proxy requests
* @param {Object} requestDetails Request details
* @return {Object} Proxy configuration
*/
async handleProxyRequest(requestDetails) {
try {
// Handle proxy host requests
if (isProxyHost(requestDetails)) {
return this.proxyConfig;
}
// Handle extension requests
if (this.isExtensionRequest(requestDetails)) {
return this.proxyConfig;
}
// Handle container requests
if (requestDetails.tabId > 0) {
return await this.handleContainerRequest(requestDetails);
}
// Handle direct requests
return await this.handleDirectRequest(requestDetails);
} catch (error) {
console.error("Proxy request handling failed:", error);
return { type: "direct" };
}
}
/**
* Handle container-specific proxy requests
* @param {Object} requestDetails Request details
* @return {Object} Proxy configuration
*/
async handleContainerRequest(requestDetails) {
try {
const tab = await browser.tabs.get(requestDetails.tabId);
const context = await this.getContextIdentity(tab);
if (!context) {
return this.getDefaultProxy();
}
return await this.getContainerProxy(context, requestDetails);
} catch (error) {
console.error("Container request handling failed:", error);
return this.getDefaultProxy();
}
}
/**
* Handle direct (non-container) proxy requests
* @param {Object} requestDetails Request details
* @return {Object} Proxy configuration
*/
async handleDirectRequest(requestDetails) {
try {
// Check for local service ports first
if (isLocalHost(requestDetails.url)) {
const localProxyConfig = this.handleLocalServiceRequest(requestDetails);
if (localProxyConfig !== undefined) {
return localProxyConfig;
}
}
// Handle I2P and proxy hosts
if (i2pHost(requestDetails)) {
console.debug("(proxy) Direct I2P host request:", requestDetails.url);
return this.proxyConfig;
}
if (isProxyHost(requestDetails)) {
console.debug("(proxy) Direct proxy host request:", requestDetails.url);
return this.proxyConfig;
}
// Handle router console requests
if (isRouterHost(requestDetails.url)) {
console.debug(
"(proxy) Direct router console request:",
requestDetails.url
);
return null;
}
// RPC request handling
if (requestDetails.url.includes("rpc")) {
console.debug("(proxy) Direct RPC request:", requestDetails.url);
return this.proxyConfig;
}
// Default to direct connection for non-I2P traffic
console.debug("(proxy) Direct clearnet request:", requestDetails.url);
return { type: "direct" };
} catch (error) {
console.error("Direct request handling failed:", error);
return { type: "direct" };
}
}
/**
* Handle local service port requests
* @private
* @param {Object} requestDetails Request details
* @return {Object|undefined} Proxy configuration or undefined
*/
handleLocalServiceRequest(requestDetails) {
// Local service port mapping
const LOCAL_SERVICES = {
[PROXY_CONFIG.PORTS.IRC]: true, // IRC Console
[PROXY_CONFIG.PORTS.TOR]: true, // Tor Console
[PROXY_CONFIG.PORTS.BLOG]: true, // Blog Console
[PROXY_CONFIG.PORTS.TORRENT]: true, // Torrent Console
};
// Extract port from URL
const url = new URL(requestDetails.url);
const port = url.port;
// Return null proxy for local service ports
if (LOCAL_SERVICES[port]) {
console.debug(
`(proxy) Local service request on port ${port} :`,
requestDetails.url
);
return null;
}
// Let the main proxy logic handle other local requests
return undefined;
}
/**
* Get container identity
* @param {Object} tab Browser tab
* @return {Object} Container context
*/
async getContextIdentity(tab) {
try {
if (
tab.cookieStoreId === "firefox-default" ||
tab.cookieStoreId === "firefox-private"
) {
return null;
}
return await browser.contextualIdentities.get(tab.cookieStoreId);
} catch (error) {
console.error("Context identity lookup failed:", error);
return null;
}
}
/**
* Get container-specific proxy configuration
* @param {Object} context Container context
* @param {Object} requestDetails Request details
* @return {Object} Proxy configuration
*/
async getContainerProxy(context, requestDetails) {
const proxyMap = {
[PROXY_CONFIG.MESSAGES.IRC]: () => this.getIRCProxy(requestDetails),
[PROXY_CONFIG.MESSAGES.TOR]: () => this.getTorProxy(requestDetails),
[PROXY_CONFIG.MESSAGES.BLOG]: () => this.getBlogProxy(requestDetails),
[PROXY_CONFIG.MESSAGES.TITLE]: () => this.getMainProxy(requestDetails),
[PROXY_CONFIG.MESSAGES.ROUTER]: () => this.getRouterProxy(requestDetails),
[PROXY_CONFIG.MESSAGES.TORRENT]: () =>
this.getTorrentProxy(requestDetails),
};
const handler = proxyMap[context.name];
return handler ? await handler() : this.getDefaultProxy();
}
/**
* Get service-specific proxy configurations
*/
getIRCProxy(requestDetails) {
return !requestDetails.url.includes(PROXY_CONFIG.PORTS.IRC)
? this.proxyConfig
: null;
}
getTorProxy(requestDetails) {
return !requestDetails.url.includes(PROXY_CONFIG.PORTS.TOR)
? this.proxyConfig
: null;
}
getBlogProxy(requestDetails) {
return !requestDetails.url.includes(PROXY_CONFIG.PORTS.BLOG)
? this.proxyConfig
: null;
}
getMainProxy(requestDetails) {
if (
requestDetails.url.startsWith(
`http ://${proxy_host()}:${control_port()}/i2psnark/`
)
) {
return null;
}
return this.proxyConfig;
}
getRouterProxy(requestDetails) {
return isRouterHost(requestDetails.url) ? null : this.proxyConfig;
}
getTorrentProxy(requestDetails) {
return requestDetails.url.includes(PROXY_CONFIG.PORTS.TORRENT)
? null
: this.getRouterProxy(requestDetails);
}
/**
* Get default proxy configuration
* @return {Object} Default proxy
*/
getDefaultProxy() {
return { type: "direct" };
}
/**
* Handle proxy errors
* @param {Error} error Proxy error
*/
handleProxyError(error) {
if (error.includes("Invalid proxy server type")) {
console.warn("Invalid proxy configuration:", error);
} else {
console.error("Proxy error:", error);
}
}
/**
* Handle storage changes
*/
async handleStorageChange() {
try {
await this.updateConfig();
await this.setupProxyListener();
} catch (error) {
console.error("Storage update failed:", error);
}
}
/**
* Handle window creation
*/
async handleWindowCreation() {
try {
await this.updateConfig();
await this.setupProxyListener();
} catch (error) {
console.error("Window creation handling failed:", error);
}
}
/**
* Update proxy configuration
*/
async updateConfig() {
console.info(
"Updating proxy configuration:",
`Scheme : ${proxy_scheme()},`,
`Host : ${proxy_host()},`,
`Port : ${proxy_port()},`,
`Control : ${control_host()} :${control_port()}`
);
}
/**
* Check if request is from extension
* @param {Object} requestDetails Request details
* @return {boolean}
*/
isExtensionRequest(requestDetails) {
return requestDetails.originUrl === browser.runtime.getURL("security.html");
}
}
// Initialize managers
NetworkManager.initialize();
const proxyManager = new ProxyManager();
// Export for testing
if (typeof module !== "undefined" && module.exports) {
module.exports = {
NetworkManager,
ProxyManager,
PROXY_CONFIG,
};
}

View File

@ -26,7 +26,7 @@ const MESSAGE_KEYS = {
/**
* UI Manager for handling element visibility
*/
class UIManager {
class ProxyUIManager {
/**
* Toggle element visibility
* @param {Element|NodeList} elements - Elements to modify
@ -125,13 +125,16 @@ class ProxyStatusManager {
*/
static async handleProxySuccess(response) {
console.info("(proxyinfo) Proxy check successful");
UIManager.updateContent(UI_ELEMENTS.PROXY_STATUS, MESSAGE_KEYS.SUCCESS);
ProxyUIManager.updateContent(
UI_ELEMENTS.PROXY_STATUS,
MESSAGE_KEYS.SUCCESS
);
const readinessElements = UIManager.getElements(
const readinessElements = ProxyUIManager.getElements(
UI_ELEMENTS.READINESS_CLASS
);
if (readinessElements) {
UIManager.toggleVisibility(readinessElements, true);
ProxyUIManager.toggleVisibility(readinessElements, true);
}
}
@ -141,13 +144,16 @@ class ProxyStatusManager {
*/
static async handleProxyError(error) {
console.error("(proxyinfo) Proxy check failed:", error);
UIManager.updateContent(UI_ELEMENTS.PROXY_STATUS, MESSAGE_KEYS.FAILURE);
ProxyUIManager.updateContent(
UI_ELEMENTS.PROXY_STATUS,
MESSAGE_KEYS.FAILURE
);
const readinessElements = UIManager.getElements(
const readinessElements = ProxyUIManager.getElements(
UI_ELEMENTS.READINESS_CLASS
);
if (readinessElements) {
UIManager.toggleVisibility(readinessElements, false);
ProxyUIManager.toggleVisibility(readinessElements, false);
}
}
@ -161,15 +167,19 @@ class ProxyStatusManager {
try {
await fetch(logoUrl);
const consoleLinks = UIManager.getElements(UI_ELEMENTS.CONSOLE_LINKS);
const consoleLinks = ProxyUIManager.getElements(
UI_ELEMENTS.CONSOLE_LINKS
);
if (consoleLinks) {
UIManager.toggleVisibility(consoleLinks, true);
ProxyUIManager.toggleVisibility(consoleLinks, true);
}
console.info("(proxyinfo) Console check successful");
} catch (error) {
const consoleLinks = UIManager.getElements(UI_ELEMENTS.CONSOLE_LINKS);
const consoleLinks = ProxyUIManager.getElements(
UI_ELEMENTS.CONSOLE_LINKS
);
if (consoleLinks) {
UIManager.toggleVisibility(consoleLinks, false);
ProxyUIManager.toggleVisibility(consoleLinks, false);
}
console.error("(proxyinfo) Console check failed:", error);
}
@ -198,7 +208,7 @@ document.addEventListener("DOMContentLoaded", initializeProxyChecks, {
if (typeof module !== "undefined" && module.exports) {
module.exports = {
ProxyStatusManager,
UIManager,
UIManager: ProxyUIManager,
PROXY_CONFIG,
UI_ELEMENTS,
};

1639
scrub.js

File diff suppressed because it is too large Load Diff