Title: [235969] trunk
Revision
235969
Author
[email protected]
Date
2018-09-13 01:24:17 -0700 (Thu, 13 Sep 2018)

Log Message

[GTK][WPE] Allow to run script dialogs asynchronously in the UI process
https://bugs.webkit.org/show_bug.cgi?id=189544

Reviewed by Michael Catanzaro.

Source/WebKit:

Script dialogs are sync in the WebProcess, but we don't need to block the UI process while they are running. Our
current API doesn't allow it, because it always expects the dialog to be closed in the signal handler. API
changes are backwards compatible.

* UIProcess/API/glib/WebKitScriptDialog.cpp:
(webkitScriptDialogCreate): Added to heap allocate a WebKitScriptDialog.
(webkitScriptDialogIsRunning): Common implementation here, a script dialog is considered to be running if it has
a competion handler pending.
(webkit_script_dialog_ref): WebKitScriptDialog is now refcounted.
(webkit_script_dialog_unref): Ditto.
(webkit_script_dialog_close): New method to notify that we are done with the dialog.
* UIProcess/API/glib/WebKitScriptDialogPrivate.h:
(_WebKitScriptDialog::_WebKitScriptDialog): Use a single constructor and keep the completion handler.
* UIProcess/API/glib/WebKitUIClient.cpp: Do not call the completion handler, pass it to the web view.
* UIProcess/API/glib/WebKitWebView.cpp:
(webkitWebViewDispose): Close the current script dialog if there's any.
(webkit_web_view_class_init): Document how to handle dialogs asynchronously.
(webkitWebViewRunJavaScriptAlert): Do not stack allocate the WebKitScriptDialog, create it with
webkitScriptDialogCreate() passing the completion handler.
(webkitWebViewRunJavaScriptConfirm): Ditto.
(webkitWebViewRunJavaScriptPrompt): Ditto.
(webkitWebViewRunJavaScriptBeforeUnloadConfirm): Ditto.
* UIProcess/API/glib/WebKitWebViewPrivate.h:
* UIProcess/API/gtk/WebKitScriptDialog.h:
* UIProcess/API/gtk/WebKitScriptDialogGtk.cpp:
(scriptDialogResponseCallback): Hnadle the response callback.
(webkitScriptDialogRun): Do not use gtk_dialog_run(), connect to response signal and show the dialogs instead.
* UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
* UIProcess/API/gtk/docs/webkit2gtk-docs.sgml:
* UIProcess/API/wpe/WebKitScriptDialogWPE.cpp:

Tools:

Add test cases for the new API.

* TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp:
(testWebViewJavaScriptDialogs):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (235968 => 235969)


--- trunk/Source/WebKit/ChangeLog	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/ChangeLog	2018-09-13 08:24:17 UTC (rev 235969)
@@ -1,3 +1,41 @@
+2018-09-13  Carlos Garcia Campos  <[email protected]>
+
+        [GTK][WPE] Allow to run script dialogs asynchronously in the UI process
+        https://bugs.webkit.org/show_bug.cgi?id=189544
+
+        Reviewed by Michael Catanzaro.
+
+        Script dialogs are sync in the WebProcess, but we don't need to block the UI process while they are running. Our
+        current API doesn't allow it, because it always expects the dialog to be closed in the signal handler. API
+        changes are backwards compatible.
+
+        * UIProcess/API/glib/WebKitScriptDialog.cpp:
+        (webkitScriptDialogCreate): Added to heap allocate a WebKitScriptDialog.
+        (webkitScriptDialogIsRunning): Common implementation here, a script dialog is considered to be running if it has
+        a competion handler pending.
+        (webkit_script_dialog_ref): WebKitScriptDialog is now refcounted.
+        (webkit_script_dialog_unref): Ditto.
+        (webkit_script_dialog_close): New method to notify that we are done with the dialog.
+        * UIProcess/API/glib/WebKitScriptDialogPrivate.h:
+        (_WebKitScriptDialog::_WebKitScriptDialog): Use a single constructor and keep the completion handler.
+        * UIProcess/API/glib/WebKitUIClient.cpp: Do not call the completion handler, pass it to the web view.
+        * UIProcess/API/glib/WebKitWebView.cpp:
+        (webkitWebViewDispose): Close the current script dialog if there's any.
+        (webkit_web_view_class_init): Document how to handle dialogs asynchronously.
+        (webkitWebViewRunJavaScriptAlert): Do not stack allocate the WebKitScriptDialog, create it with
+        webkitScriptDialogCreate() passing the completion handler.
+        (webkitWebViewRunJavaScriptConfirm): Ditto.
+        (webkitWebViewRunJavaScriptPrompt): Ditto.
+        (webkitWebViewRunJavaScriptBeforeUnloadConfirm): Ditto.
+        * UIProcess/API/glib/WebKitWebViewPrivate.h:
+        * UIProcess/API/gtk/WebKitScriptDialog.h:
+        * UIProcess/API/gtk/WebKitScriptDialogGtk.cpp:
+        (scriptDialogResponseCallback): Hnadle the response callback.
+        (webkitScriptDialogRun): Do not use gtk_dialog_run(), connect to response signal and show the dialogs instead.
+        * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
+        * UIProcess/API/gtk/docs/webkit2gtk-docs.sgml:
+        * UIProcess/API/wpe/WebKitScriptDialogWPE.cpp:
+
 2018-09-12  Dan Bernstein  <[email protected]>
 
         Update availability annotations to match the macOS and iOS SDKs in the Xcode 10 GM seed

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitScriptDialog.cpp (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitScriptDialog.cpp	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitScriptDialog.cpp	2018-09-13 08:24:17 UTC (rev 235969)
@@ -22,22 +22,58 @@
 
 #include "WebKitScriptDialogPrivate.h"
 
-static WebKitScriptDialog* webkitScriptDialogCopy(WebKitScriptDialog* dialog)
+G_DEFINE_BOXED_TYPE(WebKitScriptDialog, webkit_script_dialog, webkit_script_dialog_ref, webkit_script_dialog_unref)
+
+WebKitScriptDialog* webkitScriptDialogCreate(unsigned type, const CString& message, const CString& defaultText, Function<void(bool, const String&)>&& completionHandler)
 {
-    WebKitScriptDialog* copy = static_cast<WebKitScriptDialog*>(fastZeroedMalloc(sizeof(WebKitScriptDialog)));
-    new (copy) WebKitScriptDialog(dialog);
-    return copy;
+    auto* dialog = static_cast<WebKitScriptDialog*>(fastMalloc(sizeof(WebKitScriptDialog)));
+    new (dialog) WebKitScriptDialog(type, message, defaultText, WTFMove(completionHandler));
+    return dialog;
 }
 
-static void webkitScriptDialogFree(WebKitScriptDialog* dialog)
+bool webkitScriptDialogIsRunning(WebKitScriptDialog* scriptDialog)
 {
-    dialog->~WebKitScriptDialog();
-    fastFree(dialog);
+    return !!scriptDialog->completionHandler;
 }
 
-G_DEFINE_BOXED_TYPE(WebKitScriptDialog, webkit_script_dialog, webkitScriptDialogCopy, webkitScriptDialogFree)
+/**
+ * webkit_script_dialog_ref:
+ * @dialog: a #WebKitScriptDialog
+ *
+ * Atomically increments the reference count of @dialog by one. This
+ * function is MT-safe and may be called from any thread.
+ *
+ * Returns: The passed in #WebKitScriptDialog
+ *
+ * Since: 2.24
+ */
+WebKitScriptDialog* webkit_script_dialog_ref(WebKitScriptDialog* dialog)
+{
+    g_atomic_int_inc(&dialog->referenceCount);
+    return dialog;
+}
 
 /**
+ * webkit_script_dialog_unref:
+ * @dialog: a #WebKitScriptDialog
+ *
+ * Atomically decrements the reference count of @dialog by one. If the
+ * reference count drops to 0, all memory allocated by the #WebKitScriptdialog is
+ * released. This function is MT-safe and may be called from any
+ * thread.
+ *
+ * Since: 2.24
+ */
+void webkit_script_dialog_unref(WebKitScriptDialog* dialog)
+{
+    if (g_atomic_int_dec_and_test(&dialog->referenceCount)) {
+        webkit_script_dialog_close(dialog);
+        dialog->~WebKitScriptDialog();
+        fastFree(dialog);
+    }
+}
+
+/**
  * webkit_script_dialog_get_dialog_type:
  * @dialog: a #WebKitScriptDialog
  *
@@ -124,3 +160,37 @@
 
     dialog->text = text;
 }
+
+/**
+ * webkit_script_dialog_close:
+ * @dialog: a #WebKitScriptDialog
+ *
+ * Close @dialog. When handling a #WebKitScriptDialog asynchronously (webkit_script_dialog_ref()
+ * was called in #WebKitWebView::script-dialog callback), this function needs to be called to notify
+ * that we are done with the script dialog. The dialog will be closed on destruction if this function
+ * hasn't been called before.
+ *
+ * Since: 2.24
+ */
+void webkit_script_dialog_close(WebKitScriptDialog* dialog)
+{
+    g_return_if_fail(dialog);
+
+    if (!dialog->completionHandler)
+        return;
+
+    auto completionHandler = std::exchange(dialog->completionHandler, nullptr);
+
+    switch (dialog->type) {
+    case WEBKIT_SCRIPT_DIALOG_ALERT:
+        completionHandler(false, emptyString());
+        break;
+    case WEBKIT_SCRIPT_DIALOG_CONFIRM:
+    case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
+        completionHandler(dialog->confirmed, emptyString());
+        break;
+    case WEBKIT_SCRIPT_DIALOG_PROMPT:
+        completionHandler(false, String::fromUTF8(dialog->text.data()));
+        break;
+    }
+}

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitScriptDialogPrivate.h (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitScriptDialogPrivate.h	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitScriptDialogPrivate.h	2018-09-13 08:24:17 UTC (rev 235969)
@@ -25,43 +25,31 @@
 #include <wtf/text/WTFString.h>
 
 struct _WebKitScriptDialog {
-    _WebKitScriptDialog(unsigned type, const CString& message)
+    _WebKitScriptDialog(unsigned type, const CString& message, const CString& defaultText, Function<void(bool, const String&)>&& completionHandler)
         : type(type)
         , message(message)
-        , confirmed(false)
-    {
-    }
-
-    _WebKitScriptDialog(unsigned type, const CString& message, const CString& defaultText)
-        : type(type)
-        , message(message)
         , defaultText(defaultText)
-        , confirmed(false)
+        , completionHandler(WTFMove(completionHandler))
     {
-        ASSERT(type == WEBKIT_SCRIPT_DIALOG_PROMPT);
     }
 
-    _WebKitScriptDialog(WebKitScriptDialog* dialog)
-        : type(dialog->type)
-        , message(dialog->message)
-        , defaultText(dialog->defaultText)
-        , confirmed(dialog->confirmed)
-        , text(dialog->text)
-    {
-    }
-
     unsigned type;
     CString message;
     CString defaultText;
 
-    bool confirmed;
+    bool confirmed { false };
     CString text;
 
+    Function<void(bool, const String&)> completionHandler;
+
 #if PLATFORM(GTK)
     GtkWidget* nativeDialog { nullptr };
 #endif
+
+    int referenceCount { 1 };
 };
 
+WebKitScriptDialog* webkitScriptDialogCreate(unsigned type, const CString& message, const CString& defaultText, Function<void(bool, const String&)>&& completionHandler);
 void webkitScriptDialogRun(WebKitScriptDialog*, WebKitWebView*);
 bool webkitScriptDialogIsRunning(WebKitScriptDialog*);
 void webkitScriptDialogAccept(WebKitScriptDialog*);

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp	2018-09-13 08:24:17 UTC (rev 235969)
@@ -67,24 +67,17 @@
 
     void runJavaScriptAlert(WebPageProxy*, const String& message, WebFrameProxy*, const WebCore::SecurityOriginData&, Function<void()>&& completionHandler) final
     {
-        webkitWebViewRunJavaScriptAlert(m_webView, message.utf8());
-        completionHandler();
+        webkitWebViewRunJavaScriptAlert(m_webView, message.utf8(), WTFMove(completionHandler));
     }
 
     void runJavaScriptConfirm(WebPageProxy*, const String& message, WebFrameProxy*, const WebCore::SecurityOriginData&, Function<void(bool)>&& completionHandler) final
     {
-        completionHandler(webkitWebViewRunJavaScriptConfirm(m_webView, message.utf8()));
+        webkitWebViewRunJavaScriptConfirm(m_webView, message.utf8(), WTFMove(completionHandler));
     }
 
     void runJavaScriptPrompt(WebPageProxy*, const String& message, const String& defaultValue, WebFrameProxy*, const WebCore::SecurityOriginData&, Function<void(const String&)>&& completionHandler) final
     {
-        CString result = webkitWebViewRunJavaScriptPrompt(m_webView, message.utf8(), defaultValue.utf8());
-        if (result.isNull()) {
-            completionHandler(String());
-            return;
-        }
-
-        completionHandler(String::fromUTF8(result.data()));
+        webkitWebViewRunJavaScriptPrompt(m_webView, message.utf8(), defaultValue.utf8(), WTFMove(completionHandler));
     }
 
     bool canRunBeforeUnloadConfirmPanel() const final { return true; }
@@ -91,7 +84,7 @@
 
     void runBeforeUnloadConfirmPanel(WebPageProxy*, const String& message, WebFrameProxy*, const WebCore::SecurityOriginData&, Function<void(bool)>&& completionHandler) final
     {
-        completionHandler(webkitWebViewRunJavaScriptBeforeUnloadConfirm(m_webView, message.utf8()));
+        webkitWebViewRunJavaScriptBeforeUnloadConfirm(m_webView, message.utf8(), WTFMove(completionHandler));
     }
 
     void mouseDidMoveOverElement(WebPageProxy&, const WebHitTestResultData& data, WebEvent::Modifiers modifiers, API::Object*) final

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp	2018-09-13 08:24:17 UTC (rev 235969)
@@ -71,7 +71,6 @@
 #include <WebCore/RefPtrCairo.h>
 #include <WebCore/URL.h>
 #include <glib/gi18n-lib.h>
-#include <wtf/SetForScope.h>
 #include <wtf/glib/GRefPtr.h>
 #include <wtf/glib/WTFGType.h>
 #include <wtf/text/CString.h>
@@ -807,6 +806,11 @@
         webView->priv->websiteDataManager = nullptr;
     }
 
+    if (webView->priv->currentScriptDialog) {
+        webkit_script_dialog_close(webView->priv->currentScriptDialog);
+        ASSERT(!webView->priv->currentScriptDialog);
+    }
+
 #if PLATFORM(WPE)
     webView->priv->view->close();
 #endif
@@ -1355,6 +1359,12 @@
      * </para></listitem>
      * </itemizedlist>
      *
+     * It is possible to handle the script dialog request asynchronously, by simply
+     * caling webkit_script_dialog_ref() on the @dialog argument and calling
+     * webkit_script_dialog_close() when done.
+     * If the last reference is removed on a #WebKitScriptDialog and the dialog has not been
+     * closed, webkit_script_dialog_close() will be called.
+     *
      * Returns: %TRUE to stop other handlers from being invoked for the event.
      *    %FALSE to propagate the event further.
      */
@@ -1366,7 +1376,7 @@
         g_signal_accumulator_true_handled, nullptr,
         g_cclosure_marshal_generic,
         G_TYPE_BOOLEAN, 1,
-        WEBKIT_TYPE_SCRIPT_DIALOG | G_SIGNAL_TYPE_STATIC_SCOPE);
+        WEBKIT_TYPE_SCRIPT_DIALOG);
 
     /**
      * WebKitWebView::decide-policy:
@@ -2101,39 +2111,52 @@
     g_signal_emit(webView, signals[CLOSE], 0, NULL);
 }
 
-void webkitWebViewRunJavaScriptAlert(WebKitWebView* webView, const CString& message)
+void webkitWebViewRunJavaScriptAlert(WebKitWebView* webView, const CString& message, Function<void()>&& completionHandler)
 {
-    WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_ALERT, message);
-    SetForScope<WebKitScriptDialog*> change(webView->priv->currentScriptDialog, &dialog);
+    ASSERT(!webView->priv->currentScriptDialog);
+    webView->priv->currentScriptDialog = webkitScriptDialogCreate(WEBKIT_SCRIPT_DIALOG_ALERT, message, { }, [webView, completionHandler = WTFMove(completionHandler)](bool, const String&) {
+        completionHandler();
+        webView->priv->currentScriptDialog = nullptr;
+    });
     gboolean returnValue;
-    g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
+    g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, webView->priv->currentScriptDialog, &returnValue);
+    webkit_script_dialog_unref(webView->priv->currentScriptDialog);
 }
 
-bool webkitWebViewRunJavaScriptConfirm(WebKitWebView* webView, const CString& message)
+void webkitWebViewRunJavaScriptConfirm(WebKitWebView* webView, const CString& message, Function<void(bool)>&& completionHandler)
 {
-    WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_CONFIRM, message);
-    SetForScope<WebKitScriptDialog*> change(webView->priv->currentScriptDialog, &dialog);
+    ASSERT(!webView->priv->currentScriptDialog);
+    webView->priv->currentScriptDialog = webkitScriptDialogCreate(WEBKIT_SCRIPT_DIALOG_CONFIRM, message, { }, [webView, completionHandler = WTFMove(completionHandler)](bool result, const String&) {
+        completionHandler(result);
+        webView->priv->currentScriptDialog = nullptr;
+    });
     gboolean returnValue;
-    g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
-    return dialog.confirmed;
+    g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, webView->priv->currentScriptDialog, &returnValue);
+    webkit_script_dialog_unref(webView->priv->currentScriptDialog);
 }
 
-CString webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CString& message, const CString& defaultText)
+void webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CString& message, const CString& defaultText, Function<void(const String&)>&& completionHandler)
 {
-    WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_PROMPT, message, defaultText);
-    SetForScope<WebKitScriptDialog*> change(webView->priv->currentScriptDialog, &dialog);
+    ASSERT(!webView->priv->currentScriptDialog);
+    webView->priv->currentScriptDialog = webkitScriptDialogCreate(WEBKIT_SCRIPT_DIALOG_PROMPT, message, defaultText, [webView, completionHandler = WTFMove(completionHandler)](bool, const String& result) {
+        completionHandler(result);
+        webView->priv->currentScriptDialog = nullptr;
+    });
     gboolean returnValue;
-    g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
-    return dialog.text;
+    g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, webView->priv->currentScriptDialog, &returnValue);
+    webkit_script_dialog_unref(webView->priv->currentScriptDialog);
 }
 
-bool webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const CString& message)
+void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const CString& message, Function<void(bool)>&& completionHandler)
 {
-    WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM, message);
-    SetForScope<WebKitScriptDialog*> change(webView->priv->currentScriptDialog, &dialog);
+    ASSERT(!webView->priv->currentScriptDialog);
+    webView->priv->currentScriptDialog = webkitScriptDialogCreate(WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM, message, { }, [webView, completionHandler = WTFMove(completionHandler)](bool result, const String&) {
+        completionHandler(result);
+        webView->priv->currentScriptDialog = nullptr;
+    });
     gboolean returnValue;
-    g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
-    return dialog.confirmed;
+    g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, webView->priv->currentScriptDialog, &returnValue);
+    webkit_script_dialog_unref(webView->priv->currentScriptDialog);
 }
 
 bool webkitWebViewIsShowingScriptDialog(WebKitWebView* webView)

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h	2018-09-13 08:24:17 UTC (rev 235969)
@@ -52,10 +52,10 @@
 void webkitWebViewReadyToShowPage(WebKitWebView*);
 void webkitWebViewRunAsModal(WebKitWebView*);
 void webkitWebViewClosePage(WebKitWebView*);
-void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message);
-bool webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message);
-CString webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText);
-bool webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message);
+void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message, Function<void()>&& completionHandler);
+void webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message, Function<void(bool)>&& completionHandler);
+void webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText, Function<void(const String&)>&& completionHandler);
+void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message, Function<void(bool)>&& completionHandler);
 bool webkitWebViewIsShowingScriptDialog(WebKitWebView*);
 bool webkitWebViewIsScriptDialogRunning(WebKitWebView*, WebKitScriptDialog*);
 String webkitWebViewGetCurrentScriptDialogMessage(WebKitWebView*);

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitScriptDialog.h (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitScriptDialog.h	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitScriptDialog.h	2018-09-13 08:24:17 UTC (rev 235969)
@@ -56,6 +56,12 @@
 WEBKIT_API GType
 webkit_script_dialog_get_type                (void);
 
+WEBKIT_API WebKitScriptDialog *
+webkit_script_dialog_ref                     (WebKitScriptDialog *dialog);
+
+WEBKIT_API void
+webkit_script_dialog_unref                   (WebKitScriptDialog *dialog);
+
 WEBKIT_API WebKitScriptDialogType
 webkit_script_dialog_get_dialog_type         (WebKitScriptDialog *dialog);
 
@@ -73,6 +79,9 @@
 webkit_script_dialog_prompt_set_text         (WebKitScriptDialog *dialog,
                                               const gchar        *text);
 
+WEBKIT_API void
+webkit_script_dialog_close                   (WebKitScriptDialog *dialog);
+
 G_END_DECLS
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitScriptDialogGtk.cpp (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitScriptDialogGtk.cpp	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitScriptDialogGtk.cpp	2018-09-13 08:24:17 UTC (rev 235969)
@@ -27,6 +27,29 @@
 #include <gtk/gtk.h>
 #include <wtf/glib/GUniquePtr.h>
 
+static void scriptDialogResponseCallback(GtkWidget* dialog, int responseID, WebKitScriptDialog* scriptDialog)
+{
+    switch (scriptDialog->type) {
+    case WEBKIT_SCRIPT_DIALOG_ALERT:
+        break;
+    case WEBKIT_SCRIPT_DIALOG_CONFIRM:
+    case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
+        scriptDialog->confirmed = responseID == GTK_RESPONSE_OK;
+        break;
+    case WEBKIT_SCRIPT_DIALOG_PROMPT:
+        if (responseID == GTK_RESPONSE_OK) {
+            if (auto* entry = g_object_get_data(G_OBJECT(dialog), "wk-script-dialog-entry"))
+                scriptDialog->text = gtk_entry_get_text(GTK_ENTRY(entry));
+        }
+        break;
+    }
+
+    scriptDialog->nativeDialog = nullptr;
+    webkit_script_dialog_close(scriptDialog);
+    webkit_script_dialog_unref(scriptDialog);
+    gtk_widget_destroy(dialog);
+}
+
 static GtkWidget* webkitWebViewCreateJavaScriptDialog(WebKitWebView* webView, GtkMessageType type, GtkButtonsType buttons, int defaultResponse, const char* primaryText, const char* secondaryText = nullptr)
 {
     GtkWidget* parent = gtk_widget_get_toplevel(GTK_WIDGET(webView));
@@ -49,45 +72,34 @@
     switch (scriptDialog->type) {
     case WEBKIT_SCRIPT_DIALOG_ALERT:
         dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE, scriptDialog->message.data());
-        scriptDialog->nativeDialog = dialog;
-        gtk_dialog_run(GTK_DIALOG(dialog));
         break;
     case WEBKIT_SCRIPT_DIALOG_CONFIRM:
         dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK, scriptDialog->message.data());
-        scriptDialog->nativeDialog = dialog;
-        scriptDialog->confirmed = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK;
         break;
     case WEBKIT_SCRIPT_DIALOG_PROMPT: {
         dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK, scriptDialog->message.data());
-        scriptDialog->nativeDialog = dialog;
         GtkWidget* entry = gtk_entry_new();
+        g_object_set_data(G_OBJECT(dialog), "wk-script-dialog-entry", entry);
         gtk_entry_set_text(GTK_ENTRY(entry), scriptDialog->defaultText.data());
         gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry);
         gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
         gtk_widget_show(entry);
-        if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
-            scriptDialog->text = gtk_entry_get_text(GTK_ENTRY(entry));
         break;
     }
     case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
         dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, GTK_RESPONSE_OK,
             _("Are you sure you want to leave this page?"), scriptDialog->message.data());
-        scriptDialog->nativeDialog = dialog;
         gtk_dialog_add_buttons(GTK_DIALOG(dialog), _("Stay on Page"), GTK_RESPONSE_CLOSE, _("Leave Page"), GTK_RESPONSE_OK, nullptr);
         gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
-        scriptDialog->confirmed = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK;
         break;
     }
 
-    gtk_widget_destroy(dialog);
-    scriptDialog->nativeDialog = nullptr;
+    ASSERT(dialog);
+    scriptDialog->nativeDialog = dialog;
+    g_signal_connect(dialog, "response", G_CALLBACK(scriptDialogResponseCallback), webkit_script_dialog_ref(scriptDialog));
+    gtk_widget_show(dialog);
 }
 
-bool webkitScriptDialogIsRunning(WebKitScriptDialog* scriptDialog)
-{
-    return !!scriptDialog->nativeDialog;
-}
-
 void webkitScriptDialogAccept(WebKitScriptDialog* scriptDialog)
 {
     int response = 0;

Modified: trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt	2018-09-13 08:24:17 UTC (rev 235969)
@@ -231,6 +231,7 @@
 webkit_web_view_get_editor_state
 webkit_web_view_get_session_state
 webkit_web_view_restore_session_state
+webkit_web_view_get_main_resource
 
 <SUBSECTION WebKitJavascriptResult>
 WebKitJavascriptResult
@@ -243,12 +244,14 @@
 <SUBSECTION WebKitScriptDialog>
 WebKitScriptDialog
 WebKitScriptDialogType
+webkit_script_dialog_ref
+webkit_script_dialog_unref
 webkit_script_dialog_get_dialog_type
 webkit_script_dialog_get_message
 webkit_script_dialog_confirm_set_confirmed
 webkit_script_dialog_prompt_get_default_text
 webkit_script_dialog_prompt_set_text
-webkit_web_view_get_main_resource
+webkit_script_dialog_close
 
 <SUBSECTION WebKitWebViewSessionState>
 WebKitWebViewSessionState

Modified: trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml	2018-09-13 08:24:17 UTC (rev 235969)
@@ -137,5 +137,10 @@
     <xi:include href="" /></xi:include>
   </index>
 
+  <index id="api-index-2-24" role="2.24">
+    <title>Index of new symbols in 2.24</title>
+    <xi:include href="" /></xi:include>
+  </index>
+
   <xi:include href="" /></xi:include>
 </book>

Modified: trunk/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialog.h (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialog.h	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialog.h	2018-09-13 08:24:17 UTC (rev 235969)
@@ -56,6 +56,12 @@
 WEBKIT_API GType
 webkit_script_dialog_get_type                (void);
 
+WEBKIT_API WebKitScriptDialog *
+webkit_script_dialog_ref                     (WebKitScriptDialog *dialog);
+
+WEBKIT_API void
+webkit_script_dialog_unref                   (WebKitScriptDialog *dialog);
+
 WEBKIT_API WebKitScriptDialogType
 webkit_script_dialog_get_dialog_type         (WebKitScriptDialog *dialog);
 
@@ -73,6 +79,9 @@
 webkit_script_dialog_prompt_set_text         (WebKitScriptDialog *dialog,
                                               const gchar        *text);
 
+WEBKIT_API void
+webkit_script_dialog_close                   (WebKitScriptDialog *dialog);
+
 G_END_DECLS
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialogWPE.cpp (235968 => 235969)


--- trunk/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialogWPE.cpp	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Source/WebKit/UIProcess/API/wpe/WebKitScriptDialogWPE.cpp	2018-09-13 08:24:17 UTC (rev 235969)
@@ -26,11 +26,6 @@
 {
 }
 
-bool webkitScriptDialogIsRunning(WebKitScriptDialog*)
-{
-    return false;
-}
-
 void webkitScriptDialogAccept(WebKitScriptDialog*)
 {
 }

Modified: trunk/Tools/ChangeLog (235968 => 235969)


--- trunk/Tools/ChangeLog	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Tools/ChangeLog	2018-09-13 08:24:17 UTC (rev 235969)
@@ -1,3 +1,15 @@
+2018-09-13  Carlos Garcia Campos  <[email protected]>
+
+        [GTK][WPE] Allow to run script dialogs asynchronously in the UI process
+        https://bugs.webkit.org/show_bug.cgi?id=189544
+
+        Reviewed by Michael Catanzaro.
+
+        Add test cases for the new API.
+
+        * TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp:
+        (testWebViewJavaScriptDialogs):
+
 2018-09-12  Fujii Hironori  <[email protected]>
 
         [Win][Clang][ImageDiff] Fix compilation error and warning of PlatformImageCairo.cpp

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp (235968 => 235969)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp	2018-09-13 07:20:25 UTC (rev 235968)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp	2018-09-13 08:24:17 UTC (rev 235969)
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "WebViewTest.h"
 #include <wtf/HashSet.h>
+#include <wtf/RunLoop.h>
 #include <wtf/glib/GRefPtr.h>
 #include <wtf/text/StringHash.h>
 
@@ -158,7 +159,15 @@
             break;
         }
 
-        g_main_loop_quit(m_mainLoop);
+        if (m_delayedScriptDialogs) {
+            webkit_script_dialog_ref(dialog);
+            RunLoop::main().dispatch([this, dialog] {
+                webkit_script_dialog_close(dialog);
+                webkit_script_dialog_unref(dialog);
+                g_main_loop_quit(m_mainLoop);
+            });
+        } else
+            g_main_loop_quit(m_mainLoop);
     }
 
     void scriptConfirm(WebKitScriptDialog* dialog)
@@ -365,6 +374,7 @@
     Vector<WebViewEvents> m_webViewEvents;
     WebKitScriptDialogType m_scriptDialogType;
     bool m_scriptDialogConfirmed;
+    bool m_delayedScriptDialogs { false };
     bool m_allowPermissionRequests;
     gboolean m_verifyMediaTypes;
     gboolean m_expectedAudioMedia;
@@ -558,30 +568,36 @@
         "<html><body _onbeforeunload_=\"return beforeUnloadHandler();\"><input id=\"testInput\" type=\"text\"></input><script>function beforeUnloadHandler() { return \"%s\"; }</script></body></html>";
 #endif
 
-    test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_ALERT;
-    GUniquePtr<char> alertDialogMessage(g_strdup_printf(jsAlertFormat, kAlertDialogMessage));
-    GUniquePtr<char> alertHTML(g_strdup_printf(htmlOnLoadFormat, alertDialogMessage.get()));
-    test->loadHtml(alertHTML.get(), 0);
-    test->waitUntilMainLoopFinishes();
-    webkit_web_view_stop_loading(test->m_webView);
-    test->waitUntilLoadFinished();
+    for (unsigned i = 0; i <= 1; ++i) {
+        test->m_delayedScriptDialogs = !!i;
 
-    test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_CONFIRM;
-    GUniquePtr<char> confirmDialogMessage(g_strdup_printf(jsConfirmFormat, kConfirmDialogMessage));
-    GUniquePtr<char> confirmHTML(g_strdup_printf(htmlOnLoadFormat, confirmDialogMessage.get()));
-    test->loadHtml(confirmHTML.get(), 0);
-    test->waitUntilMainLoopFinishes();
-    webkit_web_view_stop_loading(test->m_webView);
-    test->waitUntilLoadFinished();
+        test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_ALERT;
+        GUniquePtr<char> alertDialogMessage(g_strdup_printf(jsAlertFormat, kAlertDialogMessage));
+        GUniquePtr<char> alertHTML(g_strdup_printf(htmlOnLoadFormat, alertDialogMessage.get()));
+        test->loadHtml(alertHTML.get(), nullptr);
+        test->waitUntilMainLoopFinishes();
+        webkit_web_view_stop_loading(test->m_webView);
+        test->waitUntilLoadFinished();
 
-    test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_PROMPT;
-    GUniquePtr<char> promptDialogMessage(g_strdup_printf(jsPromptFormat, kPromptDialogMessage));
-    GUniquePtr<char> promptHTML(g_strdup_printf(htmlOnLoadFormat, promptDialogMessage.get()));
-    test->loadHtml(promptHTML.get(), 0);
-    test->waitUntilMainLoopFinishes();
-    webkit_web_view_stop_loading(test->m_webView);
-    test->waitUntilLoadFinished();
+        test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_CONFIRM;
+        GUniquePtr<char> confirmDialogMessage(g_strdup_printf(jsConfirmFormat, kConfirmDialogMessage));
+        GUniquePtr<char> confirmHTML(g_strdup_printf(htmlOnLoadFormat, confirmDialogMessage.get()));
+        test->loadHtml(confirmHTML.get(), nullptr);
+        test->waitUntilMainLoopFinishes();
+        webkit_web_view_stop_loading(test->m_webView);
+        test->waitUntilLoadFinished();
 
+        test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_PROMPT;
+        GUniquePtr<char> promptDialogMessage(g_strdup_printf(jsPromptFormat, kPromptDialogMessage));
+        GUniquePtr<char> promptHTML(g_strdup_printf(htmlOnLoadFormat, promptDialogMessage.get()));
+        test->loadHtml(promptHTML.get(), nullptr);
+        test->waitUntilMainLoopFinishes();
+        webkit_web_view_stop_loading(test->m_webView);
+        test->waitUntilLoadFinished();
+    }
+
+    test->m_delayedScriptDialogs = false;
+
     // FIXME: implement simulateUserInteraction in WPE.
 #if PLATFORM(GTK)
     test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to