/* * Copyright (C) 2011 Collabora Ltd. * * 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., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA * * Authors: Danielle Madeley * Emilio Pozuelo Monfort */ #include #include #include #include #include #include #include "empathy-account-widget-skype.h" #include "empathy-account-widget-private.h" #include "empathy-ui-utils.h" #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT #include #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountWidget) typedef struct { TpAccount *account; TpChannel *channel; char *password; gboolean remember; } ObserveChannelsData; static ObserveChannelsData * observe_channels_data_new (TpAccount *account, TpChannel *channel, const char *password, gboolean remember) { ObserveChannelsData *data = g_slice_new0 (ObserveChannelsData); data->account = g_object_ref (account); data->channel = g_object_ref (channel); data->password = g_strdup (password); data->remember = remember; return data; } static void observe_channels_data_free (ObserveChannelsData *data) { g_object_unref (data->account); g_object_unref (data->channel); g_free (data->password); g_slice_free (ObserveChannelsData, data); } static void auth_observer_sasl_handler_invalidated (EmpathyServerSASLHandler *sasl_handler, gpointer user_data) { DEBUG ("SASL Handler done"); g_object_unref (sasl_handler); } static void auth_observer_new_sasl_handler_cb (GObject *obj, GAsyncResult *result, gpointer user_data) { ObserveChannelsData *data = user_data; EmpathyServerSASLHandler *sasl_handler; GError *error = NULL; sasl_handler = empathy_server_sasl_handler_new_finish (result, &error); if (error != NULL) { DEBUG ("Failed to create SASL handler: %s", error->message); tp_channel_close_async (data->channel, NULL, NULL); g_error_free (error); goto finally; } DEBUG ("providing password, remember = %s", data->remember ? "yes" : "no"); g_signal_connect (sasl_handler, "invalidated", G_CALLBACK (auth_observer_sasl_handler_invalidated), NULL); empathy_server_sasl_handler_provide_password (sasl_handler, data->password, data->remember); finally: observe_channels_data_free (data); } static void auth_observer_claim_cb (GObject *dispatch_operation, GAsyncResult *result, gpointer user_data) { ObserveChannelsData *data = user_data; GError *error = NULL; if (!tp_channel_dispatch_operation_claim_finish ( TP_CHANNEL_DISPATCH_OPERATION (dispatch_operation), result, &error)) { DEBUG ("Failed to claim auth channel: %s", error->message); g_error_free (error); observe_channels_data_free (data); return; } empathy_server_sasl_handler_new_async (data->account, data->channel, auth_observer_new_sasl_handler_cb, data); } static void auth_observer_observe_channels (TpSimpleObserver *auth_observer, TpAccount *account, TpConnection *connection, GList *channels, TpChannelDispatchOperation *dispatch_operation, GList *requests, TpObserveChannelsContext *context, gpointer user_data) { TpChannel *channel; GHashTable *props; GStrv available_mechanisms; const char *password = NULL; gboolean remember; /* we only do this for Psyke */ if (tp_strdiff ( tp_connection_get_connection_manager_name (connection), "psyke")) goto finally; /* can only deal with one channel */ if (g_list_length (channels) != 1) goto finally; channel = channels->data; props = tp_channel_borrow_immutable_properties (channel); available_mechanisms = tp_asv_get_boxed (props, TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_AVAILABLE_MECHANISMS, G_TYPE_STRV); /* must support X-TELEPATHY-PASSWORD */ if (!tp_strv_contains ((const char * const *) available_mechanisms, "X-TELEPATHY-PASSWORD")) goto finally; password = g_object_get_data (G_OBJECT (auth_observer), "password"); remember = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (auth_observer), "remember-password")); if (tp_str_empty (password)) goto finally; DEBUG ("claiming auth channel"); tp_channel_dispatch_operation_claim_async (dispatch_operation, auth_observer_claim_cb, observe_channels_data_new (account, channel, password, remember)); finally: tp_observe_channels_context_accept (context); } static TpBaseClient * auth_observer_new (void) { TpDBusDaemon *dbus; TpBaseClient *auth_observer; GError *error = NULL; dbus = tp_dbus_daemon_dup (&error); if (error != NULL) { g_warning ("Failed to get DBus daemon: %s", error->message); g_error_free (error); return NULL; } auth_observer = tp_simple_observer_new (dbus, FALSE, "Empathy.PsykePreAuth", FALSE, auth_observer_observe_channels, NULL, NULL); tp_base_client_set_observer_delay_approvers (auth_observer, TRUE); tp_base_client_take_observer_filter (auth_observer, tp_asv_new ( TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION, TP_PROP_CHANNEL_TYPE_SERVER_AUTHENTICATION_AUTHENTICATION_METHOD, G_TYPE_STRING, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, NULL)); if (!tp_base_client_register (auth_observer, &error)) { DEBUG ("Failed to register Psyke pre-auth observer: %s", error->message); g_error_free (error); } g_object_unref (dbus); return auth_observer; } enum { PS_COL_ENUM_VALUE, PS_COL_DISPLAY_NAME, NUM_PS_COLS }; static void account_widget_skype_combo_changed_cb (GtkComboBox *combo, EmpathyAccountWidget *self) { EmpathyAccountWidgetPriv *priv = GET_PRIV (self); const char *prop_name = g_object_get_data (G_OBJECT (combo), "dbus-property"); TpConnection *conn; EmpPrivacySetting prop_value; GtkTreeIter iter; GValue value = { 0, }; gtk_combo_box_get_active_iter (combo, &iter); gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter, PS_COL_ENUM_VALUE, &prop_value, -1); DEBUG ("Combo changed: %s", prop_name); g_value_init (&value, G_TYPE_UINT); g_value_set_uint (&value, prop_value); conn = tp_account_get_connection ( empathy_account_settings_get_account (priv->settings)); tp_cli_dbus_properties_call_set (conn, -1, EMP_IFACE_CONNECTION_INTERFACE_PRIVACY_SETTINGS, prop_name, &value, NULL, NULL, NULL, NULL); g_value_unset (&value); } static void account_widget_skype_toggle_changed_cb (GtkToggleButton *toggle, EmpathyAccountWidget *self) { EmpathyAccountWidgetPriv *priv = GET_PRIV (self); const char *prop_name = g_object_get_data (G_OBJECT (toggle), "dbus-property"); TpConnection *conn; GValue value = { 0, }; DEBUG ("Toggle changed: %s", prop_name); g_value_init (&value, G_TYPE_BOOLEAN); g_value_set_boolean (&value, gtk_toggle_button_get_active (toggle)); conn = tp_account_get_connection ( empathy_account_settings_get_account (priv->settings)); tp_cli_dbus_properties_call_set (conn, -1, EMP_IFACE_CONNECTION_INTERFACE_PRIVACY_SETTINGS, prop_name, &value, NULL, NULL, NULL, NULL); g_value_unset (&value); } static void account_widget_skype_set_value (EmpathyAccountWidget *self, GtkWidget *widget, GValue *value) { g_return_if_fail (value != NULL); if (GTK_IS_COMBO_BOX (widget)) { GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget)); guint prop_value; GtkTreeIter iter; gboolean valid; g_return_if_fail (G_VALUE_HOLDS_UINT (value)); prop_value = g_value_get_uint (value); g_signal_handlers_block_by_func (widget, account_widget_skype_combo_changed_cb, self); for (valid = gtk_tree_model_get_iter_first (model, &iter); valid; valid = gtk_tree_model_iter_next (model, &iter)) { guint v; gtk_tree_model_get (model, &iter, PS_COL_ENUM_VALUE, &v, -1); if (v == prop_value) { gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter); break; } } g_signal_handlers_unblock_by_func (widget, account_widget_skype_combo_changed_cb, self); } else if (GTK_IS_TOGGLE_BUTTON (widget)) { g_return_if_fail (G_VALUE_HOLDS_BOOLEAN (value)); g_signal_handlers_block_by_func (widget, account_widget_skype_toggle_changed_cb, self); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), g_value_get_boolean (value)); g_signal_handlers_unblock_by_func (widget, account_widget_skype_toggle_changed_cb, self); } else { g_assert_not_reached (); } } static void account_widget_build_skype_get_password_saved_cb (TpProxy *account, const GValue *value, const GError *in_error, gpointer user_data, GObject *password_entry) { GtkWidget *remember_password = user_data; gboolean password_saved; if (in_error != NULL) { DEBUG ("Failed to get PasswordSaved: %s", in_error->message); return; } g_return_if_fail (G_VALUE_HOLDS_BOOLEAN (value)); password_saved = g_value_get_boolean (value); DEBUG ("PasswordSaved: %s", password_saved ? "yes" : "no"); /* don't wipe the password if there's a real value in there */ if (g_object_get_data (password_entry, "fake-password") == NULL && !tp_str_empty (gtk_entry_get_text (GTK_ENTRY (password_entry)))) return; gtk_entry_set_text (GTK_ENTRY (password_entry), password_saved ? "xxxxxxxxxxxx": ""); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (remember_password), password_saved); g_object_set_data (password_entry, "fake-password", GUINT_TO_POINTER (password_saved)); } static void account_widget_build_skype_account_properties_changed_cb (TpProxy *account, const char *iface, GHashTable *changed, const char **invalidated, gpointer user_data, GObject *password_entry) { GValue *value; if (tp_strdiff (iface, EMP_IFACE_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE)) return; value = g_hash_table_lookup (changed, "PasswordSaved"); if (value == NULL) return; account_widget_build_skype_get_password_saved_cb (account, value, NULL, user_data, password_entry); } static void account_widget_skype_additional_apply_forget_passwd_cb (TpProxy *account, const GError *in_error, gpointer user_data, GObject *weak_obj) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (weak_obj); if (in_error != NULL) { DEBUG ("Did not forget password: %s", in_error->message); } else { DEBUG ("Password forgot, proceed to reconnect"); } /* reconnect is required */ g_simple_async_result_set_op_res_gboolean (simple, in_error == NULL); g_simple_async_result_complete (simple); g_object_unref (simple); } static void account_widget_skype_additional_apply_async (EmpathyAccountWidget *self, GAsyncReadyCallback callback, gpointer user_data) { EmpathyAccountWidgetPriv *priv = GET_PRIV (self); TpAccount *account = empathy_account_settings_get_account (priv->settings); GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, NULL); GtkWidget *password_entry, *remember_password; GObject *auth_observer; const char *password = NULL; gboolean remember; /* sync the password with the observer */ auth_observer = g_object_get_data (G_OBJECT (self), "auth-observer"); password_entry = g_object_get_data (G_OBJECT (self), "password-entry"); remember_password = g_object_get_data (G_OBJECT (self), "remember-password"); if (g_object_get_data (G_OBJECT (password_entry), "fake-password") == NULL) password = gtk_entry_get_text (GTK_ENTRY (password_entry)); remember = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON (remember_password)); g_object_set_data_full (auth_observer, "password", g_strdup (password), g_free); g_object_set_data (auth_observer, "remember-password", GUINT_TO_POINTER (remember)); /* we have to forget the password, else psyke won't query for the new one */ emp_cli_account_interface_external_password_storage_call_forget_password ( TP_PROXY (account), -1, account_widget_skype_additional_apply_forget_passwd_cb, NULL, NULL, G_OBJECT (simple)); } static gboolean account_widget_build_skype_password_entry_focus (GtkWidget *password_entry, GdkEventFocus *event, EmpathyAccountWidget *self) { EmpathyAccountWidgetPriv *priv = GET_PRIV (self); TpAccount *account = empathy_account_settings_get_account (priv->settings); if (g_object_get_data (G_OBJECT (password_entry), "fake-password") != NULL) { DEBUG ("Clearing fake password for editing"); gtk_entry_set_text (GTK_ENTRY (password_entry), ""); g_object_set_data (G_OBJECT (password_entry), "fake-password", GUINT_TO_POINTER (FALSE)); } if (account != NULL && tp_account_is_enabled (account)) { DEBUG ("Highlighting Apply/Cancel button"); self->ui_details->additional_apply_async = account_widget_skype_additional_apply_async; empathy_account_widget_changed (self); } return FALSE; } static void account_widget_skype_remember_password_toggled (GtkToggleButton *button, EmpathyAccountWidget *self) { EmpathyAccountWidgetPriv *priv = GET_PRIV (self); TpAccount *account = empathy_account_settings_get_account (priv->settings); /* we only forget the password if the toggle goes inactive */ if (gtk_toggle_button_get_active (button)) return; DEBUG ("forgetting password"); emp_cli_account_interface_external_password_storage_call_forget_password ( TP_PROXY (account), -1, NULL, NULL, NULL, NULL); } static void account_widget_build_skype_get_privacy_settings_cb (TpProxy *cm, GHashTable *props, const GError *in_error, gpointer user_data, GObject *weak_obj) { EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (weak_obj); GtkBuilder *gui = user_data; guint i; static const char *widgets[] = { "allow-text-chats-from", "allow-skype-calls-from", "allow-video-from", "show-my-avatar-to", "show-my-web-status", "show-i-have-video-to" }; if (in_error != NULL) { GtkWidget *table, *infobar, *label; DEBUG ("Failed to get properties: %s", in_error->message); table = GTK_WIDGET (gtk_builder_get_object (gui, "privacy-settings-table")); gtk_widget_set_sensitive (table, FALSE); infobar = gtk_info_bar_new (); gtk_box_pack_start ( GTK_BOX (gtk_builder_get_object (gui, "privacy-settings-vbox")), infobar, FALSE, TRUE, 0); gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_ERROR); label = gtk_label_new (_("Failed to retrieve privacy settings.")); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_container_add (GTK_CONTAINER ( gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar))), label); gtk_widget_show (label); return; } for (i = 0; i < G_N_ELEMENTS (widgets); i++) { GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (gui, widgets[i])); const char *prop_name = g_object_get_data (G_OBJECT (widget), "dbus-property"); GValue *value; DEBUG ("Widget '%s' (%s), prop = %s", widgets[i], G_OBJECT_TYPE_NAME (widget), prop_name); value = g_hash_table_lookup (props, prop_name); if (value == NULL) { g_warning ("Couldn't get a value for %s", prop_name); continue; } account_widget_skype_set_value (self, widget, value); } } static void account_widget_skype_properties_changed_cb (TpProxy *conn, const char *interface, GHashTable *props, const char **invalidated, gpointer user_data, GObject *weak_obj) { EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (weak_obj); GtkWidget *table = user_data; GHashTableIter iter; const char *prop; GValue *value; g_hash_table_iter_init (&iter, props); while (g_hash_table_iter_next (&iter, (gpointer) &prop, (gpointer) &value)) { GList *children, *ptr; DEBUG ("Property changed: %s", prop); /* find this value in the widget tree */ children = gtk_container_get_children (GTK_CONTAINER (table)); for (ptr = children; ptr != NULL; ptr = ptr->next) { GtkWidget *widget = ptr->data; const char *prop_name = g_object_get_data (G_OBJECT (widget), "dbus-property"); if (!tp_strdiff (prop_name, prop)) { DEBUG ("Got child %p (%s)", widget, G_OBJECT_TYPE_NAME (widget)); account_widget_skype_set_value (self, widget, value); break; } } g_list_free (children); } } /** * account_widget_build_skype_setup_combo: * @gui: * @widget: * @first_option: a list of options from the enum, terminated by -1 */ static void account_widget_build_skype_setup_combo (EmpathyAccountWidget *self, GtkBuilder *gui, const char *widget, const char *prop_name, int first_option, ...) { GtkWidget *combo; GtkListStore *store; va_list var_args; int option; static const char *options[NUM_EMP_PRIVACY_SETTINGS] = { N_("No one"), N_("My contacts"), N_("Anyone"), N_("Known Numbers") }; combo = GTK_WIDGET (gtk_builder_get_object (gui, widget)); g_return_if_fail (combo != NULL); store = gtk_list_store_new (NUM_PS_COLS, G_TYPE_UINT, /* PS_COL_ENUM_VALUE */ G_TYPE_STRING /* PS_COL_DISPLAY_NAME */ ); gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store)); va_start (var_args, first_option); for (option = first_option; option != -1; option = va_arg (var_args, int)) { gtk_list_store_insert_with_values (store, NULL, -1, PS_COL_ENUM_VALUE, option, PS_COL_DISPLAY_NAME, gettext (options[option]), -1); } va_end (var_args); g_object_set_data (G_OBJECT (combo), "dbus-property", (gpointer) prop_name); g_signal_connect (combo, "changed", G_CALLBACK (account_widget_skype_combo_changed_cb), self); } static void account_widget_skype_privacy_settings (GtkWidget *button, EmpathyAccountWidget *self) { EmpathyAccountWidgetPriv *priv = GET_PRIV (self); TpConnection *conn; char *filename; GtkBuilder *gui; GtkWidget *dialog, *show_my_web_status, *table, *vbox; GtkWidget *toplevel, *infobar, *label; DEBUG ("Loading privacy settings"); filename = empathy_file_lookup ("empathy-account-widget-skype.ui", "libempathy-gtk"); gui = empathy_builder_get_file (filename, "privacy-settings-dialog", &dialog, "privacy-settings-table", &table, "privacy-settings-vbox", &vbox, "show-my-web-status", &show_my_web_status, NULL); toplevel = gtk_widget_get_toplevel (self->ui_details->widget); if (gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel)) gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel)); /* make the settings insensitive when the account is disconnected */ tp_account_bind_connection_status_to_property ( empathy_account_settings_get_account (priv->settings), table, "sensitive", FALSE); /* set up an informative info bar */ infobar = gtk_info_bar_new (); gtk_box_pack_start (GTK_BOX (vbox), infobar, FALSE, TRUE, 0); gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_INFO); label = gtk_label_new (_("Privacy settings can only be changed while the " "account is connected.")); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_container_add ( GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar))), label); gtk_widget_show (label); g_object_bind_property (table, "sensitive", infobar, "visible", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); account_widget_build_skype_setup_combo (self, gui, "allow-text-chats-from", "AllowTextChannelsFrom", EMP_PRIVACY_SETTING_ANYONE, EMP_PRIVACY_SETTING_CONTACTS, -1); account_widget_build_skype_setup_combo (self, gui, "allow-skype-calls-from", "AllowCallChannelsFrom", EMP_PRIVACY_SETTING_ANYONE, EMP_PRIVACY_SETTING_CONTACTS, -1); account_widget_build_skype_setup_combo (self, gui, "allow-video-from", "AllowVideoFrom", EMP_PRIVACY_SETTING_ANYONE, EMP_PRIVACY_SETTING_CONTACTS, -1); account_widget_build_skype_setup_combo (self, gui, "show-i-have-video-to", "ShowIHaveVideoTo", EMP_PRIVACY_SETTING_ANYONE, EMP_PRIVACY_SETTING_CONTACTS, EMP_PRIVACY_SETTING_NOBODY, -1); account_widget_build_skype_setup_combo (self, gui, "show-my-avatar-to", "ShowMyAvatarTo", EMP_PRIVACY_SETTING_ANYONE, EMP_PRIVACY_SETTING_CONTACTS, -1); g_object_set_data (G_OBJECT (show_my_web_status), "dbus-property", "ShowMyWebStatus"); g_signal_connect (show_my_web_status, "toggled", G_CALLBACK (account_widget_skype_toggle_changed_cb), self); /* get the current parameter values from psyke */ conn = tp_account_get_connection ( empathy_account_settings_get_account (priv->settings)); tp_cli_dbus_properties_call_get_all (conn, -1, EMP_IFACE_CONNECTION_INTERFACE_PRIVACY_SETTINGS, account_widget_build_skype_get_privacy_settings_cb, g_object_ref (gui), g_object_unref, G_OBJECT (self)); tp_cli_dbus_properties_connect_to_properties_changed (conn, account_widget_skype_properties_changed_cb, table, NULL, G_OBJECT (self), NULL); g_object_unref (gui); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } static void account_widget_build_skype_set_pixmap (GtkBuilder *gui, const char *widget, const char *file) { GtkImage *image = GTK_IMAGE (gtk_builder_get_object (gui, widget)); char *filename = empathy_file_lookup (file, "data"); gtk_image_set_from_file (image, filename); g_free (filename); } void empathy_account_widget_build_skype (EmpathyAccountWidget *self, const char *filename) { static TpBaseClient *auth_observer = NULL; EmpathyAccountWidgetPriv *priv = GET_PRIV (self); TpAccount *account = empathy_account_settings_get_account (priv->settings); GtkWidget *password_entry, *remember_password; if (priv->simple || priv->creating_account) { GtkWidget *skype_info; /* if we don't have an account it means we're doing the initial setup */ self->ui_details->gui = empathy_builder_get_file (filename, "table_common_skype_settings_setup", &priv->table_common_settings, "vbox_skype_settings_setup", &self->ui_details->widget, "skype-info-vbox", &skype_info, "entry_password_setup", &password_entry, "remember-password-setup", &remember_password, NULL); account_widget_build_skype_set_pixmap (self->ui_details->gui, "plugged-into-skype-logo", "plugged-into-skype.png"); account_widget_build_skype_set_pixmap (self->ui_details->gui, "canonical-logo", "canonical-logo.png"); gtk_box_pack_end (GTK_BOX (self->ui_details->widget), skype_info, TRUE, TRUE, 0); empathy_account_widget_handle_params (self, "entry_id_setup", "account", NULL); self->ui_details->default_focus = g_strdup ("entry_id_setup"); } else { GtkWidget *edit_privacy_settings_button, *skype_info; self->ui_details->gui = empathy_builder_get_file (filename, "table_common_skype_settings", &priv->table_common_settings, "vbox_skype_settings", &self->ui_details->widget, "skype-info-vbox", &skype_info, "edit-privacy-settings-button", &edit_privacy_settings_button, "entry_password", &password_entry, "remember-password", &remember_password, NULL); empathy_builder_connect (self->ui_details->gui, self, "edit-privacy-settings-button", "clicked", account_widget_skype_privacy_settings, "remember-password", "toggled", account_widget_skype_remember_password_toggled, NULL); if (account != NULL) tp_account_bind_connection_status_to_property (account, edit_privacy_settings_button, "sensitive", FALSE); else gtk_widget_set_sensitive (edit_privacy_settings_button, FALSE); account_widget_build_skype_set_pixmap (self->ui_details->gui, "plugged-into-skype-logo", "plugged-into-skype.png"); account_widget_build_skype_set_pixmap (self->ui_details->gui, "canonical-logo", "canonical-logo.png"); gtk_box_pack_end (GTK_BOX (self->ui_details->widget), skype_info, TRUE, TRUE, 0); empathy_account_widget_handle_params (self, "entry_id", "account", NULL); self->ui_details->default_focus = g_strdup ("entry_id"); } /* create the Psyke pre-authentication observer */ if (auth_observer == NULL) { /* the auth observer lives for the lifetime of the process */ DEBUG ("Creating Psyke authentication observer"); auth_observer = auth_observer_new (); } g_object_set_data (G_OBJECT (self), "auth-observer", auth_observer); g_object_set_data (G_OBJECT (self), "password-entry", password_entry); g_object_set_data (G_OBJECT (self), "remember-password", remember_password); g_object_bind_property (remember_password, "active", password_entry, "sensitive", G_BINDING_SYNC_CREATE); /* find out if we know the password */ if (account != NULL && tp_proxy_has_interface_by_id (account, EMP_IFACE_QUARK_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE)) { tp_cli_dbus_properties_call_get (account, -1, EMP_IFACE_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE, "PasswordSaved", account_widget_build_skype_get_password_saved_cb, remember_password, NULL, G_OBJECT (password_entry)); tp_cli_dbus_properties_connect_to_properties_changed (account, account_widget_build_skype_account_properties_changed_cb, remember_password, NULL, G_OBJECT (password_entry), NULL); } /* if the user changes the password, it's probably no longer a fake * password */ g_signal_connect (password_entry, "focus-in-event", G_CALLBACK (account_widget_build_skype_password_entry_focus), self); } gboolean empathy_account_widget_skype_show_eula (GtkWindow *parent) { GtkWidget *dialog, *textview, *vbox, *scrolledwindow; GtkTextBuffer *buffer; gchar *filename, *l10n_filename; const gchar * const * langs; GError *error = NULL; gchar *eula; gint result; gsize len; gint i; filename = empathy_file_lookup ("skype-eula.txt", "data"); langs = g_get_language_names (); for (i = 0; langs[i] != NULL; i++) { l10n_filename = g_strconcat (filename, ".", langs[i], NULL); g_file_get_contents (l10n_filename, &eula, &len, NULL); g_free (l10n_filename); if (eula != NULL) break; } if (eula == NULL) { DEBUG ("Could not open translated Skype EULA"); g_file_get_contents (filename, &eula, &len, &error); } g_free (filename); if (error != NULL) { g_warning ("Could not open Skype EULA: %s", error->message); g_error_free (error); return FALSE; } dialog = gtk_dialog_new_with_buttons (_("End User License Agreement"), parent, GTK_DIALOG_MODAL, _("Decline"), GTK_RESPONSE_CANCEL, _("Accept"), GTK_RESPONSE_ACCEPT, NULL); buffer = gtk_text_buffer_new (NULL); gtk_text_buffer_set_text (buffer, eula, len); g_free (eula); textview = gtk_text_view_new_with_buffer (buffer); gtk_text_view_set_editable (GTK_TEXT_VIEW (textview), FALSE); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textview), GTK_WRAP_WORD_CHAR); vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); scrolledwindow = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_add_with_viewport ( GTK_SCROLLED_WINDOW (scrolledwindow), textview); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0); gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 250); gtk_widget_show_all (dialog); result = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); return (result == GTK_RESPONSE_ACCEPT); } static gboolean is_other_psyke_account (TpAccount *ours, TpAccount *other) { gboolean paths_diff; if (ours == NULL) paths_diff = TRUE; else paths_diff = tp_strdiff ( tp_proxy_get_object_path (ours), tp_proxy_get_object_path (other)); return (paths_diff && tp_account_is_enabled (other) && !tp_strdiff (tp_account_get_connection_manager (other), "psyke")); } gboolean empathy_accounts_dialog_skype_disable_other_accounts (TpAccount *account, GtkWindow *parent) { TpAccountManager *am = tp_account_manager_dup (); GList *accounts, *ptr; gboolean other_psyke_accounts = FALSE; /* check if any other psyke accounts are enabled */ accounts = tp_account_manager_get_valid_accounts (am); for (ptr = accounts; ptr != NULL; ptr = ptr->next) { TpAccount *a = ptr->data; if (is_other_psyke_account (account, a)) { other_psyke_accounts = TRUE; break; } } g_list_free (accounts); if (other_psyke_accounts) { #if 0 /* this dialog is a good idea, but currently lacking from the UX spec, * so it's being left out for now */ GtkWidget *msg = gtk_message_dialog_new (parent, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s\n\n%s", _("Multiple Skype accounts can not be enabled simultaneously. " "Enabling this Skype account will disable all others."), _("Continue to enable this account?")); int response; response = gtk_dialog_run (GTK_DIALOG (msg)); gtk_widget_destroy (msg); if (response != GTK_RESPONSE_YES) { /* the user chose not to proceed */ g_object_unref (am); return FALSE; } #endif /* the user chose to proceed, disable the other accounts */ accounts = tp_account_manager_get_valid_accounts (am); for (ptr = accounts; ptr != NULL; ptr = ptr->next) { TpAccount *a = ptr->data; if (is_other_psyke_account (account, a)) { tp_account_set_enabled_async (a, FALSE, NULL, NULL); } } g_list_free (accounts); } g_object_unref (am); return TRUE; }