diff --git a/Base/home/anon/.config/BrowserAutoplayAllowlist.txt b/Base/home/anon/.config/BrowserAutoplayAllowlist.txt new file mode 100644 index 0000000000..1596b5587c --- /dev/null +++ b/Base/home/anon/.config/BrowserAutoplayAllowlist.txt @@ -0,0 +1 @@ +file:// diff --git a/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.cpp b/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.cpp new file mode 100644 index 0000000000..e51cc98b19 --- /dev/null +++ b/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "AutoplaySettingsWidget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static constexpr bool default_allow_autoplay_on_all_websites = false; + +ErrorOr AutoplayAllowlistModel::filter_list_file_path() const +{ + return String::formatted("{}/BrowserAutoplayAllowlist.txt", Core::StandardPaths::config_directory()); +} + +void AutoplayAllowlistModel::reset_default_values() +{ + m_domain_list = {}; + m_was_modified = true; + did_update(UpdateFlag::InvalidateAllIndices); +} + +ErrorOr> AutoplaySettingsWidget::create() +{ + auto allowlist_model = TRY(try_make_ref_counted()); + TRY(allowlist_model->load()); + + auto widget = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) AutoplaySettingsWidget(move(allowlist_model)))); + TRY(widget->load_from_gml(autoplay_settings_widget_gml)); + + widget->m_allow_autoplay_on_all_websites_checkbox = widget->find_descendant_of_type_named("allow_autoplay_on_all_websites_checkbox"); + widget->m_allow_autoplay_on_all_websites_checkbox->set_checked(Config::read_bool("Browser"sv, "Preferences"sv, "AllowAutoplayOnAllWebsites"sv, default_allow_autoplay_on_all_websites), GUI::AllowCallback::No); + widget->m_allow_autoplay_on_all_websites_checkbox->on_checked = [widget](auto) { + widget->set_modified(true); + }; + + widget->m_allowlist_view = widget->find_descendant_of_type_named("allowlist_view"); + widget->m_allowlist_view->set_model(widget->m_allowlist_model); + widget->m_allowlist_view->on_context_menu_request = [widget](GUI::ModelIndex const& index, GUI::ContextMenuEvent const& event) { + widget->m_allowlist_view->set_cursor(index, GUI::AbstractView::SelectionUpdate::Set); + widget->m_entry_context_menu->popup(event.screen_position()); + }; + + widget->m_add_website_button = widget->find_descendant_of_type_named("add_website_button"); + widget->m_add_website_button->on_click = [widget](unsigned) { + String text; + + if (GUI::InputBox::show(widget->window(), text, "Website:"sv, "Add website to autoplay allowlist"sv, GUI::InputType::NonemptyText) == GUI::Dialog::ExecResult::OK) { + widget->m_allowlist_model->add_domain(text.to_deprecated_string()); + widget->set_modified(true); + } + }; + + auto delete_action = GUI::CommonActions::make_delete_action([widget](GUI::Action const&) { + if (!widget->m_allowlist_view->selection().is_empty()) { + widget->m_allowlist_model->delete_domain(widget->m_allowlist_view->selection().first().row()); + widget->set_modified(true); + } + }); + widget->m_entry_context_menu = TRY(GUI::Menu::try_create()); + widget->m_entry_context_menu->add_action(move(delete_action)); + + return widget; +} + +AutoplaySettingsWidget::AutoplaySettingsWidget(NonnullRefPtr allowlist_model) + : m_allowlist_model(move(allowlist_model)) +{ +} + +void AutoplaySettingsWidget::apply_settings() +{ + m_allowlist_model->save().release_value_but_fixme_should_propagate_errors(); + Config::write_bool("Browser"sv, "Preferences"sv, "AllowAutoplayOnAllWebsites"sv, m_allow_autoplay_on_all_websites_checkbox->is_checked()); +} + +void AutoplaySettingsWidget::reset_default_values() +{ + m_allowlist_model->reset_default_values(); + m_allow_autoplay_on_all_websites_checkbox->set_checked(default_allow_autoplay_on_all_websites); +} diff --git a/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.gml b/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.gml new file mode 100644 index 0000000000..3428c5ca1b --- /dev/null +++ b/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.gml @@ -0,0 +1,35 @@ +@GUI::Frame { + fill_with_background_color: true + layout: @GUI::VerticalBoxLayout { + margins: [8] + } + + @GUI::CheckBox { + name: "allow_autoplay_on_all_websites_checkbox" + text: "Allow media to automatically play on all websites" + } + + @GUI::GroupBox { + title: "Autoplay Allowlist" + layout: @GUI::VerticalBoxLayout { + margins: [8] + } + + @GUI::ListView { + name: "allowlist_view" + } + + @GUI::Widget { + fixed_height: 32 + layout: @GUI::HorizontalBoxLayout {} + + @GUI::Layout::Spacer {} + + @GUI::Button { + name: "add_website_button" + fixed_width: 100 + text: "Add website..." + } + } + } +} diff --git a/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.h b/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.h new file mode 100644 index 0000000000..ce381caec1 --- /dev/null +++ b/Userland/Applications/BrowserSettings/AutoplaySettingsWidget.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include "ContentFilterSettingsWidget.h" +#include +#include +#include +#include +#include +#include + +class AutoplayAllowlistModel : public DomainListModel { +public: + virtual ErrorOr filter_list_file_path() const override; + virtual void reset_default_values() override; +}; + +class AutoplaySettingsWidget : public GUI::SettingsWindow::Tab { + C_OBJECT_ABSTRACT(AutoplaySettingsWidget) + +public: + static ErrorOr> create(); + + virtual void apply_settings() override; + virtual void reset_default_values() override; + +private: + explicit AutoplaySettingsWidget(NonnullRefPtr); + + RefPtr m_entry_context_menu; + RefPtr m_allow_autoplay_on_all_websites_checkbox; + RefPtr m_add_website_button; + RefPtr m_allowlist_view; + NonnullRefPtr m_allowlist_model; +}; diff --git a/Userland/Applications/BrowserSettings/CMakeLists.txt b/Userland/Applications/BrowserSettings/CMakeLists.txt index bf36952912..5627c250d5 100644 --- a/Userland/Applications/BrowserSettings/CMakeLists.txt +++ b/Userland/Applications/BrowserSettings/CMakeLists.txt @@ -4,16 +4,19 @@ serenity_component( TARGETS BrowserSettings ) +compile_gml(AutoplaySettingsWidget.gml AutoplaySettingsWidgetGML.h autoplay_settings_widget_gml) compile_gml(BrowserSettingsWidget.gml BrowserSettingsWidgetGML.h browser_settings_widget_gml) compile_gml(ContentFilterSettingsWidget.gml ContentFilterSettingsWidgetGML.h content_filter_settings_widget_gml) set(SOURCES + AutoplaySettingsWidget.cpp BrowserSettingsWidget.cpp ContentFilterSettingsWidget.cpp main.cpp ) set(GENERATED_SOURCES + AutoplaySettingsWidgetGML.h BrowserSettingsWidgetGML.h ContentFilterSettingsWidgetGML.h ) diff --git a/Userland/Applications/BrowserSettings/ContentFilterSettingsWidget.cpp b/Userland/Applications/BrowserSettings/ContentFilterSettingsWidget.cpp index 6ef9631db6..d4c6dc8c4b 100644 --- a/Userland/Applications/BrowserSettings/ContentFilterSettingsWidget.cpp +++ b/Userland/Applications/BrowserSettings/ContentFilterSettingsWidget.cpp @@ -7,6 +7,7 @@ #include "ContentFilterSettingsWidget.h" #include +#include #include #include #include @@ -19,15 +20,15 @@ static constexpr bool s_default_enable_content_filtering = true; -static DeprecatedString filter_list_file_path() +ErrorOr DomainListModel::filter_list_file_path() const { - return DeprecatedString::formatted("{}/BrowserContentFilters.txt", Core::StandardPaths::config_directory()); + return String::formatted("{}/BrowserContentFilters.txt", Core::StandardPaths::config_directory()); } ErrorOr DomainListModel::load() { // FIXME: This should be somewhat shared with Browser. - auto file = TRY(Core::File::open(filter_list_file_path(), Core::File::OpenMode::Read)); + auto file = TRY(Core::File::open(TRY(filter_list_file_path()), Core::File::OpenMode::Read)); auto content_filter_list = TRY(Core::BufferedFile::create(move(file))); auto buffer = TRY(ByteBuffer::create_uninitialized(4096)); while (TRY(content_filter_list->can_read_line())) { @@ -49,7 +50,7 @@ ErrorOr DomainListModel::save() for (auto const& domain : m_domain_list) TRY(builder.try_appendff("{}\n", domain)); - auto file = TRY(Core::File::open(filter_list_file_path(), Core::File::OpenMode::Write)); + auto file = TRY(Core::File::open(TRY(filter_list_file_path()), Core::File::OpenMode::Write)); TRY(file->write_until_depleted(TRY(builder.to_byte_buffer()).bytes())); return {}; } diff --git a/Userland/Applications/BrowserSettings/ContentFilterSettingsWidget.h b/Userland/Applications/BrowserSettings/ContentFilterSettingsWidget.h index c61ee19be5..a83522d558 100644 --- a/Userland/Applications/BrowserSettings/ContentFilterSettingsWidget.h +++ b/Userland/Applications/BrowserSettings/ContentFilterSettingsWidget.h @@ -13,9 +13,10 @@ class DomainListModel : public GUI::Model { public: + virtual ErrorOr filter_list_file_path() const; ErrorOr load(); ErrorOr save(); - void reset_default_values(); + virtual void reset_default_values(); virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return m_domain_list.size(); } virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return 1; } @@ -24,7 +25,7 @@ public: void add_domain(DeprecatedString name); void delete_domain(size_t index); -private: +protected: bool m_was_modified { false }; Vector m_domain_list; }; diff --git a/Userland/Applications/BrowserSettings/main.cpp b/Userland/Applications/BrowserSettings/main.cpp index 4115546bb6..13c6d0643f 100644 --- a/Userland/Applications/BrowserSettings/main.cpp +++ b/Userland/Applications/BrowserSettings/main.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include "AutoplaySettingsWidget.h" #include "BrowserSettingsWidget.h" #include "ContentFilterSettingsWidget.h" #include @@ -27,6 +28,7 @@ ErrorOr serenity_main(Main::Arguments arguments) TRY(Core::System::unveil("/res", "r")); TRY(Core::System::unveil("/home", "r")); + TRY(Core::System::unveil("/home/anon/.config/BrowserAutoplayAllowlist.txt", "rwc")); TRY(Core::System::unveil("/home/anon/.config/BrowserContentFilters.txt", "rwc")); TRY(Core::System::unveil(nullptr, nullptr)); @@ -36,6 +38,7 @@ ErrorOr serenity_main(Main::Arguments arguments) window->set_icon(app_icon.bitmap_for_size(16)); (void)TRY(window->add_tab("Browser"_short_string, "browser"sv)); (void)TRY(window->add_tab(TRY("Content Filtering"_string), "content-filtering"sv)); + (void)TRY(window->add_tab(TRY(AutoplaySettingsWidget::create()), TRY("Autoplay"_string), "autoplay"sv)); window->set_active_tab(selected_tab); window->show();