Diff
Modified: trunk/Source/WebKit/ChangeLog (280171 => 280172)
--- trunk/Source/WebKit/ChangeLog 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/ChangeLog 2021-07-22 10:54:07 UTC (rev 280172)
@@ -1,3 +1,48 @@
+2021-07-22 Philippe Normand <[email protected]>
+
+ [GLib] Expose API to access/modify capture devices states
+ https://bugs.webkit.org/show_bug.cgi?id=227902
+
+ Reviewed by Carlos Garcia Campos.
+
+ Introduce new GLib API (and corresponding GObject properties):
+
+ webkit_web_view_get_camera_capture_state
+ webkit_web_view_get_microphone_capture_state
+ webkit_web_view_set_camera_capture_state
+ webkit_web_view_set_microphone_capture_state
+ webkit_web_view_get_display_capture_state
+ webkit_web_view_set_display_capture_state
+ webkit_user_media_permission_is_for_display_device
+
+ This can be useful in Web browsers willing to indicate the status of the capture devices
+ currently in use by the WebView.
+
+ Covered by API tests.
+
+ * UIProcess/API/glib/WebKitUIClient.cpp:
+ * UIProcess/API/glib/WebKitUserMediaPermissionRequest.cpp:
+ (webkit_user_media_permission_is_for_display_device):
+ * UIProcess/API/glib/WebKitWebView.cpp:
+ (webkitWebViewMediaCaptureStateDidChange):
+ (webkitWebViewSetProperty):
+ (webkitWebViewGetProperty):
+ (webkit_web_view_class_init):
+ (webkitWebViewConfigureMediaCapture):
+ (webkit_web_view_get_camera_capture_state):
+ (webkit_web_view_set_camera_capture_state):
+ (webkit_web_view_get_microphone_capture_state):
+ (webkit_web_view_set_microphone_capture_state):
+ (webkit_web_view_get_display_capture_state):
+ (webkit_web_view_set_display_capture_state):
+ * UIProcess/API/glib/WebKitWebViewPrivate.h:
+ * UIProcess/API/gtk/WebKitUserMediaPermissionRequest.h:
+ * UIProcess/API/gtk/WebKitWebView.h:
+ * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
+ * UIProcess/API/wpe/WebKitUserMediaPermissionRequest.h:
+ * UIProcess/API/wpe/WebKitWebView.h:
+ * UIProcess/API/wpe/docs/wpe-1.0-sections.txt:
+
2021-07-22 Martin Robinson <[email protected]>
[css-scroll-snap] Pass the full target point when selecting a snap offset
Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp 2021-07-22 10:54:07 UTC (rev 280172)
@@ -352,6 +352,11 @@
webkitWebViewIsPlayingAudioChanged(m_webView);
}
+ void mediaCaptureStateDidChange(WebCore::MediaProducer::MediaStateFlags mediaStateFlags) final
+ {
+ webkitWebViewMediaCaptureStateDidChange(m_webView, mediaStateFlags);
+ }
+
#if ENABLE(POINTER_LOCK)
void requestPointerLock(WebPageProxy* page) final
{
Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitUserMediaPermissionRequest.cpp (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/glib/WebKitUserMediaPermissionRequest.cpp 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitUserMediaPermissionRequest.cpp 2021-07-22 10:54:07 UTC (rev 280172)
@@ -118,7 +118,7 @@
*/
gboolean webkit_user_media_permission_is_for_audio_device(WebKitUserMediaPermissionRequest* request)
{
- g_return_val_if_fail(request->priv->request, FALSE);
+ g_return_val_if_fail(WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request), FALSE);
return request->priv->request->requiresAudioCapture();
}
@@ -132,10 +132,24 @@
*/
gboolean webkit_user_media_permission_is_for_video_device(WebKitUserMediaPermissionRequest* request)
{
- g_return_val_if_fail(request->priv->request, FALSE);
+ g_return_val_if_fail(WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request), FALSE);
return request->priv->request->requiresVideoCapture();
}
+/**
+ * webkit_user_media_permission_is_for_display_device:
+ * @request: a #WebKitUserMediaPermissionRequest
+ *
+ * Returns: %TRUE if access to a display device was requested.
+ *
+ * Since: 2.34
+ */
+gboolean webkit_user_media_permission_is_for_display_device(WebKitUserMediaPermissionRequest* request)
+{
+ g_return_val_if_fail(WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request), FALSE);
+ return request->priv->request->requiresDisplayCapture();
+}
+
static void webkitUserMediaPermissionRequestGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
{
WebKitUserMediaPermissionRequest* request = WEBKIT_USER_MEDIA_PERMISSION_REQUEST(object);
Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp 2021-07-22 10:54:07 UTC (rev 280172)
@@ -207,6 +207,10 @@
PROP_WEBSITE_POLICIES,
PROP_IS_WEB_PROCESS_RESPONSIVE,
+ PROP_CAMERA_CAPTURE_STATE,
+ PROP_MICROPHONE_CAPTURE_STATE,
+ PROP_DISPLAY_CAPTURE_STATE,
+
N_PROPERTIES,
};
@@ -352,6 +356,22 @@
g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_IS_PLAYING_AUDIO]);
}
+void webkitWebViewMediaCaptureStateDidChange(WebKitWebView* webView, WebCore::MediaProducer::MediaStateFlags mediaStateFlags)
+{
+ if (mediaStateFlags.isEmpty()) {
+ g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_CAMERA_CAPTURE_STATE]);
+ g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_DISPLAY_CAPTURE_STATE]);
+ g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_MICROPHONE_CAPTURE_STATE]);
+ return;
+ }
+ if (mediaStateFlags.containsAny(WebCore::MediaProducer::AudioCaptureMask))
+ g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_MICROPHONE_CAPTURE_STATE]);
+ if (mediaStateFlags.containsAny(WebCore::MediaProducer::VideoCaptureMask))
+ g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_CAMERA_CAPTURE_STATE]);
+ if (mediaStateFlags.containsAny(WebCore::MediaProducer::DisplayCaptureMask))
+ g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_DISPLAY_CAPTURE_STATE]);
+}
+
class PageLoadStateObserver final : public PageLoadState::Observer {
WTF_MAKE_FAST_ALLOCATED;
public:
@@ -872,6 +892,15 @@
case PROP_WEBSITE_POLICIES:
webView->priv->websitePolicies = static_cast<WebKitWebsitePolicies*>(g_value_get_object(value));
break;
+ case PROP_CAMERA_CAPTURE_STATE:
+ webkit_web_view_set_camera_capture_state(webView, static_cast<WebKitMediaCaptureState>(g_value_get_enum(value)));
+ break;
+ case PROP_MICROPHONE_CAPTURE_STATE:
+ webkit_web_view_set_microphone_capture_state(webView, static_cast<WebKitMediaCaptureState>(g_value_get_enum(value)));
+ break;
+ case PROP_DISPLAY_CAPTURE_STATE:
+ webkit_web_view_set_display_capture_state(webView, static_cast<WebKitMediaCaptureState>(g_value_get_enum(value)));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
@@ -943,6 +972,15 @@
case PROP_IS_WEB_PROCESS_RESPONSIVE:
g_value_set_boolean(value, webkit_web_view_get_is_web_process_responsive(webView));
break;
+ case PROP_CAMERA_CAPTURE_STATE:
+ g_value_set_enum(value, webkit_web_view_get_camera_capture_state(webView));
+ break;
+ case PROP_MICROPHONE_CAPTURE_STATE:
+ g_value_set_enum(value, webkit_web_view_get_microphone_capture_state(webView));
+ break;
+ case PROP_DISPLAY_CAPTURE_STATE:
+ g_value_set_enum(value, webkit_web_view_get_display_capture_state(webView));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
@@ -1337,6 +1375,81 @@
TRUE,
WEBKIT_PARAM_READABLE);
+ /**
+ * WebKitWebView:camera-capture-state:
+ *
+ * Capture state of the camera device. Whenever the user grants a media-request sent by the web
+ * page, requesting video capture capabilities (`navigator.mediaDevices.getUserMedia({video:
+ * true})`) this property will be set to %WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE.
+ *
+ * The application can monitor this property and provide a visual indicator allowing to optionally
+ * deactivate or mute the capture device by setting this property respectively to
+ * %WEBKIT_MEDIA_CAPTURE_STATE_NONE or %WEBKIT_MEDIA_CAPTURE_STATE_MUTED.
+ *
+ * If the capture state of the device is set to %WEBKIT_MEDIA_CAPTURE_STATE_NONE the web-page
+ * can still re-request the permission to the user. Permission desision caching is left to the
+ * application.
+ *
+ * Since: 2.34
+ */
+ sObjProperties[PROP_CAMERA_CAPTURE_STATE] = g_param_spec_enum(
+ "camera-capture-state",
+ "Camera Capture State",
+ _("The capture state of the camera device"),
+ WEBKIT_TYPE_MEDIA_CAPTURE_STATE,
+ WEBKIT_MEDIA_CAPTURE_STATE_NONE,
+ WEBKIT_PARAM_READWRITE);
+
+ /**
+ * WebKitWebView:microphone-capture-state:
+ *
+ * Capture state of the microphone device. Whenever the user grants a media-request sent by the web
+ * page, requesting audio capture capabilities (`navigator.mediaDevices.getUserMedia({audio:
+ * true})`) this property will be set to %WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE.
+ *
+ * The application can monitor this property and provide a visual indicator allowing to
+ * optionally deactivate or mute the capture device by setting this property respectively to
+ * %WEBKIT_MEDIA_CAPTURE_STATE_NONE or %WEBKIT_MEDIA_CAPTURE_STATE_MUTED.
+ *
+ * If the capture state of the device is set to %WEBKIT_MEDIA_CAPTURE_STATE_NONE the web-page
+ * can still re-request the permission to the user. Permission desision caching is left to the
+ * application.
+ *
+ * Since: 2.34
+ */
+ sObjProperties[PROP_MICROPHONE_CAPTURE_STATE] = g_param_spec_enum(
+ "microphone-capture-state",
+ "Microphone Capture State",
+ _("The capture state of the microphone device"),
+ WEBKIT_TYPE_MEDIA_CAPTURE_STATE,
+ WEBKIT_MEDIA_CAPTURE_STATE_NONE,
+ WEBKIT_PARAM_READWRITE);
+
+ /**
+ * WebKitWebView:display-capture-state:
+ *
+ * Capture state of the display device. Whenever the user grants a media-request sent by the web
+ * page, requesting screencasting capabilities (`navigator.mediaDevices.getDisplayMedia() this
+ * property will be set to %WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE.
+ *
+ * The application can monitor this property and provide a visual indicator allowing to
+ * optionally deactivate or mute the capture device by setting this property respectively to
+ * %WEBKIT_MEDIA_CAPTURE_STATE_NONE or %WEBKIT_MEDIA_CAPTURE_STATE_MUTED.
+ *
+ * If the capture state of the device is set to %WEBKIT_MEDIA_CAPTURE_STATE_NONE the web-page
+ * can still re-request the permission to the user. Permission desision caching is left to the
+ * application.
+ *
+ * Since: 2.34
+ */
+ sObjProperties[PROP_DISPLAY_CAPTURE_STATE] = g_param_spec_enum(
+ "display-capture-state",
+ "Display Capture State",
+ _("The capture state of the display device"),
+ WEBKIT_TYPE_MEDIA_CAPTURE_STATE,
+ WEBKIT_MEDIA_CAPTURE_STATE_NONE,
+ WEBKIT_PARAM_READWRITE);
+
g_object_class_install_properties(gObjectClass, N_PROPERTIES, sObjProperties);
/**
@@ -4230,10 +4343,10 @@
* when it's emitted with %WEBKIT_LOAD_COMMITTED event.
*
* Note that this function provides no information about the security of the web
- * page if the current #WebKitTLSErrorsPolicy is @WEBKIT_TLS_ERRORS_POLICY_IGNORE,
+ * page if the current #WebKitTLSErrorsPolicy is %WEBKIT_TLS_ERRORS_POLICY_IGNORE,
* as subresources of the page may be controlled by an attacker. This function
* may safely be used to determine the security status of the current page only
- * if the current #WebKitTLSErrorsPolicy is @WEBKIT_TLS_ERRORS_POLICY_FAIL, in
+ * if the current #WebKitTLSErrorsPolicy is %WEBKIT_TLS_ERRORS_POLICY_FAIL, in
* which case subresources that fail certificate verification will be blocked.
*
* Returns: %TRUE if the @web_view connection uses HTTPS and a response has been received
@@ -4754,3 +4867,187 @@
getPage(webView).setCORSDisablingPatterns(WTFMove(allowListVector));
}
+
+static void webkitWebViewConfigureMediaCapture(WebKitWebView* webView, WebCore::MediaProducer::MediaCaptureKind captureKind, WebKitMediaCaptureState captureState, bool isFromDisplayCapture = false)
+{
+ auto& page = getPage(webView);
+ auto mutedState = page.mutedStateFlags();
+
+ switch (captureState) {
+ case WEBKIT_MEDIA_CAPTURE_STATE_NONE:
+ page.stopMediaCapture(captureKind, [webView, captureKind] {
+ switch (captureKind) {
+ case WebCore::MediaProducer::MediaCaptureKind::Audio:
+ g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_MICROPHONE_CAPTURE_STATE]);
+ break;
+ case WebCore::MediaProducer::MediaCaptureKind::Video:
+ g_object_notify_by_pspec(G_OBJECT(webView), sObjProperties[PROP_CAMERA_CAPTURE_STATE]);
+ break;
+ case WebCore::MediaProducer::MediaCaptureKind::AudioVideo:
+ ASSERT_NOT_REACHED();
+ return;
+ }
+ });
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE:
+ switch (captureKind) {
+ case WebCore::MediaProducer::MediaCaptureKind::Audio:
+ mutedState.remove(WebCore::MediaProducer::MutedState::AudioCaptureIsMuted);
+ break;
+ case WebCore::MediaProducer::MediaCaptureKind::Video:
+ if (isFromDisplayCapture)
+ mutedState.remove(WebCore::MediaProducer::MutedState::ScreenCaptureIsMuted);
+ else
+ mutedState.remove(WebCore::MediaProducer::MutedState::VideoCaptureIsMuted);
+ break;
+ case WebCore::MediaProducer::MediaCaptureKind::AudioVideo:
+ ASSERT_NOT_REACHED();
+ return;
+ }
+ page.setMuted(mutedState);
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_MUTED:
+ switch (captureKind) {
+ case WebCore::MediaProducer::MediaCaptureKind::Audio:
+ mutedState.add(WebCore::MediaProducer::MutedState::AudioCaptureIsMuted);
+ break;
+ case WebCore::MediaProducer::MediaCaptureKind::Video:
+ if (isFromDisplayCapture)
+ mutedState.add(WebCore::MediaProducer::MutedState::ScreenCaptureIsMuted);
+ else
+ mutedState.add(WebCore::MediaProducer::MutedState::VideoCaptureIsMuted);
+ break;
+ case WebCore::MediaProducer::MediaCaptureKind::AudioVideo:
+ ASSERT_NOT_REACHED();
+ return;
+ }
+ page.setMuted(mutedState);
+ break;
+ }
+}
+
+/**
+ * webkit_web_view_get_camera_capture_state:
+ * @web_view: a #WebKitWebView
+ *
+ * Get the camera capture state of a #WebKitWebView.
+ *
+ * Returns: The #WebKitMediaCaptureState of the camera device. If #WebKitSettings:enable-mediastream
+ * is %FALSE, this method will return %WEBKIT_MEDIA_CAPTURE_STATE_NONE.
+ *
+ * Since: 2.34
+ */
+WebKitMediaCaptureState webkit_web_view_get_camera_capture_state(WebKitWebView* webView)
+{
+ auto state = getPage(webView).reportedMediaState();
+ if (state & WebCore::MediaProducer::MediaState::HasActiveVideoCaptureDevice)
+ return WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE;
+ if (state & WebCore::MediaProducer::MediaState::HasMutedVideoCaptureDevice)
+ return WEBKIT_MEDIA_CAPTURE_STATE_MUTED;
+ return WEBKIT_MEDIA_CAPTURE_STATE_NONE;
+}
+
+/**
+ * webkit_web_view_set_camera_capture_state:
+ * @web_view: a #WebKitWebView
+ * @state: a #WebKitMediaCaptureState
+ *
+ * Set the camera capture state of a #WebKitWebView.
+ *
+ * If #WebKitSettings:enable-mediastream is %FALSE, this method will have no visible effect. Once the
+ * state of the device has been set to %WEBKIT_MEDIA_CAPTURE_STATE_NONE it cannot be changed
+ * anymore. The page can however request capture again using the mediaDevices API.
+ *
+ * Since: 2.34
+ */
+void webkit_web_view_set_camera_capture_state(WebKitWebView* webView, WebKitMediaCaptureState state)
+{
+ if (webkit_web_view_get_camera_capture_state(webView) == WEBKIT_MEDIA_CAPTURE_STATE_NONE)
+ return;
+
+ webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducer::MediaCaptureKind::Video, state);
+}
+
+/**
+ * webkit_web_view_get_microphone_capture_state:
+ * @web_view: a #WebKitWebView
+ *
+ * Get the microphone capture state of a #WebKitWebView.
+ *
+ * Returns: The #WebKitMediaCaptureState of the microphone device. If #WebKitSettings:enable-mediastream
+ * is %FALSE, this method will return %WEBKIT_MEDIA_CAPTURE_STATE_NONE.
+ *
+ * Since: 2.34
+ */
+WebKitMediaCaptureState webkit_web_view_get_microphone_capture_state(WebKitWebView* webView)
+{
+ auto state = getPage(webView).reportedMediaState();
+ if (state & WebCore::MediaProducer::MediaState::HasActiveAudioCaptureDevice)
+ return WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE;
+ if (state & WebCore::MediaProducer::MediaState::HasMutedAudioCaptureDevice)
+ return WEBKIT_MEDIA_CAPTURE_STATE_MUTED;
+ return WEBKIT_MEDIA_CAPTURE_STATE_NONE;
+}
+
+/**
+ * webkit_web_view_set_microphone_capture_state:
+ * @web_view: a #WebKitWebView
+ * @state: a #WebKitMediaCaptureState
+ *
+ * Set the microphone capture state of a #WebKitWebView.
+ *
+ * If #WebKitSettings:enable-mediastream is %FALSE, this method will have no visible effect. Once the
+ * state of the device has been set to %WEBKIT_MEDIA_CAPTURE_STATE_NONE it cannot be changed
+ * anymore. The page can however request capture again using the mediaDevices API.
+ *
+ * Since: 2.34
+ */
+void webkit_web_view_set_microphone_capture_state(WebKitWebView* webView, WebKitMediaCaptureState state)
+{
+ if (webkit_web_view_get_microphone_capture_state(webView) == WEBKIT_MEDIA_CAPTURE_STATE_NONE)
+ return;
+
+ webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducer::MediaCaptureKind::Audio, state);
+}
+
+/**
+ * webkit_web_view_get_display_capture_state:
+ * @web_view: a #WebKitWebView
+ *
+ * Get the display capture state of a #WebKitWebView.
+ *
+ * Returns: The #WebKitMediaCaptureState of the display device. If #WebKitSettings:enable-mediastream
+ * is %FALSE, this method will return %WEBKIT_MEDIA_CAPTURE_STATE_NONE.
+ *
+ * Since: 2.34
+ */
+WebKitMediaCaptureState webkit_web_view_get_display_capture_state(WebKitWebView* webView)
+{
+ auto state = getPage(webView).reportedMediaState();
+ if (state & WebCore::MediaProducer::MediaState::HasActiveDisplayCaptureDevice)
+ return WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE;
+ if (state & WebCore::MediaProducer::MediaState::HasMutedDisplayCaptureDevice)
+ return WEBKIT_MEDIA_CAPTURE_STATE_MUTED;
+ return WEBKIT_MEDIA_CAPTURE_STATE_NONE;
+}
+
+/**
+ * webkit_web_view_set_display_capture_state:
+ * @web_view: a #WebKitWebView
+ * @state: a #WebKitMediaCaptureState
+ *
+ * Set the display capture state of a #WebKitWebView.
+ *
+ * If #WebKitSettings:enable-mediastream is %FALSE, this method will have no visible effect. Once the
+ * state of the device has been set to %WEBKIT_MEDIA_CAPTURE_STATE_NONE it cannot be changed
+ * anymore. The page can however request capture again using the mediaDevices API.
+ *
+ * Since: 2.34
+ */
+void webkit_web_view_set_display_capture_state(WebKitWebView* webView, WebKitMediaCaptureState state)
+{
+ if (webkit_web_view_get_display_capture_state(webView) == WEBKIT_MEDIA_CAPTURE_STATE_NONE)
+ return;
+
+ webkitWebViewConfigureMediaCapture(webView, WebCore::MediaProducer::MediaCaptureKind::Video, state, true);
+}
Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h 2021-07-22 10:54:07 UTC (rev 280172)
@@ -91,6 +91,7 @@
bool webkitWebViewEmitShowNotification(WebKitWebView*, WebKitNotification*);
void webkitWebViewWebProcessTerminated(WebKitWebView*, WebKitWebProcessTerminationReason);
void webkitWebViewIsPlayingAudioChanged(WebKitWebView*);
+void webkitWebViewMediaCaptureStateDidChange(WebKitWebView*, WebCore::MediaProducer::MediaStateFlags);
void webkitWebViewSelectionDidChange(WebKitWebView*);
void webkitWebViewRequestInstallMissingMediaPlugins(WebKitWebView*, WebKit::InstallMissingMediaPluginsPermissionRequest&);
WebKitWebsiteDataManager* webkitWebViewGetWebsiteDataManager(WebKitWebView*);
Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitUserMediaPermissionRequest.h (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitUserMediaPermissionRequest.h 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitUserMediaPermissionRequest.h 2021-07-22 10:54:07 UTC (rev 280172)
@@ -64,6 +64,9 @@
WEBKIT_API gboolean
webkit_user_media_permission_is_for_video_device (WebKitUserMediaPermissionRequest *request);
+WEBKIT_API gboolean
+webkit_user_media_permission_is_for_display_device (WebKitUserMediaPermissionRequest *request);
+
G_END_DECLS
#endif
Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebView.h (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebView.h 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebView.h 2021-07-22 10:54:07 UTC (rev 280172)
@@ -205,6 +205,22 @@
WEBKIT_WEB_PROCESS_TERMINATED_BY_API
} WebKitWebProcessTerminationReason;
+/**
+ * WebKitMediaCaptureState:
+ * @WEBKIT_MEDIA_CAPTURE_STATE_NONE: Media capture is disabled.
+ * @WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE: Media capture is active.
+ * @WEBKIT_MEDIA_CAPTURE_STATE_MUTED: Media capture is muted.
+ *
+ * Enum values used to specify the capture state of a media device.
+ *
+ * Since: 2.34
+ */
+typedef enum {
+ WEBKIT_MEDIA_CAPTURE_STATE_NONE,
+ WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE,
+ WEBKIT_MEDIA_CAPTURE_STATE_MUTED,
+} WebKitMediaCaptureState;
+
struct _WebKitWebView {
WebKitWebViewBase parent;
@@ -600,6 +616,27 @@
WEBKIT_API void
webkit_web_view_terminate_web_process (WebKitWebView *web_view);
+WEBKIT_API WebKitMediaCaptureState
+webkit_web_view_get_camera_capture_state (WebKitWebView *web_view);
+
+WEBKIT_API void
+webkit_web_view_set_camera_capture_state (WebKitWebView *web_view,
+ WebKitMediaCaptureState state);
+
+WEBKIT_API WebKitMediaCaptureState
+webkit_web_view_get_microphone_capture_state (WebKitWebView *web_view);
+
+WEBKIT_API void
+webkit_web_view_set_microphone_capture_state (WebKitWebView *web_view,
+ WebKitMediaCaptureState state);
+
+WEBKIT_API WebKitMediaCaptureState
+webkit_web_view_get_display_capture_state (WebKitWebView *web_view);
+
+WEBKIT_API void
+webkit_web_view_set_display_capture_state (WebKitWebView *web_view,
+ WebKitMediaCaptureState state);
+
G_END_DECLS
#endif
Modified: trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt 2021-07-22 10:54:07 UTC (rev 280172)
@@ -199,6 +199,7 @@
WebKitSnapshotRegion
WebKitWebProcessTerminationReason
WebKitAutoplayPolicy
+WebKitMediaCaptureState
<SUBSECTION Editing Commands>
WEBKIT_EDITING_COMMAND_CUT
@@ -293,6 +294,12 @@
webkit_web_view_get_is_web_process_responsive
webkit_web_view_terminate_web_process
webkit_web_view_set_cors_allowlist
+webkit_web_view_get_camera_capture_state
+webkit_web_view_get_microphone_capture_state
+webkit_web_view_set_camera_capture_state
+webkit_web_view_set_microphone_capture_state
+webkit_web_view_get_display_capture_state
+webkit_web_view_set_display_capture_state
<SUBSECTION WebKitJavascriptResult>
WebKitJavascriptResult
@@ -796,6 +803,7 @@
WebKitUserMediaPermissionRequest
webkit_user_media_permission_is_for_audio_device
webkit_user_media_permission_is_for_video_device
+webkit_user_media_permission_is_for_display_device
<SUBSECTION Standard>
WebKitUserMediaPermissionRequestClass
Modified: trunk/Source/WebKit/UIProcess/API/wpe/WebKitUserMediaPermissionRequest.h (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/wpe/WebKitUserMediaPermissionRequest.h 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/wpe/WebKitUserMediaPermissionRequest.h 2021-07-22 10:54:07 UTC (rev 280172)
@@ -64,6 +64,9 @@
WEBKIT_API gboolean
webkit_user_media_permission_is_for_video_device (WebKitUserMediaPermissionRequest *request);
+WEBKIT_API gboolean
+webkit_user_media_permission_is_for_display_device (WebKitUserMediaPermissionRequest *request);
+
G_END_DECLS
#endif
Modified: trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebView.h (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebView.h 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebView.h 2021-07-22 10:54:07 UTC (rev 280172)
@@ -186,6 +186,22 @@
typedef void (* WebKitFrameDisplayedCallback) (WebKitWebView *web_view,
gpointer user_data);
+/**
+ * WebKitMediaCaptureState:
+ * @WEBKIT_MEDIA_CAPTURE_STATE_NONE: Media capture is disabled.
+ * @WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE: Media capture is active.
+ * @WEBKIT_MEDIA_CAPTURE_STATE_MUTED: Media capture is muted.
+ *
+ * Enum values used to specify the capture state of a media device.
+ *
+ * Since: 2.34
+ */
+typedef enum {
+ WEBKIT_MEDIA_CAPTURE_STATE_NONE,
+ WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE,
+ WEBKIT_MEDIA_CAPTURE_STATE_MUTED,
+} WebKitMediaCaptureState;
+
struct _WebKitWebView {
GObject parent;
@@ -577,6 +593,27 @@
webkit_web_view_set_cors_allowlist (WebKitWebView *web_view,
const gchar * const *allowlist);
+WEBKIT_API WebKitMediaCaptureState
+webkit_web_view_get_camera_capture_state (WebKitWebView *web_view);
+
+WEBKIT_API void
+webkit_web_view_set_camera_capture_state (WebKitWebView *web_view,
+ WebKitMediaCaptureState state);
+
+WEBKIT_API WebKitMediaCaptureState
+webkit_web_view_get_microphone_capture_state (WebKitWebView *web_view);
+
+WEBKIT_API void
+webkit_web_view_set_microphone_capture_state (WebKitWebView *web_view,
+ WebKitMediaCaptureState state);
+
+WEBKIT_API WebKitMediaCaptureState
+webkit_web_view_get_display_capture_state (WebKitWebView *web_view);
+
+WEBKIT_API void
+webkit_web_view_set_display_capture_state (WebKitWebView *web_view,
+ WebKitMediaCaptureState state);
+
G_END_DECLS
#endif
Modified: trunk/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt (280171 => 280172)
--- trunk/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt 2021-07-22 10:54:07 UTC (rev 280172)
@@ -173,6 +173,7 @@
WebKitWebProcessTerminationReason
WebKitFrameDisplayedCallback
WebKitAutoplayPolicy
+WebKitMediaCaptureState
<SUBSECTION Editing Commands>
WEBKIT_EDITING_COMMAND_CUT
@@ -265,6 +266,12 @@
webkit_web_view_get_is_web_process_responsive
webkit_web_view_terminate_web_process
webkit_web_view_set_cors_allowlist
+webkit_web_view_get_camera_capture_state
+webkit_web_view_get_microphone_capture_state
+webkit_web_view_set_camera_capture_state
+webkit_web_view_set_microphone_capture_state
+webkit_web_view_get_display_capture_state
+webkit_web_view_set_display_capture_state
<SUBSECTION WebKitJavascriptResult>
WebKitJavascriptResult
@@ -800,6 +807,7 @@
WebKitUserMediaPermissionRequest
webkit_user_media_permission_is_for_audio_device
webkit_user_media_permission_is_for_video_device
+webkit_user_media_permission_is_for_display_device
<SUBSECTION Standard>
WebKitUserMediaPermissionRequestClass
Modified: trunk/Tools/ChangeLog (280171 => 280172)
--- trunk/Tools/ChangeLog 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Tools/ChangeLog 2021-07-22 10:54:07 UTC (rev 280172)
@@ -1,3 +1,35 @@
+2021-07-22 Philippe Normand <[email protected]>
+
+ [GLib] Expose API to access/modify capture devices states
+ https://bugs.webkit.org/show_bug.cgi?id=227902
+
+ Reviewed by Carlos Garcia Campos.
+
+ The GTK MiniBrowser is now able to show media capture indicators, through the URI entry. A
+ new API test was added, checking support for getDisplayMedia().
+
+ * MiniBrowser/gtk/BrowserTab.c:
+ (decidePermissionRequest):
+ * MiniBrowser/gtk/BrowserWindow.c:
+ (webViewMediaCaptureStateChanged):
+ (webViewUriEntryIconPressed):
+ (browserWindowSwitchTab):
+ * TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp:
+ (testWebViewUserMediaPermissionRequests):
+ (testWebViewAudioOnlyUserMediaPermissionRequests):
+ (testWebViewDisplayUserMediaPermissionRequests):
+ (beforeAll):
+ * TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp:
+ (displayCaptureChanged):
+ (WebViewTest::waitUntilDisplayCaptureStateChangedTo):
+ (microphoneCaptureChanged):
+ (WebViewTest::waitUntilMicrophoneCaptureStateChangedTo):
+ (cameraCaptureChanged):
+ (WebViewTest::waitUntilCameraCaptureStateChangedTo):
+ * TestWebKitAPI/glib/WebKitGLib/WebViewTest.h:
+ * flatpak/flatpakutils.py:
+ (WebkitFlatpak.run_in_sandbox):
+
2021-07-21 Alexey Proskuryakov <[email protected]>
MiniBrowser xcconfig should include ccache.xcconfig conditionally
Modified: trunk/Tools/MiniBrowser/gtk/BrowserTab.c (280171 => 280172)
--- trunk/Tools/MiniBrowser/gtk/BrowserTab.c 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Tools/MiniBrowser/gtk/BrowserTab.c 2021-07-22 10:54:07 UTC (rev 280172)
@@ -307,16 +307,20 @@
text = g_strdup("Allow notifications request?");
} else if (WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request)) {
title = "UserMedia request";
- gboolean is_for_audio_device = webkit_user_media_permission_is_for_audio_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request));
- gboolean is_for_video_device = webkit_user_media_permission_is_for_video_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request));
+ gboolean isForAudioDevice = webkit_user_media_permission_is_for_audio_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request));
+ gboolean isForVideoDevice = webkit_user_media_permission_is_for_video_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request));
+ gboolean isForDisplayDevice = webkit_user_media_permission_is_for_display_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request));
+
const char *mediaType = NULL;
- if (is_for_audio_device) {
- if (is_for_video_device)
+ if (isForAudioDevice) {
+ if (isForVideoDevice)
mediaType = "audio/video";
else
mediaType = "audio";
- } else if (is_for_video_device)
+ } else if (isForVideoDevice)
mediaType = "video";
+ else if (isForDisplayDevice)
+ mediaType = "display";
text = g_strdup_printf("Allow access to %s device?", mediaType);
} else if (WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request)) {
title = "Media plugin missing request";
Modified: trunk/Tools/MiniBrowser/gtk/BrowserWindow.c (280171 => 280172)
--- trunk/Tools/MiniBrowser/gtk/BrowserWindow.c 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Tools/MiniBrowser/gtk/BrowserWindow.c 2021-07-22 10:54:07 UTC (rev 280172)
@@ -649,6 +649,72 @@
updateUriEntryIcon(window);
}
+static void webViewMediaCaptureStateChanged(WebKitWebView* webView, GParamSpec* paramSpec, BrowserWindow* window)
+{
+ const gchar* name = g_param_spec_get_name(paramSpec);
+ // FIXME: the URI entry is not great storage in case more than one capture device is in use,
+ // because it can store only one secondary icon.
+ GtkEntry *entry = GTK_ENTRY(window->uriEntry);
+
+ if (g_str_has_prefix(name, "microphone")) {
+ switch (webkit_web_view_get_microphone_capture_state(webView)) {
+ case WEBKIT_MEDIA_CAPTURE_STATE_NONE:
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, NULL);
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_MUTED:
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, "microphone-sensivity-mutes-symbolic");
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE:
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, "audio-input-microphone-symbolic");
+ break;
+ }
+ } else if (g_str_has_prefix(name, "camera")) {
+ switch (webkit_web_view_get_camera_capture_state(webView)) {
+ case WEBKIT_MEDIA_CAPTURE_STATE_NONE:
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, NULL);
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_MUTED:
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, "camera-disabled-symbolic");
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE:
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, "camera-web-symbolic");
+ break;
+ }
+ } else if (g_str_has_prefix(name, "display")) {
+ switch (webkit_web_view_get_display_capture_state(webView)) {
+ case WEBKIT_MEDIA_CAPTURE_STATE_NONE:
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, NULL);
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_MUTED:
+ // FIXME: I found no suitable icon for this.
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, "media-playback-stop-symbolic");
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE:
+ gtk_entry_set_icon_from_icon_name(entry, GTK_ENTRY_ICON_SECONDARY, "video-display-symbolic");
+ break;
+ }
+ }
+}
+
+static void webViewUriEntryIconPressed(GtkEntry* entry, GtkEntryIconPosition position, GdkEvent* event, BrowserWindow* window)
+{
+ if (position != GTK_ENTRY_ICON_SECONDARY)
+ return;
+
+ // FIXME: What about audio/video?
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ switch (webkit_web_view_get_display_capture_state(webView)) {
+ case WEBKIT_MEDIA_CAPTURE_STATE_NONE:
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_MUTED:
+ webkit_web_view_set_display_capture_state(webView, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ break;
+ case WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE:
+ webkit_web_view_set_display_capture_state(webView, WEBKIT_MEDIA_CAPTURE_STATE_MUTED);
+ break;
+ }
+}
+
static void webViewIsLoadingChanged(WebKitWebView *webView, GParamSpec *paramSpec, BrowserWindow *window)
{
gboolean isLoading = webkit_web_view_is_loading(webView);
@@ -1180,7 +1246,13 @@
#if !GTK_CHECK_VERSION(3, 98, 0)
g_signal_connect(webView, "scroll-event", G_CALLBACK(scrollEventCallback), window);
#endif
+ g_signal_connect_object(webView, "notify::camera-capture-state", G_CALLBACK(webViewMediaCaptureStateChanged), window, 0);
+ g_signal_connect_object(webView, "notify::microphone-capture-state", G_CALLBACK(webViewMediaCaptureStateChanged), window, 0);
+ g_signal_connect_object(webView, "notify::display-capture-state", G_CALLBACK(webViewMediaCaptureStateChanged), window, 0);
+ g_object_set(window->uriEntry, "secondary-icon-activatable", TRUE, NULL);
+ g_signal_connect(window->uriEntry, "icon-press", G_CALLBACK(webViewUriEntryIconPressed), window);
+
WebKitBackForwardList *backForwardlist = webkit_web_view_get_back_forward_list(webView);
browserWindowUpdateNavigationMenu(window, backForwardlist);
g_signal_connect(backForwardlist, "changed", G_CALLBACK(backForwardlistChanged), window);
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp (280171 => 280172)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestUIClient.cpp 2021-07-22 10:54:07 UTC (rev 280172)
@@ -240,6 +240,7 @@
WebKitUserMediaPermissionRequest* userMediaRequest = WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request);
g_assert_true(webkit_user_media_permission_is_for_audio_device(userMediaRequest) == test->m_expectedAudioMedia);
g_assert_true(webkit_user_media_permission_is_for_video_device(userMediaRequest) == test->m_expectedVideoMedia);
+ g_assert_true(webkit_user_media_permission_is_for_display_device(userMediaRequest) == test->m_expectedDisplayMedia);
}
if (test->m_allowPermissionRequests)
@@ -256,6 +257,61 @@
g_main_loop_quit(test->m_mainLoop);
}
+
+ static void displayCaptureChanged(WebKitWebView* webView, GParamSpec*, UIClientTest* test)
+ {
+ if (test->m_expectedDisplayCaptureState && *test->m_expectedDisplayCaptureState != webkit_web_view_get_display_capture_state(webView))
+ return;
+
+ g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(displayCaptureChanged), test);
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ void waitUntilDisplayCaptureStateChangedTo(WebKitMediaCaptureState expectedCaptureState)
+ {
+ *m_expectedDisplayCaptureState = expectedCaptureState;
+ g_signal_connect(m_webView, "notify::display-capture-state", G_CALLBACK(displayCaptureChanged), this);
+ g_main_loop_run(m_mainLoop);
+ g_assert_cmpuint(webkit_web_view_get_display_capture_state(m_webView), ==, expectedCaptureState);
+ m_expectedDisplayCaptureState.reset();
+ }
+
+ static void microphoneCaptureChanged(WebKitWebView* webView, GParamSpec*, UIClientTest* test)
+ {
+ if (test->m_expectedMicrophoneCaptureState && *test->m_expectedMicrophoneCaptureState != webkit_web_view_get_microphone_capture_state(webView))
+ return;
+
+ g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(microphoneCaptureChanged), test);
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ void waitUntilMicrophoneCaptureStateChangedTo(WebKitMediaCaptureState expectedCaptureState)
+ {
+ *m_expectedMicrophoneCaptureState = expectedCaptureState;
+ g_signal_connect(m_webView, "notify::microphone-capture-state", G_CALLBACK(microphoneCaptureChanged), this);
+ g_main_loop_run(m_mainLoop);
+ g_assert_cmpuint(webkit_web_view_get_microphone_capture_state(m_webView), ==, expectedCaptureState);
+ m_expectedMicrophoneCaptureState.reset();
+ }
+
+ static void cameraCaptureChanged(WebKitWebView* webView, GParamSpec*, UIClientTest* test)
+ {
+ if (test->m_expectedCameraCaptureState && *test->m_expectedCameraCaptureState != webkit_web_view_get_camera_capture_state(webView))
+ return;
+
+ g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(cameraCaptureChanged), test);
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ void waitUntilCameraCaptureStateChangedTo(WebKitMediaCaptureState expectedCaptureState)
+ {
+ *m_expectedCameraCaptureState = expectedCaptureState;
+ g_signal_connect(m_webView, "notify::camera-capture-state", G_CALLBACK(cameraCaptureChanged), this);
+ g_main_loop_run(m_mainLoop);
+ g_assert_cmpuint(webkit_web_view_get_camera_capture_state(m_webView), ==, expectedCaptureState);
+ m_expectedCameraCaptureState.reset();
+ }
+
UIClientTest()
: m_scriptDialogType(WEBKIT_SCRIPT_DIALOG_ALERT)
, m_scriptDialogConfirmed(true)
@@ -263,6 +319,7 @@
, m_verifyMediaTypes(false)
, m_expectedAudioMedia(false)
, m_expectedVideoMedia(false)
+ , m_expectedDisplayMedia(false)
, m_mouseTargetModifiers(0)
{
webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE);
@@ -415,6 +472,7 @@
gboolean m_verifyMediaTypes;
gboolean m_expectedAudioMedia;
gboolean m_expectedVideoMedia;
+ gboolean m_expectedDisplayMedia;
WindowProperties m_windowProperties;
HashSet<WTF::String> m_windowPropertiesChanged;
GRefPtr<WebKitHitTestResult> m_mouseTargetHitTestResult;
@@ -426,6 +484,10 @@
bool m_shouldCreateWebViewsInNewWindowsAutomatically { false };
cairo_rectangle_int_t m_defaultGeometryNewWindows;
#endif
+
+ std::optional<WebKitMediaCaptureState> m_expectedCameraCaptureState;
+ std::optional<WebKitMediaCaptureState> m_expectedDisplayCaptureState;
+ std::optional<WebKitMediaCaptureState> m_expectedMicrophoneCaptureState;
};
static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer)
@@ -1001,17 +1063,45 @@
test->m_verifyMediaTypes = TRUE;
test->m_expectedAudioMedia = TRUE;
test->m_expectedVideoMedia = TRUE;
+ test->m_expectedDisplayMedia = FALSE;
// Test denying a permission request.
test->m_allowPermissionRequests = false;
test->loadHtml(userMediaRequestHTML, nullptr);
test->waitUntilTitleChangedTo("NotAllowedError");
+ g_assert_cmpuint(webkit_web_view_get_display_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ g_assert_cmpuint(webkit_web_view_get_microphone_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ g_assert_cmpuint(webkit_web_view_get_camera_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
// Test allowing a permission request.
test->m_allowPermissionRequests = true;
test->loadHtml(userMediaRequestHTML, nullptr);
test->waitUntilTitleChangedTo("OK");
+ g_assert_cmpuint(webkit_web_view_get_display_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ g_assert_cmpuint(webkit_web_view_get_microphone_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ g_assert_cmpuint(webkit_web_view_get_camera_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ webkit_web_view_set_microphone_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_MUTED);
+ test->waitUntilMicrophoneCaptureStateChangedTo(WEBKIT_MEDIA_CAPTURE_STATE_MUTED);
+
+ webkit_web_view_set_microphone_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ test->waitUntilMicrophoneCaptureStateChangedTo(WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+
+ webkit_web_view_set_camera_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_MUTED);
+ test->waitUntilCameraCaptureStateChangedTo(WEBKIT_MEDIA_CAPTURE_STATE_MUTED);
+
+ webkit_web_view_set_camera_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ test->waitUntilCameraCaptureStateChangedTo(WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+
+ webkit_web_view_set_camera_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ test->waitUntilCameraCaptureStateChangedTo(WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+
+ // A de-activated capture device cannot be re-activated.
+ webkit_web_view_set_camera_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ g_assert_cmpuint(webkit_web_view_get_camera_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+
+ g_assert_cmpuint(webkit_web_view_get_microphone_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+
webkit_settings_set_enable_media_stream(settings, enabled);
webkit_settings_set_enable_mock_capture_devices(settings, FALSE);
webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, TRUE);
@@ -1041,16 +1131,86 @@
test->m_verifyMediaTypes = TRUE;
test->m_expectedAudioMedia = TRUE;
test->m_expectedVideoMedia = FALSE;
+ test->m_expectedDisplayMedia = FALSE;
// Test denying a permission request.
test->m_allowPermissionRequests = false;
test->loadHtml(userMediaRequestHTML, nullptr);
test->waitUntilTitleChangedTo("NotAllowedError");
+ g_assert_cmpuint(webkit_web_view_get_display_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ g_assert_cmpuint(webkit_web_view_get_microphone_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ g_assert_cmpuint(webkit_web_view_get_camera_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
webkit_settings_set_enable_media_stream(settings, enabled);
webkit_settings_set_enable_mock_capture_devices(settings, FALSE);
webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, TRUE);
}
+
+static void testWebViewDisplayUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
+{
+ WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
+ gboolean enabled = webkit_settings_get_enable_media_stream(settings);
+ webkit_settings_set_enable_media_stream(settings, TRUE);
+ webkit_settings_set_enable_mock_capture_devices(settings, TRUE);
+ webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, FALSE);
+
+ test->showInWindow();
+ static const char* displayMediaRequestHTML = "<html>"
+ " <script>"
+ " function runTest()"
+ " {"
+ " navigator.mediaDevices.getDisplayMedia()"
+ " .then((stream) => { document.title = \"OK\"; })"
+ " .catch((e) => { document.title = e.name; });"
+ " }"
+ " </script>"
+ " <body>"
+ " <input style=\"position:absolute; left:0; top:0; margin:0; padding:0\" type=\"button\" value=\"click me\" _onclick_=\"runTest();\"/>"
+ " </body>"
+ "</html>";
+
+ test->m_verifyMediaTypes = TRUE;
+ test->m_expectedAudioMedia = FALSE;
+ test->m_expectedVideoMedia = FALSE;
+ test->m_expectedDisplayMedia = TRUE;
+
+ // Test denying a permission request.
+ test->m_allowPermissionRequests = false;
+ test->loadHtml(displayMediaRequestHTML, nullptr);
+ test->waitUntilLoadFinished();
+ test->clickMouseButton(5, 5);
+ test->waitUntilTitleChangedTo("NotAllowedError");
+ g_assert_cmpuint(webkit_web_view_get_display_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ g_assert_cmpuint(webkit_web_view_get_microphone_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ g_assert_cmpuint(webkit_web_view_get_camera_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+
+ // Test allowing a permission request.
+ test->m_allowPermissionRequests = true;
+ test->loadHtml(displayMediaRequestHTML, nullptr);
+ test->waitUntilLoadFinished();
+ test->clickMouseButton(5, 5);
+ test->waitUntilTitleChangedTo("OK");
+ g_assert_cmpuint(webkit_web_view_get_display_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ g_assert_cmpuint(webkit_web_view_get_microphone_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ g_assert_cmpuint(webkit_web_view_get_camera_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+
+ webkit_web_view_set_display_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_MUTED);
+ test->waitUntilDisplayCaptureStateChangedTo(WEBKIT_MEDIA_CAPTURE_STATE_MUTED);
+
+ webkit_web_view_set_display_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ test->waitUntilDisplayCaptureStateChangedTo(WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+
+ webkit_web_view_set_display_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+ test->waitUntilDisplayCaptureStateChangedTo(WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+
+ // A de-activated capture device cannot be re-activated.
+ webkit_web_view_set_display_capture_state(test->m_webView, WEBKIT_MEDIA_CAPTURE_STATE_ACTIVE);
+ g_assert_cmpuint(webkit_web_view_get_display_capture_state(test->m_webView), ==, WEBKIT_MEDIA_CAPTURE_STATE_NONE);
+
+ webkit_settings_set_enable_media_stream(settings, enabled);
+ webkit_settings_set_enable_mock_capture_devices(settings, FALSE);
+ webkitSettingsSetMediaCaptureRequiresSecureConnection(settings, TRUE);
+}
#endif // ENABLE(MEDIA_STREAM)
#if ENABLE(POINTER_LOCK)
@@ -1343,6 +1503,7 @@
UIClientTest::add("WebKitWebView", "usermedia-enumeratedevices-permission-check", testWebViewUserMediaEnumerateDevicesPermissionCheck);
UIClientTest::add("WebKitWebView", "usermedia-permission-requests", testWebViewUserMediaPermissionRequests);
UIClientTest::add("WebKitWebView", "audio-usermedia-permission-request", testWebViewAudioOnlyUserMediaPermissionRequests);
+ UIClientTest::add("WebKitWebView", "display-usermedia-permission-request", testWebViewDisplayUserMediaPermissionRequests);
#endif
// FIXME: Implement mouse click in WPE.
#if PLATFORM(GTK)
Modified: trunk/Tools/flatpak/flatpakutils.py (280171 => 280172)
--- trunk/Tools/flatpak/flatpakutils.py 2021-07-22 09:00:27 UTC (rev 280171)
+++ trunk/Tools/flatpak/flatpakutils.py 2021-07-22 10:54:07 UTC (rev 280172)
@@ -801,8 +801,10 @@
"JSC",
"MESA",
"LIBGL",
+ "PIPEWIRE",
"RUST",
"SCCACHE",
+ "SPA",
"WAYLAND",
"WEBKIT",
"WEBKIT2",