Merge lp:~charlesk/indicator-power/custom-bus-for-upower into lp:indicator-power/15.04

Proposed by Charles Kerr
Status: Approved
Approved by: Ted Gould
Approved revision: 283
Proposed branch: lp:~charlesk/indicator-power/custom-bus-for-upower
Merge into: lp:indicator-power/15.04
Diff against target: 1005 lines (+556/-176)
7 files modified
README (+11/-0)
src/CMakeLists.txt (+1/-0)
src/brightness.c (+71/-30)
src/bus.c (+195/-0)
src/bus.h (+50/-0)
src/device-provider-upower.c (+67/-23)
src/service.c (+161/-123)
To merge this branch: bzr merge lp:~charlesk/indicator-power/custom-bus-for-upower
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+246234@code.launchpad.net

Commit message

Add support for finer-grained dbus service mocking

Description of the change

== Change Description

Add support for finer-grained dbus service mocking.

Use case: say we want to feed the indicator a dbusmocked upower, but don't want to mock the entire system bus because we also talk to powerd on the system bus. This lets us specify via environment variables where to look for each bus dependency.

== Checklist

> Are there any related MPs required for this MP to build/function as expected? Please list.

No

> Is your branch in sync with latest trunk? (e.g. bzr pull lp:trunk -> no changes)

Yes

> Did the code build without warnings?

Yes

> Did the tests run successfully?

Yes

> Did you perform an exploratory manual test run of your code change and any related functionality?

Yes

> If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?

N/A

> Did your component test plan pass? If on a device, what image number?

15.03 nexus 4 r63

> Please list which manual tests are germane for the reviewer in this MR.

This is QA scaffolding; no manual tests affected

> Did you provide a link to this page https://wiki.ubuntu.com/Process/Merges/Checklists/indicator-power

Yes

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ted Gould (ted) wrote :

Have to say I'm a little nervous with abstracting the bus stuff out this much. I like the standardization of using g_bus_own_name() to setup the ordering of the callbacks and ensure that we're doing everything right there. Naturually, that loses some flexibility. I like sitting outside the process and using dbusmock better so that it can be the same name, on the bus configured to be DBUS_SYSTEM_BUS_ADDRESS so that the indicator can be simpler.

That said, I don't see anything wrong with this code and have no objection other than "not the way I would have done it."

review: Approve
Revision history for this message
Allan LeSage (allanlesage) wrote :

Getting requests for this awesome new feature already (from paulliu), let's land 'er!

Unmerged revisions

283. By Charles Kerr

pass the G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT flag when calling g_dbus_connection_new_for_address() on an arbitrary bus address

282. By Charles Kerr

when connecting to a custom bus address, use G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION

281. By Charles Kerr

document the debugging environment variables

280. By Charles Kerr

move indicator_power_get_screen_busname() to bus.c

279. By Charles Kerr

use indicator_power_get_bus() for acquiring the bus that we look for powerd on

278. By Charles Kerr

use indicator_power_get_bus() for acquiring the bus that we look for upower on

277. By Charles Kerr

use indicator_power_get_bus() for acquiring the indicator's bus

276. By Charles Kerr

add indicator_power_get_bus() which lets environment variables let a custom bus override other buses.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'README'
2--- README 1970-01-01 00:00:00 +0000
3+++ README 2015-01-12 23:02:27 +0000
4@@ -0,0 +1,11 @@
5+Environment variables used for testing:
6+
7+ - INDICATOR_POWER_BUS_ADDRESS_UPOWER overrides the system bus default
8+ - INDICATOR_POWER_BUS_NAME_UPOWER overrides the 'org.freedesktop.UPower' default
9+
10+ - INDICATOR_POWER_BUS_ADDRESS_INDICATOR overrides the session bus default
11+ - INDICATOR_POWER_BUS_NAME_INDICATOR overrides the 'com.canonical.indicator.power' default
12+
13+ - INDICATOR_POWER_BUS_ADDRESS_POWERD overrides the system bus default
14+ - INDICATOR_POWER_BUS_NAME_POWERD overrides the 'com.canonical.powerd' default
15+
16
17=== modified file 'src/CMakeLists.txt'
18--- src/CMakeLists.txt 2014-10-14 19:09:32 +0000
19+++ src/CMakeLists.txt 2015-01-12 23:02:27 +0000
20@@ -6,6 +6,7 @@
21 # handwritten sources
22 set(SERVICE_MANUAL_SOURCES
23 brightness.c
24+ bus.c
25 device-provider-mock.c
26 device-provider-upower.c
27 device-provider.c
28
29=== modified file 'src/brightness.c'
30--- src/brightness.c 2014-09-12 16:37:02 +0000
31+++ src/brightness.c 2015-01-12 23:02:27 +0000
32@@ -18,6 +18,7 @@
33 */
34
35 #include "brightness.h"
36+#include "bus.h"
37
38 #include <gio/gio.h>
39
40@@ -40,11 +41,11 @@
41
42 typedef struct
43 {
44- GDBusConnection * system_bus;
45 GCancellable * cancellable;
46
47 GSettings * settings;
48
49+ GDBusConnection * bus;
50 guint powerd_name_tag;
51
52 double percentage;
53@@ -124,6 +125,8 @@
54 }
55 }
56
57+static void set_bus(IndicatorPowerBrightness * self, GDBusConnection * bus);
58+
59 static void
60 my_dispose(GObject * o)
61 {
62@@ -136,14 +139,9 @@
63 g_clear_object(&p->cancellable);
64 }
65
66- if (p->powerd_name_tag)
67- {
68- g_bus_unwatch_name(p->powerd_name_tag);
69- p->powerd_name_tag = 0;
70- }
71-
72 g_clear_object(&p->settings);
73- g_clear_object(&p->system_bus);
74+
75+ set_bus(self, NULL);
76
77 G_OBJECT_CLASS(indicator_power_brightness_parent_class)->dispose(o);
78 }
79@@ -269,8 +267,8 @@
80 {
81 priv_t * p = get_priv(self);
82
83- g_dbus_connection_call(p->system_bus,
84- "com.canonical.powerd",
85+ g_dbus_connection_call(p->bus,
86+ indicator_power_get_powerd_busname(),
87 "/com/canonical/powerd",
88 "com.canonical.powerd",
89 "getBrightnessParams",
90@@ -284,20 +282,13 @@
91 }
92
93 static void
94-on_powerd_appeared(GDBusConnection * connection,
95+on_powerd_appeared(GDBusConnection * bus G_GNUC_UNUSED,
96 const gchar * bus_name G_GNUC_UNUSED,
97 const gchar * name_owner G_GNUC_UNUSED,
98 gpointer gself)
99 {
100- IndicatorPowerBrightness * self = INDICATOR_POWER_BRIGHTNESS(gself);
101- priv_t * p = get_priv(self);
102-
103- /* keep a handle to the system bus */
104- g_clear_object(&p->system_bus);
105- p->system_bus = g_object_ref(connection);
106-
107 /* update our cache of powerd's brightness params */
108- call_powerd_get_brightness_params(self);
109+ call_powerd_get_brightness_params(gself);
110 }
111
112 static void
113@@ -319,7 +310,7 @@
114 /* setUserBrightness doesn't return anything,
115 so this function is just to check for bus error messages */
116 static void
117-on_set_uscreen_user_brightness_result(GObject * system_bus,
118+on_set_uscreen_user_brightness_result(GObject * bus,
119 GAsyncResult * res,
120 gpointer gself G_GNUC_UNUSED)
121 {
122@@ -327,7 +318,7 @@
123 GVariant * v;
124
125 error = NULL;
126- v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(system_bus), res, &error);
127+ v = g_dbus_connection_call_finish(G_DBUS_CONNECTION(bus), res, &error);
128 if (error != NULL)
129 {
130 if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
131@@ -345,8 +336,8 @@
132 {
133 priv_t * p = get_priv(self);
134
135- g_dbus_connection_call(p->system_bus,
136- "com.canonical.Unity.Screen",
137+ g_dbus_connection_call(p->bus,
138+ indicator_power_get_screen_busname(),
139 "/com/canonical/Unity/Screen",
140 "com.canonical.Unity.Screen",
141 "setUserBrightness",
142@@ -399,6 +390,58 @@
143 g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_AUTO]);
144 }
145
146+/***
147+****
148+***/
149+
150+static void
151+set_bus (IndicatorPowerBrightness * self, GDBusConnection * bus)
152+{
153+ priv_t * p = get_priv(self);
154+
155+ if (p->bus != NULL)
156+ {
157+ g_bus_unwatch_name(p->powerd_name_tag);
158+ p->powerd_name_tag = 0;
159+
160+ g_clear_object(&p->bus);
161+ }
162+
163+ if (bus != NULL)
164+ {
165+ p->bus = g_object_ref(bus);
166+
167+ p->powerd_name_tag = g_bus_watch_name_on_connection(p->bus,
168+ indicator_power_get_powerd_busname(),
169+ G_BUS_NAME_WATCHER_FLAGS_NONE,
170+ on_powerd_appeared,
171+ on_powerd_vanished,
172+ self,
173+ NULL);
174+ }
175+}
176+
177+static void
178+on_bus_ready (GObject * unused G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
179+{
180+ GDBusConnection * bus;
181+ GError * error = NULL;
182+
183+ bus = indicator_power_get_bus_finish(res, &error);
184+ if (error != NULL)
185+ {
186+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
187+ g_warning ("Error getting bus: %s", error->message);
188+
189+ g_error_free (error);
190+ }
191+ else
192+ {
193+ set_bus (INDICATOR_POWER_BRIGHTNESS(gself), bus);
194+ }
195+
196+ g_clear_object(&bus);
197+}
198
199 /***
200 **** Instantiation
201@@ -433,13 +476,11 @@
202 g_settings_schema_unref(schema);
203 }
204
205- p->powerd_name_tag = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
206- "com.canonical.powerd",
207- G_BUS_NAME_WATCHER_FLAGS_NONE,
208- on_powerd_appeared,
209- on_powerd_vanished,
210- self,
211- NULL);
212+ indicator_power_get_bus(g_getenv("INDICATOR_POWER_BUS_ADDRESS_POWERD"),
213+ G_BUS_TYPE_SYSTEM,
214+ p->cancellable,
215+ on_bus_ready,
216+ self);
217 }
218
219 static void
220
221=== added file 'src/bus.c'
222--- src/bus.c 1970-01-01 00:00:00 +0000
223+++ src/bus.c 2015-01-12 23:02:27 +0000
224@@ -0,0 +1,195 @@
225+/*
226+ * Copyright 2014 Canonical Ltd.
227+ *
228+ * This program is free software: you can redistribute it and/or modify it
229+ * under the terms of the GNU General Public License version 3, as published
230+ * by the Free Software Foundation.
231+ *
232+ * This program is distributed in the hope that it will be useful, but
233+ * WITHOUT ANY WARRANTY; without even the implied warranties of
234+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
235+ * PURPOSE. See the GNU General Public License for more details.
236+ *
237+ * You should have received a copy of the GNU General Public License along
238+ * with this program. If not, see <http://www.gnu.org/licenses/>.
239+ *
240+ * Authors:
241+ * Charles Kerr <charles.kerr@canonical.com>
242+ */
243+
244+#include "bus.h"
245+
246+typedef GDBusConnection* (*FinishFunc)(GAsyncResult*, GError**);
247+
248+struct bus_data
249+{
250+ char * address;
251+ FinishFunc finish_func;
252+ GSimpleAsyncResult * result;
253+};
254+
255+GDBusConnection*
256+indicator_power_get_bus_finish(GAsyncResult * result,
257+ GError ** error)
258+{
259+ GSimpleAsyncResult * simple;
260+ GDBusConnection * bus;
261+
262+ g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, NULL), NULL);
263+
264+ simple = (GSimpleAsyncResult *) result;
265+
266+ if (g_simple_async_result_propagate_error (simple, error))
267+ return NULL;
268+
269+ bus = G_DBUS_CONNECTION(g_simple_async_result_get_op_res_gpointer (simple));
270+ g_object_ref(bus);
271+ return bus;
272+}
273+
274+static void
275+on_bus_ready (GObject * unused G_GNUC_UNUSED, GAsyncResult * res, gpointer gdata)
276+{
277+ struct bus_data * data;
278+ GError * error = NULL;
279+ GDBusConnection * bus;
280+
281+ data = gdata;
282+ error = NULL;
283+ bus = data->finish_func(res, &error);
284+ if (error != NULL)
285+ {
286+ if ((data->address != NULL) && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
287+ g_simple_async_result_set_error (data->result, error->domain, error->code, "\"%s\" unreachable, %s", data->address, error->message);
288+ else
289+ g_simple_async_result_set_from_error (data->result, error);
290+
291+ g_error_free (error);
292+ }
293+
294+ if (bus != NULL)
295+ g_simple_async_result_set_op_res_gpointer(data->result, g_object_ref(bus), g_object_unref);
296+ g_simple_async_result_complete_in_idle(data->result);
297+
298+ g_object_unref(data->result);
299+ g_free(data->address);
300+ g_free(data);
301+}
302+
303+void indicator_power_get_bus(const char * address,
304+ GBusType bus_type,
305+ GCancellable * cancellable,
306+ GAsyncReadyCallback callback,
307+ gpointer user_data)
308+{
309+ GSimpleAsyncResult * result;
310+
311+ result = g_simple_async_result_new(NULL,
312+ callback,
313+ user_data,
314+ NULL);
315+ g_simple_async_result_set_check_cancellable(result, cancellable);
316+
317+
318+ struct bus_data * data = g_new0(struct bus_data, 1);
319+ data->result = result;
320+
321+ if ((address != NULL) && g_dbus_is_address(address))
322+ {
323+ g_debug("Getting bus for address '%s'", address);
324+ data->address = g_strdup(address);
325+ data->finish_func = g_dbus_connection_new_for_address_finish;
326+ g_dbus_connection_new_for_address(address,
327+ G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION|G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
328+ NULL /*GDBusAuthObserver*/,
329+ cancellable,
330+ on_bus_ready,
331+ data);
332+ }
333+ else
334+ {
335+ g_debug("Getting GBusType %d", (int)bus_type);
336+ data->finish_func = g_dbus_connection_new_for_address_finish;
337+ data->finish_func = g_bus_get_finish;
338+ g_bus_get(bus_type,
339+ cancellable,
340+ on_bus_ready,
341+ data);
342+ }
343+}
344+
345+/***
346+****
347+***/
348+
349+static const char*
350+get_name_from_env_with_fallback (const char * env, const char * fallback)
351+{
352+ const char * name = g_getenv(env);
353+
354+ if ((name == NULL) || !g_dbus_is_name(name))
355+ name = fallback;
356+
357+ return name;
358+}
359+
360+const char*
361+indicator_power_get_indicator_busname(void)
362+{
363+ static const char * name = NULL;
364+
365+ if (G_UNLIKELY(name == NULL))
366+ {
367+ name = get_name_from_env_with_fallback("INDICATOR_POWER_BUS_NAME_INDICATOR",
368+ "com.canonical.indicator.power");
369+ g_debug("%s indicator busname is \"%s\"", G_STRLOC, name);
370+ }
371+
372+ return name;
373+}
374+
375+const char*
376+indicator_power_get_upower_busname(void)
377+{
378+ static const char * name = NULL;
379+
380+ if (G_UNLIKELY(name == NULL))
381+ {
382+ name = get_name_from_env_with_fallback("INDICATOR_POWER_BUS_NAME_UPOWER",
383+ "org.freedesktop.UPower");
384+ g_debug("%s upower busname is \"%s\"", G_STRLOC, name);
385+ }
386+
387+ return name;
388+}
389+
390+const char*
391+indicator_power_get_powerd_busname(void)
392+{
393+ static const char * name = NULL;
394+
395+ if (G_UNLIKELY(name == NULL))
396+ {
397+ name = get_name_from_env_with_fallback("INDICATOR_POWER_BUS_NAME_POWERD",
398+ "com.canonical.powerd");
399+ g_debug("%s powerd busname is \"%s\"", G_STRLOC, name);
400+ }
401+
402+ return name;
403+}
404+
405+const char*
406+indicator_power_get_screen_busname(void)
407+{
408+ static const char * name = NULL;
409+
410+ if (G_UNLIKELY(name == NULL))
411+ {
412+ name = get_name_from_env_with_fallback("INDICATOR_POWER_BUS_NAME_SCREEN",
413+ "com.canonical.Unity.Screen");
414+ g_debug("%s screen busname is \"%s\"", G_STRLOC, name);
415+ }
416+
417+ return name;
418+}
419+
420
421=== added file 'src/bus.h'
422--- src/bus.h 1970-01-01 00:00:00 +0000
423+++ src/bus.h 2015-01-12 23:02:27 +0000
424@@ -0,0 +1,50 @@
425+/*
426+ * Copyright 2014 Canonical Ltd.
427+ *
428+ * This program is free software: you can redistribute it and/or modify it
429+ * under the terms of the GNU General Public License version 3, as published
430+ * by the Free Software Foundation.
431+ *
432+ * This program is distributed in the hope that it will be useful, but
433+ * WITHOUT ANY WARRANTY; without even the implied warranties of
434+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
435+ * PURPOSE. See the GNU General Public License for more details.
436+ *
437+ * You should have received a copy of the GNU General Public License along
438+ * with this program. If not, see <http://www.gnu.org/licenses/>.
439+ *
440+ * Authors:
441+ * Charles Kerr <charles.kerr@canonical.com>
442+ */
443+
444+#ifndef __INDICATOR_POWER_BUS_H__
445+#define __INDICATOR_POWER_BUS_H__
446+
447+#include <gio/gio.h>
448+
449+G_BEGIN_DECLS
450+
451+const char* indicator_power_get_indicator_busname (void);
452+const char* indicator_power_get_powerd_busname (void);
453+const char* indicator_power_get_screen_busname (void);
454+const char* indicator_power_get_upower_busname (void);
455+
456+/**
457+ * Asynchronously get a bus connection.
458+ *
459+ * If address_name is a valid address, it's used. Otherwise, the bus_type is retrieved.
460+ * This can be used to let a debug bus address override another address; e.g.
461+ * indicator_power_get_bus(g_getenv("INDICATOR_POWER_BUS_ADDRESS_UPOWER"), G_BUS_TYPE_SYSTEM, ...
462+ */
463+void indicator_power_get_bus (const char * address_name,
464+ GBusType bus_type,
465+ GCancellable * cancellable,
466+ GAsyncReadyCallback callback,
467+ gpointer user_data);
468+
469+GDBusConnection* indicator_power_get_bus_finish (GAsyncResult * result,
470+ GError ** error);
471+
472+G_END_DECLS
473+
474+#endif /* __INDICATOR_POWER_BUS_H__ */
475
476=== modified file 'src/device-provider-upower.c'
477--- src/device-provider-upower.c 2014-09-08 14:50:22 +0000
478+++ src/device-provider-upower.c 2015-01-12 23:02:27 +0000
479@@ -17,12 +17,11 @@
480 * with this program. If not, see <http://www.gnu.org/licenses/>.
481 */
482
483+#include "bus.h"
484 #include "device.h"
485 #include "device-provider.h"
486 #include "device-provider-upower.h"
487
488-#define BUS_NAME "org.freedesktop.UPower"
489-
490 #define MGR_IFACE "org.freedesktop.UPower"
491 #define MGR_PATH "/org/freedesktop/UPower"
492
493@@ -175,7 +174,7 @@
494 data->self = self;
495
496 g_dbus_connection_call(p->bus,
497- BUS_NAME,
498+ indicator_power_get_upower_busname(),
499 path,
500 "org.freedesktop.DBus.Properties",
501 "GetAll",
502@@ -409,7 +408,7 @@
503
504 /* start listening for UPower events on the bus */
505 static void
506-on_bus_name_appeared(GDBusConnection * bus,
507+on_bus_name_appeared(GDBusConnection * bus G_GNUC_UNUSED,
508 const gchar * name G_GNUC_UNUSED,
509 const gchar * name_owner,
510 gpointer gself)
511@@ -420,7 +419,6 @@
512
513 self = INDICATOR_POWER_DEVICE_PROVIDER_UPOWER(gself);
514 p = get_priv(self);
515- p->bus = G_DBUS_CONNECTION(g_object_ref(bus));
516
517 /* listen for signals from the boss */
518 tag = g_dbus_connection_signal_subscribe(p->bus,
519@@ -450,7 +448,7 @@
520
521 /* rebuild our devices list */
522 g_dbus_connection_call(p->bus,
523- BUS_NAME,
524+ indicator_power_get_upower_busname(),
525 MGR_PATH,
526 MGR_IFACE,
527 "EnumerateDevices",
528@@ -490,9 +488,6 @@
529 g_dbus_connection_signal_unsubscribe(p->bus, GPOINTER_TO_UINT(l->data));
530 g_slist_free(p->subscriptions);
531 p->subscriptions = NULL;
532-
533- /* clear the bus */
534- g_clear_object(&p->bus);
535 }
536
537 /***
538@@ -518,6 +513,8 @@
539 **** GObject virtual functions
540 ***/
541
542+static void set_bus (IndicatorPowerDeviceProviderUPower * self, GDBusConnection * connection);
543+
544 static void
545 my_dispose (GObject * o)
546 {
547@@ -541,13 +538,7 @@
548 p->queued_paths_timer = 0;
549 }
550
551- if (p->name_tag != 0)
552- {
553- g_bus_unwatch_name(p->name_tag);
554- on_bus_name_vanished(NULL, NULL, self);
555-
556- p->name_tag = 0;
557- }
558+ set_bus (self, NULL);
559
560 G_OBJECT_CLASS (indicator_power_device_provider_upower_parent_class)->dispose(o);
561 }
562@@ -568,6 +559,61 @@
563 }
564
565 /***
566+**** Bus
567+***/
568+
569+static void
570+set_bus (IndicatorPowerDeviceProviderUPower * self, GDBusConnection * bus)
571+{
572+ priv_t * p = get_priv(self);
573+
574+ if (p->bus != NULL)
575+ {
576+ g_bus_unwatch_name(p->name_tag);
577+ on_bus_name_vanished(NULL, NULL, self);
578+ p->name_tag = 0;
579+
580+ g_clear_object(&p->bus);
581+ }
582+
583+ if (bus != NULL)
584+ {
585+ p->bus = g_object_ref(bus);
586+ g_debug("%s: using bus '%s'", G_STRFUNC, g_dbus_connection_get_unique_name(bus));
587+
588+ p->name_tag = g_bus_watch_name_on_connection(p->bus,
589+ indicator_power_get_upower_busname(),
590+ G_BUS_NAME_WATCHER_FLAGS_NONE,
591+ on_bus_name_appeared,
592+ on_bus_name_vanished,
593+ self,
594+ NULL);
595+ }
596+}
597+
598+static void
599+on_bus_ready (GObject * unused G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
600+{
601+ GDBusConnection * bus;
602+ GError * error = NULL;
603+
604+ bus = indicator_power_get_bus_finish(res, &error);
605+ if (error != NULL)
606+ {
607+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
608+ g_warning ("Error getting bus: %s", error->message);
609+
610+ g_error_free (error);
611+ }
612+ else
613+ {
614+ set_bus (INDICATOR_POWER_DEVICE_PROVIDER_UPOWER(gself), bus);
615+ }
616+
617+ g_clear_object(&bus);
618+}
619+
620+/***
621 **** Instantiation
622 ***/
623
624@@ -603,13 +649,11 @@
625 g_free,
626 NULL);
627
628- p->name_tag = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
629- BUS_NAME,
630- G_BUS_NAME_WATCHER_FLAGS_NONE,
631- on_bus_name_appeared,
632- on_bus_name_vanished,
633- self,
634- NULL);
635+ indicator_power_get_bus(g_getenv("INDICATOR_POWER_BUS_ADDRESS_UPOWER"),
636+ G_BUS_TYPE_SYSTEM,
637+ p->cancellable,
638+ on_bus_ready,
639+ self);
640 }
641
642 /***
643
644=== modified file 'src/service.c'
645--- src/service.c 2014-10-14 19:07:50 +0000
646+++ src/service.c 2015-01-12 23:02:27 +0000
647@@ -22,6 +22,7 @@
648 #include <gio/gio.h>
649 #include <url-dispatcher.h>
650
651+#include "bus.h"
652 #include "brightness.h"
653 #include "dbus-shared.h"
654 #include "device.h"
655@@ -29,7 +30,6 @@
656 #include "notifier.h"
657 #include "service.h"
658
659-#define BUS_NAME "com.canonical.indicator.power"
660 #define BUS_PATH "/com/canonical/indicator/power"
661
662 #define SETTINGS_SHOW_TIME_S "show-time"
663@@ -108,7 +108,7 @@
664
665 guint own_id;
666 guint actions_export_id;
667- GDBusConnection * conn;
668+ GDBusConnection * bus;
669
670 struct ProfileMenuInfo menus[N_PROFILES];
671
672@@ -581,7 +581,7 @@
673 g_simple_action_set_state (p->header_action, create_header_state (self));
674 }
675
676- if (p->conn == NULL) /* we haven't built the menus yet */
677+ if (p->bus == NULL) /* we haven't built the menus yet */
678 return;
679
680 if (sections & SECTION_DEVICES)
681@@ -822,108 +822,6 @@
682 }
683
684 /***
685-**** GDBus Name Ownership & Menu / Action Exporting
686-***/
687-
688-static void
689-on_bus_acquired (GDBusConnection * connection,
690- const gchar * name,
691- gpointer gself)
692-{
693- int i;
694- guint id;
695- GError * err = NULL;
696- IndicatorPowerService * self = INDICATOR_POWER_SERVICE(gself);
697- priv_t * p = self->priv;
698- GString * path = g_string_new (NULL);
699-
700- g_debug ("bus acquired: %s", name);
701-
702- p->conn = g_object_ref (G_OBJECT (connection));
703- g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_BUS]);
704-
705- /* export the battery properties */
706- indicator_power_notifier_set_bus (p->notifier, connection);
707-
708- /* export the actions */
709- if ((id = g_dbus_connection_export_action_group (connection,
710- BUS_PATH,
711- G_ACTION_GROUP (p->actions),
712- &err)))
713- {
714- p->actions_export_id = id;
715- }
716- else
717- {
718- g_warning ("cannot export action group: %s", err->message);
719- g_clear_error (&err);
720- }
721-
722- /* export the menus */
723- for (i=0; i<N_PROFILES; ++i)
724- {
725- struct ProfileMenuInfo * menu = &p->menus[i];
726-
727- g_string_printf (path, "%s/%s", BUS_PATH, menu_names[i]);
728-
729- if ((id = g_dbus_connection_export_menu_model (connection,
730- path->str,
731- G_MENU_MODEL (menu->menu),
732- &err)))
733- {
734- menu->export_id = id;
735- }
736- else
737- {
738- g_warning ("cannot export %s menu: %s", path->str, err->message);
739- g_clear_error (&err);
740- }
741- }
742-
743- g_string_free (path, TRUE);
744-}
745-
746-static void
747-unexport (IndicatorPowerService * self)
748-{
749- int i;
750- priv_t * p = self->priv;
751-
752- /* unexport the menus */
753- for (i=0; i<N_PROFILES; ++i)
754- {
755- guint * id = &self->priv->menus[i].export_id;
756-
757- if (*id)
758- {
759- g_dbus_connection_unexport_menu_model (p->conn, *id);
760- *id = 0;
761- }
762- }
763-
764- /* unexport the actions */
765- if (p->actions_export_id)
766- {
767- g_dbus_connection_unexport_action_group (p->conn, p->actions_export_id);
768- p->actions_export_id = 0;
769- }
770-}
771-
772-static void
773-on_name_lost (GDBusConnection * connection G_GNUC_UNUSED,
774- const gchar * name,
775- gpointer gself)
776-{
777- IndicatorPowerService * self = INDICATOR_POWER_SERVICE (gself);
778-
779- g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, name);
780-
781- unexport (self);
782-
783- g_signal_emit (self, signals[SIGNAL_NAME_LOST], 0, NULL);
784-}
785-
786-/***
787 **** Events
788 ***/
789
790@@ -980,7 +878,7 @@
791 switch (property_id)
792 {
793 case PROP_BUS:
794- g_value_set_object (value, p->conn);
795+ g_value_set_object (value, p->bus);
796 break;
797
798 case PROP_DEVICE_PROVIDER:
799@@ -1011,19 +909,15 @@
800 }
801 }
802
803+static void set_bus (IndicatorPowerService*, GDBusConnection*);
804+
805 static void
806 my_dispose (GObject * o)
807 {
808 IndicatorPowerService * self = INDICATOR_POWER_SERVICE(o);
809 priv_t * p = self->priv;
810
811- if (p->own_id)
812- {
813- g_bus_unown_name (p->own_id);
814- p->own_id = 0;
815- }
816-
817- unexport (self);
818+ set_bus(self, NULL);
819
820 if (p->cancellable != NULL)
821 {
822@@ -1045,14 +939,161 @@
823 g_clear_object (&p->header_action);
824 g_clear_object (&p->actions);
825
826- g_clear_object (&p->conn);
827-
828 indicator_power_service_set_device_provider (self, NULL);
829
830 G_OBJECT_CLASS (indicator_power_service_parent_class)->dispose (o);
831 }
832
833 /***
834+****
835+***/
836+
837+static void
838+unexport (IndicatorPowerService * self)
839+{
840+ int i;
841+ priv_t * p = self->priv;
842+
843+ /* unexport the menus */
844+ for (i=0; i<N_PROFILES; ++i)
845+ {
846+ guint * id = &self->priv->menus[i].export_id;
847+
848+ if (*id)
849+ {
850+ g_dbus_connection_unexport_menu_model (p->bus, *id);
851+ *id = 0;
852+ }
853+ }
854+
855+ /* unexport the actions */
856+ if (p->actions_export_id)
857+ {
858+ g_dbus_connection_unexport_action_group (p->bus, p->actions_export_id);
859+ p->actions_export_id = 0;
860+ }
861+}
862+
863+static void
864+on_name_lost (GDBusConnection * connection G_GNUC_UNUSED,
865+ const gchar * name,
866+ gpointer gself)
867+{
868+ IndicatorPowerService * self = INDICATOR_POWER_SERVICE (gself);
869+
870+ g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, name);
871+
872+ unexport (self);
873+
874+ g_signal_emit (self, signals[SIGNAL_NAME_LOST], 0, NULL);
875+}
876+
877+static void
878+export (IndicatorPowerService * self)
879+{
880+ priv_t * p = self->priv;
881+ GString * path = g_string_new(NULL);
882+ GError * error;
883+ guint id;
884+ int i;
885+
886+ p->own_id = g_bus_own_name_on_connection(p->bus,
887+ indicator_power_get_indicator_busname(),
888+ G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
889+ NULL,
890+ on_name_lost,
891+ self,
892+ NULL);
893+
894+ /* export the battery properties */
895+ indicator_power_notifier_set_bus(p->notifier, p->bus);
896+
897+ /* export the actions */
898+ error = NULL;
899+ if ((id = g_dbus_connection_export_action_group(p->bus,
900+ BUS_PATH,
901+ G_ACTION_GROUP(p->actions),
902+ &error)))
903+ {
904+ p->actions_export_id = id;
905+ }
906+ else
907+ {
908+ g_warning("cannot export action group: %s", error->message);
909+ g_clear_error(&error);
910+ }
911+
912+ /* export the menus */
913+ for (i=0; i<N_PROFILES; ++i)
914+ {
915+ struct ProfileMenuInfo * menu = &p->menus[i];
916+
917+ g_string_printf (path, "%s/%s", BUS_PATH, menu_names[i]);
918+
919+ if ((id = g_dbus_connection_export_menu_model(p->bus,
920+ path->str,
921+ G_MENU_MODEL (menu->menu),
922+ &error)))
923+ {
924+ menu->export_id = id;
925+ }
926+ else
927+ {
928+ g_warning("cannot export %s menu: %s", path->str, error->message);
929+ g_clear_error(&error);
930+ }
931+ }
932+
933+ g_string_free (path, TRUE);
934+}
935+
936+static void
937+set_bus (IndicatorPowerService * self, GDBusConnection * bus)
938+{
939+ priv_t * p = self->priv;
940+
941+ if (p->bus != NULL)
942+ {
943+ unexport (self);
944+
945+ g_bus_unown_name (p->own_id);
946+ p->own_id = 0;
947+
948+ g_clear_object(&p->bus);
949+ }
950+
951+ if (bus != NULL)
952+ {
953+ p->bus = g_object_ref(bus);
954+ g_object_notify_by_pspec(G_OBJECT(self), properties[PROP_BUS]);
955+
956+ export(self);
957+ }
958+}
959+
960+static void
961+on_bus_ready (GObject * unused G_GNUC_UNUSED, GAsyncResult * res, gpointer gself)
962+{
963+ GDBusConnection * bus;
964+ GError * error = NULL;
965+
966+ bus = indicator_power_get_bus_finish(res, &error);
967+ if (error != NULL)
968+ {
969+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
970+ g_warning ("Error getting indicator bus: %s", error->message);
971+
972+ g_error_free (error);
973+ }
974+ else
975+ {
976+ set_bus (INDICATOR_POWER_SERVICE(gself), bus);
977+ }
978+
979+ g_clear_object(&bus);
980+}
981+
982+/***
983 **** Instantiation
984 ***/
985
986@@ -1087,14 +1128,11 @@
987 g_signal_connect_swapped(p->brightness, "notify::auto-brightness-supported",
988 G_CALLBACK(on_auto_brightness_supported_changed), self);
989
990- p->own_id = g_bus_own_name(G_BUS_TYPE_SESSION,
991- BUS_NAME,
992- G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
993- on_bus_acquired,
994- NULL,
995- on_name_lost,
996- self,
997- NULL);
998+ indicator_power_get_bus(g_getenv("INDICATOR_POWER_BUS_ADDRESS_INDICATOR"),
999+ G_BUS_TYPE_SESSION,
1000+ p->cancellable,
1001+ on_bus_ready,
1002+ self);
1003 }
1004
1005 static void

Subscribers

People subscribed via source and target branches