1 /*
2 * plugins-manager: Single-instance managing plugins
3 *
4 * Copyright 2012-2020 Stephan Haller <nomad@froevel.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 *
21 *
22 */
23
24 /**
25 * SECTION:plugins-manager
26 * @short_description: The plugin manager class
27 * @include: xfdashboard/plugins-manager.h
28 *
29 * #XfdashboardPluginsManager is a single instance object. It is managing all
30 * plugins by loading and enabling or disabling them.
31 *
32 * The plugin manager will look up each plugin at the following paths and order:
33 *
34 * - Paths specified in environment variable XFDASHBOARD_PLUGINS_PATH (colon-seperated list)
35 * - $XDG_DATA_HOME/xfdashboard/plugins
36 * - (install prefix)/lib/xfdashboard/plugins
37 */
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include <libxfdashboard/plugins-manager.h>
44
45 #include <glib/gi18n-lib.h>
46
47 #include <libxfdashboard/plugin.h>
48 #include <libxfdashboard/application.h>
49 #include <libxfdashboard/compat.h>
50 #include <libxfdashboard/debug.h>
51
52
53 /* Define this class in GObject system */
54 struct _XfdashboardPluginsManagerPrivate
55 {
56 /* Instance related */
57 gboolean isInited;
58 GList *searchPaths;
59 GList *plugins;
60
61 XfconfChannel *xfconfChannel;
62
63 XfdashboardApplication *application;
64 guint applicationInitializedSignalID;
65 };
66
67 G_DEFINE_TYPE_WITH_PRIVATE(XfdashboardPluginsManager,
68 xfdashboard_plugins_manager,
69 G_TYPE_OBJECT)
70
71 /* IMPLEMENTATION: Private variables and methods */
72 #define ENABLED_PLUGINS_XFCONF_PROP "/enabled-plugins"
73
74 /* Single instance of plugin manager */
75 static XfdashboardPluginsManager* _xfdashboard_plugins_manager=NULL;
76
77 /* Add path to search path but avoid duplicates */
_xfdashboard_plugins_manager_add_search_path(XfdashboardPluginsManager * self,const gchar * inPath)78 static gboolean _xfdashboard_plugins_manager_add_search_path(XfdashboardPluginsManager *self,
79 const gchar *inPath)
80 {
81 XfdashboardPluginsManagerPrivate *priv;
82 gchar *normalizedPath;
83 GList *iter;
84 gchar *iterPath;
85
86 g_return_val_if_fail(XFDASHBOARD_IS_PLUGINS_MANAGER(self), FALSE);
87 g_return_val_if_fail(inPath && *inPath, FALSE);
88
89 priv=self->priv;
90
91 /* Normalize requested path to add to list of search paths that means
92 * that it should end with a directory seperator.
93 */
94 if(!g_str_has_suffix(inPath, G_DIR_SEPARATOR_S))
95 {
96 normalizedPath=g_strjoin(NULL, inPath, G_DIR_SEPARATOR_S, NULL);
97 }
98 else normalizedPath=g_strdup(inPath);
99
100 /* Check if path is already in list of search paths */
101 for(iter=priv->searchPaths; iter; iter=g_list_next(iter))
102 {
103 /* Get search path at iterator */
104 iterPath=(gchar*)iter->data;
105
106 /* If the path at iterator matches the requested one that it is
107 * already in list of search path, so return here with fail result.
108 */
109 if(g_strcmp0(iterPath, normalizedPath)==0)
110 {
111 XFDASHBOARD_DEBUG(self, PLUGINS,
112 "Path '%s' was already added to search paths of plugin manager",
113 normalizedPath);
114
115 /* Release allocated resources */
116 if(normalizedPath) g_free(normalizedPath);
117
118 /* Return fail result */
119 return(FALSE);
120 }
121 }
122
123 /* If we get here the requested path is not in list of search path and
124 * we can add it now.
125 */
126 priv->searchPaths=g_list_append(priv->searchPaths, g_strdup(normalizedPath));
127 XFDASHBOARD_DEBUG(self, PLUGINS,
128 "Added path '%s' to search paths of plugin manager",
129 normalizedPath);
130
131 /* Release allocated resources */
132 if(normalizedPath) g_free(normalizedPath);
133
134 /* Return success result */
135 return(TRUE);
136 }
137
138 /* Find path to plugin */
_xfdashboard_plugins_manager_find_plugin_path(XfdashboardPluginsManager * self,const gchar * inPluginName)139 static gchar* _xfdashboard_plugins_manager_find_plugin_path(XfdashboardPluginsManager *self,
140 const gchar *inPluginName)
141 {
142 XfdashboardPluginsManagerPrivate *priv;
143 gchar *path;
144 GList *iter;
145 gchar *iterPath;
146
147 g_return_val_if_fail(XFDASHBOARD_IS_PLUGINS_MANAGER(self), NULL);
148 g_return_val_if_fail(inPluginName && *inPluginName, NULL);
149
150 priv=self->priv;
151
152 /* Iterate through list of search paths, lookup file name containing plugin name
153 * followed by suffix ".so" and return first path found.
154 */
155 for(iter=priv->searchPaths; iter; iter=g_list_next(iter))
156 {
157 /* Get search path at iterator */
158 iterPath=(gchar*)iter->data;
159
160 /* Create full path of search path and plugin name */
161 path=g_strdup_printf("%s%s%s.%s", iterPath, G_DIR_SEPARATOR_S, inPluginName, G_MODULE_SUFFIX);
162 if(!path) continue;
163
164 XFDASHBOARD_DEBUG(self, PLUGINS,
165 "Trying path %s for plugin '%s'",
166 path,
167 inPluginName);
168
169 /* Check if file exists and return it if we does */
170 if(g_file_test(path, G_FILE_TEST_IS_REGULAR))
171 {
172 XFDASHBOARD_DEBUG(self, PLUGINS,
173 "Found path %s for plugin '%s'",
174 path,
175 inPluginName);
176 return(path);
177 }
178
179 /* Release allocated resources */
180 if(path) g_free(path);
181 }
182
183 /* If we get here we did not found any suitable file, so return NULL */
184 XFDASHBOARD_DEBUG(self, PLUGINS,
185 "Plugin '%s' not found in search paths",
186 inPluginName);
187 return(NULL);
188 }
189
190 /* Find plugin with requested ID */
_xfdashboard_plugins_manager_find_plugin_by_id(XfdashboardPluginsManager * self,const gchar * inPluginID)191 static XfdashboardPlugin* _xfdashboard_plugins_manager_find_plugin_by_id(XfdashboardPluginsManager *self,
192 const gchar *inPluginID)
193 {
194 XfdashboardPluginsManagerPrivate *priv;
195 XfdashboardPlugin *plugin;
196 const gchar *pluginID;
197 GList *iter;
198
199 g_return_val_if_fail(XFDASHBOARD_IS_PLUGINS_MANAGER(self), NULL);
200 g_return_val_if_fail(inPluginID && *inPluginID, NULL);
201
202 priv=self->priv;
203
204 /* Iterate through list of loaded plugins and return the plugin
205 * with requested ID.
206 */
207 for(iter=priv->plugins; iter; iter=g_list_next(iter))
208 {
209 /* Get currently iterated plugin */
210 plugin=XFDASHBOARD_PLUGIN(iter->data);
211
212 /* Get plugin ID */
213 pluginID=xfdashboard_plugin_get_id(plugin);
214
215 /* Check if plugin has requested ID then return it */
216 if(g_strcmp0(pluginID, inPluginID)==0) return(plugin);
217 }
218
219 /* If we get here the plugin with requested ID was not in the list of
220 * loaded plugins, so return NULL.
221 */
222 return(NULL);
223 }
224
225 /* Checks if a plugin with requested ID exists */
_xfdashboard_plugins_manager_has_plugin_id(XfdashboardPluginsManager * self,const gchar * inPluginID)226 static gboolean _xfdashboard_plugins_manager_has_plugin_id(XfdashboardPluginsManager *self,
227 const gchar *inPluginID)
228 {
229 XfdashboardPlugin *plugin;
230
231 g_return_val_if_fail(XFDASHBOARD_IS_PLUGINS_MANAGER(self), FALSE);
232 g_return_val_if_fail(inPluginID && *inPluginID, FALSE);
233
234 /* Get plugin by requested ID. If NULL is returned the plugin does not exist */
235 plugin=_xfdashboard_plugins_manager_find_plugin_by_id(self, inPluginID);
236 if(!plugin) return(FALSE);
237
238 /* If we get here the plugin was found */
239 return(TRUE);
240 }
241
242 /* Try to load plugin */
_xfdashboard_plugins_manager_load_plugin(XfdashboardPluginsManager * self,const gchar * inPluginID,GError ** outError)243 static gboolean _xfdashboard_plugins_manager_load_plugin(XfdashboardPluginsManager *self,
244 const gchar *inPluginID,
245 GError **outError)
246 {
247 XfdashboardPluginsManagerPrivate *priv;
248 gchar *path;
249 XfdashboardPlugin *plugin;
250 GError *error;
251
252 g_return_val_if_fail(XFDASHBOARD_IS_PLUGINS_MANAGER(self), FALSE);
253 g_return_val_if_fail(inPluginID && *inPluginID, FALSE);
254 g_return_val_if_fail(outError==NULL || *outError==NULL, FALSE);
255
256 priv=self->priv;
257 error=NULL;
258
259 /* Check if plugin with requested ID exists already in list of loaded plugins */
260 if(_xfdashboard_plugins_manager_has_plugin_id(self, inPluginID))
261 {
262 XFDASHBOARD_DEBUG(self, PLUGINS,
263 "Plugin ID '%s' already loaded.",
264 inPluginID);
265
266 /* The plugin is already loaded so return success result */
267 return(TRUE);
268 }
269
270 /* Find path to plugin */
271 path=_xfdashboard_plugins_manager_find_plugin_path(self, inPluginID);
272 if(!path)
273 {
274 /* Set error */
275 g_set_error(outError,
276 XFDASHBOARD_PLUGIN_ERROR,
277 XFDASHBOARD_PLUGIN_ERROR_ERROR,
278 "Could not find module for plugin ID '%s'",
279 inPluginID);
280
281 /* Return error */
282 return(FALSE);
283 }
284
285 /* Create and load plugin */
286 plugin=xfdashboard_plugin_new(path, &error);
287 if(!plugin)
288 {
289 /* Propagate error */
290 g_propagate_error(outError, error);
291
292 /* Return error */
293 return(FALSE);
294 }
295
296 /* Enable plugin if early initialization is requested by plugin */
297 if(xfdashboard_plugin_get_flags(plugin) & XFDASHBOARD_PLUGIN_FLAG_EARLY_INITIALIZATION)
298 {
299 XFDASHBOARD_DEBUG(self, PLUGINS,
300 "Enabling plugin '%s' on load because early initialization was requested",
301 inPluginID);
302 xfdashboard_plugin_enable(plugin);
303 }
304
305 /* Store enabled plugin in list of enabled plugins */
306 priv->plugins=g_list_prepend(priv->plugins, plugin);
307
308 /* Plugin loaded so return success result */
309 return(TRUE);
310 }
311
312 /* Property for list of enabled plugins in xfconf has changed */
_xfdashboard_plugins_manager_on_enabled_plugins_changed(XfdashboardPluginsManager * self,const gchar * inProperty,const GValue * inValue,gpointer inUserData)313 static void _xfdashboard_plugins_manager_on_enabled_plugins_changed(XfdashboardPluginsManager *self,
314 const gchar *inProperty,
315 const GValue *inValue,
316 gpointer inUserData)
317 {
318 XfdashboardPluginsManagerPrivate *priv;
319 gchar **enabledPlugins;
320
321 g_return_if_fail(XFDASHBOARD_IS_PLUGINS_MANAGER(self));
322 g_return_if_fail(XFCONF_IS_CHANNEL(inUserData));
323
324 priv=self->priv;
325
326 /* If plugin managed is not inited do not load or "unload" any plugin */
327 if(!priv->isInited) return;
328
329 /* Get new list of enabled plugins */
330 enabledPlugins=xfconf_channel_get_string_list(xfdashboard_application_get_xfconf_channel(NULL),
331 ENABLED_PLUGINS_XFCONF_PROP);
332
333 /* Iterate through list of loaded plugin and check if it also in new list
334 * of enabled plugins. If it is not then disable this plugin.
335 */
336 if(priv->plugins)
337 {
338 GList *iter;
339 XfdashboardPlugin *plugin;
340 const gchar *pluginID;
341
342 iter=priv->plugins;
343 while(iter)
344 {
345 GList *nextIter;
346 gchar **listIter;
347 gchar *listIterPluginID;
348 gboolean found;
349
350 /* Get next item getting iterated before doing anything
351 * because the current item may get removed and the iterator
352 * would get invalid.
353 */
354 nextIter=g_list_next(iter);
355
356 /* Get currently iterated plugin */
357 plugin=XFDASHBOARD_PLUGIN(iter->data);
358
359 /* Get plugin ID */
360 pluginID=xfdashboard_plugin_get_id(plugin);
361
362 /* Check if plugin ID is still in new list of enabled plugins */
363 found=FALSE;
364 for(listIter=enabledPlugins; !found && *listIter; listIter++)
365 {
366 /* Get plugin ID of new enabled plugins currently iterated */
367 listIterPluginID=*listIter;
368
369 /* Check if plugin ID matches this iterated one. If so,
370 * set flag that plugin was found.
371 */
372 if(g_strcmp0(pluginID, listIterPluginID)==0) found=TRUE;
373 }
374
375 /* Check that found flag is set. If it is not then disable plugin */
376 if(!found)
377 {
378 XFDASHBOARD_DEBUG(self, PLUGINS,
379 "Disable plugin '%s'",
380 pluginID);
381
382 /* Disable plugin */
383 xfdashboard_plugin_disable(plugin);
384 }
385
386 /* Move iterator to next item */
387 iter=nextIter;
388 }
389 }
390
391 /* Iterate through new list of enabled plugin and check if it is already
392 * or still in the list of loaded plugins. If it not in this list then
393 * try to load this plugin. If it is then enable it again when it is in
394 * disable state.
395 */
396 if(enabledPlugins)
397 {
398 gchar **iter;
399 gchar *pluginID;
400 GError *error;
401 XfdashboardPlugin *plugin;
402
403 error=NULL;
404
405 /* Iterate through new list of enabled plugins and load new plugins */
406 for(iter=enabledPlugins; *iter; iter++)
407 {
408 /* Get plugin ID to check */
409 pluginID=*iter;
410
411 /* Check if a plugin with this ID exists already */
412 plugin=_xfdashboard_plugins_manager_find_plugin_by_id(self, pluginID);
413 if(!plugin)
414 {
415 /* The plugin does not exist so try to load it */
416 if(!_xfdashboard_plugins_manager_load_plugin(self, pluginID, &error))
417 {
418 /* Show error message */
419 g_warning("Could not load plugin '%s': %s",
420 pluginID,
421 error ? error->message : "Unknown error");
422
423 /* Release allocated resources */
424 if(error)
425 {
426 g_error_free(error);
427 error=NULL;
428 }
429 }
430 else
431 {
432 XFDASHBOARD_DEBUG(self, PLUGINS,
433 "Loaded plugin '%s'",
434 pluginID);
435 }
436 }
437 else
438 {
439 /* The plugin exists already so check if it is disabled and
440 * re-enable it.
441 */
442 if(!xfdashboard_plugin_is_enabled(plugin))
443 {
444 XFDASHBOARD_DEBUG(self, PLUGINS,
445 "Re-enable plugin '%s'",
446 pluginID);
447 xfdashboard_plugin_enable(plugin);
448 }
449 }
450 }
451 }
452
453 /* Release allocated resources */
454 if(enabledPlugins) g_strfreev(enabledPlugins);
455 }
456
457 /* Application was fully initialized so enabled all loaded plugin except the
458 * ones which are already enabled, e.g. plugins which requested early initialization.
459 */
_xfdashboard_plugins_manager_on_application_initialized(XfdashboardPluginsManager * self,gpointer inUserData)460 static void _xfdashboard_plugins_manager_on_application_initialized(XfdashboardPluginsManager *self,
461 gpointer inUserData)
462 {
463 XfdashboardPluginsManagerPrivate *priv;
464 GList *iter;
465 XfdashboardPlugin *plugin;
466
467 g_return_if_fail(XFDASHBOARD_IS_PLUGINS_MANAGER(self));
468 g_return_if_fail(XFDASHBOARD_IS_APPLICATION(inUserData));
469
470 priv=self->priv;
471
472 /* Iterate through all loaded plugins and enable all plugins which are
473 * not enabled yet.
474 */
475 XFDASHBOARD_DEBUG(self, PLUGINS, "Plugin manager will now enable all remaining plugins because application is fully initialized now");
476 for(iter=priv->plugins; iter; iter=g_list_next(iter))
477 {
478 /* Get plugin */
479 plugin=XFDASHBOARD_PLUGIN(iter->data);
480
481 /* If plugin is not enabled do it now */
482 if(!xfdashboard_plugin_is_enabled(plugin))
483 {
484 /* Enable plugin */
485 XFDASHBOARD_DEBUG(self, PLUGINS,
486 "Enabling plugin '%s'",
487 xfdashboard_plugin_get_id(plugin));
488 xfdashboard_plugin_enable(plugin);
489 }
490 }
491
492 /* Disconnect signal handler as this signal is emitted only once */
493 if(priv->application)
494 {
495 if(priv->applicationInitializedSignalID)
496 {
497 g_signal_handler_disconnect(priv->application, priv->applicationInitializedSignalID);
498 priv->applicationInitializedSignalID=0;
499 }
500
501 priv->application=NULL;
502 }
503 }
504
505 /* IMPLEMENTATION: GObject */
506
507 /* Construct this object */
_xfdashboard_plugins_manager_constructor(GType inType,guint inNumberConstructParams,GObjectConstructParam * inConstructParams)508 static GObject* _xfdashboard_plugins_manager_constructor(GType inType,
509 guint inNumberConstructParams,
510 GObjectConstructParam *inConstructParams)
511 {
512 GObject *object;
513
514 if(!_xfdashboard_plugins_manager)
515 {
516 object=G_OBJECT_CLASS(xfdashboard_plugins_manager_parent_class)->constructor(inType, inNumberConstructParams, inConstructParams);
517 _xfdashboard_plugins_manager=XFDASHBOARD_PLUGINS_MANAGER(object);
518 }
519 else
520 {
521 object=g_object_ref(G_OBJECT(_xfdashboard_plugins_manager));
522 }
523
524 return(object);
525 }
526
527 /* Dispose this object */
_xfdashboard_plugins_manager_dispose_remove_plugin(gpointer inData)528 static void _xfdashboard_plugins_manager_dispose_remove_plugin(gpointer inData)
529 {
530 XfdashboardPlugin *plugin;
531
532 g_return_if_fail(inData && XFDASHBOARD_IS_PLUGIN(inData));
533
534 plugin=XFDASHBOARD_PLUGIN(inData);
535
536 /* Disable plugin */
537 xfdashboard_plugin_disable(plugin);
538
539 /* Unload plugin */
540 g_type_module_unuse(G_TYPE_MODULE(plugin));
541 }
542
_xfdashboard_plugins_manager_dispose(GObject * inObject)543 static void _xfdashboard_plugins_manager_dispose(GObject *inObject)
544 {
545 XfdashboardPluginsManager *self=XFDASHBOARD_PLUGINS_MANAGER(inObject);
546 XfdashboardPluginsManagerPrivate *priv=self->priv;
547
548 /* Release allocated resources */
549 if(priv->application)
550 {
551 if(priv->applicationInitializedSignalID)
552 {
553 g_signal_handler_disconnect(priv->application, priv->applicationInitializedSignalID);
554 priv->applicationInitializedSignalID=0;
555 }
556
557 priv->application=NULL;
558 }
559
560 if(priv->plugins)
561 {
562 g_list_free_full(priv->plugins, (GDestroyNotify)_xfdashboard_plugins_manager_dispose_remove_plugin);
563 priv->plugins=NULL;
564 }
565
566 if(priv->searchPaths)
567 {
568 g_list_free_full(priv->searchPaths, g_free);
569 priv->searchPaths=NULL;
570 }
571
572 /* Call parent's class dispose method */
573 G_OBJECT_CLASS(xfdashboard_plugins_manager_parent_class)->dispose(inObject);
574 }
575
576 /* Finalize this object */
_xfdashboard_plugins_manager_finalize(GObject * inObject)577 static void _xfdashboard_plugins_manager_finalize(GObject *inObject)
578 {
579 /* Release allocated resources finally, e.g. unset singleton */
580 if(G_LIKELY(G_OBJECT(_xfdashboard_plugins_manager)==inObject))
581 {
582 _xfdashboard_plugins_manager=NULL;
583 }
584
585 /* Call parent's class dispose method */
586 G_OBJECT_CLASS(xfdashboard_plugins_manager_parent_class)->finalize(inObject);
587 }
588
589 /* Class initialization
590 * Override functions in parent classes and define properties
591 * and signals
592 */
xfdashboard_plugins_manager_class_init(XfdashboardPluginsManagerClass * klass)593 static void xfdashboard_plugins_manager_class_init(XfdashboardPluginsManagerClass *klass)
594 {
595 GObjectClass *gobjectClass=G_OBJECT_CLASS(klass);
596
597 /* Override functions */
598 gobjectClass->constructor=_xfdashboard_plugins_manager_constructor;
599 gobjectClass->dispose=_xfdashboard_plugins_manager_dispose;
600 gobjectClass->finalize=_xfdashboard_plugins_manager_finalize;
601 }
602
603 /* Object initialization
604 * Create private structure and set up default values
605 */
xfdashboard_plugins_manager_init(XfdashboardPluginsManager * self)606 static void xfdashboard_plugins_manager_init(XfdashboardPluginsManager *self)
607 {
608 XfdashboardPluginsManagerPrivate *priv;
609
610 priv=self->priv=xfdashboard_plugins_manager_get_instance_private(self);
611
612 /* Set default values */
613 priv->isInited=FALSE;
614 priv->searchPaths=NULL;
615 priv->plugins=NULL;
616 priv->xfconfChannel=xfdashboard_application_get_xfconf_channel(NULL);
617 priv->application=xfdashboard_application_get_default();
618
619 /* Connect signal to get notified about changed of enabled-plugins
620 * property in Xfconf.
621 */
622 g_signal_connect_swapped(priv->xfconfChannel,
623 "property-changed::"ENABLED_PLUGINS_XFCONF_PROP,
624 G_CALLBACK(_xfdashboard_plugins_manager_on_enabled_plugins_changed),
625 self);
626
627 /* Connect signal to get notified when application is fully initialized
628 * to enable loaded plugins.
629 */
630 priv->applicationInitializedSignalID=
631 g_signal_connect_swapped(priv->application,
632 "initialized",
633 G_CALLBACK(_xfdashboard_plugins_manager_on_application_initialized),
634 self);
635 }
636
637 /* IMPLEMENTATION: Public API */
638
639 /**
640 * xfdashboard_plugins_manager_get_default:
641 *
642 * Retrieves the singleton instance of #XfdashboardPluginsManager.
643 *
644 * Return value: (transfer full): The instance of #XfdashboardPluginsManager.
645 * Use g_object_unref() when done.
646 */
xfdashboard_plugins_manager_get_default(void)647 XfdashboardPluginsManager* xfdashboard_plugins_manager_get_default(void)
648 {
649 GObject *singleton;
650
651 singleton=g_object_new(XFDASHBOARD_TYPE_PLUGINS_MANAGER, NULL);
652 return(XFDASHBOARD_PLUGINS_MANAGER(singleton));
653 }
654
655 /**
656 * xfdashboard_plugins_manager_setup:
657 * @self: A #XfdashboardPluginsManager
658 *
659 * Initializes the plugin manager at @self by loading all enabled plugins. This
660 * function can only be called once and is initialized by the application at
661 * start-up. So you usually do not have to call this function or it does anything
662 * as the plugin manager is already setup.
663 *
664 * The plugin manager will continue initializing successfully even if a plugin
665 * could not be loaded. In this case just a warning is printed.
666 *
667 * Return value: Returns %TRUE if plugin manager was initialized successfully
668 * or was already initialized. Otherwise %FALSE will be returned.
669 */
xfdashboard_plugins_manager_setup(XfdashboardPluginsManager * self)670 gboolean xfdashboard_plugins_manager_setup(XfdashboardPluginsManager *self)
671 {
672 XfdashboardPluginsManagerPrivate *priv;
673 gchar *path;
674 const gchar *envPath;
675 gchar **enabledPlugins;
676 gchar **iter;
677 GError *error;
678
679 g_return_val_if_fail(XFDASHBOARD_IS_PLUGINS_MANAGER(self), FALSE);
680
681 priv=self->priv;
682 error=NULL;
683
684 /* If plugin manager is already initialized then return immediately */
685 if(priv->isInited) return(TRUE);
686
687 /* Add search paths. Some paths may fail because they already exist
688 * in list of search paths. So this should not fail this function.
689 */
690 envPath=g_getenv("XFDASHBOARD_PLUGINS_PATH");
691 if(envPath)
692 {
693 gchar **paths;
694
695 iter=paths=g_strsplit(envPath, ":", -1);
696 while(*iter)
697 {
698 _xfdashboard_plugins_manager_add_search_path(self, *iter);
699 iter++;
700 }
701 g_strfreev(paths);
702 }
703
704 path=g_build_filename(g_get_user_data_dir(), "xfdashboard", "plugins", NULL);
705 _xfdashboard_plugins_manager_add_search_path(self, path);
706 g_free(path);
707
708 path=g_build_filename(PACKAGE_LIBDIR, "xfdashboard", "plugins", NULL);
709 _xfdashboard_plugins_manager_add_search_path(self, path);
710 g_free(path);
711
712 /* Get list of enabled plugins and try to load them */
713 enabledPlugins=xfconf_channel_get_string_list(xfdashboard_application_get_xfconf_channel(NULL),
714 ENABLED_PLUGINS_XFCONF_PROP);
715
716 /* Try to load all enabled plugin and collect each error occurred. */
717 for(iter=enabledPlugins; iter && *iter; iter++)
718 {
719 gchar *pluginID;
720
721 /* Get plugin name */
722 pluginID=*iter;
723 XFDASHBOARD_DEBUG(self, PLUGINS,
724 "Try to load plugin '%s'",
725 pluginID);
726
727 /* Try to load plugin */
728 if(!_xfdashboard_plugins_manager_load_plugin(self, pluginID, &error))
729 {
730 /* Show error message */
731 g_warning("Could not load plugin '%s': %s",
732 pluginID,
733 error ? error->message : "Unknown error");
734
735 /* Release allocated resources */
736 if(error)
737 {
738 g_error_free(error);
739 error=NULL;
740 }
741 }
742 else
743 {
744 XFDASHBOARD_DEBUG(self, PLUGINS,
745 "Loaded plugin '%s'",
746 pluginID);
747 }
748 }
749
750 /* If we get here then initialization was successful so set flag that
751 * this plugin manager is initialized and return with TRUE result.
752 */
753 priv->isInited=TRUE;
754
755 /* Release allocated resources */
756 if(enabledPlugins) g_strfreev(enabledPlugins);
757
758 return(TRUE);
759 }
760