Title: [210574] trunk
Revision
210574
Author
mcatanz...@igalia.com
Date
2017-01-10 19:56:12 -0800 (Tue, 10 Jan 2017)

Log Message

[GTK] No way for applications to set notification permissions without waiting for permission request
https://bugs.webkit.org/show_bug.cgi?id=163366

Reviewed by Carlos Garcia Campos.

Source/WebKit2:

Websites can check the Notification.permission DOM property to check if they have permission
to show notifications *without triggering a permission request*. But the WebKitGTK+ API has
no way to affirmatively indicate notifications are allowed without a permission request. The
only way is via the permission request API, which is too late. It's a problem for Epiphany.
For example, open the Riot Matrix client in a web app; you will immediately see an info bar
informing the user that Riot does not have permission to send desktop notifications, even
though Epiphany automatically grants notification permission in web app mode when requested.
This problem is not exclusive to web apps; there is simply no way for notification
permission to be set correctly prior to a permission request for it. Fix this by introducing
a webkit_web_context_initialize_notification_permissions() API, and add a signal
WebKitWebContext::initialize-notification-permissions to indicate when it should be called.

* UIProcess/API/gtk/WebKitNotificationProvider.cpp:
(notificationPermissionsCallback):
(WebKitNotificationProvider::create):
(WebKitNotificationProvider::WebKitNotificationProvider):
(WebKitNotificationProvider::notificationPermissions):
(WebKitNotificationProvider::setNotificationPermissions):
* UIProcess/API/gtk/WebKitNotificationProvider.h:
* UIProcess/API/gtk/WebKitSecurityOrigin.cpp:
(webkitSecurityOriginGetSecurityOrigin):
* UIProcess/API/gtk/WebKitSecurityOriginPrivate.h:
* UIProcess/API/gtk/WebKitWebContext.cpp:
(webkitWebContextConstructed):
(webkit_web_context_class_init):
(addOriginToMap):
(webkit_web_context_initialize_notification_permissions):
(webkitWebContextInitializeNotificationPermissions):
* UIProcess/API/gtk/WebKitWebContext.h:
* UIProcess/API/gtk/WebKitWebContextPrivate.h:
* UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:

Tools:

* TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp:
(testWebViewNotification):
(setInitialNotificationPermissionsAllowedCallback):
(setInitialNotificationPermissionsDisallowedCallback):
(testWebViewNotificationInitialPermissionAllowed):
(testWebViewNotificationInitialPermissionDisallowed):
(beforeAll):
* TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h:
* TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp:
(WebViewTest::WebViewTest):
(WebViewTest::initializeWebView):
* TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h:

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (210573 => 210574)


--- trunk/Source/WebKit2/ChangeLog	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/ChangeLog	2017-01-11 03:56:12 UTC (rev 210574)
@@ -1,3 +1,42 @@
+2017-01-10  Michael Catanzaro  <mcatanz...@igalia.com>
+
+        [GTK] No way for applications to set notification permissions without waiting for permission request
+        https://bugs.webkit.org/show_bug.cgi?id=163366
+
+        Reviewed by Carlos Garcia Campos.
+
+        Websites can check the Notification.permission DOM property to check if they have permission
+        to show notifications *without triggering a permission request*. But the WebKitGTK+ API has
+        no way to affirmatively indicate notifications are allowed without a permission request. The
+        only way is via the permission request API, which is too late. It's a problem for Epiphany.
+        For example, open the Riot Matrix client in a web app; you will immediately see an info bar
+        informing the user that Riot does not have permission to send desktop notifications, even
+        though Epiphany automatically grants notification permission in web app mode when requested.
+        This problem is not exclusive to web apps; there is simply no way for notification
+        permission to be set correctly prior to a permission request for it. Fix this by introducing
+        a webkit_web_context_initialize_notification_permissions() API, and add a signal
+        WebKitWebContext::initialize-notification-permissions to indicate when it should be called.
+
+        * UIProcess/API/gtk/WebKitNotificationProvider.cpp:
+        (notificationPermissionsCallback):
+        (WebKitNotificationProvider::create):
+        (WebKitNotificationProvider::WebKitNotificationProvider):
+        (WebKitNotificationProvider::notificationPermissions):
+        (WebKitNotificationProvider::setNotificationPermissions):
+        * UIProcess/API/gtk/WebKitNotificationProvider.h:
+        * UIProcess/API/gtk/WebKitSecurityOrigin.cpp:
+        (webkitSecurityOriginGetSecurityOrigin):
+        * UIProcess/API/gtk/WebKitSecurityOriginPrivate.h:
+        * UIProcess/API/gtk/WebKitWebContext.cpp:
+        (webkitWebContextConstructed):
+        (webkit_web_context_class_init):
+        (addOriginToMap):
+        (webkit_web_context_initialize_notification_permissions):
+        (webkitWebContextInitializeNotificationPermissions):
+        * UIProcess/API/gtk/WebKitWebContext.h:
+        * UIProcess/API/gtk/WebKitWebContextPrivate.h:
+        * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
+
 2017-01-10  Keith Rollin  <krol...@apple.com>
 
         Record/replay: fix range used for fuzzy matching

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitNotificationProvider.cpp (210573 => 210574)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitNotificationProvider.cpp	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitNotificationProvider.cpp	2017-01-11 03:56:12 UTC (rev 210574)
@@ -28,8 +28,10 @@
 #include "WebKitNotificationProvider.h"
 
 #include "APIArray.h"
+#include "APIDictionary.h"
 #include "WKNotificationManager.h"
 #include "WebKitNotificationPrivate.h"
+#include "WebKitWebContextPrivate.h"
 #include "WebKitWebViewPrivate.h"
 #include "WebNotificationManagerProxy.h"
 #include "WebPageProxy.h"
@@ -52,6 +54,11 @@
     toNotificationProvider(clientInfo)->cancel(*toImpl(notification));
 }
 
+static WKDictionaryRef notificationPermissionsCallback(const void* clientInfo)
+{
+    return toAPI(toNotificationProvider(clientInfo)->notificationPermissions().leakRef());
+}
+
 static void clearNotificationsCallback(WKArrayRef notificationIDs, const void* clientInfo)
 {
     toNotificationProvider(clientInfo)->clearNotifications(toImpl(notificationIDs));
@@ -61,13 +68,14 @@
 {
 }
 
-Ref<WebKitNotificationProvider> WebKitNotificationProvider::create(WebNotificationManagerProxy* notificationManager)
+Ref<WebKitNotificationProvider> WebKitNotificationProvider::create(WebNotificationManagerProxy* notificationManager, WebKitWebContext* webContext)
 {
-    return adoptRef(*new WebKitNotificationProvider(notificationManager));
+    return adoptRef(*new WebKitNotificationProvider(notificationManager, webContext));
 }
 
-WebKitNotificationProvider::WebKitNotificationProvider(WebNotificationManagerProxy* notificationManager)
-    : m_notificationManager(notificationManager)
+WebKitNotificationProvider::WebKitNotificationProvider(WebNotificationManagerProxy* notificationManager, WebKitWebContext* webContext)
+    : m_webContext(webContext)
+    , m_notificationManager(notificationManager)
 {
     ASSERT(notificationManager);
 
@@ -81,7 +89,7 @@
         0, // didDestroyNotificationCallback,
         0, // addNotificationManagerCallback,
         0, // removeNotificationManagerCallback,
-        0, // notificationPermissionsCallback,
+        notificationPermissionsCallback,
         clearNotificationsCallback,
     };
 
@@ -152,3 +160,14 @@
     for (const auto& item : notificationIDs->elementsOfType<API::UInt64>())
         cancelNotificationByID(item->value());
 }
+
+RefPtr<API::Dictionary> WebKitNotificationProvider::notificationPermissions()
+{
+    webkitWebContextInitializeNotificationPermissions(m_webContext);
+    return m_notificationPermissions;
+}
+
+void WebKitNotificationProvider::setNotificationPermissions(HashMap<String, RefPtr<API::Object>>&& permissionsMap)
+{
+    m_notificationPermissions = API::Dictionary::create(WTFMove(permissionsMap));
+}

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitNotificationProvider.h (210573 => 210574)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitNotificationProvider.h	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitNotificationProvider.h	2017-01-11 03:56:12 UTC (rev 210574)
@@ -22,6 +22,7 @@
 
 #include "WebKitPrivate.h"
 #include "WebKitNotification.h"
+#include "WebKitWebContext.h"
 #include <wtf/HashMap.h>
 #include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
@@ -35,14 +36,17 @@
 class WebKitNotificationProvider : public RefCounted<WebKitNotificationProvider> {
 public:
     virtual ~WebKitNotificationProvider();
-    static Ref<WebKitNotificationProvider> create(WebNotificationManagerProxy*);
+    static Ref<WebKitNotificationProvider> create(WebNotificationManagerProxy*, WebKitWebContext*);
 
     void show(WebPageProxy*, const WebNotification&);
     void cancel(const WebNotification&);
     void clearNotifications(const API::Array*);
 
+    RefPtr<API::Dictionary> notificationPermissions();
+    void setNotificationPermissions(HashMap<String, RefPtr<API::Object>>&&);
+
 private:
-    WebKitNotificationProvider(WebNotificationManagerProxy*);
+    WebKitNotificationProvider(WebNotificationManagerProxy*, WebKitWebContext*);
 
     void cancelNotificationByID(uint64_t);
     static void notificationCloseCallback(WebKitNotification*, WebKitNotificationProvider*);
@@ -50,6 +54,8 @@
 
     void withdrawAnyPreviousNotificationMatchingTag(const CString&);
 
+    WebKitWebContext* m_webContext;
+    RefPtr<API::Dictionary> m_notificationPermissions;
     RefPtr<WebNotificationManagerProxy> m_notificationManager;
     HashMap<uint64_t, GRefPtr<WebKitNotification>> m_notifications;
 };

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityOrigin.cpp (210573 => 210574)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityOrigin.cpp	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityOrigin.cpp	2017-01-11 03:56:12 UTC (rev 210574)
@@ -70,6 +70,12 @@
     return origin;
 }
 
+WebCore::SecurityOrigin& webkitSecurityOriginGetSecurityOrigin(WebKitSecurityOrigin* origin)
+{
+    ASSERT(origin);
+    return origin->securityOrigin.get();
+}
+
 /**
  * webkit_security_origin_new:
  * @protocol: The protocol for the new origin

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityOriginPrivate.h (210573 => 210574)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityOriginPrivate.h	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityOriginPrivate.h	2017-01-11 03:56:12 UTC (rev 210574)
@@ -30,3 +30,4 @@
 #include <WebCore/SecurityOrigin.h>
 
 WebKitSecurityOrigin* webkitSecurityOriginCreate(Ref<WebCore::SecurityOrigin>&&);
+WebCore::SecurityOrigin& webkitSecurityOriginGetSecurityOrigin(WebKitSecurityOrigin*);

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp (210573 => 210574)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp	2017-01-11 03:56:12 UTC (rev 210574)
@@ -41,6 +41,7 @@
 #include "WebKitPluginPrivate.h"
 #include "WebKitPrivate.h"
 #include "WebKitSecurityManagerPrivate.h"
+#include "WebKitSecurityOriginPrivate.h"
 #include "WebKitSettingsPrivate.h"
 #include "WebKitURISchemeRequestPrivate.h"
 #include "WebKitUserContentManagerPrivate.h"
@@ -110,6 +111,7 @@
 enum {
     DOWNLOAD_STARTED,
     INITIALIZE_WEB_EXTENSIONS,
+    INITIALIZE_NOTIFICATION_PERMISSIONS,
 
     LAST_SIGNAL
 };
@@ -285,7 +287,7 @@
     priv->geolocationProvider = WebKitGeolocationProvider::create(priv->processPool->supplement<WebGeolocationManagerProxy>());
 #endif
 #if ENABLE(NOTIFICATIONS)
-    priv->notificationProvider = WebKitNotificationProvider::create(priv->processPool->supplement<WebNotificationManagerProxy>());
+    priv->notificationProvider = WebKitNotificationProvider::create(priv->processPool->supplement<WebNotificationManagerProxy>(), webContext);
 #endif
 }
 
@@ -386,6 +388,30 @@
             nullptr, nullptr,
             g_cclosure_marshal_VOID__VOID,
             G_TYPE_NONE, 0);
+
+    /**
+     * WebKitWebContext::initialize-notification-permissions:
+     * @context: the #WebKitWebContext
+     *
+     * This signal is emitted when a #WebKitWebContext needs to set
+     * initial notification permissions for a web process. It is emitted
+     * when a new web process is about to be launched, and signals the
+     * most appropriate moment to use
+     * webkit_web_context_initialize_notification_permissions(). If no
+     * notification permissions have changed since the last time this
+     * signal was emitted, then there is no need to call
+     * webkit_web_context_initialize_notification_permissions() again.
+     *
+     * Since: 2.16
+     */
+    signals[INITIALIZE_NOTIFICATION_PERMISSIONS] =
+        g_signal_new("initialize-notification-permissions",
+            G_TYPE_FROM_CLASS(gObjectClass),
+            G_SIGNAL_RUN_LAST,
+            G_STRUCT_OFFSET(WebKitWebContextClass, initialize_notification_permissions),
+            nullptr, nullptr,
+            g_cclosure_marshal_VOID__VOID,
+            G_TYPE_NONE, 0);
 }
 
 static gpointer createDefaultWebContext(gpointer)
@@ -1218,6 +1244,54 @@
     return context->priv->processCountLimit;
 }
 
+static void addOriginToMap(WebKitSecurityOrigin* origin, HashMap<String, RefPtr<API::Object>>* map, bool allowed)
+{
+    String string = webkitSecurityOriginGetSecurityOrigin(origin).toString();
+    if (string != "null")
+        map->set(string, API::Boolean::create(allowed));
+}
+
+/**
+ * webkit_web_context_initialize_notification_permissions:
+ * @context: the #WebKitWebContext
+ * @allowed_origins: (element-type WebKitSecurityOrigin): a #GList of security origins
+ * @disallowed_origins: (element-type WebKitSecurityOrigin): a #GList of security origins
+ *
+ * Sets initial desktop notification permissions for the @context.
+ * @allowed_origins and @disallowed_origins must each be #GList of
+ * #WebKitSecurityOrigin objects representing origins that will,
+ * respectively, either always or never have permission to show desktop
+ * notifications. No #WebKitNotificationPermissionRequest will ever be
+ * generated for any of the security origins represented in
+ * @allowed_origins or @disallowed_origins. This function is necessary
+ * because some webpages proactively check whether they have permission
+ * to display notifications without ever creating a permission request.
+ *
+ * This function only affects web processes that have not already been
+ * created. The best time to call it is when handling
+ * #WebKitWebContext::initialize-notification-permissions so as to
+ * ensure that new web processes receive the most recent set of
+ * permissions.
+ *
+ * Since: 2.16
+ */
+void webkit_web_context_initialize_notification_permissions(WebKitWebContext* context, GList* allowedOrigins, GList* disallowedOrigins)
+{
+    HashMap<String, RefPtr<API::Object>> map;
+    g_list_foreach(allowedOrigins, [](gpointer data, gpointer userData) {
+        addOriginToMap(static_cast<WebKitSecurityOrigin*>(data), static_cast<HashMap<String, RefPtr<API::Object>>*>(userData), true);
+    }, &map);
+    g_list_foreach(disallowedOrigins, [](gpointer data, gpointer userData) {
+        addOriginToMap(static_cast<WebKitSecurityOrigin*>(data), static_cast<HashMap<String, RefPtr<API::Object>>*>(userData), false);
+    }, &map);
+    context->priv->notificationProvider->setNotificationPermissions(WTFMove(map));
+}
+
+void webkitWebContextInitializeNotificationPermissions(WebKitWebContext* context)
+{
+    g_signal_emit(context, signals[INITIALIZE_NOTIFICATION_PERMISSIONS], 0);
+}
+
 WebKitDownload* webkitWebContextGetOrCreateDownload(DownloadProxy* downloadProxy)
 {
     GRefPtr<WebKitDownload> download = downloadsMap().get(downloadProxy);

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h (210573 => 210574)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h	2017-01-11 03:56:12 UTC (rev 210574)
@@ -128,9 +128,10 @@
 struct _WebKitWebContextClass {
     GObjectClass parent;
 
-    void (* download_started)          (WebKitWebContext *context,
-                                        WebKitDownload   *download);
-    void (* initialize_web_extensions) (WebKitWebContext *context);
+    void (* download_started)                    (WebKitWebContext *context,
+                                                  WebKitDownload   *download);
+    void (* initialize_web_extensions)           (WebKitWebContext *context);
+    void (* initialize_notification_permissions) (WebKitWebContext *context);
 
     void (*_webkit_reserved0) (void);
     void (*_webkit_reserved1) (void);
@@ -137,7 +138,6 @@
     void (*_webkit_reserved2) (void);
     void (*_webkit_reserved3) (void);
     void (*_webkit_reserved4) (void);
-    void (*_webkit_reserved5) (void);
 };
 
 WEBKIT_API GType
@@ -264,6 +264,12 @@
 WEBKIT_API WebKitProcessModel
 webkit_web_context_get_process_model                (WebKitWebContext              *context);
 
+WEBKIT_API void
+webkit_web_context_initialize_notification_permissions
+                                                    (WebKitWebContext              *context,
+                                                     GList                         *allowed_origins,
+                                                     GList                         *disallowed_origins);
+
 G_END_DECLS
 
 #endif

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h (210573 => 210574)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h	2017-01-11 03:56:12 UTC (rev 210574)
@@ -48,5 +48,6 @@
 void webkitWebContextWebViewDestroyed(WebKitWebContext*, WebKitWebView*);
 WebKitWebView* webkitWebContextGetWebViewForPage(WebKitWebContext*, WebKit::WebPageProxy*);
 GVariant* webkitWebContextInitializeWebExtensions(WebKitWebContext*);
+void webkitWebContextInitializeNotificationPermissions(WebKitWebContext*);
 
 #endif // WebKitWebContextPrivate_h

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt (210573 => 210574)


--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt	2017-01-11 03:56:12 UTC (rev 210574)
@@ -59,6 +59,7 @@
 webkit_web_context_allow_tls_certificate_for_host
 webkit_web_context_get_process_model
 webkit_web_context_set_process_model
+webkit_web_context_initialize_notification_permissions
 
 <SUBSECTION URI Scheme>
 WebKitURISchemeRequestCallback

Modified: trunk/Tools/ChangeLog (210573 => 210574)


--- trunk/Tools/ChangeLog	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Tools/ChangeLog	2017-01-11 03:56:12 UTC (rev 210574)
@@ -1,3 +1,23 @@
+2017-01-10  Michael Catanzaro  <mcatanz...@igalia.com>
+
+        [GTK] No way for applications to set notification permissions without waiting for permission request
+        https://bugs.webkit.org/show_bug.cgi?id=163366
+
+        Reviewed by Carlos Garcia Campos.
+
+        * TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp:
+        (testWebViewNotification):
+        (setInitialNotificationPermissionsAllowedCallback):
+        (setInitialNotificationPermissionsDisallowedCallback):
+        (testWebViewNotificationInitialPermissionAllowed):
+        (testWebViewNotificationInitialPermissionDisallowed):
+        (beforeAll):
+        * TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h:
+        * TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp:
+        (WebViewTest::WebViewTest):
+        (WebViewTest::initializeWebView):
+        * TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h:
+
 2017-01-10  Tim Horton  <timothy_hor...@apple.com>
 
         MobileMiniBrowser tests don't work by default

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp (210573 => 210574)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp	2017-01-11 03:56:12 UTC (rev 210574)
@@ -632,8 +632,18 @@
 
 class NotificationWebViewTest: public WebViewTest {
 public:
-    MAKE_GLIB_TEST_FIXTURE(NotificationWebViewTest);
+    MAKE_GLIB_TEST_FIXTURE_WITH_SETUP_TEARDOWN(NotificationWebViewTest, setup, teardown);
 
+    static void setup()
+    {
+        WebViewTest::shouldInitializeWebViewInConstructor = false;
+    }
+
+    static void teardown()
+    {
+        WebViewTest::shouldInitializeWebViewInConstructor = true;
+    }
+
     enum NotificationEvent {
         None,
         Permission,
@@ -647,6 +657,7 @@
     static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest *request, NotificationWebViewTest* test)
     {
         g_assert(WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST(request));
+        g_assert(test->m_isExpectingPermissionRequest);
         test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
 
         test->m_event = Permission;
@@ -699,10 +710,9 @@
         g_main_loop_quit(test->m_mainLoop);
     }
 
-    NotificationWebViewTest()
-        : m_notification(nullptr)
-        , m_event(None)
+    void initialize()
     {
+        initializeWebView();
         g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), this);
         g_signal_connect(m_webView, "show-notification", G_CALLBACK(showNotificationCallback), this);
         webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "notifications");
@@ -716,9 +726,18 @@
         webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "notifications");
     }
 
+    bool hasPermission()
+    {
+        auto* result = runJavaScriptAndWaitUntilFinished("Notification.permission;", nullptr);
+        g_assert(result);
+        GUniquePtr<char> value(_javascript_ResultToCString(result));
+        return !g_strcmp0(value.get(), "granted");
+    }
+
    void requestPermissionAndWaitUntilGiven()
     {
         m_event = None;
+        m_isExpectingPermissionRequest = true;
         webkit_web_view_run_javascript(m_webView, "Notification.requestPermission();", nullptr, nullptr, nullptr);
         g_main_loop_run(m_mainLoop);
     }
@@ -769,18 +788,24 @@
         g_main_loop_run(m_mainLoop);
     }
 
-    NotificationEvent m_event;
-    WebKitNotification* m_notification;
+    NotificationEvent m_event { None };
+    WebKitNotification* m_notification { nullptr };
+    bool m_isExpectingPermissionRequest { false };
+    bool m_hasPermission { false };
 };
 
 static void testWebViewNotification(NotificationWebViewTest* test, gconstpointer)
 {
+    test->initialize();
+
     // Notifications don't work with local or special schemes.
     test->loadURI(gServer->getURIForPath("/").data());
     test->waitUntilLoadFinished();
+    g_assert(!test->hasPermission());
 
     test->requestPermissionAndWaitUntilGiven();
     g_assert(test->m_event == NotificationWebViewTest::Permission);
+    g_assert(test->hasPermission());
 
     static const char* title = "This is a notification";
     static const char* body = "This is the body.";
@@ -818,6 +843,45 @@
     g_assert(test->m_event == NotificationWebViewTest::Closed);
 }
 
+static void setInitialNotificationPermissionsAllowedCallback(WebKitWebContext* context, NotificationWebViewTest* test)
+{
+    GUniquePtr<char> baseURI(soup_uri_to_string(gServer->baseURI(), FALSE));
+    GList* allowedOrigins = g_list_prepend(nullptr, webkit_security_origin_new_for_uri(baseURI.get()));
+    webkit_web_context_initialize_notification_permissions(test->m_webContext.get(), allowedOrigins, nullptr);
+    g_list_free_full(allowedOrigins, reinterpret_cast<GDestroyNotify>(webkit_security_origin_unref));
+}
+
+static void setInitialNotificationPermissionsDisallowedCallback(WebKitWebContext* context, NotificationWebViewTest* test)
+{
+    GUniquePtr<char> baseURI(soup_uri_to_string(gServer->baseURI(), FALSE));
+    GList* disallowedOrigins = g_list_prepend(nullptr, webkit_security_origin_new_for_uri(baseURI.get()));
+    webkit_web_context_initialize_notification_permissions(test->m_webContext.get(), nullptr, disallowedOrigins);
+    g_list_free_full(disallowedOrigins, reinterpret_cast<GDestroyNotify>(webkit_security_origin_unref));
+}
+
+static void testWebViewNotificationInitialPermissionAllowed(NotificationWebViewTest* test, gconstpointer)
+{
+    g_signal_connect(test->m_webContext.get(), "initialize-notification-permissions", G_CALLBACK(setInitialNotificationPermissionsAllowedCallback), test);
+    test->initialize();
+
+    test->loadURI(gServer->getURIForPath("/").data());
+    test->waitUntilLoadFinished();
+    g_assert(test->hasPermission());
+
+    test->requestNotificationAndWaitUntilShown("This is a notification", "This is the body.");
+    g_assert(test->m_event == NotificationWebViewTest::Shown);
+}
+
+static void testWebViewNotificationInitialPermissionDisallowed(NotificationWebViewTest* test, gconstpointer)
+{
+    g_signal_connect(test->m_webContext.get(), "initialize-notification-permissions", G_CALLBACK(setInitialNotificationPermissionsDisallowedCallback), test);
+    test->initialize();
+
+    test->loadURI(gServer->getURIForPath("/").data());
+    test->waitUntilLoadFinished();
+    g_assert(!test->hasPermission());
+}
+
 static void testWebViewIsPlayingAudio(IsPlayingAudioWebViewTest* test, gconstpointer)
 {
     // The web view must be realized for the video to start playback and
@@ -915,6 +979,8 @@
     SnapshotWebViewTest::add("WebKitWebView", "snapshot", testWebViewSnapshot);
     WebViewTest::add("WebKitWebView", "page-visibility", testWebViewPageVisibility);
     NotificationWebViewTest::add("WebKitWebView", "notification", testWebViewNotification);
+    NotificationWebViewTest::add("WebKitWebView", "notification-initial-permission-allowed", testWebViewNotificationInitialPermissionAllowed);
+    NotificationWebViewTest::add("WebKitWebView", "notification-initial-permission-disallowed", testWebViewNotificationInitialPermissionDisallowed);
     IsPlayingAudioWebViewTest::add("WebKitWebView", "is-playing-audio", testWebViewIsPlayingAudio);
     WebViewTest::add("WebKitWebView", "background-color", testWebViewBackgroundColor);
     WebViewTest::add("WebKitWebView", "preferred-size", testWebViewPreferredSize);

Modified: trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h (210573 => 210574)


--- trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h	2017-01-11 03:56:12 UTC (rev 210574)
@@ -43,6 +43,25 @@
         g_test_add(testPath.get(), ClassName, 0, ClassName::setUp, testFunc, ClassName::tearDown); \
     }
 
+#define MAKE_GLIB_TEST_FIXTURE_WITH_SETUP_TEARDOWN(ClassName, setup, teardown) \
+    static void setUp(ClassName* fixture, gconstpointer data) \
+    { \
+        if (setup) \
+            setup(); \
+        new (fixture) ClassName; \
+    } \
+    static void tearDown(ClassName* fixture, gconstpointer data) \
+    { \
+        fixture->~ClassName(); \
+        if (teardown) \
+            teardown(); \
+    } \
+    static void add(const char* suiteName, const char* testName, void (*testFunc)(ClassName*, const void*)) \
+    { \
+        GUniquePtr<gchar> testPath(g_strdup_printf("/webkit2/%s/%s", suiteName, testName)); \
+        g_test_add(testPath.get(), ClassName, 0, ClassName::setUp, testFunc, ClassName::tearDown); \
+    }
+
 #define ASSERT_CMP_CSTRING(s1, cmp, s2) \
     do {                                                                 \
         CString __s1 = (s1);                                             \

Modified: trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp (210573 => 210574)


--- trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp	2017-01-11 03:56:12 UTC (rev 210574)
@@ -24,19 +24,15 @@
 #include <_javascript_Core/JSRetainPtr.h>
 #include <WebCore/GUniquePtrGtk.h>
 
+bool WebViewTest::shouldInitializeWebViewInConstructor = true;
+
 WebViewTest::WebViewTest()
     : m_userContentManager(adoptGRef(webkit_user_content_manager_new()))
-    , m_webView(WEBKIT_WEB_VIEW(g_object_ref_sink(g_object_new(WEBKIT_TYPE_WEB_VIEW, "web-context", m_webContext.get(), "user-content-manager", m_userContentManager.get(), nullptr))))
     , m_mainLoop(g_main_loop_new(nullptr, TRUE))
-    , m_parentWindow(nullptr)
-    , m_javascriptResult(nullptr)
-    , m_resourceDataSize(0)
-    , m_surface(nullptr)
-    , m_expectedWebProcessCrash(false)
 {
-    assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webView));
+    if (shouldInitializeWebViewInConstructor)
+        initializeWebView();
     assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_userContentManager.get()));
-    g_signal_connect(m_webView, "web-process-crashed", G_CALLBACK(WebViewTest::webProcessCrashed), this);
 }
 
 WebViewTest::~WebViewTest()
@@ -51,6 +47,15 @@
     g_main_loop_unref(m_mainLoop);
 }
 
+void WebViewTest::initializeWebView()
+{
+    g_assert(!m_webView);
+    m_webView = WEBKIT_WEB_VIEW(g_object_ref_sink(g_object_new(WEBKIT_TYPE_WEB_VIEW, "web-context", m_webContext.get(), "user-content-manager", m_userContentManager.get(), nullptr)));
+    assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webView));
+
+    g_signal_connect(m_webView, "web-process-crashed", G_CALLBACK(WebViewTest::webProcessCrashed), this);
+}
+
 gboolean WebViewTest::webProcessCrashed(WebKitWebView*, WebViewTest* test)
 {
     if (test->m_expectedWebProcessCrash) {

Modified: trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h (210573 => 210574)


--- trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h	2017-01-11 02:26:47 UTC (rev 210573)
+++ trunk/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h	2017-01-11 03:56:12 UTC (rev 210574)
@@ -31,6 +31,9 @@
     WebViewTest();
     virtual ~WebViewTest();
 
+    static bool shouldInitializeWebViewInConstructor;
+    void initializeWebView();
+
     virtual void loadURI(const char* uri);
     virtual void loadHtml(const char* html, const char* baseURI);
     virtual void loadPlainText(const char* plainText);
@@ -81,17 +84,17 @@
     static gboolean webProcessCrashed(WebKitWebView*, WebViewTest*);
 
     GRefPtr<WebKitUserContentManager> m_userContentManager;
-    WebKitWebView* m_webView;
+    WebKitWebView* m_webView { nullptr };
     GMainLoop* m_mainLoop;
     CString m_activeURI;
-    GtkWidget* m_parentWindow;
+    GtkWidget* m_parentWindow { nullptr };
     CString m_expectedTitle;
-    WebKitJavascriptResult* m_javascriptResult;
-    GError** m_javascriptError;
-    GUniquePtr<char> m_resourceData;
-    size_t m_resourceDataSize;
-    cairo_surface_t* m_surface;
-    bool m_expectedWebProcessCrash;
+    WebKitJavascriptResult* m_javascriptResult { nullptr };
+    GError** m_javascriptError { nullptr };
+    GUniquePtr<char> m_resourceData { nullptr };
+    size_t m_resourceDataSize { 0 };
+    cairo_surface_t* m_surface { nullptr };
+    bool m_expectedWebProcessCrash { false };
 
 private:
     void doMouseButtonEvent(GdkEventType, int, int, unsigned, unsigned);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to