From 5e07c27e25af86e54cd9d98f7bc1079f9907f6c3 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 20 Feb 2021 12:05:18 +0100 Subject: [PATCH] LibWeb: Implement Window.prompt() --- .../LibWeb/Bindings/WindowObject.cpp | 30 ++++++++++++++++++- .../Libraries/LibWeb/Bindings/WindowObject.h | 1 + Userland/Libraries/LibWeb/DOM/Window.cpp | 7 +++++ Userland/Libraries/LibWeb/DOM/Window.h | 1 + .../Libraries/LibWeb/InProcessWebView.cpp | 9 ++++++ Userland/Libraries/LibWeb/InProcessWebView.h | 1 + .../Libraries/LibWeb/OutOfProcessWebView.cpp | 9 ++++++ .../Libraries/LibWeb/OutOfProcessWebView.h | 1 + Userland/Libraries/LibWeb/Page/Page.h | 1 + .../Libraries/LibWeb/WebContentClient.cpp | 8 ++++- Userland/Libraries/LibWeb/WebContentClient.h | 1 + Userland/Services/WebContent/PageHost.cpp | 5 ++++ Userland/Services/WebContent/PageHost.h | 1 + .../Services/WebContent/WebContentClient.ipc | 1 + 14 files changed, 74 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp index e0c0ad3e6fa..2abd1f54f25 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -69,6 +69,7 @@ void WindowObject::initialize() define_native_property("performance", performance_getter, nullptr, JS::Attribute::Enumerable); define_native_function("alert", alert); define_native_function("confirm", confirm); + define_native_function("prompt", prompt); define_native_function("setInterval", set_interval, 1); define_native_function("setTimeout", set_timeout, 1); define_native_function("clearInterval", clear_interval, 1); @@ -121,6 +122,10 @@ static DOM::Window* impl_from(JS::VM& vm, JS::GlobalObject& global_object) JS_DEFINE_NATIVE_FUNCTION(WindowObject::alert) { + // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#simple-dialogs + // Note: This method is defined using two overloads, instead of using an optional argument, + // for historical reasons. The practical impact of this is that alert(undefined) is + // treated as alert("undefined"), but alert() is treated as alert(""). auto* impl = impl_from(vm, global_object); if (!impl) return {}; @@ -140,7 +145,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm) if (!impl) return {}; String message = ""; - if (vm.argument_count()) { + if (!vm.argument(0).is_undefined()) { message = vm.argument(0).to_string(global_object); if (vm.exception()) return {}; @@ -148,6 +153,29 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm) return JS::Value(impl->confirm(message)); } +JS_DEFINE_NATIVE_FUNCTION(WindowObject::prompt) +{ + auto* impl = impl_from(vm, global_object); + if (!impl) + return {}; + String message = ""; + String default_ = ""; + if (!vm.argument(0).is_undefined()) { + message = vm.argument(0).to_string(global_object); + if (vm.exception()) + return {}; + } + if (!vm.argument(1).is_undefined()) { + default_ = vm.argument(1).to_string(global_object); + if (vm.exception()) + return {}; + } + auto response = impl->prompt(message, default_); + if (response.is_null()) + return JS::js_null(); + return JS::js_string(vm, response); +} + JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval) { auto* impl = impl_from(vm, global_object); diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.h b/Userland/Libraries/LibWeb/Bindings/WindowObject.h index be565d344c6..48d95212c72 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.h @@ -86,6 +86,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(alert); JS_DECLARE_NATIVE_FUNCTION(confirm); + JS_DECLARE_NATIVE_FUNCTION(prompt); JS_DECLARE_NATIVE_FUNCTION(set_interval); JS_DECLARE_NATIVE_FUNCTION(set_timeout); JS_DECLARE_NATIVE_FUNCTION(clear_interval); diff --git a/Userland/Libraries/LibWeb/DOM/Window.cpp b/Userland/Libraries/LibWeb/DOM/Window.cpp index cf1a164c389..b6fae82ebf5 100644 --- a/Userland/Libraries/LibWeb/DOM/Window.cpp +++ b/Userland/Libraries/LibWeb/DOM/Window.cpp @@ -71,6 +71,13 @@ bool Window::confirm(const String& message) return false; } +String Window::prompt(const String& message, const String& default_) +{ + if (auto* page = m_document.page()) + return page->client().page_did_request_prompt(message, default_); + return {}; +} + i32 Window::set_interval(JS::Function& callback, i32 interval) { auto timer = Timer::create_interval(*this, interval, callback); diff --git a/Userland/Libraries/LibWeb/DOM/Window.h b/Userland/Libraries/LibWeb/DOM/Window.h index 725da546d75..4227130eec9 100644 --- a/Userland/Libraries/LibWeb/DOM/Window.h +++ b/Userland/Libraries/LibWeb/DOM/Window.h @@ -57,6 +57,7 @@ public: void alert(const String&); bool confirm(const String&); + String prompt(const String&, const String&); i32 request_animation_frame(JS::Function&); void cancel_animation_frame(i32); diff --git a/Userland/Libraries/LibWeb/InProcessWebView.cpp b/Userland/Libraries/LibWeb/InProcessWebView.cpp index 7c7a22d654b..97cc9ada414 100644 --- a/Userland/Libraries/LibWeb/InProcessWebView.cpp +++ b/Userland/Libraries/LibWeb/InProcessWebView.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -425,4 +426,12 @@ bool InProcessWebView::page_did_request_confirm(const String& message) return confirm_result == GUI::Dialog::ExecResult::ExecOK; } +String InProcessWebView::page_did_request_prompt(const String& message, const String& default_) +{ + String value { default_ }; + if (GUI::InputBox::show(window(), value, message, "Prompt") == GUI::InputBox::ExecOK) + return value; + return {}; +} + } diff --git a/Userland/Libraries/LibWeb/InProcessWebView.h b/Userland/Libraries/LibWeb/InProcessWebView.h index 2350b2b3d81..62f5f96353d 100644 --- a/Userland/Libraries/LibWeb/InProcessWebView.h +++ b/Userland/Libraries/LibWeb/InProcessWebView.h @@ -107,6 +107,7 @@ private: virtual void page_did_request_scroll_into_view(const Gfx::IntRect&) override; virtual void page_did_request_alert(const String&) override; virtual bool page_did_request_confirm(const String&) override; + virtual String page_did_request_prompt(const String&, const String&) override; void layout_and_sync_size(); diff --git a/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp b/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp index 6b8988404be..36a4cf19bff 100644 --- a/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp +++ b/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp @@ -28,6 +28,7 @@ #include "WebContentClient.h" #include #include +#include #include #include #include @@ -293,6 +294,14 @@ bool OutOfProcessWebView::notify_server_did_request_confirm(Badge, const String& message, const String& default_) +{ + String response { default_ }; + if (GUI::InputBox::show(window(), response, message, "Prompt") == GUI::InputBox::ExecOK) + return response; + return {}; +} + void OutOfProcessWebView::did_scroll() { client().post_message(Messages::WebContentServer::SetViewportRect(visible_content_rect())); diff --git a/Userland/Libraries/LibWeb/OutOfProcessWebView.h b/Userland/Libraries/LibWeb/OutOfProcessWebView.h index 260792f16b5..5ca5bdd7203 100644 --- a/Userland/Libraries/LibWeb/OutOfProcessWebView.h +++ b/Userland/Libraries/LibWeb/OutOfProcessWebView.h @@ -67,6 +67,7 @@ public: void notify_server_did_request_link_context_menu(Badge, const Gfx::IntPoint&, const URL&, const String& target, unsigned modifiers); void notify_server_did_request_alert(Badge, const String& message); bool notify_server_did_request_confirm(Badge, const String& message); + String notify_server_did_request_prompt(Badge, const String& message, const String& default_); private: OutOfProcessWebView(); diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index 537c85bbfa2..66c5436b6bf 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -106,6 +106,7 @@ public: virtual void page_did_request_scroll_into_view(const Gfx::IntRect&) { } virtual void page_did_request_alert(const String&) { } virtual bool page_did_request_confirm(const String&) { return false; } + virtual String page_did_request_prompt(const String&, const String&) { return {}; } }; } diff --git a/Userland/Libraries/LibWeb/WebContentClient.cpp b/Userland/Libraries/LibWeb/WebContentClient.cpp index 1318ada0671..c90bbcb6c55 100644 --- a/Userland/Libraries/LibWeb/WebContentClient.cpp +++ b/Userland/Libraries/LibWeb/WebContentClient.cpp @@ -139,8 +139,14 @@ OwnPtr WebContentClient::ha OwnPtr WebContentClient::handle(const Messages::WebContentClient::DidRequestConfirm& message) { - bool result = m_view.notify_server_did_request_confirm({}, message.message()); + auto result = m_view.notify_server_did_request_confirm({}, message.message()); return make(result); } +OwnPtr WebContentClient::handle(const Messages::WebContentClient::DidRequestPrompt& message) +{ + auto result = m_view.notify_server_did_request_prompt({}, message.message(), message.default_()); + return make(result); +} + } diff --git a/Userland/Libraries/LibWeb/WebContentClient.h b/Userland/Libraries/LibWeb/WebContentClient.h index 1cc367364fe..87fe8cbba90 100644 --- a/Userland/Libraries/LibWeb/WebContentClient.h +++ b/Userland/Libraries/LibWeb/WebContentClient.h @@ -66,6 +66,7 @@ private: virtual void handle(const Messages::WebContentClient::DidRequestLinkContextMenu&) override; virtual OwnPtr handle(const Messages::WebContentClient::DidRequestAlert&) override; virtual OwnPtr handle(const Messages::WebContentClient::DidRequestConfirm&) override; + virtual OwnPtr handle(const Messages::WebContentClient::DidRequestPrompt&) override; OutOfProcessWebView& m_view; }; diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp index 427361fb845..f355a8ef2ba 100644 --- a/Userland/Services/WebContent/PageHost.cpp +++ b/Userland/Services/WebContent/PageHost.cpp @@ -181,4 +181,9 @@ bool PageHost::page_did_request_confirm(const String& message) return m_client.send_sync(message)->result(); } +String PageHost::page_did_request_prompt(const String& message, const String& default_) +{ + return m_client.send_sync(message, default_)->response(); +} + } diff --git a/Userland/Services/WebContent/PageHost.h b/Userland/Services/WebContent/PageHost.h index 85a7f530662..1733d3e9923 100644 --- a/Userland/Services/WebContent/PageHost.h +++ b/Userland/Services/WebContent/PageHost.h @@ -69,6 +69,7 @@ private: virtual void page_did_finish_loading(const URL&) override; virtual void page_did_request_alert(const String&) override; virtual bool page_did_request_confirm(const String&) override; + virtual String page_did_request_prompt(const String&, const String&) override; explicit PageHost(ClientConnection&); diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc index 0eb5886a9c9..9ca013cd1e2 100644 --- a/Userland/Services/WebContent/WebContentClient.ipc +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -16,4 +16,5 @@ endpoint WebContentClient = 90 DidRequestLinkContextMenu(Gfx::IntPoint content_position, URL url, String target, unsigned modifiers) =| DidRequestAlert(String message) => () DidRequestConfirm(String message) => (bool result) + DidRequestPrompt(String message, String default_) => (String response) }