Skip to content

Commit

Permalink
[WPE][GTK] Enable permissions request API
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=247065

Reviewed by Carlos Garcia Campos.

This is exposed in the GLib API as a WebKitPermissionStateQuery signalled by the WebView using the
`query-permission-state` GObject signal. When the application has a handler for this signal it has
to eventually call `webkit_permission_state_query_finish()` with a valid `WebKitPermissionState`. If
not handled, the default result is `WEBKIT_PERMISSION_STATE_PROMPT`, thus instructing the User-Agent
that it has to explicitely present a prompt asking for permission to the given feature.

* Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml:
* Source/WebKit/PlatformGTK.cmake:
* Source/WebKit/PlatformWPE.cmake:
* Source/WebKit/SourcesGTK.txt:
* Source/WebKit/SourcesWPE.txt:
* Source/WebKit/UIProcess/API/glib/WebKitAutocleanups.h.in:
* Source/WebKit/UIProcess/API/glib/WebKitPermissionStateQuery.cpp: Added.
(_WebKitPermissionStateQuery::_WebKitPermissionStateQuery):
(_WebKitPermissionStateQuery::~_WebKitPermissionStateQuery):
(webkitPermissionStateQueryCreate):
(webkit_permission_state_query_ref):
(webkit_permission_state_query_unref):
(webkit_permission_state_query_get_name):
(webkit_permission_state_query_get_security_origin):
(webkit_permission_state_query_finish):
* Source/WebKit/UIProcess/API/glib/WebKitPermissionStateQuery.h.in: Added.
* Source/WebKit/UIProcess/API/glib/WebKitPermissionStateQueryPrivate.h: Added.
* Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp:
* Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp:
(webkit_web_view_class_init):
(webkitWebViewPermissionStateQuery):
* Source/WebKit/UIProcess/API/glib/WebKitWebView.h.in:
* Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h:
* Source/WebKit/UIProcess/API/gtk/webkit.h:
* Source/WebKit/UIProcess/API/gtk/webkit2.h:
* Source/WebKit/UIProcess/API/wpe/webkit.h:
* Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp:
(testWebViewQueryPermissionRequests):
(beforeAll):

Canonical link: https://commits.webkit.org/257787@main
  • Loading branch information
philn committed May 17, 2023
1 parent 90aaaf1 commit b17b33d
Show file tree
Hide file tree
Showing 14 changed files with 424 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,7 @@ PermissionsAPIEnabled:
WebKitLegacy:
default: false
WebKit:
"PLATFORM(COCOA)" : true
"PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)" : true
default: false
WebCore:
default: false
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/PlatformWPE.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ set(WPE_API_INSTALLED_HEADERS
${WEBKIT_DIR}/UIProcess/API/wpe/WebKitOptionMenu.h
${WEBKIT_DIR}/UIProcess/API/wpe/WebKitOptionMenuItem.h
${WEBKIT_DIR}/UIProcess/API/wpe/WebKitPermissionRequest.h
${WEBKIT_DIR}/UIProcess/API/wpe/WebKitPermissionStateQuery.h
${WEBKIT_DIR}/UIProcess/API/wpe/WebKitPlugin.h
${WEBKIT_DIR}/UIProcess/API/wpe/WebKitPolicyDecision.h
${WEBKIT_DIR}/UIProcess/API/wpe/WebKitRectangle.h
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/SourcesGTK.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ UIProcess/API/glib/WebKitNotificationProvider.cpp @no-unify
UIProcess/API/glib/WebKitOptionMenu.cpp @no-unify
UIProcess/API/glib/WebKitOptionMenuItem.cpp @no-unify
UIProcess/API/glib/WebKitPermissionRequest.cpp @no-unify
UIProcess/API/glib/WebKitPermissionStateQuery.cpp @no-unify
UIProcess/API/glib/WebKitPlugin.cpp @no-unify
UIProcess/API/glib/WebKitPointerLockPermissionRequest.cpp @no-unify
UIProcess/API/glib/WebKitPolicyDecision.cpp @no-unify
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/SourcesWPE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ UIProcess/API/glib/WebKitNotificationProvider.cpp @no-unify
UIProcess/API/glib/WebKitOptionMenu.cpp @no-unify
UIProcess/API/glib/WebKitOptionMenuItem.cpp @no-unify
UIProcess/API/glib/WebKitPermissionRequest.cpp @no-unify
UIProcess/API/glib/WebKitPermissionStateQuery.cpp @no-unify
UIProcess/API/glib/WebKitPlugin.cpp @no-unify
UIProcess/API/glib/WebKitPolicyDecision.cpp @no-unify
UIProcess/API/glib/WebKitPrivate.cpp @no-unify
Expand Down
181 changes: 181 additions & 0 deletions Source/WebKit/UIProcess/API/glib/WebKitPermissionStateQuery.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Copyright (C) 2022 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#include "config.h"
#include "WebKitPermissionStateQuery.h"

#include "APISecurityOrigin.h"
#include "WebKitPermissionStateQueryPrivate.h"
#include "WebKitSecurityOriginPrivate.h"
#include <wtf/glib/WTFGType.h>

/**
* WebKitPermissionStateQuery:
* @See_also: #WebKitWebView
*
* This query represents a user's choice to allow or deny access to "powerful features" of the
* platform, as specified in the [Permissions W3C
* Specification](https://w3c.github.io/permissions/).
*
* When signalled by the #WebKitWebView through the `query-permission-state` signal, the application
* has to eventually respond, via `webkit_permission_state_query_finish()`, whether it grants,
* denies or requests a dedicated permission prompt for the given query.
*
* When a #WebKitPermissionStateQuery is not handled by the user, the user-agent is instructed to
* `prompt` the user for the given permission.
*/

struct _WebKitPermissionStateQuery {
explicit _WebKitPermissionStateQuery(const WTF::String& permissionName, API::SecurityOrigin& origin, CompletionHandler<void(std::optional<WebCore::PermissionState>)>&& completionHandler)
: permissionName(permissionName.utf8())
, securityOrigin(webkitSecurityOriginCreate(origin.securityOrigin().isolatedCopy()))
, completionHandler(WTFMove(completionHandler))
{
}

~_WebKitPermissionStateQuery()
{
// Fallback to Prompt response unless the completion handler was already called.
if (completionHandler)
completionHandler(WebCore::PermissionState::Prompt);

webkit_security_origin_unref(securityOrigin);
}

CString permissionName;
WebKitSecurityOrigin* securityOrigin;
CompletionHandler<void(std::optional<WebCore::PermissionState>)> completionHandler;
int referenceCount { 1 };
};

G_DEFINE_BOXED_TYPE(WebKitPermissionStateQuery, webkit_permission_state_query, webkit_permission_state_query_ref, webkit_permission_state_query_unref)

WebKitPermissionStateQuery* webkitPermissionStateQueryCreate(const WTF::String& permissionName, API::SecurityOrigin& origin, CompletionHandler<void(std::optional<WebCore::PermissionState>)>&& completionHandler)
{
WebKitPermissionStateQuery* query = static_cast<WebKitPermissionStateQuery*>(fastMalloc(sizeof(WebKitPermissionStateQuery)));
new (query) WebKitPermissionStateQuery(permissionName, origin, WTFMove(completionHandler));
return query;
}

/**
* webkit_permission_state_query_ref:
* @query: a #WebKitPermissionStateQuery
*
* Atomically increments the reference count of @query by one.
*
* This function is MT-safe and may be called from any thread.
*
* Returns: The passed #WebKitPermissionStateQuery
*
* Since: 2.40
*/
WebKitPermissionStateQuery* webkit_permission_state_query_ref(WebKitPermissionStateQuery* query)
{
g_return_val_if_fail(query, nullptr);

g_atomic_int_inc(&query->referenceCount);
return query;
}

/**
* webkit_permission_state_query_unref:
* @query: a #WebKitPermissionStateQuery
*
* Atomically decrements the reference count of @query by one.
*
* If the reference count drops to 0, all memory allocated by #WebKitPermissionStateQuery is
* released. This function is MT-safe and may be called from any thread.
*
* Since: 2.40
*/
void webkit_permission_state_query_unref(WebKitPermissionStateQuery* query)
{
g_return_if_fail(query);

if (g_atomic_int_dec_and_test(&query->referenceCount)) {
query->~WebKitPermissionStateQuery();
fastFree(query);
}
}

/**
* webkit_permission_state_query_get_name:
* @query: a #WebKitPermissionStateQuery
*
* Get the permission name for which access is being queried.
*
* Returns: the permission name for @query
*
* Since: 2.40
*/
const gchar*
webkit_permission_state_query_get_name(WebKitPermissionStateQuery* query)
{
g_return_val_if_fail(query, nullptr);

return query->permissionName.data();
}

/**
* webkit_permission_state_query_get_security_origin:
* @query: a #WebKitPermissionStateQuery
*
* Get the permission origin for which access is being queried.
*
* Returns: (transfer none): A #WebKitSecurityOrigin representing the origin from which the
* @query was emitted.
*
* Since: 2.40
*/
WebKitSecurityOrigin *
webkit_permission_state_query_get_security_origin(WebKitPermissionStateQuery* query)
{
g_return_val_if_fail(query, nullptr);

return query->securityOrigin;
}

/**
* webkit_permission_state_query_finish:
* @query: a #WebKitPermissionStateQuery
* @state: a #WebKitPermissionState
*
* Notify the web-engine of the selected permission state for the given query. This function should
* only be called as a response to the `WebKitWebView::query-permission-state` signal.
*
* Since: 2.40
*/
void
webkit_permission_state_query_finish(WebKitPermissionStateQuery* query, WebKitPermissionState state)
{
g_return_if_fail(query);
g_return_if_fail(query->completionHandler);

switch (state) {
case WEBKIT_PERMISSION_STATE_GRANTED:
query->completionHandler(WebCore::PermissionState::Granted);
break;
case WEBKIT_PERMISSION_STATE_DENIED:
query->completionHandler(WebCore::PermissionState::Denied);
break;
case WEBKIT_PERMISSION_STATE_PROMPT:
query->completionHandler(WebCore::PermissionState::Prompt);
break;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2022 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#pragma once

#include "APISecurityOrigin.h"
#include "WebKitPermissionStateQuery.h"
#include <WebCore/PermissionState.h>
#include <wtf/CompletionHandler.h>
#include <wtf/text/WTFString.h>

WebKitPermissionStateQuery* webkitPermissionStateQueryCreate(const WTF::String& permissionName, API::SecurityOrigin&, CompletionHandler<void(std::optional<WebCore::PermissionState>)>&&);
8 changes: 8 additions & 0 deletions Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "WebKitMediaKeySystemPermissionRequestPrivate.h"
#include "WebKitNavigationActionPrivate.h"
#include "WebKitNotificationPermissionRequestPrivate.h"
#include "WebKitPermissionStateQueryPrivate.h"
#include "WebKitPointerLockPermissionRequestPrivate.h"
#include "WebKitURIRequestPrivate.h"
#include "WebKitUserMediaPermissionRequestPrivate.h"
Expand Down Expand Up @@ -378,6 +379,13 @@ class UIClient : public API::UIClient {
}
#endif

void queryPermission(const WTF::String& permissionName, API::SecurityOrigin& origin, CompletionHandler<void(std::optional<WebCore::PermissionState>)>&& completionHandler) final
{
auto* query = webkitPermissionStateQueryCreate(permissionName, origin, WTFMove(completionHandler));
webkitWebViewPermissionStateQuery(m_webView, query);
webkit_permission_state_query_unref(query);
}

WebKitWebView* m_webView;
#if ENABLE(POINTER_LOCK)
WebKitPointerLockPermissionRequest* m_pointerLockPermissionRequest { nullptr };
Expand Down
38 changes: 37 additions & 1 deletion Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "WebKitJavascriptResultPrivate.h"
#include "WebKitNavigationClient.h"
#include "WebKitNotificationPrivate.h"
#include "WebKitPermissionStateQueryPrivate.h"
#include "WebKitPrivate.h"
#include "WebKitResponsePolicyDecision.h"
#include "WebKitScriptDialogPrivate.h"
Expand All @@ -71,11 +72,11 @@
#include "WebPageMessages.h"
#include <JavaScriptCore/APICast.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <jsc/JSCContextPrivate.h>
#include <WebCore/CertificateInfo.h>
#include <WebCore/JSDOMExceptionHandling.h>
#include <WebCore/URLSoup.h>
#include <glib/gi18n-lib.h>
#include <jsc/JSCContextPrivate.h>
#include <libsoup/soup.h>
#include <wtf/SetForScope.h>
#include <wtf/URL.h>
Expand Down Expand Up @@ -170,6 +171,8 @@ enum {

USER_MESSAGE_RECEIVED,

QUERY_PERMISSION_STATE,

LAST_SIGNAL
};

Expand Down Expand Up @@ -2396,6 +2399,33 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_USER_MESSAGE);

/**
* WebKitWebView::query-permission-state:
* @web_view: the #WebKitWebView on which the signal is emitted
* @query: the #WebKitPermissionStateQuery
*
* This signal allows the User-Agent to respond to permission requests for powerful features, as
* specified by the [Permissions W3C Specification](https://w3c.github.io/permissions/).
* You can reply to the query using webkit_permission_state_query_finish().
*
* You can handle the query asynchronously by calling webkit_permission_state_query_ref() on
* @query and returning %TRUE. If the last reference of @query is removed and the query has not
* been handled, the query result will be set to %WEBKIT_QUERY_PERMISSION_PROMPT.
*
* Returns: %TRUE if the message was handled, or %FALSE otherwise.
*
* Since: 2.40
*/
signals[QUERY_PERMISSION_STATE] = g_signal_new(
"query-permission-state",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, query_permission_state),
g_signal_accumulator_true_handled, nullptr /* accumulator data */,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1, /* number of parameters */
WEBKIT_TYPE_PERMISSION_STATE_QUERY);
}

static void webkitWebViewCompleteAuthenticationRequest(WebKitWebView* webView)
Expand Down Expand Up @@ -2992,6 +3022,12 @@ bool webkitWebViewShowOptionMenu(WebKitWebView* webView, const IntRect& rect, We
}
#endif

void webkitWebViewPermissionStateQuery(WebKitWebView* webView, WebKitPermissionStateQuery* query)
{
gboolean result;
g_signal_emit(webView, signals[QUERY_PERMISSION_STATE], 0, query, &result);
}

#if PLATFORM(WPE)
/**
* webkit_web_view_get_backend:
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ void webkitWebViewMediaCaptureStateDidChange(WebKitWebView*, WebCore::MediaProdu
void webkitWebViewSelectionDidChange(WebKitWebView*);
void webkitWebViewRequestInstallMissingMediaPlugins(WebKitWebView*, WebKit::InstallMissingMediaPluginsPermissionRequest&);
WebKitWebsiteDataManager* webkitWebViewGetWebsiteDataManager(WebKitWebView*);
void webkitWebViewPermissionStateQuery(WebKitWebView*, WebKitPermissionStateQuery*);

#if PLATFORM(GTK)
bool webkitWebViewEmitRunColorChooser(WebKitWebView*, WebKitColorChooserRequest*);
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/UIProcess/API/gtk/WebKitAutocleanups.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitUserStyleSheet, webkit_user_style_sheet_unr
G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitUserContentFilter, webkit_user_content_filter_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitWebsiteData, webkit_website_data_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitWebViewSessionState, webkit_web_view_session_state_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitPermissionStateQuery, webkit_permission_state_query_unref)

#endif /* __GI_SCANNER__ */
#endif /* G_DEFINE_AUTOPTR_CLEANUP_FUNC */
Expand Down
Loading

0 comments on commit b17b33d

Please sign in to comment.