ladybird/Libraries/LibWebView/Menu.h
Andreas Kling 46e1a08742 LibWeb: Rename ContentFilter to ContentBlocker
Rename the local content blocking implementation and its tests from
ContentFilter to ContentBlocker while keeping the existing substring
matcher backend and behavior.

Update the WebContent IPC method, WebView option names, debug toggle,
and default config file name to use content blocker terminology.
2026-05-21 21:16:56 +02:00

254 lines
6.4 KiB
C++

/*
* Copyright (c) 2025-2026, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/NonnullRefPtr.h>
#include <AK/Optional.h>
#include <AK/RefCounted.h>
#include <AK/String.h>
#include <AK/StringView.h>
#include <AK/Variant.h>
#include <AK/Vector.h>
#include <AK/WeakPtr.h>
#include <AK/Weakable.h>
#include <LibGfx/Point.h>
#include <LibWebView/Forward.h>
namespace WebView {
enum class ActionID {
NavigateBack,
NavigateForward,
Reload,
CopySelection,
CutSelection,
Paste,
SelectAll,
SearchSelectedText,
TakeVisibleScreenshot,
TakeFullScreenshot,
ManageBookmarks,
ToggleBookmark,
ToggleBookmarkViaToolbar,
ToggleBookmarksBar,
BookmarkItem,
AddBookmark,
AddBookmarkFolder,
DeleteBookmark,
DeleteBookmarkFolder,
EditBookmark,
EditBookmarkFolder,
OpenAboutPage,
OpenProcessesPage,
OpenSettingsPage,
ToggleDevTools,
ViewSource,
OpenInNewTab,
OpenInNewWindow,
CopyURL,
OpenImage,
SaveImage,
CopyImage,
OpenAudio,
OpenVideo,
PlayMedia,
PauseMedia,
MuteMedia,
UnmuteMedia,
ShowControls,
HideControls,
ToggleMediaLoopState,
EnterFullscreen,
ExitFullscreen,
ZoomIn,
ZoomOut,
ResetZoom,
ResetZoomViaToolbar,
PreferredColorScheme,
PreferredContrast,
PreferredMotion,
DumpSessionHistoryTree,
DumpDOMTree,
DumpLayoutTree,
DumpPaintTree,
DumpStackingContextTree,
DumpDisplayList,
DumpStyleSheets,
DumpStyles,
DumpCSSErrors,
DumpCookies,
DumpLocalStorage,
DumpGCGraph,
ShowLineBoxBorders,
CollectGarbage,
SpoofUserAgent,
NavigatorCompatibilityMode,
EnableScripting,
EnableContentBlocking,
BlockPopUps,
};
using ActionText = Variant<StringView, String>;
inline StringView action_text_to_string_view(ActionText const& text)
{
return text.visit([](auto const& text) -> StringView { return text; });
}
class WEBVIEW_API Action
: public RefCounted<Action>
, public Weakable<Action> {
public:
static NonnullRefPtr<Action> create(ActionText text, ActionID id, Function<void()> action);
static NonnullRefPtr<Action> create_checkable(ActionText text, ActionID id, Function<void()> action);
void activate() { m_action(); }
StringView text() const { return action_text_to_string_view(m_text); }
void set_text(ActionText);
StringView tooltip() const { return action_text_to_string_view(*m_tooltip); }
void set_tooltip(ActionText);
void set_base64_png_icon(Optional<String> base64_png_icon) { m_base64_png_icon = move(base64_png_icon); }
Optional<String const&> base64_png_icon() const { return m_base64_png_icon; }
ActionID id() const { return m_id; }
HashMap<StringView, String> const& properties() const { return m_properties; }
void add_property(StringView name, String value) { m_properties.set(name, move(value)); }
bool enabled() const { return m_enabled; }
void set_enabled(bool);
bool visible() const { return m_visible; }
void set_visible(bool);
bool engaged() const { return m_engaged; }
void set_engaged(bool);
bool is_checkable() const { return m_checked.has_value(); }
bool checked() const { return *m_checked; }
void set_checked(bool);
struct Observer {
virtual ~Observer() = default;
virtual void on_text_changed(Action&) { }
virtual void on_tooltip_changed(Action&) { }
virtual void on_enabled_state_changed(Action&) { }
virtual void on_visible_state_changed(Action&) { }
virtual void on_engaged_state_changed(Action&) { }
virtual void on_checked_state_changed(Action&) { }
};
void add_observer(NonnullOwnPtr<Observer>);
void remove_observer(Observer const& observer);
void set_group(Badge<Menu>, Menu& group) { m_group = group; }
private:
Action(ActionText text, ActionID id, Function<void()> action)
: m_text(move(text))
, m_id(id)
, m_action(move(action))
{
}
void set_checked_internal(bool checked);
ActionText m_text;
Optional<ActionText> m_tooltip;
Optional<String> m_base64_png_icon;
ActionID m_id;
HashMap<StringView, String> m_properties;
bool m_enabled { true };
bool m_visible { true };
bool m_engaged { false };
Optional<bool> m_checked;
Function<void()> m_action;
Vector<NonnullOwnPtr<Observer>, 1> m_observers;
WeakPtr<Menu> m_group;
};
struct WEBVIEW_API Separator { };
class WEBVIEW_API Menu
: public RefCounted<Menu>
, public Weakable<Menu> {
public:
using MenuItem = Variant<NonnullRefPtr<Action>, NonnullRefPtr<Menu>, Separator>;
static NonnullRefPtr<Menu> create(ActionText title);
static NonnullRefPtr<Menu> create_group(ActionText title);
void add_action(NonnullRefPtr<Action> action);
void add_submenu(NonnullRefPtr<Menu> submenu) { m_items.append(move(submenu)); }
void add_separator() { m_items.append(Separator {}); }
size_t size() const { return m_items.size(); }
void shrink(size_t size) { m_items.shrink(size); }
StringView title() const { return action_text_to_string_view(m_title); }
Span<MenuItem> items() { return m_items; }
ReadonlySpan<MenuItem> items() const { return m_items; }
HashMap<StringView, String> const& properties() const { return m_properties; }
void add_property(StringView name, String value) { m_properties.set(name, move(value)); }
void set_render_group_icon(bool render_group_icon) { m_render_group_icon = render_group_icon; }
bool render_group_icon() const { return m_render_group_icon; }
template<typename Callback>
void for_each_action(Callback const& callback)
{
for (auto& item : m_items) {
item.visit(
[&](NonnullRefPtr<Action>& action) { callback(*action); },
[&](NonnullRefPtr<Menu>& submenu) { submenu->for_each_action(callback); },
[&](Separator) {});
}
}
Function<void(Gfx::IntPoint)> on_activation;
private:
explicit Menu(ActionText title)
: m_title(move(title))
{
}
ActionText m_title;
Vector<MenuItem> m_items;
HashMap<StringView, String> m_properties;
bool m_is_group { false };
bool m_render_group_icon { false };
};
}