LibWeb+LibWebView+WebContent: Convert about:settings to a WebUI
Some checks are pending
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run

This commit is contained in:
Timothy Flynn 2025-03-24 10:22:38 -04:00 committed by Tim Flynn
commit f05b0bfd5f
Notes: github-actions[bot] 2025-03-28 11:32:05 +00:00
23 changed files with 151 additions and 264 deletions

View file

@ -5,7 +5,6 @@
*/
#include <AK/Debug.h>
#include <AK/JsonArraySerializer.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/Environment.h>
#include <LibCore/StandardPaths.h>
@ -324,35 +323,6 @@ Optional<Process&> Application::find_process(pid_t pid)
return m_process_manager.find_process(pid);
}
void Application::send_current_settings_to_view(ViewImplementation& view)
{
auto settings = m_settings.serialize_json();
StringBuilder builder;
builder.append("settings.loadSettings(\""sv);
builder.append_escaped_for_json(settings);
builder.append("\");"sv);
view.run_javascript(MUST(builder.to_string()));
}
void Application::send_available_search_engines_to_view(ViewImplementation& view)
{
StringBuilder engines;
auto serializer = MUST(JsonArraySerializer<>::try_create(engines));
for (auto const& engine : search_engines())
MUST(serializer.add(engine.name));
MUST(serializer.finish());
StringBuilder builder;
builder.append("settings.loadSearchEngines(\""sv);
builder.append_escaped_for_json(engines.string_view());
builder.append("\");"sv);
view.run_javascript(MUST(builder.to_string()));
}
void Application::process_did_exit(Process&& process)
{
if (m_in_shutdown)

View file

@ -61,9 +61,6 @@ public:
#endif
Optional<Process&> find_process(pid_t);
void send_current_settings_to_view(ViewImplementation&);
void send_available_search_engines_to_view(ViewImplementation&);
ErrorOr<LexicalPath> path_for_downloaded_file(StringView file) const;
enum class DevtoolsState {

View file

@ -26,6 +26,7 @@ set(SOURCES
WebContentClient.cpp
WebUI.cpp
WebUI/ProcessesUI.cpp
WebUI/SettingsUI.cpp
)
if (APPLE)

View file

@ -6,7 +6,6 @@
#include <AK/ByteString.h>
#include <AK/JsonObject.h>
#include <AK/JsonObjectSerializer.h>
#include <AK/JsonValue.h>
#include <AK/LexicalPath.h>
#include <AK/StringBuilder.h>
@ -40,13 +39,13 @@ static ErrorOr<JsonObject> read_settings_file(StringView settings_path)
return move(settings_json.as_object());
}
static ErrorOr<void> write_settings_file(StringView settings_path, StringView contents)
static ErrorOr<void> write_settings_file(StringView settings_path, JsonValue const& contents)
{
auto settings_directory = LexicalPath { settings_path }.parent();
TRY(Core::Directory::create(settings_directory, Core::Directory::CreateDirectories::Yes));
auto settings_file = TRY(Core::File::open(settings_path, Core::File::OpenMode::Write));
TRY(settings_file->write_until_depleted(contents));
TRY(settings_file->write_until_depleted(contents.serialized()));
return {};
}
@ -84,21 +83,19 @@ Settings::Settings(ByteString settings_path)
{
}
String Settings::serialize_json() const
JsonValue Settings::serialize_json() const
{
StringBuilder builder;
auto serializer = MUST(JsonObjectSerializer<>::try_create(builder));
MUST(serializer.add(new_tab_page_url_key, m_new_tab_page_url.serialize()));
JsonObject settings;
settings.set(new_tab_page_url_key, m_new_tab_page_url.serialize());
if (m_search_engine.has_value()) {
auto search_engine = MUST(serializer.add_object(search_engine_key));
MUST(search_engine.add(search_engine_name_key, m_search_engine->name));
MUST(search_engine.finish());
JsonObject search_engine;
search_engine.set(search_engine_name_key, m_search_engine->name);
settings.set(search_engine_key, move(search_engine));
}
MUST(serializer.finish());
return MUST(builder.to_string());
return settings;
}
void Settings::restore_defaults()

View file

@ -7,6 +7,7 @@
#pragma once
#include <AK/Badge.h>
#include <AK/JsonValue.h>
#include <AK/Optional.h>
#include <LibURL/URL.h>
#include <LibWebView/Forward.h>
@ -27,7 +28,7 @@ class Settings {
public:
static Settings create(Badge<Application>);
String serialize_json() const;
JsonValue serialize_json() const;
void restore_defaults();

View file

@ -669,39 +669,6 @@ Messages::WebContentClient::RequestWorkerAgentResponse WebContentClient::request
return IPC::File {};
}
void WebContentClient::request_current_settings(u64 page_id)
{
if (auto view = view_for_page_id(page_id); view.has_value())
WebView::Application::the().send_current_settings_to_view(*view);
}
void WebContentClient::restore_default_settings(u64 page_id)
{
WebView::Application::settings().restore_defaults();
request_current_settings(page_id);
}
void WebContentClient::set_new_tab_page_url(u64 page_id, URL::URL new_tab_page_url)
{
WebView::Application::settings().set_new_tab_page_url(move(new_tab_page_url));
request_current_settings(page_id);
}
void WebContentClient::request_available_search_engines(u64 page_id)
{
if (auto view = view_for_page_id(page_id); view.has_value())
WebView::Application::the().send_available_search_engines_to_view(*view);
}
void WebContentClient::set_search_engine(u64 page_id, Optional<String> search_engine)
{
WebView::Application::settings().set_search_engine(search_engine.map([](auto const& search_engine) {
return search_engine.bytes_as_string_view();
}));
request_current_settings(page_id);
}
Optional<ViewImplementation&> WebContentClient::view_for_page_id(u64 page_id, SourceLocation location)
{
// Don't bother logging anything for the spare WebContent process. It will only receive a load notification for about:blank.

View file

@ -130,11 +130,6 @@ private:
virtual void did_update_navigation_buttons_state(u64 page_id, bool back_enabled, bool forward_enabled) override;
virtual void did_allocate_backing_stores(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap, i32 back_bitmap_id, Gfx::ShareableBitmap) override;
virtual Messages::WebContentClient::RequestWorkerAgentResponse request_worker_agent(u64 page_id) override;
virtual void request_current_settings(u64 page_id) override;
virtual void restore_default_settings(u64 page_id) override;
virtual void set_new_tab_page_url(u64 page_id, URL::URL new_tab_page_url) override;
virtual void request_available_search_engines(u64 page_id) override;
virtual void set_search_engine(u64 page_id, Optional<String> search_engine) override;
Optional<ViewImplementation&> view_for_page_id(u64, SourceLocation = SourceLocation::current());

View file

@ -9,6 +9,7 @@
#include <LibWebView/WebContentClient.h>
#include <LibWebView/WebUI.h>
#include <LibWebView/WebUI/ProcessesUI.h>
#include <LibWebView/WebUI/SettingsUI.h>
namespace WebView {
@ -38,6 +39,8 @@ ErrorOr<RefPtr<WebUI>> WebUI::create(WebContentClient& client, String host)
if (host == "processes"sv)
web_ui = TRY(create_web_ui<ProcessesUI>(client, move(host)));
else if (host == "settings"sv)
web_ui = TRY(create_web_ui<SettingsUI>(client, move(host)));
if (web_ui)
web_ui->register_interfaces();

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/JsonArray.h>
#include <LibURL/Parser.h>
#include <LibWebView/Application.h>
#include <LibWebView/SearchEngine.h>
#include <LibWebView/WebUI/SettingsUI.h>
namespace WebView {
void SettingsUI::register_interfaces()
{
register_interface("loadCurrentSettings"sv, [this](auto const&) {
load_current_settings();
});
register_interface("restoreDefaultSettings"sv, [this](auto const&) {
restore_default_settings();
});
register_interface("setNewTabPageURL"sv, [this](auto const& data) {
set_new_tab_page_url(data);
});
register_interface("loadAvailableSearchEngines"sv, [this](auto const&) {
load_available_search_engines();
});
register_interface("setSearchEngine"sv, [this](auto const& data) {
set_search_engine(data);
});
}
void SettingsUI::load_current_settings()
{
auto settings = WebView::Application::settings().serialize_json();
async_send_message("loadSettings"sv, settings);
}
void SettingsUI::restore_default_settings()
{
WebView::Application::settings().restore_defaults();
load_current_settings();
}
void SettingsUI::set_new_tab_page_url(JsonValue const& new_tab_page_url)
{
if (!new_tab_page_url.is_string())
return;
auto parsed_new_tab_page_url = URL::Parser::basic_parse(new_tab_page_url.as_string());
if (!parsed_new_tab_page_url.has_value())
return;
WebView::Application::settings().set_new_tab_page_url(parsed_new_tab_page_url.release_value());
}
void SettingsUI::load_available_search_engines()
{
JsonArray engines;
for (auto const& engine : search_engines())
engines.must_append(engine.name);
async_send_message("loadSearchEngines"sv, move(engines));
}
void SettingsUI::set_search_engine(JsonValue const& search_engine)
{
if (search_engine.is_null())
WebView::Application::settings().set_search_engine({});
else if (search_engine.is_string())
WebView::Application::settings().set_search_engine(search_engine.as_string());
}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2025, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWebView/WebUI.h>
namespace WebView {
class SettingsUI : public WebUI {
WEB_UI(SettingsUI);
private:
virtual void register_interfaces() override;
void load_current_settings();
void restore_default_settings();
void set_new_tab_page_url(JsonValue const&);
void load_available_search_engines();
void set_search_engine(JsonValue const&);
};
}