diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2022-04-08 01:46:47 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-04-09 12:21:43 +0200 |
commit | a42e03b01a7c2c98377f3851cb4e5f07d7e3ba35 (patch) | |
tree | 812e97db21dee65573b5a669a2b643ee4ea83426 /Userland | |
parent | f9fc28931fe42700bbfc8964a0a7ceb5940a46f7 (diff) | |
download | serenity-a42e03b01a7c2c98377f3851cb4e5f07d7e3ba35.zip |
Browser+LibWeb+WebContent: Implement per-URL-pattern proxies
...at least for SOCKS5.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Applications/Browser/Browser.h | 2 | ||||
-rw-r--r-- | Userland/Applications/Browser/BrowserWindow.cpp | 29 | ||||
-rw-r--r-- | Userland/Applications/Browser/BrowserWindow.h | 1 | ||||
-rw-r--r-- | Userland/Applications/Browser/Tab.cpp | 7 | ||||
-rw-r--r-- | Userland/Applications/Browser/Tab.h | 1 | ||||
-rw-r--r-- | Userland/Applications/Browser/main.cpp | 16 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Loader/ProxyMappings.cpp | 41 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Loader/ProxyMappings.h | 31 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/OutOfProcessWebView.cpp | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/OutOfProcessWebView.h | 1 | ||||
-rw-r--r-- | Userland/Services/WebContent/ConnectionFromClient.cpp | 18 | ||||
-rw-r--r-- | Userland/Services/WebContent/ConnectionFromClient.h | 1 | ||||
-rw-r--r-- | Userland/Services/WebContent/WebContentServer.ipc | 1 |
15 files changed, 155 insertions, 6 deletions
diff --git a/Userland/Applications/Browser/Browser.h b/Userland/Applications/Browser/Browser.h index fccb78d47b..b9d186e4ae 100644 --- a/Userland/Applications/Browser/Browser.h +++ b/Userland/Applications/Browser/Browser.h @@ -14,6 +14,8 @@ namespace Browser { extern String g_home_url; extern String g_search_engine; extern Vector<String> g_content_filters; +extern Vector<String> g_proxies; +extern HashMap<String, size_t> g_proxy_mappings; extern bool g_content_filters_enabled; extern IconBag g_icon_bag; diff --git a/Userland/Applications/Browser/BrowserWindow.cpp b/Userland/Applications/Browser/BrowserWindow.cpp index 7cf6e186e1..f67501427b 100644 --- a/Userland/Applications/Browser/BrowserWindow.cpp +++ b/Userland/Applications/Browser/BrowserWindow.cpp @@ -575,15 +575,34 @@ void BrowserWindow::content_filters_changed() }); } +void BrowserWindow::proxy_mappings_changed() +{ + tab_widget().for_each_child_of_type<Browser::Tab>([](auto& tab) { + tab.proxy_mappings_changed(); + return IterationDecision::Continue; + }); +} + void BrowserWindow::config_string_did_change(String const& domain, String const& group, String const& key, String const& value) { - if (domain != "Browser" || group != "Preferences") + if (domain != "Browser") return; - if (key == "SearchEngine") - Browser::g_search_engine = value; - else if (key == "Home") - Browser::g_home_url = value; + if (group == "Preferences") { + if (key == "SearchEngine") + Browser::g_search_engine = value; + else if (key == "Home") + Browser::g_home_url = value; + } else if (group.starts_with("Proxy:")) { + dbgln("Proxy mapping changed: {}/{} = {}", group, key, value); + auto proxy_spec = group.substring_view(6); + auto existing_proxy = Browser::g_proxies.find(proxy_spec); + if (existing_proxy.is_end()) + Browser::g_proxies.append(proxy_spec); + + Browser::g_proxy_mappings.set(key, existing_proxy.index()); + proxy_mappings_changed(); + } // TODO: ColorScheme } diff --git a/Userland/Applications/Browser/BrowserWindow.h b/Userland/Applications/Browser/BrowserWindow.h index 88e4496349..fe6e9e3efe 100644 --- a/Userland/Applications/Browser/BrowserWindow.h +++ b/Userland/Applications/Browser/BrowserWindow.h @@ -41,6 +41,7 @@ public: GUI::Action& inspect_dom_node_action() { return *m_inspect_dom_node_action; } void content_filters_changed(); + void proxy_mappings_changed(); private: explicit BrowserWindow(CookieJar&, URL); diff --git a/Userland/Applications/Browser/Tab.cpp b/Userland/Applications/Browser/Tab.cpp index e634b2e58f..745ae88556 100644 --- a/Userland/Applications/Browser/Tab.cpp +++ b/Userland/Applications/Browser/Tab.cpp @@ -118,6 +118,8 @@ Tab::Tab(BrowserWindow& window) else m_web_content_view->set_content_filters({}); + m_web_content_view->set_proxy_mappings(g_proxies, g_proxy_mappings); + auto& go_back_button = toolbar.add_action(window.go_back_action()); go_back_button.on_context_menu_request = [this](auto& context_menu_event) { if (!m_history.can_go_back()) @@ -516,6 +518,11 @@ void Tab::content_filters_changed() m_web_content_view->set_content_filters({}); } +void Tab::proxy_mappings_changed() +{ + m_web_content_view->set_proxy_mappings(g_proxies, g_proxy_mappings); +} + void Tab::action_entered(GUI::Action& action) { m_statusbar->set_override_text(action.status_tip()); diff --git a/Userland/Applications/Browser/Tab.h b/Userland/Applications/Browser/Tab.h index 2e2ee353a7..a7bd6f33dc 100644 --- a/Userland/Applications/Browser/Tab.h +++ b/Userland/Applications/Browser/Tab.h @@ -51,6 +51,7 @@ public: void did_become_active(); void context_menu_requested(Gfx::IntPoint const& screen_position); void content_filters_changed(); + void proxy_mappings_changed(); void action_entered(GUI::Action&); void action_left(GUI::Action&); diff --git a/Userland/Applications/Browser/main.cpp b/Userland/Applications/Browser/main.cpp index 1842e32f1c..e963e312c3 100644 --- a/Userland/Applications/Browser/main.cpp +++ b/Userland/Applications/Browser/main.cpp @@ -31,6 +31,8 @@ String g_search_engine; String g_home_url; Vector<String> g_content_filters; bool g_content_filters_enabled { true }; +Vector<String> g_proxies; +HashMap<String, size_t> g_proxy_mappings; IconBag g_icon_bag; } @@ -96,6 +98,20 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) TRY(load_content_filters()); + for (auto& group : Config::list_groups("Browser")) { + if (!group.starts_with("Proxy:")) + continue; + + for (auto& key : Config::list_keys("Browser", group)) { + auto proxy_spec = group.substring_view(6); + auto existing_proxy = Browser::g_proxies.find(proxy_spec); + if (existing_proxy.is_end()) + Browser::g_proxies.append(proxy_spec); + + Browser::g_proxy_mappings.set(key, existing_proxy.index()); + } + } + URL first_url = Browser::url_from_user_input(Browser::g_home_url); if (specified_url) { if (Core::File::exists(specified_url)) { diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 499c8cfbd3..ae3f664a38 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -280,6 +280,7 @@ set(SOURCES Loader/ImageLoader.cpp Loader/ImageResource.cpp Loader/LoadRequest.cpp + Loader/ProxyMappings.cpp Loader/Resource.cpp Loader/ResourceLoader.cpp MimeSniff/MimeType.cpp diff --git a/Userland/Libraries/LibWeb/Loader/ProxyMappings.cpp b/Userland/Libraries/LibWeb/Loader/ProxyMappings.cpp new file mode 100644 index 0000000000..4230a72862 --- /dev/null +++ b/Userland/Libraries/LibWeb/Loader/ProxyMappings.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "ProxyMappings.h" + +Web::ProxyMappings& Web::ProxyMappings::the() +{ + static ProxyMappings instance {}; + return instance; +} + +Core::ProxyData Web::ProxyMappings::proxy_for_url(AK::URL const& url) const +{ + auto url_string = url.to_string(); + for (auto& it : m_mappings) { + dbgln("Checking {} against {}...", url, it.key); + if (url_string.matches(it.key)) { + dbgln("Matched!"); + auto result = Core::ProxyData::parse_url(m_proxies[it.value]); + if (result.is_error()) { + dbgln("Failed to parse proxy URL: {}", m_proxies[it.value]); + continue; + } + return result.release_value(); + } + } + + dbgln("No luck!"); + return {}; +} + +void Web::ProxyMappings::set_mappings(Vector<String> proxies, OrderedHashMap<String, size_t> mappings) +{ + m_proxies = move(proxies); + m_mappings = move(mappings); + + dbgln("Proxy mappings updated: proxies: {}", m_proxies); +} diff --git a/Userland/Libraries/LibWeb/Loader/ProxyMappings.h b/Userland/Libraries/LibWeb/Loader/ProxyMappings.h new file mode 100644 index 0000000000..afa7f63ae2 --- /dev/null +++ b/Userland/Libraries/LibWeb/Loader/ProxyMappings.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/HashMap.h> +#include <AK/URL.h> +#include <AK/Vector.h> +#include <LibCore/Proxy.h> + +namespace Web { + +class ProxyMappings { +public: + static ProxyMappings& the(); + + Core::ProxyData proxy_for_url(AK::URL const&) const; + void set_mappings(Vector<String> proxies, OrderedHashMap<String, size_t> mappings); + +private: + ProxyMappings() = default; + ~ProxyMappings() = default; + + Vector<String> m_proxies; + OrderedHashMap<String, size_t> m_mappings; +}; + +} diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp index 737598cc3d..76a634f80f 100644 --- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp +++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp @@ -14,6 +14,7 @@ #include <LibProtocol/RequestClient.h> #include <LibWeb/Loader/ContentFilter.h> #include <LibWeb/Loader/LoadRequest.h> +#include <LibWeb/Loader/ProxyMappings.h> #include <LibWeb/Loader/Resource.h> #include <LibWeb/Loader/ResourceLoader.h> #include <serenity.h> @@ -213,6 +214,9 @@ void ResourceLoader::load(LoadRequest& request, Function<void(ReadonlyBytes, Has } if (url.protocol() == "http" || url.protocol() == "https" || url.protocol() == "gemini") { + auto proxy = ProxyMappings::the().proxy_for_url(url); + dbgln("Proxy for {} is {}", url, proxy.type == decltype(proxy.type)::SOCKS5 ? IPv4Address(proxy.host_ipv4).to_string() : "(direct)"); + HashMap<String, String> headers; headers.set("User-Agent", m_user_agent); headers.set("Accept-Encoding", "gzip, deflate"); @@ -221,7 +225,7 @@ void ResourceLoader::load(LoadRequest& request, Function<void(ReadonlyBytes, Has headers.set(it.key, it.value); } - auto protocol_request = protocol_client().start_request(request.method(), url, headers, request.body()); + auto protocol_request = protocol_client().start_request(request.method(), url, headers, request.body(), proxy); if (!protocol_request) { auto start_request_failure_msg = "Failed to initiate load"sv; log_failure(request, start_request_failure_msg); diff --git a/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp b/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp index 04dfb260ed..887993671d 100644 --- a/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp +++ b/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp @@ -500,6 +500,11 @@ void OutOfProcessWebView::set_content_filters(Vector<String> filters) client().async_set_content_filters(filters); } +void OutOfProcessWebView::set_proxy_mappings(Vector<String> proxies, HashMap<String, size_t> mappings) +{ + client().async_set_proxy_mappings(move(proxies), move(mappings)); +} + void OutOfProcessWebView::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme) { client().async_set_preferred_color_scheme(color_scheme); diff --git a/Userland/Libraries/LibWeb/OutOfProcessWebView.h b/Userland/Libraries/LibWeb/OutOfProcessWebView.h index cf54557f19..55f513c47c 100644 --- a/Userland/Libraries/LibWeb/OutOfProcessWebView.h +++ b/Userland/Libraries/LibWeb/OutOfProcessWebView.h @@ -55,6 +55,7 @@ public: OrderedHashMap<String, String> get_local_storage_entries(); void set_content_filters(Vector<String>); + void set_proxy_mappings(Vector<String> proxies, HashMap<String, size_t> mappings); void set_preferred_color_scheme(Web::CSS::PreferredColorScheme); Function<void(Gfx::IntPoint const& screen_position)> on_context_menu_request; diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index 4798233a19..48db742020 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -7,6 +7,7 @@ #include <AK/Debug.h> #include <AK/JsonObject.h> +#include <AK/QuickSort.h> #include <LibGfx/Bitmap.h> #include <LibGfx/FontDatabase.h> #include <LibGfx/SystemTheme.h> @@ -24,6 +25,7 @@ #include <LibWeb/HTML/Window.h> #include <LibWeb/Layout/InitialContainingBlock.h> #include <LibWeb/Loader/ContentFilter.h> +#include <LibWeb/Loader/ProxyMappings.h> #include <LibWeb/Loader/ResourceLoader.h> #include <LibWeb/Painting/PaintableBox.h> #include <LibWeb/Painting/StackingContext.h> @@ -454,6 +456,22 @@ void ConnectionFromClient::set_content_filters(Vector<String> const& filters) Web::ContentFilter::the().add_pattern(filter); } +void ConnectionFromClient::set_proxy_mappings(Vector<String> const& proxies, HashMap<String, size_t> const& mappings) +{ + auto keys = mappings.keys(); + quick_sort(keys, [&](auto& a, auto& b) { return a.length() < b.length(); }); + + OrderedHashMap<String, size_t> sorted_mappings; + for (auto& key : keys) { + auto value = *mappings.get(key); + if (value >= proxies.size()) + continue; + sorted_mappings.set(key, value); + } + + Web::ProxyMappings::the().set_mappings(proxies, move(sorted_mappings)); +} + void ConnectionFromClient::set_preferred_color_scheme(Web::CSS::PreferredColorScheme const& color_scheme) { m_page_host->set_preferred_color_scheme(color_scheme); diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index 05a3dcc15f..9af25ca3a7 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -59,6 +59,7 @@ private: virtual Messages::WebContentServer::GetHoveredNodeIdResponse get_hovered_node_id() override; virtual Messages::WebContentServer::DumpLayoutTreeResponse dump_layout_tree() override; virtual void set_content_filters(Vector<String> const&) override; + virtual void set_proxy_mappings(Vector<String> const&, HashMap<String, size_t> const&) override; virtual void set_preferred_color_scheme(Web::CSS::PreferredColorScheme const&) override; virtual void set_has_focus(bool) override; virtual void set_is_scripting_enabled(bool) override; diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index 89467abe50..6cf876f62e 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -43,6 +43,7 @@ endpoint WebContentServer select_all() =| set_content_filters(Vector<String> filters) =| + set_proxy_mappings(Vector<String> proxies, HashMap<String,size_t> mappings) =| set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme) =| set_has_focus(bool has_focus) =| set_is_scripting_enabled(bool is_scripting_enabled) =| |