[WPE] Add API to notify about frame displayed view backend callback
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Dec 2018 13:31:27 +0000 (13:31 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Dec 2018 13:31:27 +0000 (13:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192224

Reviewed by Michael Catanzaro.

Source/WebKit:

Add API to add a callback to the view to be called when the view backend notifies that a frame has been
displayed.

* UIProcess/API/glib/WebKitWebView.cpp:
(FrameDisplayedCallback::FrameDisplayedCallback):
(FrameDisplayedCallback::~FrameDisplayedCallback):
(webkit_web_view_add_frame_displayed_callback):
(webkit_web_view_remove_frame_displayed_callback):
* UIProcess/API/wpe/WebKitWebView.h:
* UIProcess/API/wpe/docs/wpe-0.1-sections.txt:

Tools:

Add a test case to check the new API.

* TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:
(testWebViewFrameDisplayed):
(beforeAll):
* wpe/jhbuild.modules: Bump WPEBackend-fdo to 1.1.0.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239264 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
Source/WebKit/UIProcess/API/wpe/WebKitWebView.h
Source/WebKit/UIProcess/API/wpe/docs/wpe-0.1-sections.txt
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp
Tools/wpe/jhbuild.modules

index 71e152e..8eb81d9 100644 (file)
@@ -1,3 +1,21 @@
+2018-12-17  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [WPE] Add API to notify about frame displayed view backend callback
+        https://bugs.webkit.org/show_bug.cgi?id=192224
+
+        Reviewed by Michael Catanzaro.
+
+        Add API to add a callback to the view to be called when the view backend notifies that a frame has been
+        displayed.
+
+        * UIProcess/API/glib/WebKitWebView.cpp:
+        (FrameDisplayedCallback::FrameDisplayedCallback):
+        (FrameDisplayedCallback::~FrameDisplayedCallback):
+        (webkit_web_view_add_frame_displayed_callback):
+        (webkit_web_view_remove_frame_displayed_callback):
+        * UIProcess/API/wpe/WebKitWebView.h:
+        * UIProcess/API/wpe/docs/wpe-0.1-sections.txt:
+
 2018-12-16  Chris Fleizach  <cfleizach@apple.com>
 
         AX: Support keyboard access preference for iOS in WebKit
index f6bffad..f5d4fb6 100644 (file)
@@ -71,6 +71,7 @@
 #include <WebCore/RefPtrCairo.h>
 #include <WebCore/URLSoup.h>
 #include <glib/gi18n-lib.h>
+#include <wtf/SetForScope.h>
 #include <wtf/URL.h>
 #include <wtf/glib/GRefPtr.h>
 #include <wtf/glib/WTFGType.h>
@@ -197,6 +198,34 @@ typedef HashMap<uint64_t, GRefPtr<GTask> > SnapshotResultsMap;
 
 class PageLoadStateObserver;
 
+#if PLATFORM(WPE)
+static unsigned frameDisplayCallbackID;
+struct FrameDisplayedCallback {
+    FrameDisplayedCallback(WebKitFrameDisplayedCallback callback, gpointer userData = nullptr, GDestroyNotify destroyNotifyFunction = nullptr)
+        : id(++frameDisplayCallbackID)
+        , callback(callback)
+        , userData(userData)
+        , destroyNotifyFunction(destroyNotifyFunction)
+    {
+    }
+
+    ~FrameDisplayedCallback()
+    {
+        if (destroyNotifyFunction)
+            destroyNotifyFunction(userData);
+    }
+
+    FrameDisplayedCallback(FrameDisplayedCallback&&) = default;
+    FrameDisplayedCallback(const FrameDisplayedCallback&) = delete;
+    FrameDisplayedCallback& operator=(const FrameDisplayedCallback&) = delete;
+
+    unsigned id { 0 };
+    WebKitFrameDisplayedCallback callback { nullptr };
+    gpointer userData { nullptr };
+    GDestroyNotify destroyNotifyFunction { nullptr };
+};
+#endif // PLATFORM(WPE)
+
 struct _WebKitWebViewPrivate {
     ~_WebKitWebViewPrivate()
     {
@@ -208,6 +237,9 @@ struct _WebKitWebViewPrivate {
 #if PLATFORM(WPE)
     GRefPtr<WebKitWebViewBackend> backend;
     std::unique_ptr<WKWPE::View> view;
+    Vector<FrameDisplayedCallback> frameDisplayedCallbacks;
+    bool inFrameDisplayed;
+    HashSet<unsigned> frameDisplayedCallbacksToRemove;
 #endif
 
     WebKitWebView* relatedView;
@@ -374,6 +406,24 @@ private:
         webkitWebViewHandleDownloadRequest(m_webView, &downloadProxy);
     }
 
+    void frameDisplayed(WKWPE::View&) override
+    {
+        {
+            SetForScope<bool> inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true);
+            for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) {
+                if (!m_webView->priv->frameDisplayedCallbacksToRemove.contains(callback.id))
+                    callback.callback(m_webView, callback.userData);
+            }
+        }
+
+        while (!m_webView->priv->frameDisplayedCallbacksToRemove.isEmpty()) {
+            auto id = m_webView->priv->frameDisplayedCallbacksToRemove.takeAny();
+            m_webView->priv->frameDisplayedCallbacks.removeFirstMatching([id](const auto& item) {
+                return item.id == id;
+            });
+        }
+    }
+
     WebKitWebView* m_webView;
 };
 #endif
@@ -4091,3 +4141,55 @@ void webkit_web_view_restore_session_state(WebKitWebView* webView, WebKitWebView
 
     getPage(webView).restoreFromSessionState(webkitWebViewSessionStateGetSessionState(state), false);
 }
+
+#if PLATFORM(WPE)
+/**
+ * webkit_web_view_add_frame_displayed_callback:
+ * @web_view: a #WebKitWebView
+ * @callback: a #WebKitFrameDisplayedCallback
+ * @user_data: (closure): user data to pass to @callback
+ * @destroy_notify: (nullable): destroy notifier for @user_data
+ *
+ * Add a callback to be called when the backend notifies that a frame has been displayed in @web_view.
+ *
+ * Returns: an identifier that should be passed to webkit_web_view_remove_frame_displayed_callback()
+ *    to remove the callback.
+ *
+ * Since: 2.24
+ */
+unsigned webkit_web_view_add_frame_displayed_callback(WebKitWebView* webView, WebKitFrameDisplayedCallback callback, gpointer userData, GDestroyNotify destroyNotify)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
+    g_return_val_if_fail(callback, 0);
+
+    webView->priv->frameDisplayedCallbacks.append(FrameDisplayedCallback(callback, userData, destroyNotify));
+    return webView->priv->frameDisplayedCallbacks.last().id;
+}
+
+/**
+ * webkit_web_view_remove_frame_displayed_callback:
+ * @web_view: a #WebKitWebView
+ * @id: an identifier
+ *
+ * Removes a #WebKitFrameDisplayedCallback previously added to @web_view with
+ * webkit_web_view_add_frame_displayed_callback().
+ *
+ * Since: 2.24
+ */
+void webkit_web_view_remove_frame_displayed_callback(WebKitWebView* webView, unsigned id)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
+    g_return_if_fail(id);
+
+    Function<bool(const FrameDisplayedCallback&)> matchFunction = [id](const auto& item) {
+        return item.id == id;
+    };
+
+    if (webView->priv->inFrameDisplayed) {
+        auto index = webView->priv->frameDisplayedCallbacks.findMatching(matchFunction);
+        if (index != notFound)
+            webView->priv->frameDisplayedCallbacksToRemove.add(id);
+    } else
+        webView->priv->frameDisplayedCallbacks.removeFirstMatching(matchFunction);
+}
+#endif // PLATFORM(WPE)
index 2e389fd..4102a75 100644 (file)
@@ -166,6 +166,18 @@ typedef enum {
     WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT
 } WebKitWebProcessTerminationReason;
 
+/**
+ * WebKitFrameDisplayedCallback:
+ * @web_view: a #WebKitWebView
+ * @user_data: user data
+ *
+ * Callback to be called when a frame is displayed in a #webKitWebView.
+ *
+ * Since: 2.24
+ */
+typedef void (* WebKitFrameDisplayedCallback) (WebKitWebView *web_view,
+                                               gpointer       user_data);
+
 struct _WebKitWebView {
     GObject parent;
 
@@ -495,6 +507,16 @@ WEBKIT_API void
 webkit_web_view_restore_session_state                (WebKitWebView             *web_view,
                                                       WebKitWebViewSessionState *state);
 
+WEBKIT_API guint
+webkit_web_view_add_frame_displayed_callback         (WebKitWebView               *web_view,
+                                                      WebKitFrameDisplayedCallback callback,
+                                                      gpointer                     user_data,
+                                                      GDestroyNotify               destroy_notify);
+
+WEBKIT_API void
+webkit_web_view_remove_frame_displayed_callback      (WebKitWebView               *web_view,
+                                                      guint                        id);
+
 G_END_DECLS
 
 #endif
index 14d1385..628db42 100644 (file)
@@ -127,6 +127,7 @@ WebKitPolicyDecisionType
 WebKitSaveMode
 WebKitInsecureContentEvent
 WebKitWebProcessTerminationReason
+WebKitFrameDisplayedCallback
 
 <SUBSECTION Editing Commands>
 WEBKIT_EDITING_COMMAND_CUT
@@ -203,6 +204,8 @@ webkit_web_view_get_editor_state
 webkit_web_view_get_session_state
 webkit_web_view_restore_session_state
 webkit_web_view_get_main_resource
+webkit_web_view_add_frame_displayed_callback
+webkit_web_view_remove_frame_displayed_callback
 
 <SUBSECTION WebKitJavascriptResult>
 WebKitJavascriptResult
index e5b9339..4ea76a8 100644 (file)
@@ -1,3 +1,17 @@
+2018-12-17  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [WPE] Add API to notify about frame displayed view backend callback
+        https://bugs.webkit.org/show_bug.cgi?id=192224
+
+        Reviewed by Michael Catanzaro.
+
+        Add a test case to check the new API.
+
+        * TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp:
+        (testWebViewFrameDisplayed):
+        (beforeAll):
+        * wpe/jhbuild.modules: Bump WPEBackend-fdo to 1.1.0.
+
 2018-12-16  Adrian Perez de Castro  <aperez@igalia.com>
 
         Unreviewed build fix after r239253
index 45ec1e5..d757341 100644 (file)
@@ -1219,6 +1219,100 @@ static void testWebViewTitleChange(WebViewTitleTest* test, gconstpointer)
     g_assert_cmpstr(test->m_webViewTitles[6].data(), ==, "three");
 }
 
+#if PLATFORM(WPE)
+class FrameDisplayedTest: public WebViewTest {
+public:
+    MAKE_GLIB_TEST_FIXTURE(FrameDisplayedTest);
+
+    static void titleChangedCallback(WebKitWebView* view, GParamSpec*, WebViewTitleTest* test)
+    {
+        test->m_webViewTitles.append(webkit_web_view_get_title(view));
+    }
+
+    FrameDisplayedTest()
+        : m_id(webkit_web_view_add_frame_displayed_callback(m_webView, [](WebKitWebView*, gpointer userData) {
+            auto* test = static_cast<FrameDisplayedTest*>(userData);
+            if (!test->m_maxFrames)
+                return;
+
+            if (++test->m_frameCounter == test->m_maxFrames)
+                RunLoop::main().dispatch([test] { test->quitMainLoop(); });
+        }, this, nullptr))
+    {
+        g_assert_cmpuint(m_id, >, 0);
+    }
+
+    ~FrameDisplayedTest()
+    {
+        webkit_web_view_remove_frame_displayed_callback(m_webView, m_id);
+    }
+
+    void waitUntilFramesDisplayed(unsigned framesCount = 1)
+    {
+        m_maxFrames = framesCount;
+        m_frameCounter = 0;
+        g_main_loop_run(m_mainLoop);
+    }
+
+    unsigned m_id { 0 };
+    unsigned m_frameCounter { 0 };
+    unsigned m_maxFrames { 0 };
+};
+
+static void testWebViewFrameDisplayed(FrameDisplayedTest* test, gconstpointer)
+{
+    test->showInWindow();
+
+    test->loadHtml("<html></html>", nullptr);
+    test->waitUntilFramesDisplayed();
+
+    test->loadHtml("<html><head><style>@keyframes fadeIn { from { opacity: 0; } }</style></head><p style='animation: fadeIn 1s infinite alternate;'>Foo</p></html>", nullptr);
+    test->waitUntilFramesDisplayed(10);
+
+    bool secondCallbackCalled = false;
+    auto id = webkit_web_view_add_frame_displayed_callback(test->m_webView, [](WebKitWebView*, gpointer userData) {
+        auto* secondCallbackCalled = static_cast<bool*>(userData);
+        *secondCallbackCalled = true;
+    }, &secondCallbackCalled, nullptr);
+    test->waitUntilFramesDisplayed();
+    g_assert_true(secondCallbackCalled);
+
+    secondCallbackCalled = false;
+    webkit_web_view_remove_frame_displayed_callback(test->m_webView, id);
+    test->waitUntilFramesDisplayed();
+    g_assert_false(secondCallbackCalled);
+
+    id = webkit_web_view_add_frame_displayed_callback(test->m_webView, [](WebKitWebView* webView, gpointer userData) {
+        auto* id = static_cast<unsigned*>(userData);
+        webkit_web_view_remove_frame_displayed_callback(webView, *id);
+    }, &id, [](gpointer userData) {
+        auto* id = static_cast<unsigned*>(userData);
+        *id = 0;
+    });
+    test->waitUntilFramesDisplayed();
+    g_assert_cmpuint(id, ==, 0);
+
+    auto id2 = webkit_web_view_add_frame_displayed_callback(test->m_webView, [](WebKitWebView* webView, gpointer userData) {
+        auto* id = static_cast<unsigned*>(userData);
+        if (*id) {
+            webkit_web_view_remove_frame_displayed_callback(webView, *id);
+            *id = 0;
+        }
+    }, &id, nullptr);
+
+    secondCallbackCalled = false;
+    id = webkit_web_view_add_frame_displayed_callback(test->m_webView, [](WebKitWebView* webView, gpointer userData) {
+        auto* secondCallbackCalled = static_cast<bool*>(userData);
+        *secondCallbackCalled = true;
+    }, &secondCallbackCalled, nullptr);
+    test->waitUntilFramesDisplayed();
+    g_assert_cmpuint(id, ==, 0);
+    g_assert_false(secondCallbackCalled);
+
+    webkit_web_view_remove_frame_displayed_callback(test->m_webView, id2);
+}
+#endif
+
 static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
 {
     if (message->method != SOUP_METHOD_GET) {
@@ -1274,6 +1368,9 @@ void beforeAll()
     WebViewTest::add("WebKitWebView", "preferred-size", testWebViewPreferredSize);
 #endif
     WebViewTitleTest::add("WebKitWebView", "title-change", testWebViewTitleChange);
+#if PLATFORM(WPE)
+    FrameDisplayedTest::add("WebKitWebView", "frame-displayed", testWebViewFrameDisplayed);
+#endif
 }
 
 void afterAll()
index de13798..5e723ef 100644 (file)
       <dep package="libwpe"/>
       <dep package="glib"/>
     </dependencies>
-    <branch repo="wpewebkit" module="wpebackend-fdo-1.0.0.tar.xz" version="1.0.0"
-            hash="sha256:7a747f87a1ae46d30144369050e3ce348b58986d04e1a139ba75c198fa636729"/>
+    <branch repo="wpewebkit" module="wpebackend-fdo-1.1.0.tar.xz" version="1.1.0"
+            hash="sha256:f6c72130d16e50860cb83eb0f6e109c76f1826d2c6bee39025fb3651941761e7"/>
   </cmake>
 
   <autotools id="libgpg-error" autogen-sh="configure">