Files
holesail-browser/extension/background/proxy.js
T
Raven Scott f1e98a7edd
CI / Build & Test (push) Successful in 2m54s
docs: add CONTRIBUTING.md, CHANGELOG.md, and JSDoc to entire codebase
Add docs/CONTRIBUTING.md covering the build system, dev workflow, all
npm scripts, how to add new native host message types, code style, and
debugging guidance.

Add CHANGELOG.md at the project root documenting all features and fixes
across the 1.0.0 release.

Add JSDoc (@param, @returns) to all previously undocumented exported
functions across 35 JS files:
- native-host/holesail-manager/ (index, virtual-hosts, service-tunnels,
  servers, port-allocator)
- native-host top-level managers (startup, connect-proxy, https-proxy,
  certificate-authority, ssh-manager, rdp-manager)
- extension/background/ (logs, native-messaging, proxy, message-router)
- extension/dashboard/core/ (utils, navigation, init)
- extension/dashboard/ui/ (modal, toast, state-tag)
- extension/dashboard/pages/ (all 10 page files)
- extension/dashboard/refresh.js, events.js
- extension/dashboard/data/hostname-validator.js
- scripts/ (build-host, run-install)
2026-03-01 00:40:53 -05:00

101 lines
3.9 KiB
JavaScript

/**
* PAC (Proxy Auto-Config) proxy management.
* Builds and applies a PAC script that routes virtual host traffic through the
* CONNECT proxy (127.0.0.1:8442). Re-applies automatically if another extension
* or system setting overrides the proxy configuration.
* Depends on: state.js (extensionState, pacConfirmedActive, DEFAULT_CONNECT_PROXY_PORT, DEFAULT_PROXY_PORT)
* Depends on: logs.js (log, debugLog)
*/
/** Extract unique two-label base domains from virtualHosts array, always including hole.sail */
function getActiveTlds(virtualHosts) {
const seen = new Set(['hole.sail']);
for (const v of (virtualHosts || [])) {
if (v && v.hostname) {
const parts = v.hostname.split('.');
if (parts.length >= 3) seen.add(parts.slice(-2).join('.'));
}
}
return Array.from(seen).map(b => '.' + b);
}
/**
* Build and apply a PAC script routing all virtual host TLDs through the CONNECT proxy.
* If `tlds` is omitted, derives the active TLD list from `extensionState.virtualHosts`.
* @param {string[]} [tlds] - Array of TLD suffixes (e.g. `['.hole.sail', '.hs']`).
*/
function applyPAC(tlds) {
if (!browser.proxy || !browser.proxy.settings) {
log('applyPAC: SKIPPED - no browser.proxy.settings API');
return;
}
const proxyPort = extensionState.connectProxyPort ?? DEFAULT_CONNECT_PROXY_PORT ?? extensionState.proxyPort ?? DEFAULT_PROXY_PORT;
const activeTlds = tlds || getActiveTlds(extensionState.virtualHosts);
log('applyPAC: setting PAC port=', proxyPort, 'tlds=', activeTlds);
const clauses = activeTlds.map(t =>
` if (dnsDomainIs(host, "${t}")) return "PROXY 127.0.0.1:${proxyPort}";`
).join('\n');
const pacData = `function FindProxyForURL(url, host) {\n${clauses}\n return "DIRECT";\n}`;
browser.proxy.settings.set(
{ value: { mode: 'pac_script', pacScript: { data: pacData, mandatory: false } }, scope: 'regular' },
() => {
if (browser.runtime.lastError) {
log('applyPAC: ERROR:', browser.runtime.lastError.message);
pacConfirmedActive = false;
return;
}
browser.proxy.settings.get({}, (details) => {
if (browser.runtime.lastError) {
log('applyPAC: get ERROR:', browser.runtime.lastError.message);
return;
}
const mode = details && details.value && details.value.mode;
const loc = details && details.levelOfControl;
log('applyPAC: mode=', mode, 'levelOfControl=', loc);
if (loc === 'controlled_by_this_extension' && mode === 'pac_script') {
pacConfirmedActive = true;
log('applyPAC: ACTIVE');
} else {
pacConfirmedActive = false;
log('applyPAC: WARNING not active - mode=', mode, 'loc=', loc);
}
});
}
);
}
// Re-apply PAC whenever proxy settings change (e.g. another extension or system override)
if (browser.proxy && browser.proxy.settings && browser.proxy.settings.onChange) {
browser.proxy.settings.onChange.addListener((details) => {
const loc = details && details.levelOfControl;
const mode = details && details.value && details.value.mode;
log('proxy.settings.onChange: levelOfControl=', loc, 'mode=', mode);
if (loc === 'controlled_by_this_extension' && mode === 'pac_script') {
pacConfirmedActive = true;
return;
}
pacConfirmedActive = false;
log('proxy settings changed externally - reapplying PAC');
applyPAC();
});
}
/**
* Clear the PAC proxy setting, reverting to direct connections.
* Called when the native host disconnects.
*/
function clearProxy() {
debugLog('clearProxy');
if (!browser.proxy || !browser.proxy.settings) return;
browser.proxy.settings.set({ value: { mode: 'direct' }, scope: 'regular' }).catch(() => {});
}
// Log proxy errors for *.hole.sail to help diagnose issues
if (browser.proxy && browser.proxy.onError) {
browser.proxy.onError.addListener((details) => {
log('Proxy error:', details.error, 'url=', details.url);
});
}