Managing Chrome Extensions
Relevant source files
The following files were used as context for generating this wiki page:GeekezBrowser provides a robust system for managing Chrome extensions, serving two primary purposes. First, it dynamically generates and injects a mandatory internal extension, GeekEZ Guard, to apply unique browser fingerprint modifications for each profile. Second, it offers a user-friendly interface for loading custom, unpacked Chrome extensions (e.g., MetaMask, AdBlock) which are then automatically loaded into isolated browser environments upon launch.
This dual-extension architecture ensures that core anti-detect functionality is always active while giving users the flexibility to add their own tools to their workflow. All user-added extension configurations are stored centrally and applied to every profile launched from the application.
Sources: main.js:103-112, README.md:46-47
Architecture Overview
The extension management system is split between the Main and Renderer processes, communicating via IPC channels. The user interacts with a Settings modal in the UI (Renderer) to manage custom extensions. The paths to these extensions are saved in a central settings.json file. When a browser profile is launched, the Main process reads this configuration, generates the internal GeekEZ Guard extension, and instructs Puppeteer to load both the internal and user-defined extensions using Chromium launch arguments.
The following diagram illustrates the high-level architecture of the extension management system.
Core Components
Internal Extension: GeekEZ Guard
For every profile launch, GeekezBrowser dynamically generates a temporary internal extension named GeekEZ Guard. Its sole purpose is to inject the JavaScript necessary to apply the profile's unique fingerprint modifications. This is achieved by creating a manifest.json and a content.js file within the profile's specific directory.
The content script is configured to run at document_start in the MAIN world, ensuring that fingerprint modifications are applied before the page's own scripts execute.
Key Function: generateExtension
This function in main.js is responsible for creating the extension files on the fly.
// main.js:103-112
async function generateExtension(profilePath, fingerprint) {
const extDir = path.join(profilePath, 'extension');
await fs.ensureDir(extDir);
const manifest = {
manifest_version: 3,
name: "GeekEZ Guard",
version: "1.0.0",
description: "Privacy Protection",
content_scripts: [{ matches: ["<all_urls>"], js: ["content.js"], run_at: "document_start", all_frames: true, world: "MAIN" }]
};
const scriptContent = getInjectScript(fingerprint);
await fs.writeJson(path.join(extDir, 'manifest.json'), manifest);
await fs.writeFile(path.join(extDir, 'content.js'), scriptContent);
return extDir;
}
Sources: main.js:103-112
User-Defined Extensions
Users can add their own unpacked Chrome extensions through the Settings modal. The application does not store the extension files themselves, but rather the file paths to their directories. These paths are persisted in the settings.json file.
When a profile is launched, these paths are retrieved and passed to the Chrome instance via launch arguments, loading them alongside the internal GeekEZ Guard.
Sources: main.js:315-341, renderer.js:1282-1291
Configuration and Storage
The paths to user-defined extensions are stored in an array named userExtensions within the settings.json file, located in the application's user data directory.
File Location: [userDataPath]/BrowserProfiles/settings.json
Data Structure:
{
"preProxies": [],
"subscriptions": [],
"mode": "single",
"enablePreProxy": false,
"userExtensions": [
"C:\\path\\to\\my\\first\\extension",
"/Users/user/extensions/another-one"
]
}
This file is read by the Main process during profile launch and is modified via IPC calls from the Renderer process when a user adds or removes an extension.
Sources: mainjs:320-321, main.js:332-335
User Interface and Workflow
Extension management is handled in the Settings modal, accessible from the main application header.
Settings Modal UI
The UI is defined in index.html and consists of a dedicated "Extensions" tab. This tab contains a button to add a new extension folder and a list to display currently added extensions.
<!-- index.html:1270-1281 -->
<!-- Extensions Tab -->
<div id="settings-extensions" class="settings-section active">
<h3 style="margin-bottom:15px; color:var(--accent);" data-i18n="settingsExtTitle">Extension
Management</h3>
<p style="font-size:12px; opacity:0.7; margin-bottom:15px;" data-i18n="settingsExtDesc">
Load custom Chrome extensions. Extensions will be loaded automatically when launching profiles.
</p>
<button onclick="selectExtensionFolder()" style="margin-bottom:15px;" data-i18n="settingsExtAddBtn">
+ Add Extension Folder
</button>
<div id="userExtensionList" style="margin-top:10px;"></div>
</div>
Sources: index.html:1270-1281, renderer.js:1270-1273
Adding and Removing Extensions
The workflow for managing extensions is handled by functions in renderer.js and corresponding IPC handlers in main.js.
The following sequence diagram shows the process of adding a new extension:
IPC Handlers
The following table summarizes the IPC channels used for extension management.
| IPC Channel | Direction | Description | Source File |
|---|---|---|---|
select-extension-folder | Renderer -> Main | Opens a native dialog for the user to select an extension directory. | main.js:315-322 |
add-user-extension | Renderer -> Main | Adds a given extension path to settings.json. | main.js:323-331 |
remove-user-extension | Renderer -> Main | Removes a given extension path from settings.json. | main.js:332-341 |
get-user-extensions | Renderer -> Main | Retrieves the list of all user extension paths from settings.json. | main.js:342-347 |
Sources: main.js:315-347, renderer.js:1282-1301
Profile Launch Integration
When a user launches a profile, the launch-profile handler in main.js orchestrates the loading of all necessary extensions.
The process is as follows:
- Read the global
settings.jsonto get the list of user-defined extension paths. - Dynamically generate the
GeekEZ Guardextension for the current profile. - Combine the path of
GeekEZ Guardwith the list of user extension paths. - Construct the
--load-extensionand--disable-extensions-exceptChromium launch arguments with the combined list. - Launch the Puppeteer browser instance with these arguments.
This flow is visualized in the diagram below.
The following code snippet from main.js shows the final construction of the launch arguments.
// main.js:478-495
// 1. 生成 GeekEZ Guard 扩展
const extPath = await generateExtension(profileDir, profile.fingerprint);
// 2. 获取用户自定义扩展
const userExts = settings.userExtensions || [];
// 3. 合并所有扩展路径
let extPaths = extPath; // GeekEZ Guard
if (userExts.length > 0) {
extPaths += ',' + userExts.join(',');
}
// 4. 构建启动参数(性能优化)
const launchArgs = [
// ... other args
`--disable-extensions-except=${extPaths}`,
`--load-extension=${extPaths}`,
// ... other args
];
Sources: main.js:469-495
Summary
The extension management feature in GeekezBrowser is integral to its anti-detect capabilities and user customizability. It uses a mandatory, dynamically generated internal extension (GeekEZ Guard) to apply fingerprinting rules, ensuring core privacy protection is always active. Simultaneously, it provides a simple UI for users to add their own unpacked extensions, which are persisted globally and loaded into every browser profile. This entire process is seamlessly integrated into the profile launch sequence, using specific Chromium flags to ensure all extensions are loaded correctly within the isolated environment.
Sources: main.js, renderer.js, index.html