Merge lp:~desrt/indicator-appmenu/hud-rewrite-wip into lp:indicator-appmenu/0.4

Proposed by Allison Karlitskaya
Status: Merged
Merged at revision: 175
Proposed branch: lp:~desrt/indicator-appmenu/hud-rewrite-wip
Merge into: lp:indicator-appmenu/0.4
Diff against target: 312 lines (+75/-96)
5 files modified
src/hud-service.c (+29/-67)
src/huditem.c (+44/-0)
src/huditem.h (+2/-0)
src/hudquery.c (+0/-27)
src/hudquery.h (+0/-2)
To merge this branch: bzr merge lp:~desrt/indicator-appmenu/hud-rewrite-wip
Reviewer Review Type Date Requested Status
Indicator Applet Developers Pending
Review via email: mp+96476@code.launchpad.net

Description of the change

Switch to identifying items by unique identifier rather than their index in a possibly-changing list of results.

This should improve the reliability of item activation.

To post a comment you must log in.
Revision history for this message
Charles Kerr (charlesk) wrote :

I haven't been following hud enough to review the 'why' of this patch, but the 'how' looks fine except for item_key, which can be leaked iff its type isn't uint64

205. By Allison Karlitskaya

hud service: don't leak item key in case of type error

Caught by Charles Kerr.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/hud-service.c'
2--- src/hud-service.c 2012-03-05 04:46:53 +0000
3+++ src/hud-service.c 2012-03-08 17:50:26 +0000
4@@ -36,13 +36,9 @@
5 describe_query (HudQuery *query)
6 {
7 GVariantBuilder builder;
8- GVariant *query_key;
9- guint64 generation;
10 gint n, i;
11
12- generation = hud_query_get_generation (query);
13 n = hud_query_get_n_results (query);
14- query_key = hud_query_get_query_key (query);
15
16 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sa(sssssv)v)"));
17
18@@ -63,12 +59,12 @@
19 hud_item_get_app_icon (item),
20 hud_item_get_item_icon (item),
21 "" /* complete text */ , "" /* accel */,
22- g_variant_new ("(vtu)", query_key, generation, i));
23+ g_variant_new_uint64 (hud_item_get_id (item)));
24 }
25 g_variant_builder_close (&builder);
26
27 /* Query key */
28- g_variant_builder_add (&builder, "v", query_key);
29+ g_variant_builder_add (&builder, "v", hud_query_get_query_key (query));
30
31 return g_variant_builder_end (&builder);
32 }
33@@ -84,25 +80,6 @@
34 describe_query (query), NULL);
35 }
36
37-static gboolean
38-unpack_key (GVariant *parameters,
39- GVariant **query_key,
40- guint64 *generation,
41- guint *i)
42-{
43- gboolean success;
44- GVariant *key;
45-
46- g_variant_get_child (parameters, 0, "v", &key);
47-
48- if ((success = g_variant_is_of_type (key, G_VARIANT_TYPE ("(vtu)"))))
49- g_variant_get (key, "(vtu)", query_key, generation, i);
50-
51- g_variant_unref (key);
52-
53- return success;
54-}
55-
56 static GVariant *
57 unpack_platform_data (GVariant *parameters)
58 {
59@@ -145,48 +122,33 @@
60
61 else if (g_str_equal (method_name, "ExecuteQuery"))
62 {
63- GVariant *query_key;
64- guint64 generation;
65- HudQuery *query;
66- guint i;
67-
68- /* FIXME: ExecuteQuery DBus API should be changed to make this less awkward. */
69- if (!unpack_key (parameters, &query_key, &generation, &i))
70- {
71- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
72- "query key has invalid format");
73- return;
74- }
75-
76- query = hud_query_lookup (query_key);
77- g_variant_unref (query_key);
78-
79- if (query == NULL)
80- {
81- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
82- "query specified by query key does not exist");
83- return;
84- }
85-
86- if (generation != hud_query_get_generation (query))
87- {
88- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
89- "query specified by query key has changed (%lu v %lu)",
90- generation, hud_query_get_generation (query));
91- return;
92- }
93-
94- if (i < hud_query_get_n_results (query))
95- {
96- GVariant *platform_data;
97- HudResult *result;
98-
99- result = hud_query_get_result_by_index (query, i);
100-
101- platform_data = unpack_platform_data (parameters);
102- hud_item_activate (hud_result_get_item (result), platform_data);
103- g_variant_unref (platform_data);
104- }
105+ GVariant *platform_data;
106+ GVariant *item_key;
107+ HudItem *item;
108+
109+ g_variant_get_child (parameters, 0, "v", &item_key);
110+
111+ if (!g_variant_is_of_type (item_key, G_VARIANT_TYPE_UINT64))
112+ {
113+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
114+ "item key has invalid format");
115+ g_variant_unref (item_key);
116+ return;
117+ }
118+
119+ item = hud_item_lookup (g_variant_get_uint64 (item_key));
120+ g_variant_unref (item_key);
121+
122+ if (item == NULL)
123+ {
124+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
125+ "item specified by item key does not exist");
126+ return;
127+ }
128+
129+ platform_data = unpack_platform_data (parameters);
130+ hud_item_activate (item, platform_data);
131+ g_variant_unref (platform_data);
132
133 g_dbus_method_invocation_return_value (invocation, NULL);
134 }
135
136=== modified file 'src/huditem.c'
137--- src/huditem.c 2012-03-07 04:11:28 +0000
138+++ src/huditem.c 2012-03-08 17:50:26 +0000
139@@ -43,6 +43,9 @@
140 * This is the class vtable for #HudItem.
141 **/
142
143+static GHashTable *hud_item_table;
144+static guint64 hud_item_next_id;
145+
146 struct _HudItemPrivate
147 {
148 GObject parent_instance;
149@@ -52,6 +55,7 @@
150 HudStringList *tokens;
151 gboolean enabled;
152 guint usage;
153+ guint64 id;
154 };
155
156 G_DEFINE_TYPE (HudItem, hud_item, G_TYPE_OBJECT)
157@@ -61,6 +65,7 @@
158 {
159 HudItem *item = HUD_ITEM (object);
160
161+ g_hash_table_remove (hud_item_table, &item->priv->id);
162 hud_string_list_unref (item->priv->tokens);
163 g_free (item->priv->desktop_file);
164
165@@ -79,6 +84,8 @@
166 {
167 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
168
169+ hud_item_table = g_hash_table_new (g_int64_hash, g_int64_equal);
170+
171 gobject_class->finalize = hud_item_finalize;
172
173 g_type_class_add_private (class, sizeof (HudItemPrivate));
174@@ -110,6 +117,9 @@
175 item->priv->tokens = hud_string_list_ref (tokens);
176 item->priv->desktop_file = g_strdup (desktop_file);
177 item->priv->enabled = enabled;
178+ item->priv->id = hud_item_next_id++;
179+
180+ g_hash_table_insert (hud_item_table, &item->priv->id, item);
181
182 //item->usage = usage_tracker_get_usage (usage_tracker_get_instance (), desktop_file, identifier);
183
184@@ -241,3 +251,37 @@
185 {
186 return item->priv->enabled;
187 }
188+
189+/**
190+ * hud_item_get_id:
191+ * @item: a #HudItem
192+ *
193+ * Gets the unique identifier of this #HudItem.
194+ *
195+ * The identifier can be used to refetch the item using
196+ * hud_item_lookup() for as long as the item has not been destroyed.
197+ *
198+ * Returns: the ID of the item
199+ **/
200+guint64
201+hud_item_get_id (HudItem *item)
202+{
203+ return item->priv->id;
204+}
205+
206+/**
207+ * hud_item_lookup:
208+ * @id: an item identifier
209+ *
210+ * Looks up a #HudItem by its ID.
211+ *
212+ * The ID for a #HudItem can be queried with hud_item_get_id().
213+ *
214+ * Returns: (transfer none): the #HudItem with the given @id, or %NULL
215+ * if none exists
216+ **/
217+HudItem *
218+hud_item_lookup (guint64 id)
219+{
220+ return g_hash_table_lookup (hud_item_table, &id);
221+}
222
223=== modified file 'src/huditem.h'
224--- src/huditem.h 2012-03-04 16:08:53 +0000
225+++ src/huditem.h 2012-03-08 17:50:26 +0000
226@@ -70,5 +70,7 @@
227 const gchar * hud_item_get_item_icon (HudItem *item);
228 guint hud_item_get_usage (HudItem *item);
229 gboolean hud_item_get_enabled (HudItem *item);
230+guint64 hud_item_get_id (HudItem *item);
231+HudItem * hud_item_lookup (guint64 id);
232
233 #endif /* __HUD_ITEM_H__ */
234
235=== modified file 'src/hudquery.c'
236--- src/hudquery.c 2012-03-01 04:44:19 +0000
237+++ src/hudquery.c 2012-03-08 17:50:26 +0000
238@@ -35,10 +35,6 @@
239 * The query maintains a list of results from the search which are
240 * sorted by relevance and accessible by index. Contrast this with the
241 * stateless nature of #HudSource.
242- *
243- * The query has a "generation" counter that is bumped each time the
244- * results list changes. This can be used to guard against stale
245- * index-based references to specific search results.
246 **/
247
248 /**
249@@ -56,7 +52,6 @@
250 gint num_results;
251 guint refresh_id;
252
253- guint64 generation;
254 GPtrArray *results;
255 };
256
257@@ -105,7 +100,6 @@
258 guint max_usage = 0;
259
260 g_ptr_array_set_size (query->results, 0);
261- query->generation++;
262
263 if (query->search_string[0] != '\0')
264 hud_source_search (query->source, query->results, query->search_string);
265@@ -173,9 +167,6 @@
266 * @query: a #HudQuery
267 *
268 * Indicates that the results of @query have changed.
269- *
270- * The generation counter is increased each time this signal fires.
271- * See hud_query_get_generation().
272 **/
273 hud_query_changed_signal = g_signal_new ("changed", HUD_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, NULL,
274 NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
275@@ -282,24 +273,6 @@
276 }
277
278 /**
279- * hud_query_get_generation:
280- * @query: a #HudQuery
281- *
282- * Gets the current value of the generation counter for query.
283- *
284- * The generation counter is incremented each time the #HudQuery emits a
285- * the ::changed signal. Its purpose is to guard against stale
286- * index-based references to results of the query.
287- *
288- * Returns: the generation number
289- **/
290-guint64
291-hud_query_get_generation (HudQuery *query)
292-{
293- return query->generation;
294-}
295-
296-/**
297 * hud_query_get_n_results:
298 * @query: a #HudQuery
299 *
300
301=== modified file 'src/hudquery.h'
302--- src/hudquery.h 2012-02-28 18:29:03 +0000
303+++ src/hudquery.h 2012-03-08 17:50:26 +0000
304@@ -36,8 +36,6 @@
305 const gchar *search_string,
306 gint num_results);
307
308-guint64 hud_query_get_generation (HudQuery *query);
309-
310 GVariant * hud_query_get_query_key (HudQuery *query);
311
312 HudResult * hud_query_get_result_by_index (HudQuery *query,

Subscribers

People subscribed via source and target branches