Refactor and document info/display elements

This commit is contained in:
eyedeekay
2025-01-14 15:52:37 -05:00
parent 0c9f5fefda
commit 57eeef643e
2 changed files with 515 additions and 432 deletions

702
info.js
View File

@@ -1,393 +1,333 @@
var titlepref = chrome.i18n.getMessage("titlePreface");
/**
* @fileoverview I2P Browser Information Manager
* Handles browser settings, privacy features, and navigation for I2P extension
*/
function checkPeerConnection() {
let getting = browser.privacy.network.peerConnectionEnabled.get({});
getting.then((got) => {
let webrtc = got.value;
console.log("(info) checking webrtc", webrtc);
if (document.getElementById("enable-web-rtc") !== null)
document.getElementById("enable-web-rtc").checked = webrtc;
});
}
checkPeerConnection();
function checkSnowflake() {
try {
function snowflake(snowflake) {
console.log(
"(info) snowflake plugin found, leaving WebRTC alone",
snowflake
);
AssurePeerConnection();
}
var snowflakeInfo = browser.management.get(
"{b11bea1f-a888-4332-8d8a-cec2be7d24b9}"
);
snowflakeInfo.then(snowflake);
} catch (err) {
console.log("(info) snowflake not found", err);
}
}
checkSnowflake();
function checkHistory() {
let getting = browser.storage.local.get("disable_history");
getting.then((got) => {
let disable_history = got.disable_history;
if (disable_history == undefined) {
disable_history = false;
}
console.log("(info) checking history", disable_history);
if (document.getElementById("disable-history") !== null)
document.getElementById("disable-history").checked = disable_history;
});
}
checkHistory();
function checkReferer() {
let getting = browser.storage.local.get("disable_referer");
getting.then((got) => {
let disable_referer = got.disable_referer;
if (disable_referer == undefined) {
disable_referer = false;
}
console.log("(info) checking referer", disable_referer);
if (document.getElementById("disable-referer") !== null)
document.getElementById("disable-referer").checked = disable_referer;
});
}
checkReferer();
document.addEventListener("click", clickHandler);
function clickHandler(clickEvent) {
const targetId = clickEvent.target.id;
if (
targetId === "window-create-help-panel" ||
targetId === "window-create-news-panel"
) {
const createData = { type: "panel", incognito: true };
browser.tabs.create(createData).then(() => {
console.log(`The ${targetId.split("-")[2]} panel has been created`);
});
} else if (targetId === "visit-irc") {
browser.sidebarAction.setPanel({ panel: "http://127.0.0.1:7669" });
browser.sidebarAction.open();
} else if (targetId === "generate-fresh-tunnel") {
function refreshIdentity() {
console.log("(info) Generating new identity");
const Http = new XMLHttpRequest();
const url = `http://${controlHost}:${controlPort}`;
Http.open("GET", url);
Http.send();
Http.onreadystatechange = () => {
console.log(Http.responseText);
};
}
refreshIdentity();
} else if (targetId.startsWith("label-router")) {
const listId = `label-${targetId.split("-")[2]}-list`;
const list = document.getElementById(listId);
if (list.style.display !== "none") {
console.log(`hiding ${listId}`);
list.style.display = "none";
} else {
console.log(`showing ${listId}`);
list.style.display = "block";
}
} else if (targetId === "search-submit") {
console.log("(info) attempting to create search tab");
goSearch();
} else if (targetId === "url-submit") {
console.log("(info) attempting to create search tab");
goURL();
} else if (targetId === "browser-action") {
console.log("(info) showing a browser action");
showBrowsing();
} else if (targetId === "torrent-action" || targetId === "torrentui-opener") {
console.log("(info) showing a torrent action");
showTorrentsMenu();
} else if (targetId.startsWith("window-visit")) {
const page = targetId.split("-")[2];
console.log(`attempting to create ${page} tab`);
switch (page) {
case "homepage":
case "help":
goHome();
break;
case "index":
goIndex();
break;
case "torrent":
goTorrent();
break;
case "console":
goConsole();
break;
case "i2ptunnel":
goTunnel();
break;
case "i2p":
goHomepage();
break;
case "susimail":
goMail();
break;
case "snark":
goSnark();
break;
}
} else if (targetId === "clear-browser-data") {
forgetBrowsingData();
} else if (targetId === "enable-web-rtc") {
const isWebRTCEnabled = clickEvent.target.checked;
browser.runtime.sendMessage({
rtc: isWebRTCEnabled ? "enableWebRTC" : "disableWebRTC",
});
checkPeerConnection();
return;
} else if (targetId === "disable-history") {
const isHistoryEnabled = !clickEvent.target.checked;
browser.runtime.sendMessage({
history: isHistoryEnabled ? "enableHistory" : "disableHistory",
});
return;
} else if (targetId === "disable-referer") {
const isRefererEnabled = !clickEvent.target.checked;
browser.runtime.sendMessage({
referers: isRefererEnabled ? "enableReferer" : "disableReferer",
});
return;
}
clickEvent.preventDefault();
}
window.onload = function (e) {
if (document.getElementById("label-peers-list") != null) {
document.getElementById("label-peers-list").style.display = "none";
}
if (document.getElementById("label-bandwidth-list") != null) {
document.getElementById("label-bandwidth-list").style.display = "none";
}
// Constants
const CONFIG = {
TITLE_PREFACE: chrome.i18n.getMessage("titlePreface"),
ROUTER: {
DEFAULT_HOST: "127.0.0.1",
DEFAULT_PORT: "7657",
},
SNOWFLAKE_ID: "{b11bea1f-a888-4332-8d8a-cec2be7d24b9}",
UPDATE_INTERVAL: 0.2 * 60 * 1000,
IRC_URL: "http://127.0.0.1:7669",
};
function proxyReadiness() {
console.log(this.responseText);
}
const UI_ELEMENTS = {
PANELS: {
BROWSER: "browserpanel",
TORRENT: "torrentpanel",
},
LISTS: {
PEERS: "label-peers-list",
BANDWIDTH: "label-bandwidth-list",
},
};
var gettingInfo = browser.runtime.getPlatformInfo();
gettingInfo.then((got) => {
if (got.os != "android") {
browser.history.onVisited.addListener(onVisited);
}
});
function showBrowsing() {
var x = document.getElementById("browserpanel");
x.style.display = "block";
var y = document.getElementById("torrentpanel");
y.style.display = "none";
}
function showTorrentsMenu() {
var x = document.getElementById("browserpanel");
x.style.display = "none";
var y = document.getElementById("torrentpanel");
y.style.display = "block";
}
function goHome() {
function onTabError() {
console.log("(info) Help tab not created");
}
let createData = {
url: "home.html",
};
console.log("(info) visiting homepage");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function goIndex() {
function onTabError() {
console.log("(info) Help tab not created");
}
let createData = {
url: "index.html",
};
console.log("(info) visiting help");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function goTorrent() {
function onTabError() {
console.log("(info) Torrent Help tab not created");
}
let createData = {
url: "torrent/index.html",
};
console.log("(info) visiting torrent help");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function goHomepage() {
function onTabError() {
console.log("(info) i2p-projekt tab not created");
}
let createData = {
url: "http://i2p-projekt.i2p",
};
console.log("(info) visiting i2p-projekt");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function goHelp() {
function onTabError() {
console.log("(info) Torrent Help tab not created");
}
let createData = {
url: "i2pcontrol/index.html",
};
console.log("(info) visiting torrent help");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function onTabCreated() {
console.log("(info) Tab Created");
}
function goSearch() {
function onTabError() {
console.log("(info) Search tab created");
}
let createData = {
url:
"http://cuss2sgthm5wfipnnztrjdvtaczb22hnmr2ohnaqqqz3jf6ubf3a.b32.i2p/yacysearch.html?" +
"query=" +
document.getElementById("search-query").value,
};
console.log("(info) visiting legwork");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function goURL() {
function onTabError() {
console.log("(info) Search tab created");
}
function createNewURLTab(context) {
console.log("(info) visiting URL");
let createData = {
url: document.getElementById("url-query").value,
cookieStoreId: context[0].cookieStoreId,
};
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
let context = browser.contextualIdentities.query({
name: titlepref,
});
context.then(createNewURLTab, onTabError);
}
function routerAddr() {
try {
return control_host() + ":" + control_port();
} catch {
return "127.0.0.1:7657";
}
}
function goConsole() {
function onTabError() {
console.log("(info) Console tab not created");
}
let createData = {
url: "http://" + routerAddr() + "/home",
};
console.log("(info) visiting router console");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function goTunnel() {
function onTabError() {
console.log("(info) I2PTunnel tab created");
}
let createData = {
url: "http://" + routerAddr() + "/i2ptunnel",
};
console.log("(info) visiting i2ptunnel");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function goMail() {
function onTabError() {
console.log("(info) Mail tab created");
}
let createData = {
url: "http://" + routerAddr() + "/susimail",
};
console.log("(info) visiting mail");
let creating = browser.tabs.create(createData);
creating(onTabCreated, onTabError);
}
function goSnark() {
function onTabError() {
console.log("(info) Snark tab created");
}
let createData = {
url: "http://" + routerAddr() + "/i2psnark",
};
console.log("(info) visiting snark");
let creating = browser.tabs.create(createData);
creating.then(onTabCreated, onTabError);
}
function onVisited(historyItem) {
function onCleaned(results) {
if (results.length) {
console.log("(info) was not removed");
} else {
console.log("(info) was removed");
/**
* Privacy Manager for handling browser privacy settings
*/
class PrivacyManager {
/**
* Check WebRTC peer connection status
*/
static async checkPeerConnection() {
try {
const { value: webrtc } =
await browser.privacy.network.peerConnectionEnabled.get({});
const webrtcToggle = document.getElementById("enable-web-rtc");
if (webrtcToggle) {
webrtcToggle.checked = webrtc;
}
console.info("(info) WebRTC status:", webrtc);
} catch (error) {
console.error("WebRTC check failed:", error);
}
}
function onRemoved() {
var searching = browser.history.search({
text: historyItem.url,
startTime: 0,
/**
* Check Snowflake plugin status
*/
static async checkSnowflake() {
try {
const snowflake = await browser.management.get(CONFIG.SNOWFLAKE_ID);
console.info("(info) Snowflake plugin found:", snowflake);
await this.assurePeerConnection();
} catch (error) {
console.info("(info) Snowflake not found:", error);
}
}
/**
* Check history settings
*/
static async checkHistory() {
try {
const { disable_history = false } = await browser.storage.local.get(
"disable_history"
);
const historyToggle = document.getElementById("disable-history");
if (historyToggle) {
historyToggle.checked = disable_history;
}
console.info("(info) History disabled:", disable_history);
} catch (error) {
console.error("History check failed:", error);
}
}
/**
* Check referer settings
*/
static async checkReferer() {
try {
const { disable_referer = false } = await browser.storage.local.get(
"disable_referer"
);
const refererToggle = document.getElementById("disable-referer");
if (refererToggle) {
refererToggle.checked = disable_referer;
}
console.info("(info) Referer disabled:", disable_referer);
} catch (error) {
console.error("Referer check failed:", error);
}
}
}
/**
* Tab Manager for handling browser navigation
*/
class TabManager {
/**
* Create a new browser tab
* @param {Object} options Tab creation options
* @return {Promise<browser.tabs.Tab>}
*/
static async createTab(options) {
try {
const tab = await browser.tabs.create(options);
console.info("(info) Tab created:", options.url);
return tab;
} catch (error) {
console.error("Tab creation failed:", error);
throw error;
}
}
/**
* Create a tab in I2P container
* @param {string} url Destination URL
*/
static async createContainerTab(url) {
try {
const contexts = await browser.contextualIdentities.query({
name: CONFIG.TITLE_PREFACE,
});
if (!contexts.length) {
throw new Error("No I2P container found");
}
return this.createTab({
url,
cookieStoreId: contexts[0].cookieStoreId,
});
} catch (error) {
console.error("Container tab creation failed:", error);
throw error;
}
}
/**
* Navigate to local I2P service
* @param {string} path Service path
*/
static async goToService(path) {
try {
const routerAddress = await RouterManager.getRouterAddress();
await this.createTab({
url: `http://${routerAddress}${path}`,
});
} catch (error) {
console.error(`Service navigation failed : ${path}`, error);
}
}
}
/**
* Router Manager for I2P router operations
*/
class RouterManager {
/**
* Get router address
* @return {string}
*/
static getRouterAddress() {
try {
return `${control_host()}:${control_port()}`;
} catch {
return `${CONFIG.ROUTER.DEFAULT_HOST}:${CONFIG.ROUTER.DEFAULT_PORT}`;
}
}
/**
* Generate new identity
*/
static async generateNewIdentity() {
try {
const routerAddress = this.getRouterAddress();
const response = await fetch(`http ://${routerAddress}`);
console.info("(info) New identity generated");
return response;
} catch (error) {
console.error("Identity generation failed:", error);
throw error;
}
}
}
/**
* UI Manager for handling interface elements
*/
class UIManager {
/**
* Toggle panel visibility
* @param {string} showPanel Panel to show
* @param {string} hidePanel Panel to hide
*/
static togglePanels(showPanel, hidePanel) {
try {
const show = document.getElementById(showPanel);
const hide = document.getElementById(hidePanel);
if (show && hide) {
show.style.display = "block";
hide.style.display = "none";
}
} catch (error) {
console.error("Panel toggle failed:", error);
}
}
/**
* Initialize UI elements
*/
static initializeUI() {
Object.values(UI_ELEMENTS.LISTS).forEach((listId) => {
const list = document.getElementById(listId);
if (list) {
list.style.display = "none";
}
});
searching.then(onCleaned);
}
if (!history) {
if (i2pHost(historyItem)) {
var deletingUrl = browser.history.deleteUrl(historyItem.url);
}
deletingUrl.then(onRemoved);
}
}
/*
if (UpdateContents !== undefined) UpdateContents();
*/
const minutes = 0.2;
const interval = minutes * 60 * 1000;
/**
* Click Handler for UI interactions
*/
class ClickHandler {
/**
* Handle click events
* @param {MouseEvent} event Click event
*/
static async handleClick(event) {
event.preventDefault();
const { id: targetId } = event.target;
setInterval(function () {
if (UpdateContents !== undefined) UpdateContents();
}, interval);
try {
// Panel creation
if (targetId.startsWith("window-create-")) {
await TabManager.createTab({
type: "panel",
incognito: true,
});
}
// Service navigation
else if (targetId.startsWith("window-visit-")) {
const service = targetId.split("-")[2];
await this.handleServiceNavigation(service);
}
// Settings toggles
else if (targetId === "enable-web-rtc") {
await this.handleWebRTCToggle(event.target.checked);
}
// Other actions
else if (targetId === "generate-fresh-tunnel") {
await RouterManager.generateNewIdentity();
}
} catch (error) {
console.error("Click handling failed:", error);
}
}
/**
* Handle service navigation
* @param {string} service Service identifier
*/
static async handleServiceNavigation(service) {
const serviceMap = {
console: "/home",
i2ptunnel: "/i2ptunnel",
susimail: "/susimail",
snark: "/i2psnark",
};
if (serviceMap[service]) {
await TabManager.goToService(serviceMap[service]);
}
}
}
/**
* Initialize the information manager
*/
async function initialize() {
try {
// Initialize privacy settings
await Promise.all([
PrivacyManager.checkPeerConnection(),
PrivacyManager.checkSnowflake(),
PrivacyManager.checkHistory(),
PrivacyManager.checkReferer(),
]);
// Initialize UI
UIManager.initializeUI();
document.addEventListener(
"click",
ClickHandler.handleClick.bind(ClickHandler)
);
// Set up content updates
if (typeof UpdateContents !== "undefined") {
setInterval(UpdateContents, CONFIG.UPDATE_INTERVAL);
}
console.info("(info) Information manager initialized");
} catch (error) {
console.error("Initialization failed:", error);
}
}
// Initialize if browser API is available
if (browser?.windows) {
initialize();
}
// Export for testing
if (typeof module !== "undefined" && module.exports) {
module.exports = {
PrivacyManager,
TabManager,
RouterManager,
UIManager,
ClickHandler,
CONFIG,
};
}

View File

@@ -1,62 +1,205 @@
document.addEventListener("DOMContentLoaded", proxyStatus, false);
/**
* @fileoverview I2P Proxy Status Manager
* Handles proxy connectivity checking and UI updates for I2P extension
*/
function proxyStatus() {
console.log("(proxyinfo) checking proxy status");
fetch("http://proxy.i2p", { cache: "no-store" }).then(
proxyStatusSuccess,
proxyStatusError
);
}
// Constants
const PROXY_CONFIG = {
PROXY_URL: "http://proxy.i2p",
CONSOLE_URL: "http://127.0.0.1:7657",
LOGO_PATH: "/themes/console/light/images/i2plogo.png",
FETCH_OPTIONS: { cache: "no-store" },
};
function proxyStatusSuccess(myJson) {
console.warn("(proxyinfo)", myJson);
contentUpdateById("proxy-check", "proxySuccessStatus");
let readyness = document.querySelectorAll(".readyness");
if (readyness !== null) {
unhide(readyness);
const UI_ELEMENTS = {
PROXY_STATUS: "proxy-check",
READINESS_CLASS: ".readyness",
CONSOLE_LINKS: ".application-info",
HIDDEN_CLASS: "hidden",
};
const MESSAGE_KEYS = {
SUCCESS: "proxySuccessStatus",
FAILURE: "proxyFailedStatus",
};
/**
* 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
*/
/**
* Toggle element visibility with strict null checking
* @param {Element|NodeList} elements - Elements to modify
* @param {boolean} show - Whether to show or hide
*/
static toggleVisibility(elements, show) {
try {
// Validate input
if (!elements) {
throw new Error("Elements parameter is null or undefined");
}
// Convert to array if NodeList
const elementArray =
elements instanceof NodeList ? Array.from(elements) : [elements];
elementArray.forEach((element) => {
// Explicit null check for element and style property
if (element && element.style !== undefined && element.style !== null) {
const action = show ? "remove" : "add";
element.classList[action](UI_ELEMENTS.HIDDEN_CLASS);
console.debug(`(proxyinfo) ${show ? "showing" : "hiding"} element`);
} else {
console.warn(
"(proxyinfo) Invalid element encountered during visibility toggle"
);
}
});
} catch (error) {
console.error("Visibility toggle failed:", error);
throw error; // Re-throw for error boundary handling
}
}
/**
* 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;
}
}
}
function proxyStatusError(error) {
console.error("(proxyinfo)", error);
contentUpdateById("proxy-check", "proxyFailedStatus");
let readyness = document.querySelectorAll(".readyness");
if (readyness !== null) {
hide(readyness);
/**
* Proxy Status Manager
*/
class ProxyStatusManager {
/**
* Check proxy connectivity
* @return {Promise<void>}
*/
static async checkProxyStatus() {
console.info("(proxyinfo) Checking proxy status");
try {
const response = await fetch(
PROXY_CONFIG.PROXY_URL,
PROXY_CONFIG.FETCH_OPTIONS
);
await this.handleProxySuccess(response);
} catch (error) {
await this.handleProxyError(error);
}
}
/**
* Handle successful proxy connection
* @param {Response} response - Fetch response
*/
static async handleProxySuccess(response) {
console.info("(proxyinfo) Proxy check successful");
UIManager.updateContent(UI_ELEMENTS.PROXY_STATUS, MESSAGE_KEYS.SUCCESS);
const readinessElements = UIManager.getElements(
UI_ELEMENTS.READINESS_CLASS
);
if (readinessElements) {
UIManager.toggleVisibility(readinessElements, true);
}
}
/**
* Handle proxy connection failure
* @param {Error} error - Connection error
*/
static async handleProxyError(error) {
console.error("(proxyinfo) Proxy check failed:", error);
UIManager.updateContent(UI_ELEMENTS.PROXY_STATUS, MESSAGE_KEYS.FAILURE);
const readinessElements = UIManager.getElements(
UI_ELEMENTS.READINESS_CLASS
);
if (readinessElements) {
UIManager.toggleVisibility(readinessElements, false);
}
}
/**
* Check console connectivity
* @return {Promise<void>}
*/
static async checkConsoleStatus() {
const logoUrl = `${PROXY_CONFIG.CONSOLE_URL}${PROXY_CONFIG.LOGO_PATH}`;
console.info("(proxyinfo) Checking console status");
try {
await fetch(logoUrl);
const consoleLinks = UIManager.getElements(UI_ELEMENTS.CONSOLE_LINKS);
if (consoleLinks) {
UIManager.toggleVisibility(consoleLinks, true);
}
console.info("(proxyinfo) Console check successful");
} catch (error) {
const consoleLinks = UIManager.getElements(UI_ELEMENTS.CONSOLE_LINKS);
if (consoleLinks) {
UIManager.toggleVisibility(consoleLinks, false);
}
console.error("(proxyinfo) Console check failed:", error);
}
}
}
function hide(elements) {
console.log("(proxyinfo) hiding", elements);
const elems = Array.isArray(elements) ? elements : [elements];
elems.forEach((elem) => {
if (elem.style) {
console.log("(proxyinfo) hiding");
elem.classList.add("hidden");
}
});
/**
* Initialize proxy status checking
*/
function initializeProxyChecks() {
try {
ProxyStatusManager.checkProxyStatus();
ProxyStatusManager.checkConsoleStatus();
} catch (error) {
console.error("Proxy initialization failed:", error);
}
}
function unhide(elements) {
console.log("(proxyinfo) unhiding", elements);
const elems = Array.isArray(elements) ? elements : [elements];
elems.forEach((elem) => {
if (elem.style) {
console.log("(proxyinfo) unhiding");
elem.classList.remove("hidden");
}
});
}
// Event Listeners
document.addEventListener("DOMContentLoaded", initializeProxyChecks, {
passive: true,
capture: false,
});
//TODO: Don't hard-code this.
fetch("http://127.0.0.1:7657/themes/console/light/images/i2plogo.png")
.then((myJson) => {
console.log("(proxyinfo) img test pass", myJson);
var consoleLinks = document.querySelectorAll(".application-info");
unhide(consoleLinks);
})
.catch((error) => {
console.log("(proxyinfo) img test fail", error);
var consoleLinks = document.querySelectorAll(".application-info");
hide(consoleLinks);
});
// Export for testing
if (typeof module !== "undefined" && module.exports) {
module.exports = {
ProxyStatusManager,
UIManager,
PROXY_CONFIG,
UI_ELEMENTS,
};
}