mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-07-25 13:50:51 +02:00
refactor: ensure that camoufox profile always launch with persistent state
This commit is contained in:
@@ -123,11 +123,16 @@ export async function startCamoufoxProcess(
|
|||||||
// Generate a unique ID for this instance
|
// Generate a unique ID for this instance
|
||||||
const id = generateCamoufoxId();
|
const id = generateCamoufoxId();
|
||||||
|
|
||||||
|
// Ensure profile path is absolute if provided
|
||||||
|
const absoluteProfilePath = profilePath
|
||||||
|
? path.resolve(profilePath)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
// Create the Camoufox configuration
|
// Create the Camoufox configuration
|
||||||
const config: CamoufoxConfig = {
|
const config: CamoufoxConfig = {
|
||||||
id,
|
id,
|
||||||
options,
|
options: JSON.parse(JSON.stringify(options)), // Deep clone to avoid reference sharing
|
||||||
profilePath,
|
profilePath: absoluteProfilePath,
|
||||||
url,
|
url,
|
||||||
customConfig,
|
customConfig,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ export function listCamoufoxConfigs(): CamoufoxConfig[] {
|
|||||||
.filter((config): config is CamoufoxConfig => config !== null)
|
.filter((config): config is CamoufoxConfig => config !== null)
|
||||||
.map((config) => {
|
.map((config) => {
|
||||||
config.options = "Removed for logging" as any;
|
config.options = "Removed for logging" as any;
|
||||||
|
config.customConfig = "Removed for logging" as any;
|
||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -147,5 +148,6 @@ export function updateCamoufoxConfig(config: CamoufoxConfig): boolean {
|
|||||||
* @returns A unique ID string
|
* @returns A unique ID string
|
||||||
*/
|
*/
|
||||||
export function generateCamoufoxId(): string {
|
export function generateCamoufoxId(): string {
|
||||||
return `camoufox_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
|
// Include process ID to ensure uniqueness across multiple processes
|
||||||
|
return `camoufox_${Date.now()}_${process.pid}_${Math.floor(Math.random() * 10000)}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,14 +74,17 @@ export async function runCamoufoxWorker(id: string): Promise<void> {
|
|||||||
process.on("unhandledRejection", () => void gracefulShutdown());
|
process.on("unhandledRejection", () => void gracefulShutdown());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Prepare options for Camoufox
|
// Deep clone to avoid reference sharing and ensure fresh configuration for each instance
|
||||||
const camoufoxOptions: LaunchOptions = { ...config.options };
|
const camoufoxOptions: LaunchOptions = JSON.parse(
|
||||||
|
JSON.stringify(config.options || {}),
|
||||||
|
);
|
||||||
|
|
||||||
// Add profile path if provided
|
// Add profile path if provided
|
||||||
if (config.profilePath) {
|
if (config.profilePath) {
|
||||||
camoufoxOptions.user_data_dir = config.profilePath;
|
camoufoxOptions.user_data_dir = config.profilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure block options are properly set
|
||||||
if (camoufoxOptions.block_images) {
|
if (camoufoxOptions.block_images) {
|
||||||
camoufoxOptions.block_images = true;
|
camoufoxOptions.block_images = true;
|
||||||
}
|
}
|
||||||
@@ -99,7 +102,7 @@ export async function runCamoufoxWorker(id: string): Promise<void> {
|
|||||||
camoufoxOptions.headless = true;
|
camoufoxOptions.headless = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always set these defaults
|
// Always set these defaults - ensure they are applied for each instance
|
||||||
camoufoxOptions.i_know_what_im_doing = true;
|
camoufoxOptions.i_know_what_im_doing = true;
|
||||||
camoufoxOptions.config = {
|
camoufoxOptions.config = {
|
||||||
disableTheming: true,
|
disableTheming: true,
|
||||||
@@ -107,12 +110,18 @@ export async function runCamoufoxWorker(id: string): Promise<void> {
|
|||||||
...(camoufoxOptions.config || {}),
|
...(camoufoxOptions.config || {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate the configuration using launchOptions
|
// Generate fresh options for this specific instance
|
||||||
const generatedOptions = await launchOptions(camoufoxOptions);
|
const generatedOptions = await launchOptions(camoufoxOptions);
|
||||||
|
|
||||||
// If we have a custom config from Rust, use it directly as environment variables
|
// Start with process environment to ensure proper inheritance
|
||||||
let finalEnv = generatedOptions.env || {};
|
let finalEnv = { ...process.env };
|
||||||
|
|
||||||
|
// Add generated options environment variables
|
||||||
|
if (generatedOptions.env) {
|
||||||
|
finalEnv = { ...finalEnv, ...generatedOptions.env };
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a custom config from Rust, use it directly as environment variables
|
||||||
if (config.customConfig) {
|
if (config.customConfig) {
|
||||||
try {
|
try {
|
||||||
// Parse the custom config JSON string
|
// Parse the custom config JSON string
|
||||||
@@ -125,16 +134,16 @@ export async function runCamoufoxWorker(id: string): Promise<void> {
|
|||||||
finalEnv = { ...finalEnv, ...customEnvVars };
|
finalEnv = { ...finalEnv, ...customEnvVars };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
console.error(
|
||||||
"Failed to parse custom config, using generated config:",
|
`Camoufox worker ${id}: Failed to parse custom config, using generated config:`,
|
||||||
error,
|
error,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Launch the server with the final configuration - ensure unique wsPath for each instance
|
||||||
// Launch the server with the final configuration
|
|
||||||
const finalOptions: any = {
|
const finalOptions: any = {
|
||||||
...generatedOptions,
|
...generatedOptions,
|
||||||
|
user_data_dir: config.profilePath,
|
||||||
wsPath: `/ws_${config.id}`,
|
wsPath: `/ws_${config.id}`,
|
||||||
env: finalEnv,
|
env: finalEnv,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ const OS_NAME: "mac" | "win" | "lin" = OS_MAP[process.platform];
|
|||||||
|
|
||||||
export function getEnvVars(configMap: Record<string, string>) {
|
export function getEnvVars(configMap: Record<string, string>) {
|
||||||
const envVars: {
|
const envVars: {
|
||||||
[key: string]: string | number | boolean;
|
[key: string]: string | undefined;
|
||||||
} = {};
|
} = {};
|
||||||
let updatedConfigData: Uint8Array;
|
let updatedConfigData: Uint8Array;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
updatedConfigData = new TextEncoder().encode(JSON.stringify(configMap));
|
// Ensure we're working with a fresh copy of the config
|
||||||
|
const configCopy = JSON.parse(JSON.stringify(configMap));
|
||||||
|
updatedConfigData = new TextEncoder().encode(JSON.stringify(configCopy));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Error updating config: ${e}`);
|
console.error(`Error updating config: ${e}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
@@ -212,8 +212,13 @@ impl CamoufoxNodecarLauncher {
|
|||||||
// Build nodecar command arguments
|
// Build nodecar command arguments
|
||||||
let mut args = vec!["camoufox".to_string(), "start".to_string()];
|
let mut args = vec!["camoufox".to_string(), "start".to_string()];
|
||||||
|
|
||||||
// Add profile path
|
// Add profile path - ensure it's an absolute path
|
||||||
args.extend(["--profile-path".to_string(), profile_path.to_string()]);
|
let absolute_profile_path = std::path::Path::new(profile_path)
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap_or_else(|_| std::path::Path::new(profile_path).to_path_buf())
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string();
|
||||||
|
args.extend(["--profile-path".to_string(), absolute_profile_path]);
|
||||||
|
|
||||||
// Add URL if provided
|
// Add URL if provided
|
||||||
if let Some(url) = url {
|
if let Some(url) = url {
|
||||||
|
|||||||
Reference in New Issue
Block a user