browser-plugin: Rework scriptable method argument parsing and dispatch
Since we're going to move to a much more complicated (async!) solution in a little bit, we're going to require a lot more machinery to handle that. To help with that, let's rework invocation dispatch so that it's more generic. Introduce a parse_args system similar to gjs_parse_args, use X Macros to help with the repetitive parts of the method dispatch. This shouldn't cause any API breaks, so API_VERSION should still be 4. https://bugzilla.gnome.org/show_bug.cgi?id=679099
This commit is contained in:
parent
67689f1a6d
commit
6a117ac12f
@ -373,31 +373,6 @@ plugin_object_deallocate (NPObject *npobj)
|
|||||||
g_slice_free (PluginObject, obj);
|
g_slice_free (PluginObject, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NPIdentifier api_version_id;
|
|
||||||
static NPIdentifier shell_version_id;
|
|
||||||
static NPIdentifier get_info_id;
|
|
||||||
static NPIdentifier list_extensions_id;
|
|
||||||
static NPIdentifier enable_extension_id;
|
|
||||||
static NPIdentifier install_extension_id;
|
|
||||||
static NPIdentifier uninstall_extension_id;
|
|
||||||
static NPIdentifier onextension_changed_id;
|
|
||||||
static NPIdentifier onrestart_id;
|
|
||||||
static NPIdentifier get_errors_id;
|
|
||||||
static NPIdentifier launch_extension_prefs_id;
|
|
||||||
|
|
||||||
static bool
|
|
||||||
plugin_object_has_method (NPObject *npobj,
|
|
||||||
NPIdentifier name)
|
|
||||||
{
|
|
||||||
return (name == get_info_id ||
|
|
||||||
name == list_extensions_id ||
|
|
||||||
name == enable_extension_id ||
|
|
||||||
name == install_extension_id ||
|
|
||||||
name == uninstall_extension_id ||
|
|
||||||
name == get_errors_id ||
|
|
||||||
name == launch_extension_prefs_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
uuid_is_valid (NPString string)
|
uuid_is_valid (NPString string)
|
||||||
{
|
{
|
||||||
@ -469,8 +444,67 @@ jsonify_variant (GVariant *variant,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_list_extensions (PluginObject *obj,
|
parse_args (const gchar *format_str,
|
||||||
NPVariant *result)
|
uint32_t argc,
|
||||||
|
const NPVariant *argv,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
gsize i;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
if (strlen (format_str) != argc)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
va_start (args, argv);
|
||||||
|
|
||||||
|
for (i = 0; format_str[i]; i++)
|
||||||
|
{
|
||||||
|
gpointer arg_location;
|
||||||
|
const NPVariant arg = argv[i];
|
||||||
|
|
||||||
|
arg_location = va_arg (args, gpointer);
|
||||||
|
|
||||||
|
switch (format_str[i])
|
||||||
|
{
|
||||||
|
case 'u':
|
||||||
|
{
|
||||||
|
NPString string;
|
||||||
|
|
||||||
|
if (!NPVARIANT_IS_STRING (arg))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
string = NPVARIANT_TO_STRING (arg);
|
||||||
|
|
||||||
|
if (!uuid_is_valid (string))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
*(gchar **) arg_location = g_strndup (string.UTF8Characters, string.UTF8Length);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
if (!NPVARIANT_IS_BOOLEAN (arg))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
*(gboolean *) arg_location = NPVARIANT_TO_BOOLEAN (arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
out:
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
plugin_list_extensions (PluginObject *obj,
|
||||||
|
uint32_t argc,
|
||||||
|
const NPVariant *args,
|
||||||
|
NPVariant *result)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GVariant *res;
|
GVariant *res;
|
||||||
@ -494,20 +528,21 @@ plugin_list_extensions (PluginObject *obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_enable_extension (PluginObject *obj,
|
plugin_enable_extension (PluginObject *obj,
|
||||||
NPString uuid,
|
uint32_t argc,
|
||||||
gboolean enabled)
|
const NPVariant *argv,
|
||||||
|
NPVariant *result)
|
||||||
{
|
{
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
gchar *uuid_str;
|
gchar *uuid;
|
||||||
|
gboolean enabled;
|
||||||
gsize length;
|
gsize length;
|
||||||
gchar **uuids;
|
gchar **uuids;
|
||||||
const gchar **new_uuids;
|
const gchar **new_uuids;
|
||||||
|
|
||||||
if (!uuid_is_valid (uuid))
|
if (!parse_args ("ub", argc, argv, &uuid, &enabled))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
|
||||||
uuids = g_settings_get_strv (obj->settings, ENABLED_EXTENSIONS_KEY);
|
uuids = g_settings_get_strv (obj->settings, ENABLED_EXTENSIONS_KEY);
|
||||||
length = g_strv_length (uuids);
|
length = g_strv_length (uuids);
|
||||||
|
|
||||||
@ -515,7 +550,7 @@ plugin_enable_extension (PluginObject *obj,
|
|||||||
{
|
{
|
||||||
new_uuids = g_new (const gchar *, length + 2); /* New key, NULL */
|
new_uuids = g_new (const gchar *, length + 2); /* New key, NULL */
|
||||||
memcpy (new_uuids, uuids, length * sizeof (*new_uuids));
|
memcpy (new_uuids, uuids, length * sizeof (*new_uuids));
|
||||||
new_uuids[length] = uuid_str;
|
new_uuids[length] = uuid;
|
||||||
new_uuids[length + 1] = NULL;
|
new_uuids[length + 1] = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -524,7 +559,7 @@ plugin_enable_extension (PluginObject *obj,
|
|||||||
new_uuids = g_new (const gchar *, length);
|
new_uuids = g_new (const gchar *, length);
|
||||||
for (i = 0; i < length; i ++)
|
for (i = 0; i < length; i ++)
|
||||||
{
|
{
|
||||||
if (g_str_equal (uuids[i], uuid_str))
|
if (g_str_equal (uuids[i], uuid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
new_uuids[j] = uuids[i];
|
new_uuids[j] = uuids[i];
|
||||||
@ -540,60 +575,58 @@ plugin_enable_extension (PluginObject *obj,
|
|||||||
|
|
||||||
g_strfreev (uuids);
|
g_strfreev (uuids);
|
||||||
g_free (new_uuids);
|
g_free (new_uuids);
|
||||||
g_free (uuid_str);
|
g_free (uuid);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_install_extension (PluginObject *obj,
|
plugin_install_extension (PluginObject *obj,
|
||||||
NPString uuid)
|
uint32_t argc,
|
||||||
|
const NPVariant *argv,
|
||||||
|
NPVariant *result)
|
||||||
{
|
{
|
||||||
gchar *uuid_str;
|
gchar *uuid;
|
||||||
|
|
||||||
if (!uuid_is_valid (uuid))
|
if (!parse_args ("u", argc, argv, &uuid))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
|
||||||
|
|
||||||
g_dbus_proxy_call (obj->proxy,
|
g_dbus_proxy_call (obj->proxy,
|
||||||
"InstallRemoteExtension",
|
"InstallRemoteExtension",
|
||||||
g_variant_new ("(s)", uuid_str),
|
g_variant_new ("(s)", uuid),
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
-1, /* timeout */
|
-1, /* timeout */
|
||||||
NULL, /* cancellable */
|
NULL, /* cancellable */
|
||||||
NULL, /* callback */
|
NULL, /* callback */
|
||||||
NULL /* user_data */);
|
NULL /* user_data */);
|
||||||
|
|
||||||
g_free (uuid_str);
|
g_free (uuid);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_uninstall_extension (PluginObject *obj,
|
plugin_uninstall_extension (PluginObject *obj,
|
||||||
NPString uuid,
|
uint32_t argc,
|
||||||
NPVariant *result)
|
const NPVariant *argv,
|
||||||
|
NPVariant *result)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GVariant *res;
|
GVariant *res;
|
||||||
gchar *uuid_str;
|
gchar *uuid;
|
||||||
|
|
||||||
if (!uuid_is_valid (uuid))
|
if (!parse_args ("u", argc, argv, &uuid))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
|
||||||
|
|
||||||
res = g_dbus_proxy_call_sync (obj->proxy,
|
res = g_dbus_proxy_call_sync (obj->proxy,
|
||||||
"UninstallExtension",
|
"UninstallExtension",
|
||||||
g_variant_new ("(s)",
|
g_variant_new ("(s)", uuid),
|
||||||
uuid_str),
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
-1, /* timeout */
|
-1, /* timeout */
|
||||||
NULL, /* cancellable */
|
NULL, /* cancellable */
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
g_free (uuid_str);
|
g_free (uuid);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
@ -606,28 +639,27 @@ plugin_uninstall_extension (PluginObject *obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_get_info (PluginObject *obj,
|
plugin_get_info (PluginObject *obj,
|
||||||
NPString uuid,
|
uint32_t argc,
|
||||||
NPVariant *result)
|
const NPVariant *argv,
|
||||||
|
NPVariant *result)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GVariant *res;
|
GVariant *res;
|
||||||
gchar *uuid_str;
|
gchar *uuid;
|
||||||
|
|
||||||
if (!uuid_is_valid (uuid))
|
if (!parse_args ("u", argc, argv, &uuid))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
|
||||||
|
|
||||||
res = g_dbus_proxy_call_sync (obj->proxy,
|
res = g_dbus_proxy_call_sync (obj->proxy,
|
||||||
"GetExtensionInfo",
|
"GetExtensionInfo",
|
||||||
g_variant_new ("(s)", uuid_str),
|
g_variant_new ("(s)", uuid),
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
-1, /* timeout */
|
-1, /* timeout */
|
||||||
NULL, /* cancellable */
|
NULL, /* cancellable */
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
g_free (uuid_str);
|
g_free (uuid);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
@ -640,29 +672,26 @@ plugin_get_info (PluginObject *obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_get_errors (PluginObject *obj,
|
plugin_get_errors (PluginObject *obj,
|
||||||
NPString uuid,
|
uint32_t argc,
|
||||||
NPVariant *result)
|
const NPVariant *argv,
|
||||||
|
NPVariant *result)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GVariant *res;
|
GVariant *res;
|
||||||
gchar *uuid_str;
|
gchar *uuid;
|
||||||
|
|
||||||
if (!uuid_is_valid (uuid))
|
if (!parse_args ("u", argc, argv, &uuid))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
|
||||||
|
|
||||||
res = g_dbus_proxy_call_sync (obj->proxy,
|
res = g_dbus_proxy_call_sync (obj->proxy,
|
||||||
"GetExtensionErrors",
|
"GetExtensionErrors",
|
||||||
g_variant_new ("(s)", uuid_str),
|
g_variant_new ("(s)", uuid),
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
-1, /* timeout */
|
-1, /* timeout */
|
||||||
NULL, /* cancellable */
|
NULL, /* cancellable */
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
g_free (uuid_str);
|
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
g_warning ("Failed to retrieve errors: %s", error->message);
|
g_warning ("Failed to retrieve errors: %s", error->message);
|
||||||
@ -674,27 +703,25 @@ plugin_get_errors (PluginObject *obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_launch_extension_prefs (PluginObject *obj,
|
plugin_launch_extension_prefs (PluginObject *obj,
|
||||||
NPString uuid,
|
uint32_t argc,
|
||||||
NPVariant *result)
|
const NPVariant *argv,
|
||||||
|
NPVariant *result)
|
||||||
{
|
{
|
||||||
gchar *uuid_str;
|
gchar *uuid;
|
||||||
|
|
||||||
if (!uuid_is_valid (uuid))
|
if (!parse_args ("u", argc, argv, &uuid))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
|
|
||||||
|
|
||||||
g_dbus_proxy_call (obj->proxy,
|
g_dbus_proxy_call (obj->proxy,
|
||||||
"LaunchExtensionPrefs",
|
"LaunchExtensionPrefs",
|
||||||
g_variant_new ("(s)", uuid_str),
|
g_variant_new ("(s)", uuid),
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
-1, /* timeout */
|
-1, /* timeout */
|
||||||
NULL, /* cancellable */
|
NULL, /* cancellable */
|
||||||
NULL, /* callback */
|
NULL, /* callback */
|
||||||
NULL /* user_data */);
|
NULL /* user_data */);
|
||||||
|
|
||||||
g_free (uuid_str);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,10 +775,40 @@ plugin_get_shell_version (PluginObject *obj,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define METHODS \
|
||||||
|
METHOD (list_extensions) \
|
||||||
|
METHOD (get_info) \
|
||||||
|
METHOD (enable_extension) \
|
||||||
|
METHOD (install_extension) \
|
||||||
|
METHOD (uninstall_extension) \
|
||||||
|
METHOD (get_errors) \
|
||||||
|
METHOD (launch_extension_prefs) \
|
||||||
|
/* */
|
||||||
|
|
||||||
|
#define METHOD(x) \
|
||||||
|
static NPIdentifier x##_id;
|
||||||
|
METHODS
|
||||||
|
#undef METHOD
|
||||||
|
|
||||||
|
static NPIdentifier api_version_id;
|
||||||
|
static NPIdentifier shell_version_id;
|
||||||
|
static NPIdentifier onextension_changed_id;
|
||||||
|
static NPIdentifier onrestart_id;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
plugin_object_has_method (NPObject *npobj,
|
||||||
|
NPIdentifier name)
|
||||||
|
{
|
||||||
|
#define METHOD(x) (name == (x##_id)) ||
|
||||||
|
/* expands to (name == list_extensions_id) || FALSE; */
|
||||||
|
return METHODS FALSE;
|
||||||
|
#undef METHOD
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
plugin_object_invoke (NPObject *npobj,
|
plugin_object_invoke (NPObject *npobj,
|
||||||
NPIdentifier name,
|
NPIdentifier name,
|
||||||
const NPVariant *args,
|
const NPVariant *argv,
|
||||||
uint32_t argc,
|
uint32_t argc,
|
||||||
NPVariant *result)
|
NPVariant *result)
|
||||||
{
|
{
|
||||||
@ -763,59 +820,13 @@ plugin_object_invoke (NPObject *npobj,
|
|||||||
|
|
||||||
VOID_TO_NPVARIANT (*result);
|
VOID_TO_NPVARIANT (*result);
|
||||||
|
|
||||||
if (!plugin_object_has_method (npobj, name))
|
#define METHOD(x) \
|
||||||
return FALSE;
|
if (name == x##_id) \
|
||||||
|
return plugin_##x (obj, argc, argv, result);
|
||||||
|
METHODS
|
||||||
|
#undef METHOD
|
||||||
|
|
||||||
if (name == list_extensions_id)
|
return FALSE;
|
||||||
return plugin_list_extensions (obj, result);
|
|
||||||
else if (name == get_info_id)
|
|
||||||
{
|
|
||||||
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
|
|
||||||
|
|
||||||
return plugin_get_info (obj, NPVARIANT_TO_STRING(args[0]), result);
|
|
||||||
}
|
|
||||||
else if (name == enable_extension_id)
|
|
||||||
{
|
|
||||||
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
|
|
||||||
if (!NPVARIANT_IS_BOOLEAN(args[1])) return FALSE;
|
|
||||||
|
|
||||||
return plugin_enable_extension (obj,
|
|
||||||
NPVARIANT_TO_STRING(args[0]),
|
|
||||||
NPVARIANT_TO_BOOLEAN(args[1]));
|
|
||||||
}
|
|
||||||
else if (name == install_extension_id)
|
|
||||||
{
|
|
||||||
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
|
|
||||||
|
|
||||||
return plugin_install_extension (obj,
|
|
||||||
NPVARIANT_TO_STRING(args[0]));
|
|
||||||
}
|
|
||||||
else if (name == uninstall_extension_id)
|
|
||||||
{
|
|
||||||
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
|
|
||||||
|
|
||||||
return plugin_uninstall_extension (obj,
|
|
||||||
NPVARIANT_TO_STRING(args[0]),
|
|
||||||
result);
|
|
||||||
}
|
|
||||||
else if (name == get_errors_id)
|
|
||||||
{
|
|
||||||
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
|
|
||||||
|
|
||||||
return plugin_get_errors (obj,
|
|
||||||
NPVARIANT_TO_STRING(args[0]),
|
|
||||||
result);
|
|
||||||
}
|
|
||||||
else if (name == launch_extension_prefs_id)
|
|
||||||
{
|
|
||||||
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
|
|
||||||
|
|
||||||
return plugin_launch_extension_prefs (obj,
|
|
||||||
NPVARIANT_TO_STRING(args[0]),
|
|
||||||
result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
Loading…
Reference in New Issue
Block a user