[kdbus] Use new API insted of direct call to org.freedesktop.DBus
[platform/upstream/glib.git] / gio / giomodule.c
index eac317a..510f652 100644 (file)
@@ -13,9 +13,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Alexander Larsson <alexl@redhat.com>
  */
@@ -37,6 +35,7 @@
 #include "gsocks5proxy.h"
 #include "gtlsbackend.h"
 #include "gvfs.h"
+#include "gnotificationbackend.h"
 #ifdef G_OS_WIN32
 #include "gregistrysettingsbackend.h"
 #endif
  * SECTION:extensionpoints
  * @short_description: Extension Points
  * @include: gio.h
- * @see_also: <link linkend="extending-gio">Extending GIO</link>
+ * @see_also: [Extending GIO][extending-gio]
  *
  * #GIOExtensionPoint provides a mechanism for modules to extend the
  * functionality of the library or application that loaded it in an 
  * organized fashion.  
  *
  * An extension point is identified by a name, and it may optionally
- * require that any implementation must by of a certain type (or derived
+ * require that any implementation must be of a certain type (or derived
  * thereof). Use g_io_extension_point_register() to register an
  * extension point, and g_io_extension_point_set_required_type() to
  * set a required type.
  * of an extension point has a name, and a priority. Use
  * g_io_extension_point_implement() to implement an extension point.
  * 
- *  |[
+ *  |[<!-- language="C" -->
  *  GIOExtensionPoint *ep;
  *
- *  /&ast; Register an extension point &ast;/
+ *  // Register an extension point
  *  ep = g_io_extension_point_register ("my-extension-point");
  *  g_io_extension_point_set_required_type (ep, MY_TYPE_EXAMPLE);
  *  ]|
  *
- *  |[
- *  /&ast; Implement an extension point &ast;/
+ *  |[<!-- language="C" -->
+ *  // Implement an extension point
  *  G_DEFINE_TYPE (MyExampleImpl, my_example_impl, MY_TYPE_EXAMPLE);
  *  g_io_extension_point_implement ("my-extension-point",
  *                                  my_example_impl_get_type (),
  *
  *  To avoid opening all modules just to find out what extension
  *  points they implement, GIO makes use of a caching mechanism,
- *  see <link linkend="gio-querymodules">gio-querymodules</link>.
+ *  see [gio-querymodules][gio-querymodules].
  *  You are expected to run this command after installing a
  *  GIO module.
  *
- *  The <envar>GIO_EXTRA_MODULES</envar> environment variable can be
- *  used to specify additional directories to automatically load modules
+ *  The `GIO_EXTRA_MODULES` environment variable can be used to
+ *  specify additional directories to automatically load modules
  *  from. This environment variable has the same syntax as the
- *  <envar>PATH</envar>. If two modules have the same base name in different
+ *  `PATH`. If two modules have the same base name in different
  *  directories, then the latter one will be ignored. If additional
  *  directories are specified GIO will load modules from the built-in
  *  directory last.
@@ -139,7 +138,7 @@ struct _GIOModuleScope {
  * Create a new scope for loading of IO modules. A scope can be used for
  * blocking duplicate modules, or blocking a module you don't want to load.
  *
- * Specify the %G_IO_MODULES_SCOPE_BLOCK_DUPLICATES flag to block modules
+ * Specify the %G_IO_MODULE_SCOPE_BLOCK_DUPLICATES flag to block modules
  * which have the same base name as a module that has already been seen
  * in this scope.
  *
@@ -628,8 +627,122 @@ g_io_modules_load_all_in_directory (const char *dirname)
   return g_io_modules_load_all_in_directory_with_scope (dirname, NULL);
 }
 
-GRecMutex default_modules_lock;
-GHashTable *default_modules;
+static gpointer
+try_class (GIOExtension *extension,
+           guint         is_supported_offset)
+{
+  GType type = g_io_extension_get_type (extension);
+  typedef gboolean (*verify_func) (void);
+  gpointer class;
+
+  class = g_type_class_ref (type);
+  if (!is_supported_offset || (* G_STRUCT_MEMBER(verify_func, class, is_supported_offset)) ())
+    return class;
+
+  g_type_class_unref (class);
+  return NULL;
+}
+
+/**
+ * _g_io_module_get_default_type:
+ * @extension_point: the name of an extension point
+ * @envvar: (allow-none): the name of an environment variable to
+ *     override the default implementation.
+ * @is_supported_offset: a vtable offset, or zero
+ *
+ * Retrieves the default class implementing @extension_point.
+ *
+ * If @envvar is not %NULL, and the environment variable with that
+ * name is set, then the implementation it specifies will be tried
+ * first. After that, or if @envvar is not set, all other
+ * implementations will be tried in order of decreasing priority.
+ *
+ * If @is_supported_offset is non-zero, then it is the offset into the
+ * class vtable at which there is a function that takes no arguments and
+ * returns a boolean.  This function will be called on each candidate
+ * implementation to check if it is actually usable or not.
+ *
+ * The result is cached after it is generated the first time, and
+ * the function is thread-safe.
+ *
+ * Returns: (transfer none): an object implementing
+ *     @extension_point, or %NULL if there are no usable
+ *     implementations.
+ */
+GType
+_g_io_module_get_default_type (const gchar *extension_point,
+                               const gchar *envvar,
+                               guint        is_supported_offset)
+{
+  static GRecMutex default_modules_lock;
+  static GHashTable *default_modules;
+  const char *use_this;
+  GList *l;
+  GIOExtensionPoint *ep;
+  GIOExtension *extension, *preferred;
+  gpointer impl;
+
+  g_rec_mutex_lock (&default_modules_lock);
+  if (default_modules)
+    {
+      gpointer key;
+
+      if (g_hash_table_lookup_extended (default_modules, extension_point, &key, &impl))
+        {
+          g_rec_mutex_unlock (&default_modules_lock);
+          return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
+        }
+    }
+  else
+    {
+      default_modules = g_hash_table_new (g_str_hash, g_str_equal);
+    }
+
+  _g_io_modules_ensure_loaded ();
+  ep = g_io_extension_point_lookup (extension_point);
+
+  if (!ep)
+    {
+      g_warn_if_reached ();
+      g_rec_mutex_unlock (&default_modules_lock);
+      return G_TYPE_INVALID;
+    }
+
+  use_this = envvar ? g_getenv (envvar) : NULL;
+  if (use_this)
+    {
+      preferred = g_io_extension_point_get_extension_by_name (ep, use_this);
+      if (preferred)
+        {
+          impl = try_class (preferred, is_supported_offset);
+          if (impl)
+            goto done;
+        }
+      else
+        g_warning ("Can't find module '%s' specified in %s", use_this, envvar);
+    }
+  else
+    preferred = NULL;
+
+  for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
+    {
+      extension = l->data;
+      if (extension == preferred)
+        continue;
+
+      impl = try_class (extension, is_supported_offset);
+      if (impl)
+        goto done;
+    }
+
+  impl = NULL;
+
+ done:
+  g_hash_table_insert (default_modules, g_strdup (extension_point), impl);
+  g_rec_mutex_unlock (&default_modules_lock);
+
+  return impl ? G_OBJECT_CLASS_TYPE (impl) : G_TYPE_INVALID;
+}
 
 static gpointer
 try_implementation (GIOExtension         *extension,
@@ -675,7 +788,7 @@ try_implementation (GIOExtension         *extension,
  * The result is cached after it is generated the first time, and
  * the function is thread-safe.
  *
- * Return value: (transfer none): an object implementing
+ * Returns: (transfer none): an object implementing
  *     @extension_point, or %NULL if there are no usable
  *     implementations.
  */
@@ -684,6 +797,8 @@ _g_io_module_get_default (const gchar         *extension_point,
                          const gchar         *envvar,
                          GIOModuleVerifyFunc  verify_func)
 {
+  static GRecMutex default_modules_lock;
+  static GHashTable *default_modules;
   const char *use_this;
   GList *l;
   GIOExtensionPoint *ep;
@@ -762,6 +877,8 @@ extern GType _g_fen_directory_monitor_get_type (void);
 extern GType _g_fen_file_monitor_get_type (void);
 extern GType _g_inotify_directory_monitor_get_type (void);
 extern GType _g_inotify_file_monitor_get_type (void);
+extern GType _g_kqueue_directory_monitor_get_type (void);
+extern GType _g_kqueue_file_monitor_get_type (void);
 extern GType _g_unix_volume_monitor_get_type (void);
 extern GType _g_local_vfs_get_type (void);
 
@@ -771,6 +888,15 @@ extern GType _g_winhttp_vfs_get_type (void);
 
 extern GType _g_dummy_proxy_resolver_get_type (void);
 extern GType _g_dummy_tls_backend_get_type (void);
+extern GType g_network_monitor_base_get_type (void);
+#ifdef HAVE_NETLINK
+extern GType _g_network_monitor_netlink_get_type (void);
+#endif
+
+#ifdef G_OS_UNIX
+extern GType g_fdo_notification_backend_get_type (void);
+extern GType g_gtk_notification_backend_get_type (void);
+#endif
 
 #ifdef G_PLATFORM_WIN32
 
@@ -780,6 +906,10 @@ static HMODULE gio_dll = NULL;
 
 #ifdef DLL_EXPORT
 
+BOOL WINAPI DllMain (HINSTANCE hinstDLL,
+                     DWORD     fdwReason,
+                     LPVOID    lpvReserved);
+
 BOOL WINAPI
 DllMain (HINSTANCE hinstDLL,
         DWORD     fdwReason,
@@ -793,6 +923,16 @@ DllMain (HINSTANCE hinstDLL,
 
 #endif
 
+void *
+_g_io_win32_get_module (void)
+{
+  if (!gio_dll)
+    GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+                        (const char *) _g_io_win32_get_module,
+                        &gio_dll);
+  return gio_dll;
+}
+
 #undef GIO_MODULE_DIR
 
 /* GIO_MODULE_DIR is used only in code called just once,
@@ -820,7 +960,9 @@ _g_io_modules_ensure_extension_points_registered (void)
 #ifdef G_OS_UNIX
 #if !GLIB_CHECK_VERSION (3, 0, 0)
       ep = g_io_extension_point_register (G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME);
+      G_GNUC_BEGIN_IGNORE_DEPRECATIONS
       g_io_extension_point_set_required_type (ep, G_TYPE_DESKTOP_APP_INFO_LOOKUP);
+      G_GNUC_END_IGNORE_DEPRECATIONS
 #endif
 #endif
       
@@ -830,6 +972,12 @@ _g_io_modules_ensure_extension_points_registered (void)
       ep = g_io_extension_point_register (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME);
       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
       
+      ep = g_io_extension_point_register (G_NFS_DIRECTORY_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_DIRECTORY_MONITOR);
+
+      ep = g_io_extension_point_register (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
+
       ep = g_io_extension_point_register (G_VOLUME_MONITOR_EXTENSION_POINT_NAME);
       g_io_extension_point_set_required_type (ep, G_TYPE_VOLUME_MONITOR);
       
@@ -850,10 +998,16 @@ _g_io_modules_ensure_extension_points_registered (void)
 
       ep = g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME);
       g_io_extension_point_set_required_type (ep, G_TYPE_TLS_BACKEND);
+
+      ep = g_io_extension_point_register (G_NETWORK_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_NETWORK_MONITOR);
+
+      ep = g_io_extension_point_register (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_NOTIFICATION_BACKEND);
     }
   
   G_UNLOCK (registered_extensions);
- }
+}
 
 void
 _g_io_modules_ensure_loaded (void)
@@ -861,6 +1015,7 @@ _g_io_modules_ensure_loaded (void)
   static gboolean loaded_dirs = FALSE;
   const char *module_path;
   GIOModuleScope *scope;
+  const gchar *module_dir;
 
   _g_io_modules_ensure_extension_points_registered ();
   
@@ -889,38 +1044,55 @@ _g_io_modules_ensure_loaded (void)
        }
 
       /* Then load the compiled in path */
-      g_io_modules_scan_all_in_directory_with_scope (GIO_MODULE_DIR, scope);
+      module_dir = g_getenv ("GIO_MODULE_DIR");
+      if (module_dir == NULL)
+        module_dir = GIO_MODULE_DIR;
+
+      g_io_modules_scan_all_in_directory_with_scope (module_dir, scope);
 
       g_io_module_scope_free (scope);
 
       /* Initialize types from built-in "modules" */
-      g_null_settings_backend_get_type ();
-      g_memory_settings_backend_get_type ();
-#if defined(HAVE_SYS_INOTIFY_H) || defined(HAVE_LINUX_INOTIFY_H)
-      _g_inotify_directory_monitor_get_type ();
-      _g_inotify_file_monitor_get_type ();
+      g_type_ensure (g_null_settings_backend_get_type ());
+      g_type_ensure (g_memory_settings_backend_get_type ());
+#if defined(HAVE_INOTIFY_INIT1)
+      g_type_ensure (_g_inotify_directory_monitor_get_type ());
+      g_type_ensure (_g_inotify_file_monitor_get_type ());
+#endif
+#if defined(HAVE_KQUEUE)
+      g_type_ensure (_g_kqueue_directory_monitor_get_type ());
+      g_type_ensure (_g_kqueue_file_monitor_get_type ());
 #endif
 #if defined(HAVE_FEN)
-      _g_fen_directory_monitor_get_type ();
-      _g_fen_file_monitor_get_type ();
+      g_type_ensure (_g_fen_directory_monitor_get_type ());
+      g_type_ensure (_g_fen_file_monitor_get_type ());
 #endif
 #ifdef G_OS_WIN32
-      _g_win32_volume_monitor_get_type ();
-      g_win32_directory_monitor_get_type ();
-      g_registry_backend_get_type ();
+      g_type_ensure (_g_win32_volume_monitor_get_type ());
+      g_type_ensure (g_win32_directory_monitor_get_type ());
+      g_type_ensure (g_registry_backend_get_type ());
+#endif
+#ifdef HAVE_COCOA
+      g_nextstep_settings_backend_get_type ();
 #endif
 #ifdef G_OS_UNIX
-      _g_unix_volume_monitor_get_type ();
+      g_type_ensure (_g_unix_volume_monitor_get_type ());
+      g_type_ensure (g_fdo_notification_backend_get_type ());
+      g_type_ensure (g_gtk_notification_backend_get_type ());
 #endif
 #ifdef G_OS_WIN32
-      _g_winhttp_vfs_get_type ();
+      g_type_ensure (_g_winhttp_vfs_get_type ());
+#endif
+      g_type_ensure (_g_local_vfs_get_type ());
+      g_type_ensure (_g_dummy_proxy_resolver_get_type ());
+      g_type_ensure (_g_socks4a_proxy_get_type ());
+      g_type_ensure (_g_socks4_proxy_get_type ());
+      g_type_ensure (_g_socks5_proxy_get_type ());
+      g_type_ensure (_g_dummy_tls_backend_get_type ());
+      g_type_ensure (g_network_monitor_base_get_type ());
+#ifdef HAVE_NETLINK
+      g_type_ensure (_g_network_monitor_netlink_get_type ());
 #endif
-      _g_local_vfs_get_type ();
-      _g_dummy_proxy_resolver_get_type ();
-      _g_socks4a_proxy_get_type ();
-      _g_socks4_proxy_get_type ();
-      _g_socks5_proxy_get_type ();
-      _g_dummy_tls_backend_get_type ();
     }
 
   G_UNLOCK (loaded_dirs);
@@ -1055,8 +1227,8 @@ lazy_load_modules (GIOExtensionPoint *extension_point)
  * The list is sorted by priority, beginning with the highest priority.
  *
  * Returns: (element-type GIOExtension) (transfer none): a #GList of
- * #GIOExtension<!-- -->s. The list is owned by GIO and should not be
- * modified.
+ *     #GIOExtensions. The list is owned by GIO and should not be
+ *     modified.
  */
 GList *
 g_io_extension_point_get_extensions (GIOExtensionPoint *extension_point)
@@ -1081,6 +1253,8 @@ g_io_extension_point_get_extension_by_name (GIOExtensionPoint *extension_point,
 {
   GList *l;
 
+  g_return_val_if_fail (name != NULL, NULL);
+
   lazy_load_modules (extension_point);
   for (l = extension_point->extensions; l != NULL; l = l->next)
     {