Upload files to "src"
This commit is contained in:
parent
1dc9787944
commit
d51a9eabe9
2 changed files with 165 additions and 159 deletions
|
|
@ -16,7 +16,10 @@ pub enum LinuxBackend {
|
|||
version
|
||||
)]
|
||||
pub struct Cli {
|
||||
#[arg(long, help = "Optional startup URL (defaults to https://duckduckgo.com)")]
|
||||
#[arg(
|
||||
long,
|
||||
help = "Optional startup URL (defaults to https://duckduckgo.com)"
|
||||
)]
|
||||
pub url: Option<String>,
|
||||
|
||||
#[arg(long, help = "Set a custom window title")]
|
||||
|
|
@ -32,7 +35,7 @@ pub struct Cli {
|
|||
long,
|
||||
value_enum,
|
||||
default_value_t = LinuxBackend::Auto,
|
||||
help = "Linux only: prefer a windowing backend (auto, x11, wayland)"
|
||||
help = "Linux only: select a GTK windowing backend (auto, x11, wayland)"
|
||||
)]
|
||||
pub linux_backend: LinuxBackend,
|
||||
|
||||
|
|
|
|||
317
src/webview.rs
317
src/webview.rs
|
|
@ -2,6 +2,8 @@
|
|||
use crate::cli::Cli;
|
||||
use anyhow::{Result, anyhow};
|
||||
use base64::Engine;
|
||||
#[cfg(target_os = "linux")]
|
||||
use gtk::prelude::*;
|
||||
use serde_json::json;
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
|
|
@ -9,13 +11,11 @@ use std::path::{Path, PathBuf};
|
|||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
#[cfg(target_os = "linux")]
|
||||
use gtk::prelude::*;
|
||||
#[cfg(target_os = "linux")]
|
||||
use tao::platform::unix::WindowExtUnix;
|
||||
use tao::dpi::LogicalSize;
|
||||
use tao::event::{Event, WindowEvent};
|
||||
use tao::event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy};
|
||||
#[cfg(target_os = "linux")]
|
||||
use tao::platform::unix::WindowExtUnix;
|
||||
use tao::window::{Icon, Window, WindowBuilder};
|
||||
#[cfg(target_os = "linux")]
|
||||
use wry::WebViewBuilderExtUnix;
|
||||
|
|
@ -38,13 +38,31 @@ const MAX_TAB_NAV_ENTRIES: usize = 100;
|
|||
#[derive(Debug)]
|
||||
enum UserEvent {
|
||||
ChromeIpc(String),
|
||||
TitleChanged { tab_id: u32, title: String },
|
||||
PageLoaded { tab_id: u32, url: String },
|
||||
DownloadStarted { url: String, file_path: String },
|
||||
DownloadTotal { file_path: String, total_bytes: Option<u64> },
|
||||
TitleChanged {
|
||||
tab_id: u32,
|
||||
title: String,
|
||||
},
|
||||
PageLoaded {
|
||||
tab_id: u32,
|
||||
url: String,
|
||||
},
|
||||
DownloadStarted {
|
||||
url: String,
|
||||
file_path: String,
|
||||
},
|
||||
DownloadTotal {
|
||||
file_path: String,
|
||||
total_bytes: Option<u64>,
|
||||
},
|
||||
DownloadTick,
|
||||
DownloadCompleted { url: String, file_path: Option<String>, success: bool },
|
||||
OpenInNewTab { url: String },
|
||||
DownloadCompleted {
|
||||
url: String,
|
||||
file_path: Option<String>,
|
||||
success: bool,
|
||||
},
|
||||
OpenInNewTab {
|
||||
url: String,
|
||||
},
|
||||
Quit,
|
||||
}
|
||||
|
||||
|
|
@ -713,7 +731,10 @@ pub fn launch_webkit(args: &Cli) -> Result<()> {
|
|||
.as_deref()
|
||||
.map(normalize_url)
|
||||
.unwrap_or_else(|| DEFAULT_HOME.to_string());
|
||||
let title = args.title.clone().unwrap_or_else(|| "RustyWolf".to_string());
|
||||
let title = args
|
||||
.title
|
||||
.clone()
|
||||
.unwrap_or_else(|| "RustyWolf".to_string());
|
||||
|
||||
if args.dry_run {
|
||||
println!(
|
||||
|
|
@ -773,10 +794,12 @@ pub fn launch_webkit(args: &Cli) -> Result<()> {
|
|||
open_tab(&mut state, &window, &proxy, start_url)?;
|
||||
|
||||
let tick_proxy = proxy.clone();
|
||||
thread::spawn(move || loop {
|
||||
thread::sleep(Duration::from_millis(300));
|
||||
if tick_proxy.send_event(UserEvent::DownloadTick).is_err() {
|
||||
break;
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
thread::sleep(Duration::from_millis(300));
|
||||
if tick_proxy.send_event(UserEvent::DownloadTick).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -790,10 +813,16 @@ pub fn launch_webkit(args: &Cli) -> Result<()> {
|
|||
eprintln!("event error: {e:#}");
|
||||
}
|
||||
}
|
||||
Event::WindowEvent { event: WindowEvent::Resized(_size), .. } => {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::Resized(_size),
|
||||
..
|
||||
} => {
|
||||
reflow_layout(&window, &state);
|
||||
}
|
||||
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -808,18 +837,14 @@ fn apply_linux_runtime_overrides(_args: &Cli) {
|
|||
|
||||
match _args.linux_backend {
|
||||
crate::cli::LinuxBackend::Auto => {}
|
||||
crate::cli::LinuxBackend::X11 => {
|
||||
unsafe {
|
||||
std::env::set_var("WINIT_UNIX_BACKEND", "x11");
|
||||
std::env::set_var("GDK_BACKEND", "x11");
|
||||
}
|
||||
}
|
||||
crate::cli::LinuxBackend::Wayland => {
|
||||
unsafe {
|
||||
std::env::set_var("WINIT_UNIX_BACKEND", "wayland");
|
||||
std::env::set_var("GDK_BACKEND", "wayland");
|
||||
}
|
||||
}
|
||||
crate::cli::LinuxBackend::X11 => unsafe {
|
||||
std::env::set_var("WINIT_UNIX_BACKEND", "x11");
|
||||
std::env::set_var("GDK_BACKEND", "x11");
|
||||
},
|
||||
crate::cli::LinuxBackend::Wayland => unsafe {
|
||||
std::env::set_var("WINIT_UNIX_BACKEND", "wayland");
|
||||
std::env::set_var("GDK_BACKEND", "wayland");
|
||||
},
|
||||
}
|
||||
|
||||
if _args.linux_disable_dmabuf {
|
||||
|
|
@ -844,7 +869,9 @@ fn sanitize_gtk_modules_env() {
|
|||
match std::env::var(name) {
|
||||
Ok(raw) => {
|
||||
let mut kept = Vec::new();
|
||||
for token in raw.split(|c: char| c == ':' || c == ';' || c == ',' || c.is_ascii_whitespace()) {
|
||||
for token in
|
||||
raw.split(|c: char| c == ':' || c == ';' || c == ',' || c.is_ascii_whitespace())
|
||||
{
|
||||
let trimmed = token.trim();
|
||||
if trimmed.is_empty() || is_appmenu_module(trimmed) {
|
||||
continue;
|
||||
|
|
@ -882,27 +909,8 @@ fn sanitize_gtk_modules_env() {
|
|||
fn resolve_webview_host_mode(args: &Cli) -> WebViewHostMode {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
return match args.linux_backend {
|
||||
crate::cli::LinuxBackend::X11 => WebViewHostMode::Child,
|
||||
crate::cli::LinuxBackend::Wayland => WebViewHostMode::Window,
|
||||
crate::cli::LinuxBackend::Auto => {
|
||||
let forced = std::env::var("WINIT_UNIX_BACKEND").ok();
|
||||
if forced.as_deref() == Some("x11") {
|
||||
return WebViewHostMode::Child;
|
||||
}
|
||||
if forced.as_deref() == Some("wayland") {
|
||||
return WebViewHostMode::Window;
|
||||
}
|
||||
|
||||
let session_type = std::env::var("XDG_SESSION_TYPE").unwrap_or_default();
|
||||
let has_wayland_display = std::env::var_os("WAYLAND_DISPLAY").is_some();
|
||||
if session_type.eq_ignore_ascii_case("wayland") || has_wayland_display {
|
||||
WebViewHostMode::Window
|
||||
} else {
|
||||
WebViewHostMode::Child
|
||||
}
|
||||
}
|
||||
};
|
||||
let _ = args;
|
||||
WebViewHostMode::Window
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
@ -956,7 +964,11 @@ fn handle_event(
|
|||
state.tabs[i].url.clone(),
|
||||
);
|
||||
}
|
||||
let enabled = if state.adblock_enabled { "true" } else { "false" };
|
||||
let enabled = if state.adblock_enabled {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
};
|
||||
if let Some(webview) = state.tabs[i].webview.as_ref() {
|
||||
let _ = webview.evaluate_script(&format!(
|
||||
"window.__rustywolfSetAdblockEnabled && window.__rustywolfSetAdblockEnabled({enabled});"
|
||||
|
|
@ -979,7 +991,10 @@ fn handle_event(
|
|||
trim_downloads(state);
|
||||
push_downloads(state);
|
||||
}
|
||||
UserEvent::DownloadTotal { file_path, total_bytes } => {
|
||||
UserEvent::DownloadTotal {
|
||||
file_path,
|
||||
total_bytes,
|
||||
} => {
|
||||
if let Some(entry) = state
|
||||
.downloads
|
||||
.iter_mut()
|
||||
|
|
@ -1005,7 +1020,11 @@ fn handle_event(
|
|||
push_downloads(state);
|
||||
}
|
||||
}
|
||||
UserEvent::DownloadCompleted { url, file_path, success } => {
|
||||
UserEvent::DownloadCompleted {
|
||||
url,
|
||||
file_path,
|
||||
success,
|
||||
} => {
|
||||
let path = file_path.unwrap_or_else(|| "Unknown destination".to_string());
|
||||
if let Some(entry) = state
|
||||
.downloads
|
||||
|
|
@ -1262,25 +1281,15 @@ fn build_chrome(
|
|||
WebViewHostMode::Window => {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if let Some(container) = gtk_chrome_container {
|
||||
match builder().build_gtk(container) {
|
||||
Ok(webview) => return Ok((webview, WebViewHostMode::Window)),
|
||||
Err(gtk_err) => {
|
||||
return builder()
|
||||
.build(window)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|fallback_err| {
|
||||
anyhow!(
|
||||
"Failed to create chrome webview: gtk hosting failed ({gtk_err}); window fallback failed ({fallback_err})"
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder()
|
||||
.build(window)
|
||||
let container = gtk_chrome_container.ok_or_else(|| {
|
||||
anyhow!("Failed to create chrome webview: missing Linux GTK chrome container")
|
||||
})?;
|
||||
builder()
|
||||
.build_gtk(container)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|err| anyhow!("Failed to create chrome webview: {err}"));
|
||||
.map_err(|err| {
|
||||
anyhow!("Failed to create chrome webview with GTK hosting: {err}")
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
@ -1302,28 +1311,18 @@ fn build_chrome(
|
|||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if let Some(container) = gtk_chrome_container {
|
||||
match builder().build_gtk(container) {
|
||||
Ok(webview) => return Ok((webview, WebViewHostMode::Window)),
|
||||
Err(gtk_err) => {
|
||||
return builder()
|
||||
.build(window)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|fallback_err| {
|
||||
anyhow!(
|
||||
"Failed to create chrome webview: child failed ({err_text}); gtk fallback failed ({gtk_err}); window fallback failed ({fallback_err})"
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
return builder()
|
||||
.build_gtk(container)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|gtk_err| {
|
||||
anyhow!(
|
||||
"Failed to create chrome webview: child failed ({err_text}); GTK fallback failed ({gtk_err})"
|
||||
)
|
||||
});
|
||||
}
|
||||
return builder()
|
||||
.build(window)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|fallback_err| {
|
||||
anyhow!(
|
||||
"Failed to create chrome webview: child failed ({err_text}); window fallback failed ({fallback_err})"
|
||||
)
|
||||
});
|
||||
return Err(anyhow!(
|
||||
"Failed to create chrome webview: child failed ({err_text}); missing Linux GTK chrome container"
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
@ -1405,7 +1404,11 @@ fn build_tab_webview(
|
|||
}
|
||||
*destination = path.clone();
|
||||
let path_string = path_to_string(&path);
|
||||
fetch_download_total(url.clone(), path_string.clone(), download_total_proxy.clone());
|
||||
fetch_download_total(
|
||||
url.clone(),
|
||||
path_string.clone(),
|
||||
download_total_proxy.clone(),
|
||||
);
|
||||
let _ = download_started_proxy.send_event(UserEvent::DownloadStarted {
|
||||
url,
|
||||
file_path: path_string,
|
||||
|
|
@ -1425,25 +1428,13 @@ fn build_tab_webview(
|
|||
WebViewHostMode::Window => {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if let Some(container) = gtk_content_container {
|
||||
match builder().build_gtk(container) {
|
||||
Ok(webview) => return Ok((webview, WebViewHostMode::Window)),
|
||||
Err(gtk_err) => {
|
||||
return builder()
|
||||
.build(window)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|fallback_err| {
|
||||
anyhow!(
|
||||
"Failed to create tab webview: gtk hosting failed ({gtk_err}); window fallback failed ({fallback_err})"
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder()
|
||||
.build(window)
|
||||
let container = gtk_content_container.ok_or_else(|| {
|
||||
anyhow!("Failed to create tab webview: missing Linux GTK content container")
|
||||
})?;
|
||||
builder()
|
||||
.build_gtk(container)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|err| anyhow!("Failed to create tab webview: {err}"));
|
||||
.map_err(|err| anyhow!("Failed to create tab webview with GTK hosting: {err}"))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
@ -1465,28 +1456,18 @@ fn build_tab_webview(
|
|||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
if let Some(container) = gtk_content_container {
|
||||
match builder().build_gtk(container) {
|
||||
Ok(webview) => return Ok((webview, WebViewHostMode::Window)),
|
||||
Err(gtk_err) => {
|
||||
return builder()
|
||||
.build(window)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|fallback_err| {
|
||||
anyhow!(
|
||||
"Failed to create tab webview: child failed ({err_text}); gtk fallback failed ({gtk_err}); window fallback failed ({fallback_err})"
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
return builder()
|
||||
.build_gtk(container)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|gtk_err| {
|
||||
anyhow!(
|
||||
"Failed to create tab webview: child failed ({err_text}); GTK fallback failed ({gtk_err})"
|
||||
)
|
||||
});
|
||||
}
|
||||
return builder()
|
||||
.build(window)
|
||||
.map(|webview| (webview, WebViewHostMode::Window))
|
||||
.map_err(|fallback_err| {
|
||||
anyhow!(
|
||||
"Failed to create tab webview: child failed ({err_text}); window fallback failed ({fallback_err})"
|
||||
)
|
||||
});
|
||||
return Err(anyhow!(
|
||||
"Failed to create tab webview: child failed ({err_text}); missing Linux GTK content container"
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
@ -1580,7 +1561,9 @@ fn close_tab(
|
|||
proxy: &EventLoopProxy<UserEvent>,
|
||||
tab_id: u32,
|
||||
) -> Result<bool> {
|
||||
let Some(index) = state.find_index(tab_id) else { return Ok(false); };
|
||||
let Some(index) = state.find_index(tab_id) else {
|
||||
return Ok(false);
|
||||
};
|
||||
state.tabs.remove(index);
|
||||
|
||||
if state.tabs.is_empty() {
|
||||
|
|
@ -1669,7 +1652,9 @@ fn apply_visibility(state: &BrowserState) {
|
|||
}
|
||||
|
||||
fn push_tabs(state: &BrowserState) {
|
||||
if state.tabs.is_empty() { return; }
|
||||
if state.tabs.is_empty() {
|
||||
return;
|
||||
}
|
||||
let payload = json!({
|
||||
"tabs": state.tabs.iter().map(|t| json!({
|
||||
"id": t.id,
|
||||
|
|
@ -1705,15 +1690,19 @@ fn push_downloads(state: &BrowserState) {
|
|||
.collect::<Vec<_>>(),
|
||||
})
|
||||
.to_string();
|
||||
let script = format!(
|
||||
"window.__rustywolfSetDownloads && window.__rustywolfSetDownloads({payload});"
|
||||
);
|
||||
let script =
|
||||
format!("window.__rustywolfSetDownloads && window.__rustywolfSetDownloads({payload});");
|
||||
let _ = state.chrome.evaluate_script(&script);
|
||||
}
|
||||
|
||||
fn push_adblock(state: &BrowserState) {
|
||||
let enabled = if state.adblock_enabled { "true" } else { "false" };
|
||||
let script = format!("window.__rustywolfSetAdblock && window.__rustywolfSetAdblock({enabled});");
|
||||
let enabled = if state.adblock_enabled {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
};
|
||||
let script =
|
||||
format!("window.__rustywolfSetAdblock && window.__rustywolfSetAdblock({enabled});");
|
||||
let _ = state.chrome.evaluate_script(&script);
|
||||
}
|
||||
|
||||
|
|
@ -1726,14 +1715,17 @@ fn push_popup_prompt(state: &BrowserState) {
|
|||
None => json!({ "visible": false }),
|
||||
}
|
||||
.to_string();
|
||||
let script = format!(
|
||||
"window.__rustywolfSetPopupPrompt && window.__rustywolfSetPopupPrompt({payload});"
|
||||
);
|
||||
let script =
|
||||
format!("window.__rustywolfSetPopupPrompt && window.__rustywolfSetPopupPrompt({payload});");
|
||||
let _ = state.chrome.evaluate_script(&script);
|
||||
}
|
||||
|
||||
fn apply_adblock_setting_to_tabs(state: &BrowserState) {
|
||||
let enabled = if state.adblock_enabled { "true" } else { "false" };
|
||||
let enabled = if state.adblock_enabled {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
};
|
||||
let script = format!(
|
||||
"window.__rustywolfSetAdblockEnabled && window.__rustywolfSetAdblockEnabled({enabled});"
|
||||
);
|
||||
|
|
@ -1860,7 +1852,9 @@ fn chrome_height(state: &BrowserState) -> f64 {
|
|||
|
||||
fn normalize_url(input: &str) -> String {
|
||||
let trimmed = input.trim();
|
||||
if trimmed == "about:blank" { return trimmed.to_string(); }
|
||||
if trimmed == "about:blank" {
|
||||
return trimmed.to_string();
|
||||
}
|
||||
if trimmed.starts_with("http://") || trimmed.starts_with("https://") {
|
||||
return trimmed.to_string();
|
||||
}
|
||||
|
|
@ -1963,8 +1957,7 @@ fn render_properties_html(state: &BrowserState) -> String {
|
|||
<body><h1>Browser Properties</h1><p class=\"muted\">Session history and download activity.</p>\
|
||||
<h2>Browsing History</h2><p class=\"muted\">{}</p><table><thead><tr><th>Visited</th><th>Title</th><th>URL</th></tr></thead><tbody>{history_rows}</tbody></table>\
|
||||
<h2>Download History</h2><p class=\"muted\">{}</p><table><thead><tr><th>Updated</th><th>Status</th><th>Saved To</th><th>Source URL</th></tr></thead><tbody>{download_rows}</tbody></table>\
|
||||
</body></html>"
|
||||
,
|
||||
</body></html>",
|
||||
if history_is_truncated {
|
||||
format!("Showing latest {PROPERTIES_MAX_ROWS} entries.")
|
||||
} else {
|
||||
|
|
@ -2105,8 +2098,8 @@ fn path_string_to_file_url(path: &str) -> String {
|
|||
fn sanitize_filename(raw: &str) -> String {
|
||||
let mut out = String::with_capacity(raw.len());
|
||||
for ch in raw.chars() {
|
||||
let invalid = matches!(ch, '<' | '>' | ':' | '"' | '/' | '\\' | '|' | '?' | '*')
|
||||
|| ch.is_control();
|
||||
let invalid =
|
||||
matches!(ch, '<' | '>' | ':' | '"' | '/' | '\\' | '|' | '?' | '*') || ch.is_control();
|
||||
out.push(if invalid { '_' } else { ch });
|
||||
}
|
||||
let trimmed = out.trim_matches('.').trim();
|
||||
|
|
@ -2119,10 +2112,10 @@ fn sanitize_filename(raw: &str) -> String {
|
|||
|
||||
fn fetch_download_total(url: String, file_path: String, proxy: EventLoopProxy<UserEvent>) {
|
||||
thread::spawn(move || {
|
||||
let total_bytes = ureq::head(&url)
|
||||
.call()
|
||||
.ok()
|
||||
.and_then(|resp| resp.header("Content-Length").and_then(|v| v.parse::<u64>().ok()));
|
||||
let total_bytes = ureq::head(&url).call().ok().and_then(|resp| {
|
||||
resp.header("Content-Length")
|
||||
.and_then(|v| v.parse::<u64>().ok())
|
||||
});
|
||||
let _ = proxy.send_event(UserEvent::DownloadTotal {
|
||||
file_path,
|
||||
total_bytes,
|
||||
|
|
@ -2162,7 +2155,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn converts_search_terms_to_duckduckgo_query() {
|
||||
assert_eq!(normalize_url("privacy browser"), "https://duckduckgo.com/?q=privacy+browser");
|
||||
assert_eq!(
|
||||
normalize_url("privacy browser"),
|
||||
"https://duckduckgo.com/?q=privacy+browser"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2172,7 +2168,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn trims_before_search() {
|
||||
assert_eq!(normalize_url(" rust webview "), "https://duckduckgo.com/?q=rust+webview");
|
||||
assert_eq!(
|
||||
normalize_url(" rust webview "),
|
||||
"https://duckduckgo.com/?q=rust+webview"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2183,9 +2182,13 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn blocks_duckduckgo_internal_popup_paths() {
|
||||
assert!(!should_open_new_tab_url("https://duckduckgo.com/post3.html"));
|
||||
assert!(!should_open_new_tab_url(
|
||||
"https://duckduckgo.com/post3.html"
|
||||
));
|
||||
assert!(!should_open_new_tab_url("https://duckduckgo.com/page3"));
|
||||
assert!(!should_open_new_tab_url("https://duckduckgo.com/page3.html"));
|
||||
assert!(!should_open_new_tab_url(
|
||||
"https://duckduckgo.com/page3.html"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue