diff --git a/next-env.d.ts b/next-env.d.ts
index 9edff1c..b87975d 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-import "./.next/types/routes.d.ts";
+import "./dist/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/package.json b/package.json
index e7e2f22..67c5466 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "donutbrowser",
"private": true,
"license": "AGPL-3.0",
- "version": "0.14.5",
+ "version": "0.14.6",
"type": "module",
"scripts": {
"dev": "next dev --turbopack -p 12341",
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index ed779d1..1b882b1 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -795,15 +795,6 @@ dependencies = [
"bzip2-sys",
]
-[[package]]
-name = "bzip2"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c"
-dependencies = [
- "libbz2-rs-sys",
-]
-
[[package]]
name = "bzip2-sys"
version = "0.1.13+1.0.8"
@@ -1597,7 +1588,7 @@ dependencies = [
[[package]]
name = "donutbrowser"
-version = "0.14.5"
+version = "0.14.6"
dependencies = [
"aes-gcm",
"argon2",
@@ -1607,7 +1598,7 @@ dependencies = [
"base64 0.22.1",
"blake3",
"boringtun",
- "bzip2 0.6.1",
+ "bzip2",
"chrono",
"clap",
"core-foundation 0.10.1",
@@ -3350,12 +3341,6 @@ dependencies = [
"once_cell",
]
-[[package]]
-name = "libbz2-rs-sys"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7"
-
[[package]]
name = "libc"
version = "0.2.180"
@@ -8763,7 +8748,7 @@ checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50"
dependencies = [
"aes",
"arbitrary",
- "bzip2 0.5.2",
+ "bzip2",
"constant_time_eq 0.3.1",
"crc32fast",
"crossbeam-utils",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 5cd81b5..0f4fb24 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "donutbrowser"
-version = "0.14.5"
+version = "0.14.6"
description = "Simple Yet Powerful Anti-Detect Browser"
authors = ["zhom@github"]
edition = "2021"
diff --git a/src-tauri/src/browser_runner.rs b/src-tauri/src/browser_runner.rs
index daf1bce..c26dd4d 100644
--- a/src-tauri/src/browser_runner.rs
+++ b/src-tauri/src/browser_runner.rs
@@ -231,6 +231,14 @@ impl BrowserRunner {
);
}
+ // Ensure DuckDuckGo is set as default search engine for Camoufox
+ let mut browser_dir = self.get_binaries_dir();
+ browser_dir.push(&profile.browser);
+ browser_dir.push(&profile.version);
+ if let Err(e) = crate::downloader::configure_camoufox_search_engine(&browser_dir) {
+ log::warn!("Failed to configure Camoufox search engine: {e}");
+ }
+
// Launch Camoufox browser
log::info!("Launching Camoufox for profile: {}", profile.name);
let camoufox_result = self
diff --git a/src-tauri/src/downloader.rs b/src-tauri/src/downloader.rs
index feb53d8..a89edb5 100644
--- a/src-tauri/src/downloader.rs
+++ b/src-tauri/src/downloader.rs
@@ -438,57 +438,7 @@ impl Downloader {
&self,
browser_dir: &Path,
) -> Result<(), Box> {
- let policies_path = browser_dir.join("distribution").join("policies.json");
-
- if !policies_path.exists() {
- if let Some(parent) = policies_path.parent() {
- std::fs::create_dir_all(parent)?;
- }
- let policies = serde_json::json!({
- "policies": {
- "SearchEngines": {
- "Default": "DuckDuckGo"
- }
- }
- });
- std::fs::write(&policies_path, serde_json::to_string_pretty(&policies)?)?;
- log::info!("Created policies.json with DuckDuckGo as default search engine");
- return Ok(());
- }
-
- let content = std::fs::read_to_string(&policies_path)?;
- let mut policies: serde_json::Value = serde_json::from_str(&content)?;
-
- let current_default = policies
- .get("policies")
- .and_then(|p| p.get("SearchEngines"))
- .and_then(|se| se.get("Default"))
- .and_then(|d| d.as_str())
- .unwrap_or("");
-
- if current_default != "None" {
- log::info!(
- "Camoufox search engine already configured to '{}', not overwriting",
- current_default
- );
- return Ok(());
- }
-
- if let Some(policies_obj) = policies.get_mut("policies") {
- if let Some(se) = policies_obj.get_mut("SearchEngines") {
- se["Default"] = serde_json::json!("DuckDuckGo");
-
- if let Some(remove_arr) = se.get_mut("Remove").and_then(|r| r.as_array_mut()) {
- remove_arr.retain(|v| v.as_str() != Some("DuckDuckGo"));
- }
- }
- }
-
- let updated = serde_json::to_string_pretty(&policies)?;
- std::fs::write(&policies_path, updated)?;
-
- log::info!("Updated Camoufox search engine from 'None' to DuckDuckGo");
- Ok(())
+ configure_camoufox_search_engine(browser_dir)
}
pub async fn download_browser(
@@ -1097,6 +1047,71 @@ pub async fn cancel_download(browser_str: String, version: String) -> Result<(),
}
}
+/// Clean up the fake "None" search engine from Camoufox policies.json so that
+/// Camoufox's built-in fallback (DuckDuckGo when nothing else is configured) can work.
+/// Called both at download time and at launch time to cover existing installations.
+pub fn configure_camoufox_search_engine(
+ browser_dir: &Path,
+) -> Result<(), Box> {
+ let policies_path = browser_dir.join("distribution").join("policies.json");
+
+ if !policies_path.exists() {
+ return Ok(());
+ }
+
+ let content = std::fs::read_to_string(&policies_path)?;
+ let mut policies: serde_json::Value = serde_json::from_str(&content)?;
+
+ let current_default = policies
+ .get("policies")
+ .and_then(|p| p.get("SearchEngines"))
+ .and_then(|se| se.get("Default"))
+ .and_then(|d| d.as_str())
+ .unwrap_or("");
+
+ if current_default != "None" {
+ return Ok(());
+ }
+
+ let mut changed = false;
+
+ if let Some(policies_obj) = policies.get_mut("policies") {
+ if let Some(se) = policies_obj.get_mut("SearchEngines") {
+ // Remove the fake "None" default so Camoufox uses its built-in fallback
+ if let Some(obj) = se.as_object_mut() {
+ obj.remove("Default");
+ changed = true;
+ }
+
+ // Remove the fake "None" search engine entry from Add
+ if let Some(add_arr) = se.get_mut("Add").and_then(|a| a.as_array_mut()) {
+ let before = add_arr.len();
+ add_arr.retain(|entry| entry.get("Name").and_then(|n| n.as_str()) != Some("None"));
+ if add_arr.len() != before {
+ changed = true;
+ }
+ }
+
+ // Ensure DuckDuckGo is not in the Remove list so it's available as fallback
+ if let Some(remove_arr) = se.get_mut("Remove").and_then(|r| r.as_array_mut()) {
+ let before = remove_arr.len();
+ remove_arr.retain(|v| v.as_str() != Some("DuckDuckGo"));
+ if remove_arr.len() != before {
+ changed = true;
+ }
+ }
+ }
+ }
+
+ if changed {
+ let updated = serde_json::to_string_pretty(&policies)?;
+ std::fs::write(&policies_path, updated)?;
+ log::info!("Cleaned up fake 'None' search engine from Camoufox policies.json");
+ }
+
+ Ok(())
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index 3872a23..23a457a 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Donut",
- "version": "0.14.5",
+ "version": "0.14.6",
"identifier": "com.donutbrowser",
"build": {
"beforeDevCommand": "pnpm copy-proxy-binary && pnpm dev",