mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 01:20:25 +00:00
5f8d852dae
Currently, if we want to add a new e.g. WebContent command line option, we have to add it to all of Qt, AppKit, and headless-browser. (Or worse, we only add it to one of these, and we have feature disparity). To prevent this, this moves command line flags to WebView::Application. The flags are assigned to ChromeOptions and WebContentOptions structs. Each chrome can still add its platform-specific options; for example, the Qt chrome has a flag to enable Qt networking. There should be no behavior change here, other than that AppKit will now support command line flags that were previously only supported by Qt.
176 lines
5.3 KiB
C++
176 lines
5.3 KiB
C++
/*
|
|
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
|
|
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/String.h>
|
|
#include <LibCore/System.h>
|
|
#include <LibFileSystem/FileSystem.h>
|
|
#include <LibWebView/URL.h>
|
|
|
|
#if defined(ENABLE_PUBLIC_SUFFIX)
|
|
# include <LibWebView/PublicSuffixData.h>
|
|
#endif
|
|
|
|
namespace WebView {
|
|
|
|
bool is_public_suffix([[maybe_unused]] StringView host)
|
|
{
|
|
#if defined(ENABLE_PUBLIC_SUFFIX)
|
|
return PublicSuffixData::the()->is_public_suffix(host);
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
Optional<String> get_public_suffix([[maybe_unused]] StringView host)
|
|
{
|
|
#if defined(ENABLE_PUBLIC_SUFFIX)
|
|
return MUST(PublicSuffixData::the()->get_public_suffix(host));
|
|
#else
|
|
return {};
|
|
#endif
|
|
}
|
|
|
|
Optional<URL::URL> sanitize_url(StringView url, Optional<StringView> search_engine, AppendTLD append_tld)
|
|
{
|
|
if (FileSystem::exists(url.trim_whitespace())) {
|
|
auto path = FileSystem::real_path(url.trim_whitespace());
|
|
if (path.is_error())
|
|
return {};
|
|
|
|
return URL::create_with_file_scheme(path.value());
|
|
}
|
|
|
|
auto format_search_engine = [&]() -> Optional<URL::URL> {
|
|
if (!search_engine.has_value())
|
|
return {};
|
|
|
|
return MUST(String::formatted(*search_engine, URL::percent_decode(url)));
|
|
};
|
|
|
|
String url_buffer;
|
|
|
|
if (append_tld == AppendTLD::Yes) {
|
|
// FIXME: Expand the list of top level domains.
|
|
if (!url.ends_with(".com"sv) && !url.ends_with(".net"sv) && !url.ends_with(".org"sv)) {
|
|
url_buffer = MUST(String::formatted("{}.com", url));
|
|
url = url_buffer;
|
|
}
|
|
}
|
|
|
|
ByteString url_with_scheme = url;
|
|
if (!(url_with_scheme.starts_with("about:"sv) || url_with_scheme.contains("://"sv) || url_with_scheme.starts_with("data:"sv)))
|
|
url_with_scheme = ByteString::formatted("https://{}"sv, url_with_scheme);
|
|
|
|
auto result = URL::create_with_url_or_path(url_with_scheme);
|
|
if (!result.is_valid())
|
|
return format_search_engine();
|
|
|
|
return result;
|
|
}
|
|
|
|
Vector<URL::URL> sanitize_urls(ReadonlySpan<ByteString> raw_urls, URL::URL const& new_tab_page_url)
|
|
{
|
|
Vector<URL::URL> sanitized_urls;
|
|
sanitized_urls.ensure_capacity(raw_urls.size());
|
|
|
|
for (auto const& raw_url : raw_urls) {
|
|
if (auto url = sanitize_url(raw_url); url.has_value())
|
|
sanitized_urls.unchecked_append(url.release_value());
|
|
}
|
|
|
|
if (sanitized_urls.is_empty())
|
|
sanitized_urls.append(new_tab_page_url);
|
|
|
|
return sanitized_urls;
|
|
}
|
|
|
|
static URLParts break_file_url_into_parts(URL::URL const& url, StringView url_string)
|
|
{
|
|
auto scheme = url_string.substring_view(0, url.scheme().bytes_as_string_view().length() + "://"sv.length());
|
|
auto path = url_string.substring_view(scheme.length());
|
|
|
|
return URLParts { scheme, path, {} };
|
|
}
|
|
|
|
static URLParts break_web_url_into_parts(URL::URL const& url, StringView url_string)
|
|
{
|
|
auto scheme = url_string.substring_view(0, url.scheme().bytes_as_string_view().length() + "://"sv.length());
|
|
auto url_without_scheme = url_string.substring_view(scheme.length());
|
|
|
|
StringView domain;
|
|
StringView remainder;
|
|
|
|
if (auto index = url_without_scheme.find_any_of("/?#"sv); index.has_value()) {
|
|
domain = url_without_scheme.substring_view(0, *index);
|
|
remainder = url_without_scheme.substring_view(*index);
|
|
} else {
|
|
domain = url_without_scheme;
|
|
}
|
|
|
|
auto public_suffix = get_public_suffix(domain);
|
|
if (!public_suffix.has_value() || !domain.ends_with(*public_suffix))
|
|
return { scheme, domain, remainder };
|
|
|
|
auto subdomain = domain.substring_view(0, domain.length() - public_suffix->bytes_as_string_view().length());
|
|
subdomain = subdomain.trim("."sv, TrimMode::Right);
|
|
|
|
if (auto index = subdomain.find_last('.'); index.has_value()) {
|
|
subdomain = subdomain.substring_view(0, *index + 1);
|
|
domain = domain.substring_view(subdomain.length());
|
|
} else {
|
|
subdomain = {};
|
|
}
|
|
|
|
auto scheme_and_subdomain = url_string.substring_view(0, scheme.length() + subdomain.length());
|
|
return { scheme_and_subdomain, domain, remainder };
|
|
}
|
|
|
|
Optional<URLParts> break_url_into_parts(StringView url_string)
|
|
{
|
|
auto url = URL::create_with_url_or_path(url_string);
|
|
if (!url.is_valid())
|
|
return {};
|
|
|
|
auto const& scheme = url.scheme();
|
|
auto scheme_length = scheme.bytes_as_string_view().length();
|
|
|
|
if (!url_string.starts_with(scheme))
|
|
return {};
|
|
if (!url_string.substring_view(scheme_length).starts_with("://"sv))
|
|
return {};
|
|
|
|
if (url.scheme() == "file"sv)
|
|
return break_file_url_into_parts(url, url_string);
|
|
if (url.scheme().is_one_of("http"sv, "https"sv))
|
|
return break_web_url_into_parts(url, url_string);
|
|
|
|
return {};
|
|
}
|
|
|
|
URLType url_type(URL::URL const& url)
|
|
{
|
|
if (url.scheme() == "mailto"sv)
|
|
return URLType::Email;
|
|
if (url.scheme() == "tel"sv)
|
|
return URLType::Telephone;
|
|
return URLType::Other;
|
|
}
|
|
|
|
String url_text_to_copy(URL::URL const& url)
|
|
{
|
|
auto url_text = MUST(url.to_string());
|
|
|
|
if (url.scheme() == "mailto"sv)
|
|
return MUST(url_text.substring_from_byte_offset("mailto:"sv.length()));
|
|
|
|
if (url.scheme() == "tel"sv)
|
|
return MUST(url_text.substring_from_byte_offset("tel:"sv.length()));
|
|
|
|
return url_text;
|
|
}
|
|
|
|
}
|