From 34047f8da8e191324121023c7cb040a120e2a523 Mon Sep 17 00:00:00 2001 From: Kafji Date: Mon, 10 Mar 2025 10:24:48 +0700 Subject: [PATCH] Allow domain-like as URL location input (#35756) * Allow domain-like as URL location input Before this patch, domain with subdomain (e.g. book.servo.org) won't be treated as URL location. This patch retifies that by adding Firefox's location bar behavior: - book.servo.org is URL location - book.servo.org. is URL location - .book.servo.org is not URL location Fixes #35754. Signed-off-by: Kafji * Chain location input interpretation attempts Signed-off-by: Kafji --------- Signed-off-by: Kafji --- ports/servoshell/parser.rs | 40 ++++++++++++++++++------ ports/servoshell/test.rs | 63 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 9 deletions(-) diff --git a/ports/servoshell/parser.rs b/ports/servoshell/parser.rs index d52fc64bead..f28c6698463 100644 --- a/ports/servoshell/parser.rs +++ b/ports/servoshell/parser.rs @@ -63,13 +63,35 @@ pub fn get_default_url( /// interpret the string as a search term. pub(crate) fn location_bar_input_to_url(request: &str, searchpage: &str) -> Option { let request = request.trim(); - ServoUrl::parse(request).ok().or_else(|| { - if request.starts_with('/') { - ServoUrl::parse(&format!("file://{}", request)).ok() - } else if request.contains('/') || is_reg_domain(request) { - ServoUrl::parse(&format!("https://{}", request)).ok() - } else { - ServoUrl::parse(&searchpage.replace("%s", request)).ok() - } - }) + ServoUrl::parse(request) + .ok() + .or_else(|| try_as_file(request)) + .or_else(|| try_as_domain(request)) + .or_else(|| try_as_search_page(request, searchpage)) +} + +fn try_as_file(request: &str) -> Option { + if request.starts_with('/') { + return ServoUrl::parse(&format!("file://{}", request)).ok(); + } + None +} + +fn try_as_domain(request: &str) -> Option { + fn is_domain_like(s: &str) -> bool { + !s.starts_with('/') && s.contains('/') || + (!s.contains(' ') && !s.starts_with('.') && s.split('.').count() > 1) + } + + if !request.contains(' ') && is_reg_domain(request) || is_domain_like(request) { + return ServoUrl::parse(&format!("https://{}", request)).ok(); + } + None +} + +fn try_as_search_page(request: &str, searchpage: &str) -> Option { + if request.is_empty() { + return None; + } + ServoUrl::parse(&searchpage.replace("%s", request)).ok() } diff --git a/ports/servoshell/test.rs b/ports/servoshell/test.rs index 0ff470f8b90..0ffb149905d 100644 --- a/ports/servoshell/test.rs +++ b/ports/servoshell/test.rs @@ -220,3 +220,66 @@ fn test_cmd_and_location_bar_url() { "file:///dev/null", ); } + +/// Like [test_url] but will produce test for Windows or non Windows using `#[cfg(target_os)]` internally. +fn test_url_any_os( + input: &str, + location: &str, + #[allow(unused)] if_exists: &str, + #[allow(unused)] if_exists_windows: &str, + otherwise: &str, +) { + #[cfg(not(target_os = "windows"))] + test_url(input, location, if_exists, otherwise); + + #[cfg(target_os = "windows")] + test_url(input, location, if_exists_windows, otherwise); +} + +// https://github.com/servo/servo/issues/35754 +#[test] +fn test_issue_35754() { + test_url_any_os( + "leah.chromebooks.lol", + "https://leah.chromebooks.lol/", + "file:///fake/cwd/leah.chromebooks.lol", + "file:///C:/fake/cwd/leah.chromebooks.lol", + "https://leah.chromebooks.lol/", + ); + + // ends with dot + test_url_any_os( + "leah.chromebooks.lol.", + "https://leah.chromebooks.lol./", + "file:///fake/cwd/leah.chromebooks.lol.", + "file:///C:/fake/cwd/leah.chromebooks.lol.", + "https://leah.chromebooks.lol./", + ); + + // starts with dot + test_url_any_os( + ".leah.chromebooks.lol", + "https://duckduckgo.com/html/?q=.leah.chromebooks.lol", + "file:///fake/cwd/.leah.chromebooks.lol", + "file:///C:/fake/cwd/.leah.chromebooks.lol", + "https://duckduckgo.com/html/?q=.leah.chromebooks.lol", + ); + + // contains spaces + test_url_any_os( + "3.5 kg in lb", + "https://duckduckgo.com/html/?q=3.5%20kg%20in%20lb", + "file:///fake/cwd/3.5%20kg%20in%20lb", + "file:///C:/fake/cwd/3.5%20kg%20in%20lb", + "https://duckduckgo.com/html/?q=3.5%20kg%20in%20lb", + ); + + // user-local domain + test_url_any_os( + "foo/bar", + "https://foo/bar", + "file:///fake/cwd/foo/bar", + "file:///C:/fake/cwd/foo/bar", + "https://foo/bar", + ); +}