From 3a40944edf76b61770e15355919c4740b8102f4e Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 14 Dec 2023 20:04:21 +0200 Subject: [PATCH] launcher: Support toggling WebKit runtime features Add support for toggling WebKit runtime features using the WebKitFeature API introduced in version 2.42, by means of a --features/-F command line flag. (cherry picked from commit 30392134d23eb3a472d7a8aa7c92a23967c001ce) --- launcher/cog-launcher.c | 105 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 9 deletions(-) diff --git a/launcher/cog-launcher.c b/launcher/cog-launcher.c index f8ad4e7a..e431b555 100644 --- a/launcher/cog-launcher.c +++ b/launcher/cog-launcher.c @@ -1052,19 +1052,82 @@ cog_launcher_add_web_permissions_option_entries(CogLauncher *launcher) g_application_add_option_group(G_APPLICATION(launcher), g_steal_pointer(&option_group)); } -static void -cog_launcher_add_web_settings_option_entries(CogLauncher *launcher) +#if WEBKIT_CHECK_VERSION(2, 42, 0) +static WebKitFeature * +find_feature(WebKitFeatureList *features, const char *identifier) { - g_return_if_fail(COG_IS_LAUNCHER(launcher)); + for (gsize i = 0; i < webkit_feature_list_get_length(features); i++) { + WebKitFeature *feature = webkit_feature_list_get(features, i); + if (!g_ascii_strcasecmp(identifier, webkit_feature_get_identifier(feature))) + return feature; + } + return NULL; +} - g_autofree GOptionEntry *option_entries = cog_option_entries_from_class(G_OBJECT_GET_CLASS(launcher->web_settings)); +static gboolean +cog_features_option_callback(const gchar *option, const gchar *value, WebKitSettings *web_settings, GError **error) +{ + g_autoptr(WebKitFeatureList) features = webkit_settings_get_all_features(); + + if (!strcmp(value, "help")) { + g_print("Multiple feature names may be specified separated by commas. No prefix or '+' enable\n" + "features, prefixes '-' and '!' disable features. Names are case-insensitive. Example:\n" + "\n %s --features='!DirPseudo,+WebAnimationsCustomEffects,webgl'\n\n" + "Available features (+/- = enabled/disabled by default):\n\n", + g_get_prgname()); + g_autoptr(GEnumClass) statusEnum = g_type_class_ref(WEBKIT_TYPE_FEATURE_STATUS); + for (gsize i = 0; i < webkit_feature_list_get_length(features); i++) { + WebKitFeature *feature = webkit_feature_list_get(features, i); + g_print(" %c %s (%s)", + webkit_feature_get_default_value(feature) ? '+' : '-', + webkit_feature_get_identifier(feature), + g_enum_get_value(statusEnum, webkit_feature_get_status(feature))->value_nick); + if (webkit_feature_get_name(feature)) + g_print(": %s", webkit_feature_get_name(feature)); + g_print("\n"); + } + exit(EXIT_SUCCESS); + } - if (!option_entries) { - g_critical("Could not deduce option entries for WebKitSettings." - " This should not happen, continuing but YMMV."); - return; + g_auto(GStrv) items = g_strsplit(value, ",", -1); + for (gsize i = 0; items[i]; i++) { + char *item = g_strchomp(items[i]); + gboolean enabled = TRUE; + switch (item[0]) { + case '!': + case '-': + enabled = FALSE; + G_GNUC_FALLTHROUGH; + case '+': + item++; + G_GNUC_FALLTHROUGH; + default: + break; + } + + if (item[0] == '\0') { + g_set_error_literal(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Empty feature name specified"); + return FALSE; + } + + WebKitFeature *feature = find_feature(features, item); + if (!feature) { + g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Feature '%s' is not available", item); + return FALSE; + } + + webkit_settings_set_feature_enabled(web_settings, feature, enabled); } + return TRUE; +} +#endif /* WEBKIT_CHECK_VERSION */ + +static void +cog_launcher_add_web_settings_option_entries(CogLauncher *launcher) +{ + g_return_if_fail(COG_IS_LAUNCHER(launcher)); + g_autoptr(GOptionGroup) option_group = g_option_group_new( "websettings", "WebKitSettings options can be used to configure features exposed to the loaded Web content.\n" @@ -1077,7 +1140,31 @@ cog_launcher_add_web_settings_option_entries(CogLauncher *launcher) "Show WebKitSettings options", launcher->web_settings, NULL); - g_option_group_add_entries(option_group, option_entries); + + g_autofree GOptionEntry *option_entries = cog_option_entries_from_class(G_OBJECT_GET_CLASS(launcher->web_settings)); + if (option_entries) { + g_option_group_add_entries(option_group, option_entries); + } else { + g_critical("Could not deduce option entries for WebKitSettings." + " This should not happen, continuing but YMMV."); + } + +#if WEBKIT_CHECK_VERSION(2, 42, 0) + static const GOptionEntry features_entries[] = { + { + .short_name = 'F', + .long_name = "features", + .description = "Enable or disable WebKit features (hint: pass 'help' for a list)", + .arg = G_OPTION_ARG_CALLBACK, + .arg_data = cog_features_option_callback, + .arg_description = "FEATURE-LIST", + }, + { + NULL, + }}; + g_option_group_add_entries(option_group, features_entries); +#endif /* WEBKIT_CHECK_VERSION */ + g_application_add_option_group(G_APPLICATION(launcher), g_steal_pointer(&option_group)); }