aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--data/com.canonical.indicator.messages5
-rw-r--r--debian/control1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/im-accounts-service.c223
-rw-r--r--src/im-accounts-service.h53
-rw-r--r--src/im-application-list.c9
-rw-r--r--src/im-menu.c33
-rw-r--r--src/im-menu.h2
-rw-r--r--src/im-phone-menu.c13
-rw-r--r--src/im-phone-menu.h3
-rw-r--r--src/messages-service.c4
12 files changed, 343 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index e27f41d..8550030 100644
--- a/configure.ac
+++ b/configure.ac
@@ -43,7 +43,8 @@ GLIB_REQUIRED_VERSION=2.35.4
INTROSPECTION_REQUIRED_VERSION=1.32.0
PKG_CHECK_MODULES(APPLET, gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION
- glib-2.0 >= $GLIB_REQUIRED_VERSION)
+ glib-2.0 >= $GLIB_REQUIRED_VERSION
+ accountsservice)
PKG_CHECK_MODULES(GIO, gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION)
diff --git a/data/com.canonical.indicator.messages b/data/com.canonical.indicator.messages
index 2210b6b..572a4a7 100644
--- a/data/com.canonical.indicator.messages
+++ b/data/com.canonical.indicator.messages
@@ -6,11 +6,14 @@ Position=50
[desktop]
ObjectPath=/com/canonical/indicator/messages/desktop
+[desktop_greeter]
+ObjectPath=/com/canonical/indicator/messages/desktop_greeter
+
[phone]
ObjectPath=/com/canonical/indicator/messages/phone
Position=100
[phone_greeter]
-ObjectPath=/com/canonical/indicator/messages/phone
+ObjectPath=/com/canonical/indicator/messages/phone_greeter
Position=100
diff --git a/debian/control b/debian/control
index b2c899d..5cdba7d 100644
--- a/debian/control
+++ b/debian/control
@@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 9),
gobject-introspection (>= 0.9.12-4~),
gtk-doc-tools,
intltool,
+ libaccountsservice-dev,
libgirepository1.0-dev (>= 0.9.12),
libgtest-dev,
python3-dbusmock,
diff --git a/src/Makefile.am b/src/Makefile.am
index bc674c2..36e6a93 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,6 +10,8 @@ indicator_messages_service_SOURCES = \
gactionmuxer.h \
gsettingsstrv.c \
gsettingsstrv.h \
+ im-accounts-service.c \
+ im-accounts-service.h \
im-menu.c \
im-menu.h \
im-phone-menu.c \
diff --git a/src/im-accounts-service.c b/src/im-accounts-service.c
new file mode 100644
index 0000000..b7ab15d
--- /dev/null
+++ b/src/im-accounts-service.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright © 2014 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Ted Gould <ted@canonical.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <act/act.h>
+
+#include "im-accounts-service.h"
+
+typedef struct _ImAccountsServicePrivate ImAccountsServicePrivate;
+
+struct _ImAccountsServicePrivate {
+ ActUserManager * user_manager;
+ GDBusProxy * touch_settings;
+ GCancellable * cancel;
+};
+
+#define IM_ACCOUNTS_SERVICE_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), IM_ACCOUNTS_SERVICE_TYPE, ImAccountsServicePrivate))
+
+static void im_accounts_service_class_init (ImAccountsServiceClass *klass);
+static void im_accounts_service_init (ImAccountsService *self);
+static void im_accounts_service_dispose (GObject *object);
+static void im_accounts_service_finalize (GObject *object);
+static void user_changed (ActUserManager * manager, ActUser * user, gpointer user_data);
+static void on_user_manager_loaded (ActUserManager * manager, GParamSpec * pspect, gpointer user_data);
+static void security_privacy_ready (GObject * obj, GAsyncResult * res, gpointer user_data);
+
+G_DEFINE_TYPE (ImAccountsService, im_accounts_service, G_TYPE_OBJECT);
+
+static void
+im_accounts_service_class_init (ImAccountsServiceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (ImAccountsServicePrivate));
+
+ object_class->dispose = im_accounts_service_dispose;
+ object_class->finalize = im_accounts_service_finalize;
+}
+
+static void
+im_accounts_service_init (ImAccountsService *self)
+{
+ ImAccountsServicePrivate * priv = IM_ACCOUNTS_SERVICE_GET_PRIVATE(self);
+
+ priv->cancel = g_cancellable_new();
+
+ priv->user_manager = act_user_manager_get_default();
+ g_signal_connect(priv->user_manager, "user-changed", G_CALLBACK(user_changed), self);
+ g_signal_connect(priv->user_manager, "notify::is-loaded", G_CALLBACK(on_user_manager_loaded), self);
+
+ gboolean isLoaded = FALSE;
+ g_object_get(G_OBJECT(priv->user_manager), "is-loaded", &isLoaded, NULL);
+ if (isLoaded) {
+ on_user_manager_loaded(priv->user_manager, NULL, NULL);
+ }
+}
+
+static void
+im_accounts_service_dispose (GObject *object)
+{
+ ImAccountsServicePrivate * priv = IM_ACCOUNTS_SERVICE_GET_PRIVATE(object);
+
+ if (priv->cancel != NULL) {
+ g_cancellable_cancel(priv->cancel);
+ g_clear_object(&priv->cancel);
+ }
+
+ g_clear_object(&priv->user_manager);
+
+ G_OBJECT_CLASS (im_accounts_service_parent_class)->dispose (object);
+}
+
+static void
+im_accounts_service_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (im_accounts_service_parent_class)->finalize (object);
+}
+
+/* Handles a User getting updated */
+static void
+user_changed (ActUserManager * manager, ActUser * user, gpointer user_data)
+{
+ if (g_strcmp0(act_user_get_user_name(user), g_get_user_name()) != 0) {
+ return;
+ }
+
+ ImAccountsServicePrivate * priv = IM_ACCOUNTS_SERVICE_GET_PRIVATE(user_data);
+ g_debug("User Updated");
+
+ /* Clear old proxies */
+ g_clear_object(&priv->touch_settings);
+
+ /* Start getting a new proxy */
+ g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.Accounts",
+ act_user_get_object_path(user),
+ "com.ubuntu.touch.AccountsService.SecurityPrivacy",
+ priv->cancel,
+ security_privacy_ready,
+ user_data);
+}
+
+/* Respond to the async of setting up the proxy. Mostly we get it or we error. */
+static void
+security_privacy_ready (GObject * obj, GAsyncResult * res, gpointer user_data)
+{
+ GError * error = NULL;
+ GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
+
+ if (error != NULL) {
+ g_warning("Unable to get a proxy on accounts service for touch settings: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+
+ ImAccountsServicePrivate * priv = IM_ACCOUNTS_SERVICE_GET_PRIVATE(user_data);
+ /* Ensure we didn't get a proxy while we weren't looking */
+ g_clear_object(&priv->touch_settings);
+ priv->touch_settings = proxy;
+}
+
+/* When the user manager is loaded see if we have a user already loaded
+ along with. */
+static void
+on_user_manager_loaded (ActUserManager * manager, GParamSpec * pspect, gpointer user_data)
+{
+ ImAccountsServicePrivate * priv = IM_ACCOUNTS_SERVICE_GET_PRIVATE(user_data);
+ ActUser * user = NULL;
+
+ g_debug("Accounts Manager Loaded");
+
+ user = act_user_manager_get_user(priv->user_manager, g_get_user_name());
+ if (user != NULL) {
+ user_changed(priv->user_manager, user, user_data);
+ g_object_unref(user);
+ }
+}
+
+/* Not the most testable way to do this but, it is a less invasive one, and we'll
+ probably restructure this codebase soonish */
+/* Gets an account service wrapper reference, so then it can be free'd */
+ImAccountsService *
+im_accounts_service_ref_default (void)
+{
+ static ImAccountsService * as = NULL;
+ if (as == NULL) {
+ as = IM_ACCOUNTS_SERVICE(g_object_new(IM_ACCOUNTS_SERVICE_TYPE, NULL));
+ g_object_add_weak_pointer(G_OBJECT(as), (gpointer *)&as);
+ return as;
+ }
+
+ return g_object_ref(as);
+}
+
+/* The draws attention setting is very legacy right now, we've patched and not changed
+ things much. We're gonna do better in the future, this function abstracts out the ugly */
+void
+im_accounts_service_set_draws_attention (ImAccountsService * service, gboolean draws_attention)
+{
+ g_return_if_fail(IM_IS_ACCOUNTS_SERVICE(service));
+ ImAccountsServicePrivate * priv = IM_ACCOUNTS_SERVICE_GET_PRIVATE(service);
+
+ if (priv->touch_settings == NULL) {
+ return;
+ }
+
+ g_dbus_connection_call(g_dbus_proxy_get_connection(priv->touch_settings),
+ g_dbus_proxy_get_name(priv->touch_settings),
+ g_dbus_proxy_get_object_path(priv->touch_settings),
+ "org.freedesktop.Accounts.User",
+ "SetXHasMessages",
+ g_variant_new("(b)", draws_attention),
+ NULL, /* reply */
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, /* timeout */
+ priv->cancel, /* cancellable */
+ NULL, NULL); /* cb */
+}
+
+/* Looks at the property that is set by settings. We default to off in any case
+ that we can or we don't know what the state is. */
+gboolean
+im_accounts_service_get_show_on_greeter (ImAccountsService * service)
+{
+ g_return_val_if_fail(IM_IS_ACCOUNTS_SERVICE(service), FALSE);
+
+ ImAccountsServicePrivate * priv = IM_ACCOUNTS_SERVICE_GET_PRIVATE(service);
+
+ if (priv->touch_settings == NULL) {
+ return FALSE;
+ }
+
+ GVariant * val = g_dbus_proxy_get_cached_property(priv->touch_settings, "MessagesWelcomeScreen");
+ if (val == NULL) {
+ return FALSE;
+ }
+
+ gboolean retval = g_variant_get_boolean(val);
+ g_variant_unref(val);
+ return retval;
+}
diff --git a/src/im-accounts-service.h b/src/im-accounts-service.h
new file mode 100644
index 0000000..d7611d8
--- /dev/null
+++ b/src/im-accounts-service.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2014 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Ted Gould <ted@canonical.com>
+ */
+
+#ifndef __IM_ACCOUNTS_SERVICE_H__
+#define __IM_ACCOUNTS_SERVICE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define IM_ACCOUNTS_SERVICE_TYPE (im_accounts_service_get_type ())
+#define IM_ACCOUNTS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IM_ACCOUNTS_SERVICE_TYPE, ImAccountsService))
+#define IM_ACCOUNTS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IM_ACCOUNTS_SERVICE_TYPE, ImAccountsServiceClass))
+#define IM_IS_ACCOUNTS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IM_ACCOUNTS_SERVICE_TYPE))
+#define IM_IS_ACCOUNTS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IM_ACCOUNTS_SERVICE_TYPE))
+#define IM_ACCOUNTS_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IM_ACCOUNTS_SERVICE_TYPE, ImAccountsServiceClass))
+
+typedef struct _ImAccountsService ImAccountsService;
+typedef struct _ImAccountsServiceClass ImAccountsServiceClass;
+
+struct _ImAccountsServiceClass {
+ GObjectClass parent_class;
+};
+
+struct _ImAccountsService {
+ GObject parent;
+};
+
+GType im_accounts_service_get_type (void);
+ImAccountsService * im_accounts_service_ref_default (void);
+void im_accounts_service_set_draws_attention (ImAccountsService * service, gboolean draws_attention);
+gboolean im_accounts_service_get_show_on_greeter (ImAccountsService * service);
+
+G_END_DECLS
+
+#endif
diff --git a/src/im-application-list.c b/src/im-application-list.c
index 15e661e..ac9b255 100644
--- a/src/im-application-list.c
+++ b/src/im-application-list.c
@@ -22,6 +22,7 @@
#include "indicator-messages-application.h"
#include "gactionmuxer.h"
#include "indicator-desktop-shortcuts.h"
+#include "im-accounts-service.h"
#include <gio/gdesktopappinfo.h>
#include <string.h>
@@ -41,6 +42,8 @@ struct _ImApplicationList
GSimpleAction * statusaction;
GHashTable *app_status;
+
+ ImAccountsService * as;
};
G_DEFINE_TYPE (ImApplicationList, im_application_list, G_TYPE_OBJECT);
@@ -170,9 +173,11 @@ im_application_list_update_root_action (ImApplicationList *list)
if (g_hash_table_find (list->applications, application_draws_attention, NULL)) {
base_icon_name = "indicator-messages-new-%s";
accessible_name = _("New Messages");
+ im_accounts_service_set_draws_attention(list->as, TRUE);
} else {
base_icon_name = "indicator-messages-%s";
accessible_name = _("Messages");
+ im_accounts_service_set_draws_attention(list->as, FALSE);
}
/* Include the IM state in the icon */
@@ -449,6 +454,8 @@ im_application_list_dispose (GObject *object)
g_clear_pointer (&list->applications, g_hash_table_unref);
g_clear_object (&list->muxer);
+ g_clear_object (&list->as);
+
G_OBJECT_CLASS (im_application_list_parent_class)->dispose (object);
}
@@ -600,6 +607,8 @@ im_application_list_init (ImApplicationList *list)
list->muxer = g_action_muxer_new ();
g_action_muxer_insert (list->muxer, NULL, G_ACTION_GROUP (list->globalactions));
+ list->as = im_accounts_service_ref_default();
+
im_application_list_update_root_action (list);
}
diff --git a/src/im-menu.c b/src/im-menu.c
index 55d4685..0c39b97 100644
--- a/src/im-menu.c
+++ b/src/im-menu.c
@@ -18,12 +18,15 @@
*/
#include "im-menu.h"
+#include "im-accounts-service.h"
struct _ImMenuPrivate
{
GMenu *toplevel_menu;
GMenu *menu;
ImApplicationList *applist;
+ gboolean on_greeter;
+ ImAccountsService *as;
};
G_DEFINE_TYPE_WITH_PRIVATE (ImMenu, im_menu, G_TYPE_OBJECT)
@@ -32,6 +35,7 @@ enum
{
PROP_0,
PROP_APPLICATION_LIST,
+ PROP_ON_GREETER,
NUM_PROPERTIES
};
@@ -43,6 +47,7 @@ im_menu_finalize (GObject *object)
g_object_unref (priv->toplevel_menu);
g_object_unref (priv->menu);
g_object_unref (priv->applist);
+ g_object_unref (priv->as);
G_OBJECT_CLASS (im_menu_parent_class)->finalize (object);
}
@@ -60,6 +65,9 @@ im_menu_get_property (GObject *object,
case PROP_APPLICATION_LIST:
g_value_set_object (value, priv->applist);
break;
+ case PROP_ON_GREETER:
+ g_value_set_boolean (value, priv->on_greeter);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -79,6 +87,9 @@ im_menu_set_property (GObject *object,
case PROP_APPLICATION_LIST: /* construct only */
priv->applist = g_value_dup_object (value);
break;
+ case PROP_ON_GREETER:
+ priv->on_greeter = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -100,6 +111,12 @@ im_menu_class_init (ImMenuClass *class)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_ON_GREETER,
+ g_param_spec_boolean ("on-greeter", "", "",
+ FALSE,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
}
static void
@@ -110,6 +127,8 @@ im_menu_init (ImMenu *menu)
priv->toplevel_menu = g_menu_new ();
priv->menu = g_menu_new ();
+ priv->on_greeter = FALSE;
+ priv->as = im_accounts_service_ref_default();
root = g_menu_item_new (NULL, "indicator.messages");
g_menu_item_set_attribute (root, "x-canonical-type", "s", "com.canonical.indicator.root");
@@ -225,3 +244,17 @@ im_menu_insert_item_sorted (ImMenu *menu,
g_menu_insert_item (priv->menu, position, item);
}
+
+/* Whether the menu should show extra data on it. Depends on the greeter
+ status and user settings */
+gboolean
+im_menu_show_data (ImMenu *menu)
+{
+ g_return_val_if_fail (IM_IS_MENU (menu), FALSE);
+ ImMenuPrivate *priv = im_menu_get_instance_private (IM_MENU (menu));
+
+ if (!priv->on_greeter)
+ return TRUE;
+
+ return im_accounts_service_get_show_on_greeter(priv->as);
+}
diff --git a/src/im-menu.h b/src/im-menu.h
index f67abc8..b76d616 100644
--- a/src/im-menu.h
+++ b/src/im-menu.h
@@ -64,4 +64,6 @@ void im_menu_insert_item_sorted (ImMenu
gint first,
gint last);
+gboolean im_menu_show_data (ImMenu *menu);
+
#endif
diff --git a/src/im-phone-menu.c b/src/im-phone-menu.c
index 754fc2b..58a23ff 100644
--- a/src/im-phone-menu.c
+++ b/src/im-phone-menu.c
@@ -142,12 +142,13 @@ im_phone_menu_init (ImPhoneMenu *menu)
}
ImPhoneMenu *
-im_phone_menu_new (ImApplicationList *applist)
+im_phone_menu_new (ImApplicationList *applist, gboolean greeter)
{
g_return_val_if_fail (IM_IS_APPLICATION_LIST (applist), NULL);
return g_object_new (IM_TYPE_PHONE_MENU,
"application-list", applist,
+ "on-greeter", greeter,
NULL);
}
@@ -179,10 +180,12 @@ im_phone_menu_add_message (ImPhoneMenu *menu,
gint n_messages;
gint pos;
GVariant *serialized_app_icon;
+ gboolean show_data;
g_return_if_fail (IM_IS_PHONE_MENU (menu));
g_return_if_fail (app_id);
+ show_data = im_menu_show_data(IM_MENU (menu));
action_name = g_strconcat (app_id, ".msg.", id, NULL);
item = g_menu_item_new (title, NULL);
@@ -190,8 +193,10 @@ im_phone_menu_add_message (ImPhoneMenu *menu,
g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.messageitem");
g_menu_item_set_attribute (item, "x-canonical-message-id", "s", id);
- g_menu_item_set_attribute (item, "x-canonical-subtitle", "s", subtitle);
- g_menu_item_set_attribute (item, "x-canonical-text", "s", body);
+ if (show_data)
+ g_menu_item_set_attribute (item, "x-canonical-subtitle", "s", subtitle);
+ if (show_data)
+ g_menu_item_set_attribute (item, "x-canonical-text", "s", body);
g_menu_item_set_attribute (item, "x-canonical-time", "x", time);
if (serialized_icon)
@@ -203,7 +208,7 @@ im_phone_menu_add_message (ImPhoneMenu *menu,
g_variant_unref (serialized_app_icon);
}
- if (actions)
+ if (actions && show_data)
g_menu_item_set_attribute (item, "x-canonical-message-actions", "v", actions);
n_messages = g_menu_model_get_n_items (G_MENU_MODEL (menu->message_section));
diff --git a/src/im-phone-menu.h b/src/im-phone-menu.h
index 4f96c8c..813634d 100644
--- a/src/im-phone-menu.h
+++ b/src/im-phone-menu.h
@@ -33,7 +33,8 @@ typedef struct _ImPhoneMenu ImPhoneMenu;
GType im_phone_menu_get_type (void);
-ImPhoneMenu * im_phone_menu_new (ImApplicationList *applist);
+ImPhoneMenu * im_phone_menu_new (ImApplicationList *applist,
+ gboolean greeter);
void im_phone_menu_add_message (ImPhoneMenu *menu,
const gchar *app_id,
diff --git a/src/messages-service.c b/src/messages-service.c
index d1ccbbc..d2c7e92 100644
--- a/src/messages-service.c
+++ b/src/messages-service.c
@@ -273,8 +273,10 @@ main (int argc, char ** argv)
}
menus = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
- g_hash_table_insert (menus, "phone", im_phone_menu_new (applications));
+ g_hash_table_insert (menus, "phone", im_phone_menu_new (applications, FALSE));
+ g_hash_table_insert (menus, "phone_greeter", im_phone_menu_new (applications, TRUE));
g_hash_table_insert (menus, "desktop", im_desktop_menu_new (applications));
+ g_hash_table_insert (menus, "desktop_greeter", im_desktop_menu_new (applications));
g_unix_signal_add(SIGTERM, sig_term_handler, mainloop);