From 08c51127ac6b99f1d1c2e505ad89c4d19d581998 Mon Sep 17 00:00:00 2001 From: Andy Holmes Date: Mon, 11 Dec 2023 13:09:32 -0800 Subject: [PATCH] online-accounts: remove goa-helper Remove the GOA subprocess helper and use GoaClient directly. The GoaClient is loaded asynchronously, with the panel being marked insensitive until ready. Any `CcPanel::parameters` passed while loading are deferred until the client is ready. --- .../cc-online-account-provider-row.c | 27 +- .../cc-online-account-provider-row.h | 8 +- .../cc-online-accounts-panel.c | 607 +++++++----------- .../gnome-control-center-goa-helper.c | 511 --------------- panels/online-accounts/meson.build | 29 +- 5 files changed, 243 insertions(+), 939 deletions(-) delete mode 100644 panels/online-accounts/gnome-control-center-goa-helper.c diff --git a/panels/online-accounts/cc-online-account-provider-row.c b/panels/online-accounts/cc-online-account-provider-row.c index d581d1523..b86426145 100644 --- a/panels/online-accounts/cc-online-account-provider-row.c +++ b/panels/online-accounts/cc-online-account-provider-row.c @@ -19,6 +19,10 @@ #include #include +#define GOA_API_IS_SUBJECT_TO_CHANGE +#define GOA_BACKEND_API_IS_SUBJECT_TO_CHANGE +#include + #include "cc-online-account-provider-row.h" #include "cc-online-accounts-resources.h" @@ -28,7 +32,7 @@ struct _CcOnlineAccountProviderRow GtkImage *icon_image; - GVariant *provider; + GoaProvider *provider; }; G_DEFINE_TYPE (CcOnlineAccountProviderRow, cc_online_account_provider_row, ADW_TYPE_ACTION_ROW) @@ -56,7 +60,7 @@ cc_online_account_provider_row_dispose (GObject *object) { CcOnlineAccountProviderRow *self = CC_ONLINE_ACCOUNT_PROVIDER_ROW (object); - g_clear_pointer (&self->provider, g_variant_unref); + g_clear_object (&self->provider); G_OBJECT_CLASS (cc_online_account_provider_row_parent_class)->dispose (object); } @@ -81,7 +85,7 @@ cc_online_account_provider_row_init (CcOnlineAccountProviderRow *self) } CcOnlineAccountProviderRow * -cc_online_account_provider_row_new (GVariant *provider) +cc_online_account_provider_row_new (GoaProvider *provider) { CcOnlineAccountProviderRow *self; g_autoptr(GIcon) icon = NULL; @@ -96,18 +100,9 @@ cc_online_account_provider_row_new (GVariant *provider) } else { - g_autoptr(GVariant) icon_variant = NULL; - - self->provider = g_variant_ref (provider); - - g_variant_get (provider, "(ssviu)", - NULL, - &name, - &icon_variant, - NULL, - NULL); - - icon = g_icon_deserialize (icon_variant); + self->provider = g_object_ref (provider); + icon = goa_provider_get_provider_icon (provider, NULL); + name = goa_provider_get_provider_name (provider, NULL); } gtk_image_set_from_gicon (self->icon_image, icon); @@ -127,7 +122,7 @@ cc_online_account_provider_row_new (GVariant *provider) return self; } -GVariant * +GoaProvider * cc_online_account_provider_row_get_provider (CcOnlineAccountProviderRow *self) { g_return_val_if_fail (CC_IS_ONLINE_ACCOUNT_PROVIDER_ROW (self), NULL); diff --git a/panels/online-accounts/cc-online-account-provider-row.h b/panels/online-accounts/cc-online-account-provider-row.h index 6f75a5bb2..f2be0abdc 100644 --- a/panels/online-accounts/cc-online-account-provider-row.h +++ b/panels/online-accounts/cc-online-account-provider-row.h @@ -21,12 +21,16 @@ #include #include +#define GOA_API_IS_SUBJECT_TO_CHANGE +#define GOA_BACKEND_API_IS_SUBJECT_TO_CHANGE +#include + G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (CcOnlineAccountProviderRow, cc_online_account_provider_row, CC, ONLINE_ACCOUNT_PROVIDER_ROW, AdwActionRow) -CcOnlineAccountProviderRow *cc_online_account_provider_row_new (GVariant *provider); +CcOnlineAccountProviderRow *cc_online_account_provider_row_new (GoaProvider *provider); -GVariant *cc_online_account_provider_row_get_provider (CcOnlineAccountProviderRow *row); +GoaProvider *cc_online_account_provider_row_get_provider (CcOnlineAccountProviderRow *row); G_END_DECLS diff --git a/panels/online-accounts/cc-online-accounts-panel.c b/panels/online-accounts/cc-online-accounts-panel.c index 139f38e17..4007a3277 100644 --- a/panels/online-accounts/cc-online-accounts-panel.c +++ b/panels/online-accounts/cc-online-accounts-panel.c @@ -32,12 +32,9 @@ #include "cc-online-account-row.h" #include "cc-online-accounts-resources.h" -#ifdef GDK_WINDOWING_X11 -#include -#endif -#ifdef GDK_WINDOWING_WAYLAND -#include -#endif +#define GOA_API_IS_SUBJECT_TO_CHANGE +#define GOA_BACKEND_API_IS_SUBJECT_TO_CHANGE +#include struct _CcOnlineAccountsPanel { @@ -59,9 +56,9 @@ struct _CcOnlineAccountsPanel GoaClient *client; GoaObject *active_object; GoaObject *removed_object; + GVariant *parameters; guint remove_account_timeout_id; - gchar *window_export_handle; }; static gboolean remove_account_timeout_cb (gpointer user_data); @@ -141,115 +138,6 @@ modify_row_for_account (CcOnlineAccountsPanel *self, g_list_free (children); } -/* Auxiliary methods */ - -G_GNUC_NULL_TERMINATED -static char * -run_goa_helper_sync (const char *command, - ...) -{ - g_autoptr(GPtrArray) argv = NULL; - g_autofree char *output = NULL; - g_autoptr(GError) error = NULL; - const char *param; - va_list args; - int status; - - argv = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (argv, g_strdup (LIBEXECDIR "/gnome-control-center-goa-helper")); - g_ptr_array_add (argv, g_strdup (command)); - - va_start (args, command); - while ((param = va_arg (args, const char*)) != NULL) - g_ptr_array_add (argv, g_strdup (param)); - va_end (args); - - g_ptr_array_add (argv, NULL); - - if (!g_spawn_sync (NULL, - (char **) argv->pdata, - NULL, - 0, - NULL, - NULL, - &output, - NULL, - &status, - &error)) - { - g_warning ("Failed to run online accounts helper: %s", error->message); - return NULL; - } - - if (!g_spawn_check_wait_status (status, NULL)) - return NULL; - - if (output == NULL || *output == '\0') - return NULL; - - return g_steal_pointer (&output); -} - -static void -run_goa_helper_in_thread_func (GTask *task, - gpointer source_object, - gpointer task_data, - GCancellable *cancellable) -{ - g_autofree char *output = NULL; - g_autoptr(GError) error = NULL; - GPtrArray *argv = task_data; - int status; - - g_spawn_sync (NULL, - (char **) argv->pdata, - NULL, 0, NULL, NULL, - &output, - NULL, - &status, - &error); - - if (error) - { - g_task_return_error (task, g_steal_pointer (&error)); - return; - } - - if (!g_spawn_check_wait_status (status, &error)) - { - g_task_return_error (task, g_steal_pointer (&error)); - return; - } - - g_task_return_pointer (task, g_steal_pointer (&output), g_free); -} - -static void -run_goa_helper_async (const gchar *command, - const gchar *param, - const gchar *window_handle, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_autoptr(GPtrArray) argv = NULL; - g_autoptr(GTask) task = NULL; - - g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - - argv = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (argv, g_strdup (LIBEXECDIR "/gnome-control-center-goa-helper")); - g_ptr_array_add (argv, g_strdup (command)); - g_ptr_array_add (argv, g_strdup (param)); - g_ptr_array_add (argv, g_strdup (window_handle)); - g_ptr_array_add (argv, NULL); - - task = g_task_new (NULL, cancellable, callback, user_data); - g_task_set_source_tag (task, run_goa_helper_async); - g_task_set_task_data (task, g_steal_pointer (&argv), (GDestroyNotify) g_ptr_array_unref); - g_task_run_in_thread (task, run_goa_helper_in_thread_func); -} - static void cancel_notification_timeout (CcOnlineAccountsPanel *self) { @@ -286,220 +174,127 @@ start_remove_account_timeout (CcOnlineAccountsPanel *self) } static void -on_show_account_finish_cb (GObject *source_object, - GAsyncResult *result, - gpointer user_data) +on_remove_button_clicked_cb (CcOnlineAccountsPanel *self, + GtkButton *button) { - CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (user_data); - g_autofree char *output = NULL; - g_autoptr(GError) error = NULL; - - output = g_task_propagate_pointer (G_TASK (result), &error); - - if (error) - { - g_warning ("Error showing account: %s", error->message); - return; - } - - if (g_strcmp0 (output, "remove") == 0) - start_remove_account_timeout (self); + GtkRoot *root; + start_remove_account_timeout (self); self->active_object = NULL; + + root = gtk_widget_get_root (GTK_WIDGET (button)); + if (root != NULL) + gtk_window_destroy (GTK_WINDOW (root)); } static void show_account (CcOnlineAccountsPanel *self, GoaObject *object) { + g_autoptr(GoaProvider) provider = NULL; + g_autofree char *title = NULL; GoaAccount *account; + GtkWidget *content_area; + GtkWidget *button; + GtkWidget *dialog; + GtkWidget *box; + const char *provider_type; - if (!self->window_export_handle) - return; - - self->active_object = g_object_ref (object); - + g_set_object (&self->active_object, object); account = goa_object_peek_account (object); - run_goa_helper_async ("show-account", - goa_account_get_id (account), - self->window_export_handle, - cc_panel_get_cancellable (CC_PANEL (self)), - on_show_account_finish_cb, - self); -} -static void -on_create_account_finish_cb (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (user_data); - g_autofree char *new_account_id = NULL; - g_autoptr(GoaObject) object = NULL; - g_autoptr(GError) error = NULL; - - new_account_id = g_task_propagate_pointer (G_TASK (result), &error); - - if (error) + /* Find the provider with a matching type */ + account = goa_object_get_account (object); + provider_type = goa_account_get_provider_type (account); + provider = goa_provider_get_for_provider_type (provider_type); + if (provider == NULL) { - g_warning ("Error showing account: %s", error->message); + g_warning ("Error showing account: Unsupported provider"); return; } - if (new_account_id) - object = goa_client_lookup_by_id (self->client, new_account_id); + dialog = g_object_new (GTK_TYPE_DIALOG, + "use-header-bar", 1, + "modal", TRUE, + "transient-for", gtk_widget_get_root (GTK_WIDGET (self)), + NULL); + /* Keep account alive so that the switches are still bound to it */ + g_object_set_data_full (G_OBJECT (dialog), "goa-account", account, g_object_unref); - if (object) - show_account (self, object); + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 42); + gtk_widget_set_margin_bottom (box, 24); + + content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + g_object_set (content_area, + "margin-top", 6, + "margin-end", 6, + "margin-bottom", 6, + "margin-start", 6, + NULL); + gtk_box_append (GTK_BOX (content_area), box); + + goa_provider_show_account (provider, + self->client, + object, + GTK_BOX (box), + NULL, + NULL); + + /* translators: This is the title of the "Show Account" dialog. The + * %s is the name of the provider. e.g., 'Google'. */ + title = g_strdup_printf (_("%s Account"), goa_account_get_provider_name (account)); + gtk_window_set_title (GTK_WINDOW (dialog), title); + + button = gtk_button_new_with_label (_("Remove Account")); + gtk_widget_set_margin_start (box, 24); + gtk_widget_set_margin_end (box, 24); + gtk_widget_set_halign (button, GTK_ALIGN_END); + gtk_widget_set_valign (button, GTK_ALIGN_END); + gtk_widget_set_visible (button, !goa_account_get_is_locked (account)); + gtk_widget_add_css_class (button, "destructive-action"); + gtk_box_append (GTK_BOX (box), button); + g_signal_connect_swapped (button, + "clicked", + G_CALLBACK (on_remove_button_clicked_cb), + self); + + gtk_window_present (GTK_WINDOW (dialog)); } static void create_account (CcOnlineAccountsPanel *self, - GVariant *provider) + GoaProvider *provider) { - g_autofree char *provider_type = NULL; - - if (!self->window_export_handle) - return; - - g_variant_get (provider, "(ssviu)", &provider_type, NULL, NULL, NULL, NULL); - - run_goa_helper_async ("create-account", - provider_type, - self->window_export_handle, - cc_panel_get_cancellable (CC_PANEL (self)), - on_create_account_finish_cb, - self); -} - -static void -add_provider_row (CcOnlineAccountsPanel *self, - GVariant *provider) -{ - CcOnlineAccountProviderRow *row; - - row = cc_online_account_provider_row_new (provider); - - gtk_list_box_append (self->providers_listbox, GTK_WIDGET (row)); -} - -static void -list_providers (CcOnlineAccountsPanel *self) -{ - g_autoptr(GVariant) providers_variant = NULL; g_autoptr(GError) error = NULL; - g_autofree char *providers = NULL; - GVariantIter iter; - GVariant *provider; + GtkWidget *dialog; + GtkWidget *content; + GoaObject *object; - providers = run_goa_helper_sync ("list-providers", NULL); + g_return_if_fail (GOA_IS_PROVIDER (provider)); - if (!providers) - return; + dialog = g_object_new (GTK_TYPE_DIALOG, + "use-header-bar", 1, + "default-width", 500, + "default-height", 350, + "modal", TRUE, + "transient-for", gtk_widget_get_root (GTK_WIDGET (self)), + NULL); - providers_variant = g_variant_parse (G_VARIANT_TYPE ("a(ssviu)"), - providers, - NULL, - NULL, - &error); + content = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + object = goa_provider_add_account (provider, + self->client, + GTK_DIALOG (dialog), + GTK_BOX (content), + &error); + gtk_window_destroy (GTK_WINDOW (dialog)); if (error) { - g_warning ("Error listing providers: %s", error->message); + g_warning ("Error creating account: %s", error->message); return; } - g_variant_iter_init (&iter, providers_variant); - - while ((provider = g_variant_iter_next_value (&iter))) - { - add_provider_row (self, provider); - g_variant_unref (provider); - } -} - -static void -add_account (CcOnlineAccountsPanel *self, - GoaObject *object) -{ - CcOnlineAccountRow *row; - - row = cc_online_account_row_new (object); - - /* Add to the listbox */ - gtk_list_box_append (self->accounts_listbox, GTK_WIDGET (row)); - gtk_widget_set_visible (GTK_WIDGET (self->accounts_frame), TRUE); -} - -static void -fill_accounts_listbox (CcOnlineAccountsPanel *self) -{ - g_autolist(GoaAccount) accounts = NULL; - GList *l; - - accounts = goa_client_get_accounts (self->client); - - for (l = accounts; l != NULL; l = l->next) - add_account (self, l->data); -} - -#ifdef GDK_WINDOWING_WAYLAND -static void -wayland_window_exported_cb (GdkToplevel *toplevel, - const char *handle, - gpointer data) - -{ - CcOnlineAccountsPanel *self = data; - - self->window_export_handle = g_strdup_printf ("wayland:%s", handle); -} -#endif - -static void -export_window_handle (CcOnlineAccountsPanel *self) -{ - GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self)); - -#ifdef GDK_WINDOWING_X11 - if (GDK_IS_X11_DISPLAY (gtk_widget_get_display (GTK_WIDGET (native)))) - { - GdkSurface *surface = gtk_native_get_surface (native); - guint32 xid = (guint32) gdk_x11_surface_get_xid (surface); - - self->window_export_handle = g_strdup_printf ("x11:%x", xid); - } -#endif -#ifdef GDK_WINDOWING_WAYLAND - if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (native)))) - { - GdkSurface *surface = gtk_native_get_surface (native); - - gdk_wayland_toplevel_export_handle (GDK_TOPLEVEL (surface), - wayland_window_exported_cb, - self, - NULL); - } -#endif -} - -static void -unexport_window_handle (CcOnlineAccountsPanel *self) -{ - if (!self->window_export_handle) - return; - -#ifdef GDK_WINDOWING_WAYLAND - GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self)); - - if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (native)))) - { - GdkSurface *surface = gtk_native_get_surface (native); - gdk_wayland_toplevel_unexport_handle (GDK_TOPLEVEL (surface)); - } -#endif - - g_clear_pointer (&self->window_export_handle, g_free); + show_account (self, object); } static void @@ -555,16 +350,16 @@ command_add (CcOnlineAccountsPanel *self, if (provider_name != NULL) { GtkWidget *child; - GVariant *provider; + GoaProvider *provider; for (child = gtk_widget_get_first_child (GTK_WIDGET (self->providers_listbox)); child; child = gtk_widget_get_next_sibling (child)) { - g_autofree gchar *provider_type = NULL; + const char *provider_type = NULL; provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (child)); - g_variant_get (provider, "(ssviu)", &provider_type, NULL, NULL, NULL, NULL); + provider_type = goa_provider_get_provider_type (provider); if (g_strcmp0 (provider_type, provider_name) == 0) break; @@ -616,35 +411,45 @@ sort_providers_func (GtkListBoxRow *a, GtkListBoxRow *b, gpointer user_data) { - GVariant *a_provider, *b_provider; + GoaProvider *a_provider, *b_provider; gboolean a_branded, b_branded; - gint a_features, b_features; + GoaProviderFeatures a_features, b_features; a_provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (a)); + a_features = goa_provider_get_provider_features (a_provider); + a_branded = (a_features & GOA_PROVIDER_FEATURE_BRANDED) != 0; + b_provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (b)); - - g_variant_get (a_provider, "(ssviu)", NULL, NULL, NULL, &a_features, NULL); - g_variant_get (b_provider, "(ssviu)", NULL, NULL, NULL, &b_features, NULL); - - /* FIXME: this needs to go away once libgoa-backend is ported to GTK4 */ -#define FEATURE_BRANDED (1 << 1) - - a_branded = (a_features & FEATURE_BRANDED) != 0; - b_branded = (a_features & FEATURE_BRANDED) != 0; - -#undef FEATURE_BRANDED + b_features = goa_provider_get_provider_features (b_provider); + b_branded = (b_features & GOA_PROVIDER_FEATURE_BRANDED) != 0; if (a_branded != b_branded) - { - if (a_branded) - return -1; - else - return 1; - } + return a_branded ? -1 : 1; return gtk_list_box_row_get_index (b) - gtk_list_box_row_get_index (a); } +static void +add_account (CcOnlineAccountsPanel *self, + GoaObject *object) +{ + CcOnlineAccountRow *row; + + row = cc_online_account_row_new (object); + gtk_list_box_append (self->accounts_listbox, GTK_WIDGET (row)); + gtk_widget_set_visible (GTK_WIDGET (self->accounts_frame), TRUE); +} + +static void +add_provider (CcOnlineAccountsPanel *self, + GoaProvider *provider) +{ + CcOnlineAccountProviderRow *row; + + row = cc_online_account_provider_row_new (provider); + gtk_list_box_append (self->providers_listbox, GTK_WIDGET (row)); +} + static void on_account_added_cb (CcOnlineAccountsPanel *self, GoaObject *object) @@ -733,7 +538,7 @@ static void on_provider_row_activated_cb (CcOnlineAccountsPanel *self, GtkListBoxRow *activated_row) { - GVariant *provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (activated_row)); + GoaProvider *provider = cc_online_account_provider_row_get_provider (CC_ONLINE_ACCOUNT_PROVIDER_ROW (activated_row)); create_account (self, provider); } @@ -744,10 +549,88 @@ remove_account_timeout_cb (gpointer user_data) CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (user_data); gtk_widget_activate (self->close_notification_button); + self->remove_account_timeout_id = 0; return G_SOURCE_REMOVE; } +static void +goa_provider_get_all_cb (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr (CcOnlineAccountsPanel) self = CC_ONLINE_ACCOUNTS_PANEL (user_data); + g_autolist(GoaProvider) providers = NULL; + g_autolist(GoaAccount) accounts = NULL; + g_autoptr (GError) error = NULL; + + /* goa_provider_get_all() doesn't have a cancellable argument, so check if + * the panel cancellable was triggered. + */ + if (g_cancellable_is_cancelled (cc_panel_get_cancellable (CC_PANEL (self)))) + return; + + if (!goa_provider_get_all_finish (&providers, res, &error)) + { + g_warning ("Error listing providers: %s", error->message); + return; + } + + for (const GList *iter = providers; iter != NULL; iter = iter->next) + add_provider (self, GOA_PROVIDER (iter->data)); + + /* Load existing accounts */ + accounts = goa_client_get_accounts (self->client); + + for (const GList *iter = accounts; iter != NULL; iter = iter->next) + add_account (self, GOA_OBJECT (iter->data)); + + g_signal_connect_swapped (self->client, + "account-added", + G_CALLBACK (on_account_added_cb), + self); + + g_signal_connect_swapped (self->client, + "account-changed", + G_CALLBACK (on_account_changed_cb), + self); + + g_signal_connect_swapped (self->client, + "account-removed", + G_CALLBACK (on_account_removed_cb), + self); + + /* With the client ready, check if we have a pending command */ + gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE); + + if (self->parameters != NULL) + { + g_autoptr (GVariant) parameters = NULL; + + parameters = g_steal_pointer (&self->parameters); + g_object_set (self, "parameters", parameters, NULL); + } +} + +static void +goa_client_new_cb (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr (CcOnlineAccountsPanel) self = CC_ONLINE_ACCOUNTS_PANEL (user_data); + g_autoptr (GError) error = NULL; + + self->client = goa_client_new_finish (res, &error); + if (self->client == NULL) + { + g_warning ("Error connect to service: %s", error->message); + gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE); + return; + } + + goa_provider_get_all (goa_provider_get_all_cb, g_object_ref (self)); +} + /* CcPanel overrides */ static const char * @@ -756,24 +639,6 @@ cc_online_accounts_panel_get_help_uri (CcPanel *panel) return "help:gnome-help/accounts"; } -/* GtkWidget overrides */ - -static void -cc_online_accounts_panel_realize (GtkWidget *widget) -{ - GTK_WIDGET_CLASS (cc_online_accounts_panel_parent_class)->realize (widget); - - export_window_handle (CC_ONLINE_ACCOUNTS_PANEL (widget)); -} - -static void -cc_online_accounts_panel_unrealize (GtkWidget *widget) -{ - unexport_window_handle (CC_ONLINE_ACCOUNTS_PANEL (widget)); - - GTK_WIDGET_CLASS (cc_online_accounts_panel_parent_class)->unrealize (widget); -} - /* GObject overrides */ static void @@ -782,6 +647,8 @@ cc_online_accounts_panel_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { + CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (object); + switch (property_id) { case PROP_PARAMETERS: @@ -804,10 +671,20 @@ cc_online_accounts_panel_set_property (GObject *object, (gchar *)g_variant_get_type (v)); } - if (g_strcmp0 (first_arg, "add") == 0) - command_add (CC_ONLINE_ACCOUNTS_PANEL (object), parameters); + /* Waiting for the client to load */ + if (!gtk_widget_get_sensitive (GTK_WIDGET (self))) + { + g_clear_pointer (&self->parameters, g_variant_unref); + self->parameters = g_value_dup_variant (value); + } + else if (g_strcmp0 (first_arg, "add") == 0) + { + command_add (CC_ONLINE_ACCOUNTS_PANEL (object), self->parameters); + } else if (first_arg != NULL) - select_account_by_id (CC_ONLINE_ACCOUNTS_PANEL (object), first_arg); + { + select_account_by_id (CC_ONLINE_ACCOUNTS_PANEL (object), first_arg); + } return; } @@ -816,16 +693,6 @@ cc_online_accounts_panel_set_property (GObject *object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } -static void -cc_online_accounts_panel_constructed (GObject *object) -{ - CcOnlineAccountsPanel *self = CC_ONLINE_ACCOUNTS_PANEL (object); - - G_OBJECT_CLASS (cc_online_accounts_panel_parent_class)->constructed (object); - - list_providers (self); -} - static void cc_online_accounts_panel_finalize (GObject *object) { @@ -848,6 +715,7 @@ cc_online_accounts_panel_finalize (GObject *object) } g_clear_object (&self->client); + g_clear_pointer (&self->parameters, g_variant_unref); G_OBJECT_CLASS (cc_online_accounts_panel_parent_class)->finalize (object); } @@ -863,10 +731,6 @@ cc_online_accounts_panel_class_init (CcOnlineAccountsPanelClass *klass) object_class->set_property = cc_online_accounts_panel_set_property; object_class->finalize = cc_online_accounts_panel_finalize; - object_class->constructed = cc_online_accounts_panel_constructed; - - widget_class->realize = cc_online_accounts_panel_realize; - widget_class->unrealize = cc_online_accounts_panel_unrealize; g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters"); @@ -889,7 +753,6 @@ cc_online_accounts_panel_class_init (CcOnlineAccountsPanelClass *klass) static void cc_online_accounts_panel_init (CcOnlineAccountsPanel *self) { - g_autoptr(GError) error = NULL; GNetworkMonitor *monitor; g_resources_register (cc_online_accounts_get_resource ()); @@ -919,31 +782,11 @@ cc_online_accounts_panel_init (CcOnlineAccountsPanel *self) "sensitive", G_BINDING_SYNC_CREATE); - /* TODO: probably want to avoid _sync() ... */ - self->client = goa_client_new_sync (cc_panel_get_cancellable (CC_PANEL (self)), &error); - if (self->client == NULL) - { - g_warning ("Error getting a GoaClient: %s (%s, %d)", - error->message, g_quark_to_string (error->domain), error->code); - gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE); - return; - } - - g_signal_connect_swapped (self->client, - "account-added", - G_CALLBACK (on_account_added_cb), - self); - - g_signal_connect_swapped (self->client, - "account-changed", - G_CALLBACK (on_account_changed_cb), - self); - - g_signal_connect_swapped (self->client, - "account-removed", - G_CALLBACK (on_account_removed_cb), - self); - - fill_accounts_listbox (self); load_custom_css (); + + /* Disable the panel while we wait for the client */ + gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE); + goa_client_new (cc_panel_get_cancellable (CC_PANEL (self)), + goa_client_new_cb, + g_object_ref (self)); } diff --git a/panels/online-accounts/gnome-control-center-goa-helper.c b/panels/online-accounts/gnome-control-center-goa-helper.c deleted file mode 100644 index e6ebb25bb..000000000 --- a/panels/online-accounts/gnome-control-center-goa-helper.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright (C) 2022 Endless OS Foundation, LLC - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: - * Georges Basile Stavracas Neto - */ - -#include "config.h" - -#include -#include - -#define GOA_API_IS_SUBJECT_TO_CHANGE -#define GOA_BACKEND_API_IS_SUBJECT_TO_CHANGE -#include - -#ifdef HAVE_GTK_X11 -#include -#endif -#ifdef HAVE_GTK_WAYLAND -#include -#endif - -static GdkDisplay * -get_wayland_display (void) -{ - static GdkDisplay *wayland_display = NULL; - - if (wayland_display) - return wayland_display; - - gdk_set_allowed_backends ("wayland"); - wayland_display = gdk_display_open (NULL); - gdk_set_allowed_backends (NULL); - if (!wayland_display) - g_warning ("Failed to open Wayland display"); - - return wayland_display; -} - -static GdkDisplay * -get_x11_display (void) -{ - static GdkDisplay *x11_display = NULL; - - if (x11_display) - return x11_display; - - gdk_set_allowed_backends ("x11"); - x11_display = gdk_display_open (NULL); - gdk_set_allowed_backends (NULL); - if (!x11_display) - g_warning ("Failed to open X11 display"); - - return x11_display; -} - -static void -set_external_parent_from_handle (GtkApplication *application, - GtkWindow *dialog, - const char *handle_str) -{ - GdkDisplay *display; - GtkWindow *fake_parent; - GdkScreen *screen; - -#ifdef HAVE_GTK_X11 - { - const char *x11_prefix = "x11:"; - if (g_str_has_prefix (handle_str, x11_prefix)) - { - display = get_x11_display (); - if (!display) - { - g_warning ("No X display connection, ignoring X11 parent"); - return; - } - } - } -#endif -#ifdef HAVE_GTK_WAYLAND - { - const char *wayland_prefix = "wayland:"; - - if (g_str_has_prefix (handle_str, wayland_prefix)) - { - display = get_wayland_display (); - if (!display) - { - g_warning ("No Wayland display connection, ignoring Wayland parent"); - return; - } - } - } -#endif - - screen = gdk_display_get_default_screen (gdk_display_get_default ()); - fake_parent = g_object_new (GTK_TYPE_APPLICATION_WINDOW, - "application", application, - "type", GTK_WINDOW_TOPLEVEL, - "screen", screen, - NULL); - g_object_ref_sink (fake_parent); - - gtk_window_set_transient_for (dialog, GTK_WINDOW (fake_parent)); - gtk_window_set_modal (dialog, TRUE); - gtk_widget_realize (GTK_WIDGET (dialog)); - -#ifdef HAVE_GTK_X11 - { - const char *x11_prefix = "x11:"; - if (g_str_has_prefix (handle_str, x11_prefix)) - { - GdkWindow *foreign_gdk_window; - int xid; - - errno = 0; - xid = strtol (handle_str + strlen (x11_prefix), NULL, 16); - if (errno != 0) - { - g_warning ("Failed to reference external X11 window, invalid XID %s", handle_str); - return; - } - - foreign_gdk_window = gdk_x11_window_foreign_new_for_display (display, xid); - if (!foreign_gdk_window) - { - g_warning ("Failed to create foreign window for XID %d", xid); - return; - } - - gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)), - foreign_gdk_window); - } - } -#endif -#ifdef HAVE_GTK_WAYLAND - { - const char *wayland_prefix = "wayland:"; - - if (g_str_has_prefix (handle_str, wayland_prefix)) - { - const char *wayland_handle_str = handle_str + strlen (wayland_prefix); - - if (!gdk_wayland_window_set_transient_for_exported (gtk_widget_get_window (GTK_WIDGET (dialog)), - (char *) wayland_handle_str)) - { - g_warning ("Failed to set window transient for external parent"); - return; - } - } - } -#endif - - gtk_window_present (dialog); -} - -/* create-account */ - -static void -on_application_activate_create_account_cb (GtkApplication *application, - char **argv) -{ - g_autoptr(GoaProvider) provider = NULL; - g_autoptr(GoaClient) client = NULL; - g_autoptr(GError) error = NULL; - GoaAccount *account; - GtkWidget *content_area; - GtkWidget *dialog; - GoaObject *object; - - client = goa_client_new_sync (NULL, &error); - if (error) - { - g_printerr ("Error retrieving online accounts client"); - exit (EXIT_FAILURE); - return; - } - - - /* Find the provider with a matching type */ - provider = goa_provider_get_for_provider_type (argv[2]); - if (!provider) - { - g_printerr ("Provider type not supported"); - exit (EXIT_FAILURE); - return; - } - - dialog = g_object_new (GTK_TYPE_DIALOG, - "use-header-bar", 1, - "default-width", 500, - "default-height", 350, - NULL); - g_signal_connect_swapped (dialog, "response", G_CALLBACK (g_application_quit), application); - set_external_parent_from_handle (application, GTK_WINDOW (dialog), argv[3]); - - content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); - gtk_container_set_border_width (GTK_CONTAINER (content_area), 0); - - object = goa_provider_add_account (provider, - client, - GTK_DIALOG (dialog), - GTK_BOX (content_area), - &error); - if (error) - { - g_printerr ("Failed to create account: %s", error->message); - exit (EXIT_FAILURE); - return; - } - - account = goa_object_peek_account (object); - g_print ("%s", goa_account_get_id (account)); -} - -static int -create_account (int argc, - char **argv) -{ - g_autoptr(GtkApplication) application = NULL; - - gtk_init (&argc, &argv); - - if (argc != 4) - { - g_printerr ("Not enough arguments"); - return EXIT_FAILURE; - } - - application = gtk_application_new ("org.gnome.Settings.GoaHelper", - G_APPLICATION_FLAGS_NONE); - g_signal_connect (application, "activate", G_CALLBACK (on_application_activate_create_account_cb), argv); - - return g_application_run (G_APPLICATION (application), 0, NULL); -} - -/* list-providers */ - -typedef struct { - GMainLoop *mainloop; - GList *providers; - GError *error; -} GetAllProvidersData; - -static void -get_all_providers_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - g_autolist(GoaProvider) providers = NULL; - GetAllProvidersData *data; - - data = user_data; - - goa_provider_get_all_finish (&providers, res, &data->error); - if (data->error) - goto out; - - data->providers = g_steal_pointer (&providers); - -out: - g_main_loop_quit (data->mainloop); -} - -static GList * -get_all_providers (GError **error) -{ - GetAllProvidersData data = (GetAllProvidersData) { - .mainloop = g_main_loop_new (NULL, FALSE), - .providers = NULL, - .error = NULL, - }; - - goa_provider_get_all (get_all_providers_cb, &data); - - g_main_loop_run (data.mainloop); - g_main_loop_unref (data.mainloop); - - if (data.error) - g_propagate_error (error, data.error); - - return data.providers; -} - -static int -list_providers (int argc, - char **argv) -{ - g_autofree char *serialized_result = NULL; - g_autolist(GoaProvider) providers = NULL; - g_autoptr(GVariant) result = NULL; - g_autoptr(GError) error = NULL; - GVariantBuilder b; - GList *l; - - providers = get_all_providers (&error); - - if (error) - { - g_printerr ("%s", error->message); - return EXIT_FAILURE; - } - - g_variant_builder_init (&b, G_VARIANT_TYPE ("a(ssviu)")); - for (l = providers; l; l = l->next) - { - GoaProvider *provider = l->data; - g_autofree char *name = NULL; - g_autoptr(GVariant) icon_variant = NULL; - g_autoptr(GIcon) icon = NULL; - - name = goa_provider_get_provider_name (provider, NULL); - icon = goa_provider_get_provider_icon (provider, NULL); - icon_variant = g_icon_serialize (icon); - - g_variant_builder_add (&b, "(ssviu)", - goa_provider_get_provider_type (provider), - name, - icon_variant, - goa_provider_get_provider_features (provider), - goa_provider_get_credentials_generation (provider)); - } - result = g_variant_builder_end (&b); - - serialized_result = g_variant_print (result, TRUE); - g_print ("%s", serialized_result); - - return EXIT_SUCCESS; -} - -/* show-account */ - -static void -on_remove_button_clicked_cb (GApplication *application) -{ - g_print ("remove"); - g_application_quit (application); -} - -static void -on_application_activate_show_account_cb (GtkApplication *application, - char **argv) -{ - g_autoptr(GoaProvider) provider = NULL; - g_autoptr(GoaObject) object = NULL; - g_autoptr(GoaClient) client = NULL; - g_autoptr(GError) error = NULL; - g_autofree char *title = NULL; - GoaAccount *account; - GtkWidget *content_area; - GtkWidget *button; - GtkWidget *dialog; - GtkWidget *box; - const char *provider_type; - - client = goa_client_new_sync (NULL, &error); - if (error) - { - g_printerr ("Error retrieving online accounts client"); - exit (EXIT_FAILURE); - return; - } - - object = goa_client_lookup_by_id (client, argv[2]); - if (!object) - { - g_printerr ("Online account does not exist"); - exit (EXIT_FAILURE); - return; - } - - /* Find the provider with a matching type */ - account = goa_object_get_account (object); - provider_type = goa_account_get_provider_type (account); - provider = goa_provider_get_for_provider_type (provider_type); - if (!provider) - { - g_printerr ("Provider type not supported"); - exit (EXIT_FAILURE); - return; - } - - dialog = g_object_new (GTK_TYPE_DIALOG, - "use-header-bar", 1, - NULL); - /* Keep account alive so that the switches are still bound to it */ - g_object_set_data_full (G_OBJECT (dialog), "goa-account", account, g_object_unref); - g_signal_connect_swapped (dialog, "response", G_CALLBACK (g_application_quit), application); - set_external_parent_from_handle (application, GTK_WINDOW (dialog), argv[3]); - - box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 42); - gtk_widget_set_margin_bottom (box, 24); - - content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); - gtk_container_set_border_width (GTK_CONTAINER (content_area), 0); - gtk_container_add (GTK_CONTAINER (content_area), box); - - goa_provider_show_account (provider, - client, - object, - GTK_BOX (box), - NULL, - NULL); - - /* - * The above call doesn't set any widgets to visible, so we have to do that. - * https://gitlab.gnome.org/GNOME/gnome-online-accounts/issues/56 - */ - gtk_widget_show_all (box); - - /* translators: This is the title of the "Show Account" dialog. The - * %s is the name of the provider. e.g., 'Google'. */ - title = g_strdup_printf (_("%s Account"), goa_account_get_provider_name (account)); - gtk_window_set_title (GTK_WINDOW (dialog), title); - - button = gtk_button_new_with_label (_("Remove Account")); - gtk_widget_set_margin_start (box, 24); - gtk_widget_set_margin_end (box, 24); - gtk_widget_set_halign (button, GTK_ALIGN_END); - gtk_widget_set_valign (button, GTK_ALIGN_END); - gtk_widget_set_visible (button, !goa_account_get_is_locked (account)); - gtk_style_context_add_class (gtk_widget_get_style_context (button), "destructive-action"); - gtk_container_add (GTK_CONTAINER (box), button); - g_signal_connect_swapped (button, "clicked", G_CALLBACK (on_remove_button_clicked_cb), application); -} - -static int -show_account (int argc, - char **argv) -{ - g_autoptr(GtkApplication) application = NULL; - - gtk_init (&argc, &argv); - - if (argc != 4) - { - g_printerr ("Not enough arguments"); - return EXIT_FAILURE; - } - - application = gtk_application_new ("org.gnome.Settings.GoaHelper", - G_APPLICATION_FLAGS_NONE); - g_signal_connect (application, "activate", G_CALLBACK (on_application_activate_show_account_cb), argv); - - return g_application_run (G_APPLICATION (application), 0, NULL); -} - -struct { - const char *command_name; - int (*command_func) (int argc, - char **argv); -} commands[] = { - { "create-account", create_account, }, - { "list-providers", list_providers, }, - { "show-account", show_account, }, -}; - - -static void -log_handler (const gchar *domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) -{ - g_printerr ("%s: %s\n", domain, message); -} - -int -main (int argc, - char **argv) -{ - gsize i; - - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - if (argc < 2) - return EXIT_FAILURE; - - /* - * This helper currently communicates to the gnome-control-center parent process - * by writing information to stdout using g_print. Therefore we need - * a custom logging handler, so to not write logs into stdout, - * which would confuse the parent process. - */ - g_log_set_default_handler (log_handler, NULL); - - for (i = 0; i < G_N_ELEMENTS (commands); i++) - { - if (g_strcmp0 (commands[i].command_name, argv[1]) == 0) - return commands[i].command_func (argc, argv); - } - - return EXIT_SUCCESS; -} diff --git a/panels/online-accounts/meson.build b/panels/online-accounts/meson.build index 06c3a0534..679566069 100644 --- a/panels/online-accounts/meson.build +++ b/panels/online-accounts/meson.build @@ -29,6 +29,7 @@ sources += gnome.compile_resources( deps = common_deps + [ goa_dep, + dependency('goa-backend-1.0', version: goa_req_version), ] panels_libs += static_library( @@ -39,32 +40,4 @@ panels_libs += static_library( c_args: cflags ) -goa_helper_deps = [ - dependency('goa-backend-1.0', version: goa_req_version), -] - -goa_helper_cflags = cflags + [ - '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir), -] - -gtk_x11_dep = dependency('gtk+-x11-3.0', required: false) -if gtk_x11_dep.found() - goa_helper_cflags += ['-DHAVE_GTK_X11'] -endif - -gtk_wayland_dep = dependency('gtk+-wayland-3.0', required: false) -if gtk_wayland_dep.found() - goa_helper_cflags += ['-DHAVE_GTK_WAYLAND'] -endif - -executable( - 'gnome-control-center-goa-helper', - 'gnome-control-center-goa-helper.c', - include_directories: [ top_inc ], - dependencies: goa_helper_deps, - c_args: goa_helper_cflags, - install: true, - install_dir: control_center_libexecdir, -) - subdir('icons')