summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2023-05-15 11:17:58 -0400
committerAndreas Kling <kling@serenityos.org>2023-05-16 12:48:39 +0200
commitc82f678fc615117caaf055219143960203ccd3e9 (patch)
tree5b9f1b63addc0fc85be8ff8fe195b7b48a019d70
parentd8f03dda08b26025469026e5498918e2fc352de5 (diff)
downloadserenity-c82f678fc615117caaf055219143960203ccd3e9.zip
LibWeb+WebContent: Add APIs to control video playback state
This allows for the browser process to control the play/pause state, whether we paint user agent controls on the video, and whether the video loops when it finishes playing.
-rw-r--r--Userland/Libraries/LibWeb/Page/Page.cpp80
-rw-r--r--Userland/Libraries/LibWeb/Page/Page.h5
-rw-r--r--Userland/Libraries/LibWebView/ViewImplementation.cpp15
-rw-r--r--Userland/Libraries/LibWebView/ViewImplementation.h4
-rw-r--r--Userland/Services/WebContent/ConnectionFromClient.cpp15
-rw-r--r--Userland/Services/WebContent/ConnectionFromClient.h4
-rw-r--r--Userland/Services/WebContent/PageHost.cpp15
-rw-r--r--Userland/Services/WebContent/PageHost.h4
-rw-r--r--Userland/Services/WebContent/WebContentServer.ipc4
9 files changed, 146 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/Page/Page.cpp b/Userland/Libraries/LibWeb/Page/Page.cpp
index 7a6cd69240..e1e5f3e915 100644
--- a/Userland/Libraries/LibWeb/Page/Page.cpp
+++ b/Userland/Libraries/LibWeb/Page/Page.cpp
@@ -5,10 +5,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <AK/ScopeGuard.h>
#include <AK/SourceLocation.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
+#include <LibWeb/HTML/HTMLVideoElement.h>
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/Page/Page.h>
#include <LibWeb/Platform/EventLoopPlugin.h>
@@ -281,4 +283,82 @@ void Page::did_request_video_context_menu(i32 video_id, CSSPixelPoint position,
client().page_did_request_video_context_menu(position, url, target, modifiers, is_playing, has_user_agent_controls, is_looping);
}
+WebIDL::ExceptionOr<void> Page::toggle_video_play_state()
+{
+ auto video_element = video_context_menu_element();
+ if (!video_element)
+ return {};
+
+ // FIXME: This runs from outside the context of any user script, so we do not have a running execution
+ // context. This pushes one to allow the promise creation hook to run.
+ auto& environment_settings = video_element->document().relevant_settings_object();
+ environment_settings.prepare_to_run_script();
+
+ ScopeGuard guard { [&] { environment_settings.clean_up_after_running_script(); } };
+
+ if (video_element->potentially_playing())
+ TRY(video_element->pause());
+ else
+ TRY(video_element->play());
+
+ return {};
+}
+
+WebIDL::ExceptionOr<void> Page::toggle_video_loop_state()
+{
+ auto video_element = video_context_menu_element();
+ if (!video_element)
+ return {};
+
+ // FIXME: This runs from outside the context of any user script, so we do not have a running execution
+ // context. This pushes one to allow the promise creation hook to run.
+ auto& environment_settings = video_element->document().relevant_settings_object();
+ environment_settings.prepare_to_run_script();
+
+ ScopeGuard guard { [&] { environment_settings.clean_up_after_running_script(); } };
+
+ if (video_element->has_attribute(HTML::AttributeNames::loop))
+ video_element->remove_attribute(HTML::AttributeNames::loop);
+ else
+ TRY(video_element->set_attribute(HTML::AttributeNames::loop, {}));
+
+ return {};
+}
+
+WebIDL::ExceptionOr<void> Page::toggle_video_controls_state()
+{
+ auto video_element = video_context_menu_element();
+ if (!video_element)
+ return {};
+
+ // FIXME: This runs from outside the context of any user script, so we do not have a running execution
+ // context. This pushes one to allow the promise creation hook to run.
+ auto& environment_settings = video_element->document().relevant_settings_object();
+ environment_settings.prepare_to_run_script();
+
+ ScopeGuard guard { [&] { environment_settings.clean_up_after_running_script(); } };
+
+ if (video_element->has_attribute(HTML::AttributeNames::controls))
+ video_element->remove_attribute(HTML::AttributeNames::controls);
+ else
+ TRY(video_element->set_attribute(HTML::AttributeNames::controls, {}));
+
+ return {};
+}
+
+JS::GCPtr<HTML::HTMLVideoElement> Page::video_context_menu_element()
+{
+ if (!m_video_context_menu_element_id.has_value())
+ return nullptr;
+
+ auto* dom_node = DOM::Node::from_id(*m_video_context_menu_element_id);
+ if (dom_node == nullptr)
+ return nullptr;
+
+ if (!is<HTML::HTMLVideoElement>(dom_node))
+ return nullptr;
+
+ return static_cast<HTML::HTMLVideoElement*>(dom_node);
+}
+
}
diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h
index ac0b9b073a..0b1ef936d9 100644
--- a/Userland/Libraries/LibWeb/Page/Page.h
+++ b/Userland/Libraries/LibWeb/Page/Page.h
@@ -116,10 +116,15 @@ public:
void accept_dialog();
void did_request_video_context_menu(i32 video_id, CSSPixelPoint, AK::URL const&, DeprecatedString const& target, unsigned modifiers, bool is_playing, bool has_user_agent_controls, bool is_looping);
+ WebIDL::ExceptionOr<void> toggle_video_play_state();
+ WebIDL::ExceptionOr<void> toggle_video_loop_state();
+ WebIDL::ExceptionOr<void> toggle_video_controls_state();
bool pdf_viewer_supported() const { return m_pdf_viewer_supported; }
private:
+ JS::GCPtr<HTML::HTMLVideoElement> video_context_menu_element();
+
PageClient& m_client;
JS::Handle<HTML::BrowsingContext> m_top_level_browsing_context;
diff --git a/Userland/Libraries/LibWebView/ViewImplementation.cpp b/Userland/Libraries/LibWebView/ViewImplementation.cpp
index 5d09a8ac68..85cd532f86 100644
--- a/Userland/Libraries/LibWebView/ViewImplementation.cpp
+++ b/Userland/Libraries/LibWebView/ViewImplementation.cpp
@@ -131,6 +131,21 @@ void ViewImplementation::run_javascript(StringView js_source)
client().async_run_javascript(js_source);
}
+void ViewImplementation::toggle_video_play_state()
+{
+ client().async_toggle_video_play_state();
+}
+
+void ViewImplementation::toggle_video_loop_state()
+{
+ client().async_toggle_video_loop_state();
+}
+
+void ViewImplementation::toggle_video_controls_state()
+{
+ client().async_toggle_video_controls_state();
+}
+
void ViewImplementation::handle_resize()
{
resize_backing_stores_if_needed(WindowResizeInProgress::Yes);
diff --git a/Userland/Libraries/LibWebView/ViewImplementation.h b/Userland/Libraries/LibWebView/ViewImplementation.h
index 21ec8de72a..23e8a5d2d4 100644
--- a/Userland/Libraries/LibWebView/ViewImplementation.h
+++ b/Userland/Libraries/LibWebView/ViewImplementation.h
@@ -70,6 +70,10 @@ public:
void run_javascript(StringView);
+ void toggle_video_play_state();
+ void toggle_video_loop_state();
+ void toggle_video_controls_state();
+
virtual void notify_server_did_layout(Badge<WebContentClient>, Gfx::IntSize content_size) = 0;
virtual void notify_server_did_paint(Badge<WebContentClient>, i32 bitmap_id, Gfx::IntSize) = 0;
virtual void notify_server_did_invalidate_content_rect(Badge<WebContentClient>, Gfx::IntRect const&) = 0;
diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp
index 329d08953f..c248d6a0d0 100644
--- a/Userland/Services/WebContent/ConnectionFromClient.cpp
+++ b/Userland/Services/WebContent/ConnectionFromClient.cpp
@@ -756,6 +756,21 @@ void ConnectionFromClient::prompt_closed(Optional<String> const& response)
m_page_host->prompt_closed(response);
}
+void ConnectionFromClient::toggle_video_play_state()
+{
+ m_page_host->toggle_video_play_state().release_value_but_fixme_should_propagate_errors();
+}
+
+void ConnectionFromClient::toggle_video_loop_state()
+{
+ m_page_host->toggle_video_loop_state().release_value_but_fixme_should_propagate_errors();
+}
+
+void ConnectionFromClient::toggle_video_controls_state()
+{
+ m_page_host->toggle_video_controls_state().release_value_but_fixme_should_propagate_errors();
+}
+
void ConnectionFromClient::inspect_accessibility_tree()
{
if (auto* doc = page().top_level_browsing_context().active_document()) {
diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h
index 0cf634560a..d2ed7a58bc 100644
--- a/Userland/Services/WebContent/ConnectionFromClient.h
+++ b/Userland/Services/WebContent/ConnectionFromClient.h
@@ -95,6 +95,10 @@ private:
virtual void confirm_closed(bool accepted) override;
virtual void prompt_closed(Optional<String> const& response) override;
+ virtual void toggle_video_play_state() override;
+ virtual void toggle_video_loop_state() override;
+ virtual void toggle_video_controls_state() override;
+
virtual Messages::WebContentServer::TakeDocumentScreenshotResponse take_document_screenshot() override;
virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override;
diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp
index 0a505ee654..258a359e10 100644
--- a/Userland/Services/WebContent/PageHost.cpp
+++ b/Userland/Services/WebContent/PageHost.cpp
@@ -334,6 +334,21 @@ void PageHost::prompt_closed(Optional<String> response)
page().prompt_closed(move(response));
}
+Web::WebIDL::ExceptionOr<void> PageHost::toggle_video_play_state()
+{
+ return page().toggle_video_play_state();
+}
+
+Web::WebIDL::ExceptionOr<void> PageHost::toggle_video_loop_state()
+{
+ return page().toggle_video_loop_state();
+}
+
+Web::WebIDL::ExceptionOr<void> PageHost::toggle_video_controls_state()
+{
+ return page().toggle_video_controls_state();
+}
+
void PageHost::page_did_request_accept_dialog()
{
m_client.async_did_request_accept_dialog();
diff --git a/Userland/Services/WebContent/PageHost.h b/Userland/Services/WebContent/PageHost.h
index 08c259f217..9f8b068057 100644
--- a/Userland/Services/WebContent/PageHost.h
+++ b/Userland/Services/WebContent/PageHost.h
@@ -49,6 +49,10 @@ public:
void confirm_closed(bool accepted);
void prompt_closed(Optional<String> response);
+ Web::WebIDL::ExceptionOr<void> toggle_video_play_state();
+ Web::WebIDL::ExceptionOr<void> toggle_video_loop_state();
+ Web::WebIDL::ExceptionOr<void> toggle_video_controls_state();
+
[[nodiscard]] Gfx::Color background_color() const;
private:
diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc
index 85331602d5..748b6deb87 100644
--- a/Userland/Services/WebContent/WebContentServer.ipc
+++ b/Userland/Services/WebContent/WebContentServer.ipc
@@ -76,4 +76,8 @@ endpoint WebContentServer
alert_closed() =|
confirm_closed(bool accepted) =|
prompt_closed(Optional<String> response) =|
+
+ toggle_video_play_state() =|
+ toggle_video_loop_state() =|
+ toggle_video_controls_state() =|
}