Ted Gould has proposed merging lp:~ted/indicator-application/approver-api into 
lp:indicator-application.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)


Adding a basic approver interface and some code to support it.  Should unblock 
some, but isn't complete.  Does pass it's first test though :)
-- 
https://code.launchpad.net/~ted/indicator-application/approver-api/+merge/29623
Your team ayatana-commits is subscribed to branch lp:indicator-application.
=== modified file '.bzrignore'
--- .bzrignore	2010-06-18 15:33:02 +0000
+++ .bzrignore	2010-07-10 02:38:38 +0000
@@ -107,3 +107,6 @@
 docs/reference/libappindicator-decl-list.txt.bak
 src/AppIndicator-0.1.vapi
 bindings/mono/policy.appindicator-sharp.dll
+src/notification-approver-client.h
+src/notification-approver-server.h
+tests/test-approver

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2010-06-01 16:07:44 +0000
+++ src/Makefile.am	2010-07-10 02:38:38 +0000
@@ -116,6 +116,7 @@
 DBUS_SPECS = \
 	dbus-properties.xml \
 	application-service.xml \
+	notification-approver.xml \
 	notification-item.xml \
 	notification-watcher.xml
 

=== modified file 'src/application-service-appstore.c'
--- src/application-service-appstore.c	2010-07-08 18:45:51 +0000
+++ src/application-service-appstore.c	2010-07-10 02:38:38 +0000
@@ -31,6 +31,7 @@
 #include "application-service-marshal.h"
 #include "dbus-properties-client.h"
 #include "dbus-shared.h"
+#include "notification-approver-client.h"
 
 /* DBus Prototypes */
 static gboolean _application_service_server_get_applications (ApplicationServiceAppstore * appstore, GPtrArray ** apps, GError ** error);
@@ -53,9 +54,15 @@
 struct _ApplicationServiceAppstorePrivate {
 	DBusGConnection * bus;
 	GList * applications;
+	GList * approvers;
 	AppLruFile * lrufile;
 };
 
+typedef struct _Approver Approver;
+struct _Approver {
+	DBusGProxy * proxy;
+};
+
 typedef struct _Application Application;
 struct _Application {
 	gchar * id;
@@ -94,6 +101,9 @@
 static void application_service_appstore_finalize   (GObject *object);
 static AppIndicatorStatus string_to_status(const gchar * status_string);
 static void apply_status (Application * app, AppIndicatorStatus status);
+static void approver_free (gpointer papprover, gpointer user_data);
+static void check_with_new_approver (gpointer papp, gpointer papprove);
+static void check_with_old_approver (gpointer papprove, gpointer papp);
 
 G_DEFINE_TYPE (ApplicationServiceAppstore, application_service_appstore, G_TYPE_OBJECT);
 
@@ -142,6 +152,7 @@
 	ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE (self);
 
 	priv->applications = NULL;
+	priv->approvers = NULL;
 	priv->lrufile = NULL;
 	
 	GError * error = NULL;
@@ -172,6 +183,12 @@
 		                                           ((Application *)priv->applications->data)->dbus_object);
 	}
 
+	if (priv->approvers != NULL) {
+		g_list_foreach(priv->approvers, approver_free, NULL);
+		g_list_free(priv->approvers);
+		priv->approvers = NULL;
+	}
+
 	G_OBJECT_CLASS (application_service_appstore_parent_class)->dispose (object);
 	return;
 }
@@ -236,11 +253,23 @@
 		app->icon_path = g_strdup("");
 	}
 
+	/* TODO: Calling approvers, but we're ignoring the results.  So, eh. */
+	g_list_foreach(priv->approvers, check_with_old_approver, app);
+
 	apply_status(app, string_to_status(g_value_get_string(g_hash_table_lookup(properties, NOTIFICATION_ITEM_PROP_STATUS))));
 
 	return;
 }
 
+/* Check the application against an approver */
+static void
+check_with_old_approver (gpointer papprove, gpointer papp)
+{
+	/* Funny the parallels, eh? */
+	check_with_new_approver(papp, papprove);
+	return;
+}
+
 /* Simple translation function -- could be optimized */
 static AppIndicatorStatus
 string_to_status(const gchar * status_string)
@@ -745,3 +774,77 @@
 	return TRUE;
 }
 
+/* Frees the data associated with an approver */
+static void
+approver_free (gpointer papprover, gpointer user_data)
+{
+	Approver * approver = (Approver *)papprover;
+	g_return_if_fail(approver != NULL);
+	
+	if (approver->proxy != NULL) {
+		g_object_unref(approver->proxy);
+		approver->proxy = NULL;
+	}
+
+	g_free(approver);
+	return;
+}
+
+/* What did the approver tell us? */
+static void
+approver_request_cb (DBusGProxy *proxy, gboolean OUT_approved, GError *error, gpointer userdata)
+{
+	g_debug("Approver responded: %s", OUT_approved ? "approve" : "rejected");
+	return;
+}
+
+/* Run the applications through the new approver */
+static void
+check_with_new_approver (gpointer papp, gpointer papprove)
+{
+	Application * app = (Application *)papp;
+	Approver * approver = (Approver *)papprove;
+
+	org_ayatana_StatusNotifierApprover_approve_item_async(approver->proxy,
+	                                                      app->id,
+	                                                      app->category,
+	                                                      0,
+	                                                      app->dbus_name,
+	                                                      app->dbus_object,
+	                                                      approver_request_cb,
+	                                                      app);
+
+	return;
+}
+
+/* Adds a new approver to the app store */
+void
+application_service_appstore_approver_add (ApplicationServiceAppstore * appstore, const gchar * dbus_name, const gchar * dbus_object)
+{
+	g_return_if_fail(IS_APPLICATION_SERVICE_APPSTORE(appstore));
+	g_return_if_fail(dbus_name != NULL);
+	g_return_if_fail(dbus_object != NULL);
+	ApplicationServiceAppstorePrivate * priv = APPLICATION_SERVICE_APPSTORE_GET_PRIVATE (appstore);
+
+	Approver * approver = g_new0(Approver, 1);
+
+	GError * error = NULL;
+	approver->proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
+	                                                  dbus_name,
+	                                                  dbus_object,
+	                                                  NOTIFICATION_APPROVER_DBUS_IFACE,
+	                                                  &error);
+	if (error != NULL) {
+		g_warning("Unable to get approver interface on '%s:%s' : %s", dbus_name, dbus_object, error->message);
+		g_error_free(error);
+		g_free(approver);
+		return;
+	}
+
+	priv->approvers = g_list_prepend(priv->approvers, approver);
+
+	g_list_foreach(priv->applications, check_with_new_approver, approver);
+
+	return;
+}
+

=== modified file 'src/application-service-appstore.h'
--- src/application-service-appstore.h	2010-07-08 18:45:51 +0000
+++ src/application-service-appstore.h	2010-07-10 02:38:38 +0000
@@ -57,11 +57,14 @@
 ApplicationServiceAppstore * application_service_appstore_new (AppLruFile * lrufile);
 GType application_service_appstore_get_type               (void);
 void  application_service_appstore_application_add        (ApplicationServiceAppstore *   appstore,
-                                                      const gchar *             dbus_name,
-                                                      const gchar *             dbus_object);
+                                                           const gchar *             dbus_name,
+                                                           const gchar *             dbus_object);
 void  application_service_appstore_application_remove     (ApplicationServiceAppstore *   appstore,
-                                                      const gchar *             dbus_name,
-                                                      const gchar *             dbus_object);
+                                                           const gchar *             dbus_name,
+                                                           const gchar *             dbus_object);
+void  application_service_appstore_approver_add           (ApplicationServiceAppstore *   appstore,
+                                                           const gchar *             dbus_name,
+                                                           const gchar *             dbus_object);
 
 G_END_DECLS
 

=== modified file 'src/application-service-watcher.c'
--- src/application-service-watcher.c	2010-01-08 20:57:22 +0000
+++ src/application-service-watcher.c	2010-07-10 02:38:38 +0000
@@ -34,6 +34,7 @@
 static gboolean _notification_watcher_server_registered_status_notifier_items (ApplicationServiceWatcher * appwatcher, GArray ** apps);
 static gboolean _notification_watcher_server_protocol_version (ApplicationServiceWatcher * appwatcher, char ** version);
 static gboolean _notification_watcher_server_register_notification_host (ApplicationServiceWatcher * appwatcher, const gchar * host);
+static gboolean _notification_watcher_server_register_notification_approver (ApplicationServiceWatcher * appwatcher, const gchar * path, const GArray * categories, DBusGMethodInvocation * method);
 static gboolean _notification_watcher_server_is_notification_host_registered (ApplicationServiceWatcher * appwatcher, gboolean * haveHost);
 static void get_name_cb (DBusGProxy * proxy, guint status, GError * error, gpointer data);
 
@@ -249,3 +250,16 @@
 
 	return;
 }
+
+static gboolean
+_notification_watcher_server_register_notification_approver (ApplicationServiceWatcher * appwatcher, const gchar * path, const GArray * categories, DBusGMethodInvocation * method)
+{
+	ApplicationServiceWatcherPrivate * priv = APPLICATION_SERVICE_WATCHER_GET_PRIVATE(appwatcher);
+
+	application_service_appstore_approver_add(priv->appstore,
+	                                          dbus_g_method_get_sender(method),
+	                                          path);
+
+	dbus_g_method_return(method, G_TYPE_NONE);
+	return TRUE;
+}

=== modified file 'src/dbus-shared.h'
--- src/dbus-shared.h	2010-03-15 17:10:43 +0000
+++ src/dbus-shared.h	2010-07-10 02:38:38 +0000
@@ -31,3 +31,5 @@
 #define NOTIFICATION_ITEM_DBUS_IFACE      "org.kde.StatusNotifierItem"
 #define NOTIFICATION_ITEM_DEFAULT_OBJ     "/StatusNotifierItem"
 
+#define NOTIFICATION_APPROVER_DBUS_IFACE  "org.ayatana.StatusNotifierApprover"
+

=== added file 'src/notification-approver.xml'
--- src/notification-approver.xml	1970-01-01 00:00:00 +0000
+++ src/notification-approver.xml	2010-07-10 02:38:38 +0000
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/">
+	<interface name="org.ayatana.StatusNotifierApprover">
+
+<!-- Methods -->
+		<method name="ApproveItem">
+			<!-- KSNI ID -->
+			<arg type="s" name="id" direction="in" />
+			<!-- KSNI Category -->
+			<arg type="s" name="category" direction="in" />
+			<!-- Application PID -->
+			<arg type="u" name="pid" direction="in" />
+			<!-- Application DBus Address -->
+			<arg type="s" name="address" direction="in" />
+			<!-- Application DBus Path for KSNI interface -->
+			<arg type="o" name="path" direction="in" />
+			<!-- So, what do you think? -->
+			<arg type="b" name="approved" direction="out" />
+		</method>
+
+	</interface>
+</node>

=== modified file 'src/notification-watcher.xml'
--- src/notification-watcher.xml	2010-03-15 17:10:43 +0000
+++ src/notification-watcher.xml	2010-07-10 02:38:38 +0000
@@ -22,6 +22,13 @@
 		<method name="IsNotificationHostRegistered">
 			<arg type="b" name="hasHost" direction="out" />
 		</method>
+		<method name="RegisterNotificationApprover">
+		    <annotation name="org.freedesktop.DBus.GLib.Async" value="true" />
+			<!-- The path where to find the approver interface -->
+			<arg type="o" name="path" direction="in" />
+			<!-- List of categories to approve, none represents all -->
+			<arg type="as" name="categories" direction="in" />
+		</method>
 
 <!-- Signals -->
 		<signal name="ServiceRegistered">

=== modified file 'tests/Makefile.am'
--- tests/Makefile.am	2010-06-11 17:34:09 +0000
+++ tests/Makefile.am	2010-07-10 02:38:38 +0000
@@ -1,5 +1,6 @@
 
 check_PROGRAMS = \
+	test-approver \
 	test-libappindicator \
 	test-libappindicator-dbus-client \
 	test-libappindicator-dbus-server \
@@ -99,6 +100,32 @@
 	$(top_builddir)/src/libappindicator.la
 
 #########################################
+##  test-approver
+#########################################
+
+test_approver_SOURCES = \
+	test-approver.c
+
+test_approver_CFLAGS = \
+	$(INDICATOR_CFLAGS) \
+	-Wall -Werror \
+	-I$(top_srcdir)/src \
+	-I$(top_builddir)/src
+
+test_approver_LDADD = \
+	$(INDICATOR_LIBS) \
+	$(top_builddir)/src/libappindicator.la
+
+test-approver-tester: test-approver Makefile.am
+	@echo "#!/bin/bash" > $@
+	@echo . $(srcdir)/run-xvfb.sh >> $@
+	@echo $(DBUS_RUNNER) --task $(builddir)/test-approver --task-name Approver --task $(top_builddir)/src/indicator-application-service --task-name Service --ignore-return >> $@
+	@chmod +x $@
+
+TESTS += test-approver-tester
+
+
+#########################################
 ##  test-libappindicator-fallback
 #########################################
 

=== added file 'tests/test-approver.c'
--- tests/test-approver.c	1970-01-01 00:00:00 +0000
+++ tests/test-approver.c	2010-07-10 02:38:38 +0000
@@ -0,0 +1,170 @@
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib-bindings.h>
+
+#include "notification-watcher-client.h"
+#include "dbus-shared.h"
+#include "app-indicator.h"
+
+#define APPROVER_PATH  "/my/approver"
+
+#define INDICATOR_ID        "test-indicator-id"
+#define INDICATOR_ICON      "test-indicator-icon-name"
+#define INDICATOR_CATEGORY  APP_INDICATOR_CATEGORY_APPLICATION_STATUS
+
+#define TEST_APPROVER_TYPE            (test_approver_get_type ())
+#define TEST_APPROVER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_APPROVER_TYPE, TestApprover))
+#define TEST_APPROVER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_APPROVER_TYPE, TestApproverClass))
+#define IS_TEST_APPROVER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_APPROVER_TYPE))
+#define IS_TEST_APPROVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_APPROVER_TYPE))
+#define TEST_APPROVER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_APPROVER_TYPE, TestApproverClass))
+
+typedef struct _TestApprover      TestApprover;
+typedef struct _TestApproverClass TestApproverClass;
+
+struct _TestApproverClass {
+	GObjectClass parent_class;
+};
+
+struct _TestApprover {
+	GObject parent;
+};
+
+GType test_approver_get_type (void);
+
+static void test_approver_class_init (TestApproverClass *klass);
+static void test_approver_init       (TestApprover *self);
+static gboolean _notification_approver_server_approve_item (TestApprover * ta, const gchar * id, const gchar * category, guint pid, const gchar * address, const gchar * path, gboolean * approved, GError ** error);
+
+#include "../src/notification-approver-server.h"
+
+GMainLoop * main_loop = NULL;
+DBusGConnection * session_bus = NULL;
+DBusGProxy * bus_proxy = NULL;
+AppIndicator * app_indicator = NULL;
+gboolean passed = FALSE;
+
+G_DEFINE_TYPE (TestApprover, test_approver, G_TYPE_OBJECT);
+
+static void
+test_approver_class_init (TestApproverClass *klass)
+{
+	dbus_g_object_type_install_info(TEST_APPROVER_TYPE,
+	                                &dbus_glib__notification_approver_server_object_info);
+
+	return;
+}
+
+static void
+test_approver_init (TestApprover *self)
+{
+	dbus_g_connection_register_g_object(session_bus,
+	                                    APPROVER_PATH,
+	                                    G_OBJECT(self));
+
+	return;
+}
+
+static gboolean 
+_notification_approver_server_approve_item (TestApprover * ta, const gchar * id, const gchar * category, guint pid, const gchar * address, const gchar * path, gboolean * approved, GError ** error)
+{
+	*approved = TRUE;
+	g_debug("Asked to approve indicator");
+
+	if (g_strcmp0(id, INDICATOR_ID) == 0) {
+		passed = TRUE;
+	}
+
+	g_main_loop_quit(main_loop);
+
+	return TRUE;
+}
+
+static void
+register_cb (DBusGProxy * proxy, GError * error, gpointer user_data)
+{
+	if (error != NULL) {
+		g_warning("Unable to register approver: %s", error->message);
+		g_error_free(error);
+		g_main_loop_quit(main_loop);
+		return;
+	}
+
+	g_debug("Building App Indicator");
+	app_indicator = app_indicator_new(INDICATOR_ID, INDICATOR_ICON, INDICATOR_CATEGORY);
+
+	GtkWidget * menu = gtk_menu_new();
+	GtkWidget * mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
+
+	app_indicator_set_menu(app_indicator, GTK_MENU(menu));
+
+	return;
+}
+
+gint owner_count = 0;
+gboolean
+check_for_service (gpointer user_data)
+{
+	g_debug("Checking for Watcher");
+
+	if (owner_count > 100) {
+		g_warning("Couldn't find watcher after 100 tries.");
+		g_main_loop_quit(main_loop);
+		return FALSE;
+	}
+
+	owner_count++;
+
+	gboolean has_owner = FALSE;
+	org_freedesktop_DBus_name_has_owner(bus_proxy, NOTIFICATION_WATCHER_DBUS_ADDR, &has_owner, NULL);
+
+	if (has_owner) {
+		const char * cats = NULL;
+		DBusGProxy * proxy = dbus_g_proxy_new_for_name(session_bus,
+		                                               NOTIFICATION_WATCHER_DBUS_ADDR,
+		                                               NOTIFICATION_WATCHER_DBUS_OBJ,
+		                                               NOTIFICATION_WATCHER_DBUS_IFACE);
+
+		g_debug("Registering Approver");
+		org_kde_StatusNotifierWatcher_register_notification_approver_async (proxy, APPROVER_PATH, &cats, register_cb, NULL);
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+int
+main (int argc, char ** argv)
+{
+	GError * error = NULL;
+
+	gtk_init(&argc, &argv);
+	g_debug("Initing");
+
+	session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+	if (error != NULL) {
+		g_warning("Unable to get session bus: %s", error->message);
+		g_error_free(error);
+		return -1;
+	}
+
+	TestApprover * approver = g_object_new(TEST_APPROVER_TYPE, NULL);
+
+	bus_proxy = dbus_g_proxy_new_for_name(session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+
+	g_timeout_add(100, check_for_service, NULL);
+
+	main_loop = g_main_loop_new(NULL, FALSE);
+	g_main_loop_run(main_loop);
+
+	g_object_unref(approver);
+
+	if (!passed) {
+		return -1;
+	}
+
+	return 0;
+}

_______________________________________________
Mailing list: https://launchpad.net/~ayatana-commits
Post to     : ayatana-commits@lists.launchpad.net
Unsubscribe : https://launchpad.net/~ayatana-commits
More help   : https://help.launchpad.net/ListHelp

Reply via email to