summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-09-07 20:30:31 +0200
committerAndreas Kling <kling@serenityos.org>2022-09-07 20:30:31 +0200
commit9567e211e7c0ae27a65c1f23c4fd9071e8c35e29 (patch)
treed0de19021f93a4ffa604c9a1e51218dbe3aa2e9d
parent7e5a8bd4b04963325e219c0cbb4c629a456c6fbc (diff)
downloadserenity-9567e211e7c0ae27a65c1f23c4fd9071e8c35e29.zip
LibWeb+WebContent: Add abstraction layer for event loop and timers
Instead of using Core::EventLoop and Core::Timer directly, LibWeb now goes through a Web::Platform abstraction layer instead. This will allow us to plug in Qt's event loop (and QTimer) over in Ladybird, to avoid having to deal with multiple event loops.
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt2
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.cpp6
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h4
-rw-r--r--Userland/Libraries/LibWeb/Forward.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/AnimationFrameCallbackDriver.h6
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp2
-rw-r--r--Userland/Libraries/LibWeb/HTML/BrowsingContext.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp14
-rw-r--r--Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/Timer.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/Timer.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/Window.h2
-rw-r--r--Userland/Libraries/LibWeb/Loader/ImageLoader.cpp4
-rw-r--r--Userland/Libraries/LibWeb/Loader/ImageLoader.h4
-rw-r--r--Userland/Libraries/LibWeb/Loader/Resource.cpp4
-rw-r--r--Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp12
-rw-r--r--Userland/Libraries/LibWeb/Platform/EventLoopPlugin.cpp28
-rw-r--r--Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h26
-rw-r--r--Userland/Libraries/LibWeb/Platform/Timer.cpp38
-rw-r--r--Userland/Libraries/LibWeb/Platform/Timer.h40
-rw-r--r--Userland/Services/WebContent/CMakeLists.txt6
-rw-r--r--Userland/Services/WebContent/EventLoopPluginSerenity.cpp34
-rw-r--r--Userland/Services/WebContent/EventLoopPluginSerenity.h23
-rw-r--r--Userland/Services/WebContent/TimerSerenity.cpp84
-rw-r--r--Userland/Services/WebContent/TimerSerenity.h42
-rw-r--r--Userland/Services/WebContent/main.cpp4
28 files changed, 365 insertions, 42 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt
index 0e7dfaa0f0..079311fe98 100644
--- a/Userland/Libraries/LibWeb/CMakeLists.txt
+++ b/Userland/Libraries/LibWeb/CMakeLists.txt
@@ -351,6 +351,8 @@ set(SOURCES
Painting/ShadowPainting.cpp
Painting/StackingContext.cpp
Painting/TextPaintable.cpp
+ Platform/EventLoopPlugin.cpp
+ Platform/Timer.cpp
RequestIdleCallback/IdleDeadline.cpp
ResizeObserver/ResizeObserver.cpp
SVG/AttributeNames.cpp
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp
index 43a88e19ed..5de2904b39 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Document.cpp
@@ -10,7 +10,6 @@
#include <AK/CharacterTypes.h>
#include <AK/StringBuilder.h>
#include <AK/Utf8View.h>
-#include <LibCore/Timer.h>
#include <LibJS/Interpreter.h>
#include <LibJS/Parser.h>
#include <LibJS/Runtime/FunctionObject.h>
@@ -67,6 +66,7 @@
#include <LibWeb/Layout/TreeBuilder.h>
#include <LibWeb/Namespace.h>
#include <LibWeb/Page/Page.h>
+#include <LibWeb/Platform/Timer.h>
#include <LibWeb/SVG/TagNames.h>
#include <LibWeb/UIEvents/EventNames.h>
#include <LibWeb/UIEvents/FocusEvent.h>
@@ -286,11 +286,11 @@ Document::Document(HTML::Window& window, const AK::URL& url)
HTML::main_thread_event_loop().register_document({}, *this);
- m_style_update_timer = Core::Timer::create_single_shot(0, [this] {
+ m_style_update_timer = Platform::Timer::create_single_shot(0, [this] {
update_style();
});
- m_layout_update_timer = Core::Timer::create_single_shot(0, [this] {
+ m_layout_update_timer = Platform::Timer::create_single_shot(0, [this] {
force_layout();
});
}
diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h
index 894e9011d9..6eda355046 100644
--- a/Userland/Libraries/LibWeb/DOM/Document.h
+++ b/Userland/Libraries/LibWeb/DOM/Document.h
@@ -386,8 +386,8 @@ private:
Optional<Color> m_active_link_color;
Optional<Color> m_visited_link_color;
- RefPtr<Core::Timer> m_style_update_timer;
- RefPtr<Core::Timer> m_layout_update_timer;
+ RefPtr<Platform::Timer> m_style_update_timer;
+ RefPtr<Platform::Timer> m_layout_update_timer;
RefPtr<HTML::HTMLParser> m_parser;
bool m_active_parser_was_aborted { false };
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index 1c7718b722..8b4ec2d74c 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -351,6 +351,10 @@ struct BorderRadiiData;
struct LinearGradientData;
}
+namespace Web::Platform {
+class Timer;
+}
+
namespace Web::RequestIdleCallback {
class IdleDeadline;
}
diff --git a/Userland/Libraries/LibWeb/HTML/AnimationFrameCallbackDriver.h b/Userland/Libraries/LibWeb/HTML/AnimationFrameCallbackDriver.h
index 397ab1f3e6..510b2c449c 100644
--- a/Userland/Libraries/LibWeb/HTML/AnimationFrameCallbackDriver.h
+++ b/Userland/Libraries/LibWeb/HTML/AnimationFrameCallbackDriver.h
@@ -8,8 +8,8 @@
#include <AK/Function.h>
#include <AK/IDAllocator.h>
-#include <LibCore/Timer.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
+#include <LibWeb/Platform/Timer.h>
namespace Web::HTML {
@@ -18,7 +18,7 @@ struct AnimationFrameCallbackDriver {
AnimationFrameCallbackDriver()
{
- m_timer = Core::Timer::create_single_shot(16, [] {
+ m_timer = Platform::Timer::create_single_shot(16, [] {
HTML::main_thread_event_loop().schedule();
});
}
@@ -57,7 +57,7 @@ struct AnimationFrameCallbackDriver {
private:
HashMap<i32, Callback> m_callbacks;
IDAllocator m_id_allocator;
- RefPtr<Core::Timer> m_timer;
+ RefPtr<Platform::Timer> m_timer;
};
}
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
index d92e1532e3..28fdb48a01 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp
@@ -229,7 +229,7 @@ BrowsingContext::BrowsingContext(Page& page, HTML::BrowsingContextContainer* con
, m_event_handler({}, *this)
, m_container(container)
{
- m_cursor_blink_timer = Core::Timer::construct(500, [this] {
+ m_cursor_blink_timer = Platform::Timer::create_repeating(500, [this] {
if (!is_focused_context())
return;
if (m_cursor_position.node() && m_cursor_position.node()->layout_node()) {
diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
index ddcd870ea1..1185caf3a9 100644
--- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
+++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h
@@ -10,7 +10,6 @@
#include <AK/Noncopyable.h>
#include <AK/RefPtr.h>
#include <AK/WeakPtr.h>
-#include <LibCore/Timer.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/Rect.h>
#include <LibGfx/Size.h>
@@ -20,6 +19,7 @@
#include <LibWeb/HTML/SessionHistoryEntry.h>
#include <LibWeb/Loader/FrameLoader.h>
#include <LibWeb/Page/EventHandler.h>
+#include <LibWeb/Platform/Timer.h>
#include <LibWeb/TreeNode.h>
namespace Web::HTML {
@@ -148,7 +148,7 @@ private:
Gfx::IntPoint m_viewport_scroll_offset;
DOM::Position m_cursor_position;
- RefPtr<Core::Timer> m_cursor_blink_timer;
+ RefPtr<Platform::Timer> m_cursor_blink_timer;
bool m_cursor_blink_state { false };
HashTable<ViewportClient*> m_viewport_clients;
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
index 34978bc6c3..5602e5545d 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
@@ -5,8 +5,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-#include <LibCore/EventLoop.h>
-#include <LibCore/Timer.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/DOM/Document.h>
@@ -15,6 +13,8 @@
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/HighResolutionTime/Performance.h>
+#include <LibWeb/Platform/EventLoopPlugin.h>
+#include <LibWeb/Platform/Timer.h>
namespace Web::HTML {
@@ -29,7 +29,7 @@ EventLoop::~EventLoop() = default;
void EventLoop::schedule()
{
if (!m_system_event_loop_timer) {
- m_system_event_loop_timer = Core::Timer::create_single_shot(0, [this] {
+ m_system_event_loop_timer = Platform::Timer::create_single_shot(0, [this] {
process();
});
}
@@ -74,13 +74,7 @@ void EventLoop::spin_until(Function<bool()> goal_condition)
// NOTE: This is achieved by returning from the function.
// 1. Wait until the condition goal is met.
- Core::EventLoop loop;
- loop.spin_until([&]() -> bool {
- if (goal_condition())
- return true;
-
- return goal_condition();
- });
+ Platform::EventLoopPlugin::the().spin_until(move(goal_condition));
// 7. Stop task, allowing whatever algorithm that invoked it to resume.
// NOTE: This is achieved by returning from the function.
diff --git a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
index 61685ae6d6..024666b992 100644
--- a/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
+++ b/Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h
@@ -84,7 +84,7 @@ private:
JS::VM* m_vm { nullptr };
- RefPtr<Core::Timer> m_system_event_loop_timer;
+ RefPtr<Platform::Timer> m_system_event_loop_timer;
// https://html.spec.whatwg.org/#performing-a-microtask-checkpoint
bool m_performing_a_microtask_checkpoint { false };
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.cpp
index c28d574fad..6bfa7806fd 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.cpp
@@ -4,14 +4,14 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-#include <LibCore/Timer.h>
#include <LibWeb/HTML/HTMLBlinkElement.h>
+#include <LibWeb/Platform/Timer.h>
namespace Web::HTML {
HTMLBlinkElement::HTMLBlinkElement(DOM::Document& document, DOM::QualifiedName qualified_name)
: HTMLElement(document, move(qualified_name))
- , m_timer(Core::Timer::construct())
+ , m_timer(Platform::Timer::create())
{
m_timer->set_interval(500);
m_timer->on_timeout = [this] { blink(); };
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h
index 39bb55d611..43097c9cad 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLBlinkElement.h
@@ -22,7 +22,7 @@ private:
void blink();
- NonnullRefPtr<Core::Timer> m_timer;
+ NonnullRefPtr<Platform::Timer> m_timer;
};
}
diff --git a/Userland/Libraries/LibWeb/HTML/Timer.cpp b/Userland/Libraries/LibWeb/HTML/Timer.cpp
index b2e75fbdbc..228b514481 100644
--- a/Userland/Libraries/LibWeb/HTML/Timer.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Timer.cpp
@@ -4,9 +4,9 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
-#include <LibCore/Timer.h>
#include <LibWeb/HTML/Timer.h>
#include <LibWeb/HTML/Window.h>
+#include <LibWeb/Platform/Timer.h>
namespace Web::HTML {
@@ -20,7 +20,7 @@ Timer::Timer(Window& window, i32 milliseconds, Function<void()> callback, i32 id
, m_callback(move(callback))
, m_id(id)
{
- m_timer = Core::Timer::create_single_shot(milliseconds, [this] {
+ m_timer = Platform::Timer::create_single_shot(milliseconds, [this] {
m_callback();
});
}
diff --git a/Userland/Libraries/LibWeb/HTML/Timer.h b/Userland/Libraries/LibWeb/HTML/Timer.h
index aa2edfb3f5..2f1aab762e 100644
--- a/Userland/Libraries/LibWeb/HTML/Timer.h
+++ b/Userland/Libraries/LibWeb/HTML/Timer.h
@@ -30,7 +30,7 @@ private:
virtual void visit_edges(Cell::Visitor&) override;
- RefPtr<Core::Timer> m_timer;
+ RefPtr<Platform::Timer> m_timer;
JS::NonnullGCPtr<Window> m_window;
Function<void()> m_callback;
i32 m_id { 0 };
diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h
index e1ce9e953b..587cc8616f 100644
--- a/Userland/Libraries/LibWeb/HTML/Window.h
+++ b/Userland/Libraries/LibWeb/HTML/Window.h
@@ -8,7 +8,9 @@
#include <AK/Badge.h>
#include <AK/IDAllocator.h>
+#include <AK/NonnullRefPtrVector.h>
#include <AK/RefPtr.h>
+#include <AK/TypeCasts.h>
#include <AK/URL.h>
#include <LibJS/Heap/Heap.h>
#include <LibWeb/Bindings/CrossOriginAbstractOperations.h>
diff --git a/Userland/Libraries/LibWeb/Loader/ImageLoader.cpp b/Userland/Libraries/LibWeb/Loader/ImageLoader.cpp
index dc4e3f3544..ecbe258b40 100644
--- a/Userland/Libraries/LibWeb/Loader/ImageLoader.cpp
+++ b/Userland/Libraries/LibWeb/Loader/ImageLoader.cpp
@@ -5,18 +5,18 @@
*/
#include <AK/Debug.h>
-#include <LibCore/Timer.h>
#include <LibGfx/Bitmap.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Element.h>
#include <LibWeb/Loader/ImageLoader.h>
#include <LibWeb/Loader/ResourceLoader.h>
+#include <LibWeb/Platform/Timer.h>
namespace Web {
ImageLoader::ImageLoader(DOM::Element& owner_element)
: m_owner_element(owner_element)
- , m_timer(Core::Timer::construct())
+ , m_timer(Platform::Timer::create())
{
}
diff --git a/Userland/Libraries/LibWeb/Loader/ImageLoader.h b/Userland/Libraries/LibWeb/Loader/ImageLoader.h
index 23c5344b1f..03a00cd682 100644
--- a/Userland/Libraries/LibWeb/Loader/ImageLoader.h
+++ b/Userland/Libraries/LibWeb/Loader/ImageLoader.h
@@ -7,8 +7,8 @@
#pragma once
#include <AK/Function.h>
-#include <LibCore/Timer.h>
#include <LibWeb/Loader/ImageResource.h>
+#include <LibWeb/Platform/Timer.h>
namespace Web {
@@ -60,7 +60,7 @@ private:
size_t m_current_frame_index { 0 };
size_t m_loops_completed { 0 };
LoadingState m_loading_state { LoadingState::Loading };
- NonnullRefPtr<Core::Timer> m_timer;
+ NonnullRefPtr<Platform::Timer> m_timer;
size_t m_redirects_count { 0 };
};
diff --git a/Userland/Libraries/LibWeb/Loader/Resource.cpp b/Userland/Libraries/LibWeb/Loader/Resource.cpp
index e5ac447050..79c54edcfa 100644
--- a/Userland/Libraries/LibWeb/Loader/Resource.cpp
+++ b/Userland/Libraries/LibWeb/Loader/Resource.cpp
@@ -6,12 +6,12 @@
#include <AK/Debug.h>
#include <AK/Function.h>
-#include <LibCore/EventLoop.h>
#include <LibCore/MimeData.h>
#include <LibTextCodec/Decoder.h>
#include <LibWeb/HTML/HTMLImageElement.h>
#include <LibWeb/Loader/Resource.h>
#include <LibWeb/Loader/ResourceLoader.h>
+#include <LibWeb/Platform/EventLoopPlugin.h>
namespace Web {
@@ -168,7 +168,7 @@ void ResourceClient::set_resource(Resource* resource)
// This ensures that these callbacks always happen in a consistent way, instead of being invoked
// synchronously in some cases, and asynchronously in others.
if (resource->is_loaded() || resource->is_failed()) {
- Core::deferred_invoke([this, strong_resource = NonnullRefPtr { *m_resource }] {
+ Platform::EventLoopPlugin::the().deferred_invoke([this, strong_resource = NonnullRefPtr { *m_resource }] {
if (m_resource != strong_resource.ptr())
return;
diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp
index 98101888d8..d562506ac6 100644
--- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp
+++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp
@@ -9,14 +9,14 @@
#include <AK/Debug.h>
#include <AK/JsonObject.h>
#include <LibCore/ElapsedTimer.h>
-#include <LibCore/EventLoop.h>
#include <LibCore/File.h>
-#include <LibCore/Timer.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 <LibWeb/Platform/EventLoopPlugin.h>
+#include <LibWeb/Platform/Timer.h>
#ifdef __serenity__
# include <serenity.h>
@@ -179,7 +179,7 @@ void ResourceLoader::load(LoadRequest& request, Function<void(ReadonlyBytes, Has
HashMap<String, String, CaseInsensitiveStringTraits> response_headers;
response_headers.set("Content-Type", "text/html; charset=UTF-8");
- deferred_invoke([success_callback = move(success_callback), response_headers = move(response_headers)] {
+ Platform::EventLoopPlugin::the().deferred_invoke([success_callback = move(success_callback), response_headers = move(response_headers)] {
success_callback(String::empty().to_byte_buffer(), response_headers, {});
});
return;
@@ -206,7 +206,7 @@ void ResourceLoader::load(LoadRequest& request, Function<void(ReadonlyBytes, Has
}
log_success(request);
- deferred_invoke([data = move(data), success_callback = move(success_callback)] {
+ Platform::EventLoopPlugin::the().deferred_invoke([data = move(data), success_callback = move(success_callback)] {
success_callback(data, {}, {});
});
return;
@@ -284,7 +284,7 @@ void ResourceLoader::load(LoadRequest& request, Function<void(ReadonlyBytes, Has
}
if (timeout.has_value() && timeout.value() > 0) {
- auto timer = Core::Timer::create_single_shot(timeout.value(), nullptr);
+ auto timer = Platform::Timer::create_single_shot(timeout.value(), nullptr);
timer->on_timeout = [timer, protocol_request, timeout_callback = move(timeout_callback)]() mutable {
protocol_request->stop();
if (timeout_callback)
@@ -312,7 +312,7 @@ void ResourceLoader::load(LoadRequest& request, Function<void(ReadonlyBytes, Has
}
log_success(request);
success_callback(payload, response_headers, status_code);
- deferred_invoke([this, &protocol_request] {
+ Platform::EventLoopPlugin::the().deferred_invoke([this, &protocol_request] {
m_active_requests.remove(protocol_request);
});
};
diff --git a/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.cpp b/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.cpp
new file mode 100644
index 0000000000..dcd9b01b26
--- /dev/null
+++ b/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/Function.h>
+#include <LibWeb/Platform/EventLoopPlugin.h>
+
+namespace Web::Platform {
+
+EventLoopPlugin* s_the;
+
+EventLoopPlugin& EventLoopPlugin::the()
+{
+ VERIFY(s_the);
+ return *s_the;
+}
+
+void EventLoopPlugin::install(EventLoopPlugin& plugin)
+{
+ VERIFY(!s_the);
+ s_the = &plugin;
+}
+
+EventLoopPlugin::~EventLoopPlugin() = default;
+
+}
diff --git a/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h b/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h
new file mode 100644
index 0000000000..de08e14fb9
--- /dev/null
+++ b/Userland/Libraries/LibWeb/Platform/EventLoopPlugin.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Forward.h>
+#include <LibWeb/Forward.h>
+
+namespace Web::Platform {
+
+class EventLoopPlugin {
+public:
+ static EventLoopPlugin& the();
+ static void install(EventLoopPlugin&);
+
+ virtual ~EventLoopPlugin();
+
+ virtual void spin_until(Function<bool()> goal_condition) = 0;
+ virtual void deferred_invoke(Function<void()>) = 0;
+ virtual NonnullRefPtr<Timer> create_timer() = 0;
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/Platform/Timer.cpp b/Userland/Libraries/LibWeb/Platform/Timer.cpp
new file mode 100644
index 0000000000..d3de49a958
--- /dev/null
+++ b/Userland/Libraries/LibWeb/Platform/Timer.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/NonnullRefPtr.h>
+#include <LibWeb/Platform/EventLoopPlugin.h>
+#include <LibWeb/Platform/Timer.h>
+
+namespace Web::Platform {
+
+Timer::~Timer() = default;
+
+NonnullRefPtr<Timer> Timer::create()
+{
+ return EventLoopPlugin::the().create_timer();
+}
+
+NonnullRefPtr<Timer> Timer::create_repeating(int interval_ms, Function<void()>&& timeout_handler)
+{
+ auto timer = EventLoopPlugin::the().create_timer();
+ timer->set_single_shot(false);
+ timer->set_interval(interval_ms);
+ timer->on_timeout = move(timeout_handler);
+ return timer;
+}
+
+NonnullRefPtr<Timer> Timer::create_single_shot(int interval_ms, Function<void()>&& timeout_handler)
+{
+ auto timer = EventLoopPlugin::the().create_timer();
+ timer->set_single_shot(true);
+ timer->set_interval(interval_ms);
+ timer->on_timeout = move(timeout_handler);
+ return timer;
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/Platform/Timer.h b/Userland/Libraries/LibWeb/Platform/Timer.h
new file mode 100644
index 0000000000..bde3ca3f3a
--- /dev/null
+++ b/Userland/Libraries/LibWeb/Platform/Timer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Function.h>
+#include <AK/RefCounted.h>
+
+namespace Web::Platform {
+
+class Timer : public RefCounted<Timer> {
+public:
+ static NonnullRefPtr<Timer> create();
+ static NonnullRefPtr<Timer> create_repeating(int interval_ms, Function<void()>&& timeout_handler);
+ static NonnullRefPtr<Timer> create_single_shot(int interval_ms, Function<void()>&& timeout_handler);
+
+ virtual ~Timer();
+
+ virtual void start() = 0;
+ virtual void start(int interval_ms) = 0;
+ virtual void restart() = 0;
+ virtual void restart(int interval_ms) = 0;
+ virtual void stop() = 0;
+
+ virtual void set_active(bool) = 0;
+
+ virtual bool is_active() const = 0;
+ virtual int interval() const = 0;
+ virtual void set_interval(int interval_ms) = 0;
+
+ virtual bool is_single_shot() const = 0;
+ virtual void set_single_shot(bool) = 0;
+
+ Function<void()> on_timeout;
+};
+
+}
diff --git a/Userland/Services/WebContent/CMakeLists.txt b/Userland/Services/WebContent/CMakeLists.txt
index 3ec41acdb5..8327b15562 100644
--- a/Userland/Services/WebContent/CMakeLists.txt
+++ b/Userland/Services/WebContent/CMakeLists.txt
@@ -10,11 +10,13 @@ compile_ipc(WebContentClient.ipc WebContentClientEndpoint.h)
set(SOURCES
ConnectionFromClient.cpp
ConsoleGlobalObject.cpp
- main.cpp
+ EventLoopPluginSerenity.cpp
PageHost.cpp
+ TimerSerenity.cpp
+ WebContentClientEndpoint.h
WebContentConsoleClient.cpp
WebContentServerEndpoint.h
- WebContentClientEndpoint.h
+ main.cpp
)
serenity_bin(WebContent)
diff --git a/Userland/Services/WebContent/EventLoopPluginSerenity.cpp b/Userland/Services/WebContent/EventLoopPluginSerenity.cpp
new file mode 100644
index 0000000000..15a6c17dd1
--- /dev/null
+++ b/Userland/Services/WebContent/EventLoopPluginSerenity.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "EventLoopPluginSerenity.h"
+#include "TimerSerenity.h"
+#include <AK/Function.h>
+#include <AK/NonnullRefPtr.h>
+#include <LibCore/EventLoop.h>
+
+namespace WebContent {
+
+EventLoopPluginSerenity::EventLoopPluginSerenity() = default;
+EventLoopPluginSerenity::~EventLoopPluginSerenity() = default;
+
+void EventLoopPluginSerenity::spin_until(Function<bool()> goal_condition)
+{
+ Core::EventLoop::current().spin_until(move(goal_condition));
+}
+
+void EventLoopPluginSerenity::deferred_invoke(Function<void()> function)
+{
+ VERIFY(function);
+ Core::deferred_invoke(move(function));
+}
+
+NonnullRefPtr<Web::Platform::Timer> EventLoopPluginSerenity::create_timer()
+{
+ return TimerSerenity::create();
+}
+
+}
diff --git a/Userland/Services/WebContent/EventLoopPluginSerenity.h b/Userland/Services/WebContent/EventLoopPluginSerenity.h
new file mode 100644
index 0000000000..0493ac7ab1
--- /dev/null
+++ b/Userland/Services/WebContent/EventLoopPluginSerenity.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Platform/EventLoopPlugin.h>
+
+namespace WebContent {
+
+class EventLoopPluginSerenity final : public Web::Platform::EventLoopPlugin {
+public:
+ EventLoopPluginSerenity();
+ virtual ~EventLoopPluginSerenity() override;
+
+ virtual void spin_until(Function<bool()> goal_condition) override;
+ virtual void deferred_invoke(Function<void()>) override;
+ virtual NonnullRefPtr<Web::Platform::Timer> create_timer() override;
+};
+
+}
diff --git a/Userland/Services/WebContent/TimerSerenity.cpp b/Userland/Services/WebContent/TimerSerenity.cpp
new file mode 100644
index 0000000000..a702ba2eca
--- /dev/null
+++ b/Userland/Services/WebContent/TimerSerenity.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "TimerSerenity.h"
+#include <AK/NonnullRefPtr.h>
+#include <LibCore/Timer.h>
+
+namespace WebContent {
+
+NonnullRefPtr<TimerSerenity> TimerSerenity::create()
+{
+ return adopt_ref(*new TimerSerenity);
+}
+
+TimerSerenity::TimerSerenity()
+ : m_timer(Core::Timer::construct())
+{
+ m_timer->on_timeout = [this] {
+ if (on_timeout)
+ on_timeout();
+ };
+}
+
+TimerSerenity::~TimerSerenity() = default;
+
+void TimerSerenity::start()
+{
+ m_timer->start();
+}
+
+void TimerSerenity::start(int interval_ms)
+{
+ m_timer->start(interval_ms);
+}
+
+void TimerSerenity::restart()
+{
+ m_timer->restart();
+}
+
+void TimerSerenity::restart(int interval_ms)
+{
+ m_timer->restart(interval_ms);
+}
+
+void TimerSerenity::stop()
+{
+ m_timer->stop();
+}
+
+void TimerSerenity::set_active(bool active)
+{
+ m_timer->set_active(active);
+}
+
+bool TimerSerenity::is_active() const
+{
+ return m_timer->is_active();
+}
+
+int TimerSerenity::interval() const
+{
+ return m_timer->interval();
+}
+
+void TimerSerenity::set_interval(int interval_ms)
+{
+ m_timer->set_interval(interval_ms);
+}
+
+bool TimerSerenity::is_single_shot() const
+{
+ return m_timer->is_single_shot();
+}
+
+void TimerSerenity::set_single_shot(bool single_shot)
+{
+ m_timer->set_single_shot(single_shot);
+}
+
+}
diff --git a/Userland/Services/WebContent/TimerSerenity.h b/Userland/Services/WebContent/TimerSerenity.h
new file mode 100644
index 0000000000..d0f9200839
--- /dev/null
+++ b/Userland/Services/WebContent/TimerSerenity.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/NonnullRefPtr.h>
+#include <LibCore/Forward.h>
+#include <LibWeb/Platform/Timer.h>
+
+namespace WebContent {
+
+class TimerSerenity final : public Web::Platform::Timer {
+public:
+ static NonnullRefPtr<TimerSerenity> create();
+
+ virtual ~TimerSerenity();
+
+ virtual void start() override;
+ virtual void start(int interval_ms) override;
+ virtual void restart() override;
+ virtual void restart(int interval_ms) override;
+ virtual void stop() override;
+
+ virtual void set_active(bool) override;
+
+ virtual bool is_active() const override;
+ virtual int interval() const override;
+ virtual void set_interval(int interval_ms) override;
+
+ virtual bool is_single_shot() const override;
+ virtual void set_single_shot(bool) override;
+
+private:
+ TimerSerenity();
+
+ NonnullRefPtr<Core::Timer> m_timer;
+};
+
+}
diff --git a/Userland/Services/WebContent/main.cpp b/Userland/Services/WebContent/main.cpp
index 9db9c3ed40..5a06e6e00c 100644
--- a/Userland/Services/WebContent/main.cpp
+++ b/Userland/Services/WebContent/main.cpp
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include "EventLoopPluginSerenity.h"
#include <LibCore/EventLoop.h>
#include <LibCore/LocalServer.h>
#include <LibCore/System.h>
@@ -11,6 +12,7 @@
#include <LibMain/Main.h>
#include <LibWeb/ImageDecoding.h>
#include <LibWeb/Loader/ResourceLoader.h>
+#include <LibWeb/Platform/EventLoopPlugin.h>
#include <LibWeb/WebSockets/WebSocket.h>
#include <LibWebView/ImageDecoderClientAdapter.h>
#include <LibWebView/RequestServerAdapter.h>
@@ -28,6 +30,8 @@ ErrorOr<int> serenity_main(Main::Arguments)
TRY(Core::System::unveil("/tmp/user/%uid/portal/websocket", "rw"));
TRY(Core::System::unveil(nullptr, nullptr));
+ Web::Platform::EventLoopPlugin::install(*new WebContent::EventLoopPluginSerenity);
+
Web::ImageDecoding::Decoder::initialize(WebView::ImageDecoderClientAdapter::create());
Web::WebSockets::WebSocketClientManager::initialize(TRY(WebView::WebSocketClientManagerAdapter::try_create()));
Web::ResourceLoader::initialize(TRY(WebView::RequestServerAdapter::try_create()));