# HG changeset patch
# Node ID d34320d577ea
# Parent  7f840f5c4ba7
diff --git a/finch/finchui.c b/finch/finchui.c
--- a/finch/finchui.c
+++ b/finch/finchui.c
@@ -51,40 +51,6 @@
 G_DEFINE_TYPE(FinchUi, finch_ui, PURPLE_TYPE_UI)
 
 /******************************************************************************
- * Helpers
- *****************************************************************************/
-static gboolean
-finch_history_init(GError **error) {
-	PurpleHistoryManager *manager = NULL;
-	PurpleHistoryAdapter *adapter = NULL;
-	gchar *filename = NULL;
-	const gchar *id = NULL;
-
-	manager = purple_history_manager_get_default();
-
-	/* Attempt to create the config directory. */
-	g_mkdir_with_parents(purple_config_dir(), 0700);
-
-	filename = g_build_filename(purple_config_dir(), "history.db", NULL);
-	adapter = purple_sqlite_history_adapter_new(filename);
-	g_free(filename);
-
-	id = purple_history_adapter_get_id(adapter);
-	if(!purple_history_manager_register(manager, adapter, error)) {
-		g_clear_object(&adapter);
-
-		return FALSE;
-	}
-
-	/* The manager adds a ref to the adapter on registration, so we can remove
-	 * our reference.
-	 */
-	g_clear_object(&adapter);
-
-	return purple_history_manager_set_active(manager, id, error);
-}
-
-/******************************************************************************
  * PurpleUi Implementation
  *****************************************************************************/
 static void
@@ -93,7 +59,7 @@
 }
 
 static gboolean
-finch_ui_start(G_GNUC_UNUSED PurpleUi *ui, GError **error) {
+finch_ui_start(G_GNUC_UNUSED PurpleUi *ui, G_GNUC_UNUSED GError **error) {
 	finch_debug_init();
 
 #ifdef STANDALONE
@@ -104,18 +70,6 @@
 	gnt_init();
 #endif /* STANDALONE */
 
-	if(!finch_history_init(error)) {
-		const char *error_message = "unknown";
-
-		if(error != NULL && *error != NULL) {
-			error_message = (*error)->message;
-		}
-
-		g_critical("failed to initialize the history api: %s", error_message);
-
-		return FALSE;
-	}
-
 	purple_prefs_add_none("/purple/gnt");
 
 	/* Accounts */
@@ -217,6 +171,20 @@
 	return backend;
 }
 
+static PurpleHistoryAdapter *
+finch_ui_get_history_adapter(G_GNUC_UNUSED PurpleUi *ui) {
+	PurpleHistoryAdapter *adapter = NULL;
+	char *filename = NULL;
+
+	g_mkdir_with_parents(purple_config_dir(), 0700);
+
+	filename = g_build_filename(purple_config_dir(), "history.db", NULL);
+	adapter = purple_sqlite_history_adapter_new(filename);
+	g_free(filename);
+
+	return adapter;
+}
+
 /******************************************************************************
  * GObject Implementation
  *****************************************************************************/
@@ -232,6 +200,7 @@
 	ui_class->start = finch_ui_start;
 	ui_class->stop = finch_ui_stop;
 	ui_class->get_settings_backend = finch_ui_get_settings_backend;
+	ui_class->get_history_adapter = finch_ui_get_history_adapter;
 }
 
 /******************************************************************************
diff --git a/libpurple/core.c b/libpurple/core.c
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -93,8 +93,9 @@
 }
 
 gboolean
-purple_core_init(PurpleUi *ui, G_GNUC_UNUSED GError **error) {
-	PurpleCore *core;
+purple_core_init(PurpleUi *ui, GError **error) {
+	PurpleCore *core = NULL;
+	PurpleHistoryAdapter *adapter = NULL;
 	const char *force_error_message = NULL;
 
 	g_return_val_if_fail(PURPLE_IS_UI(ui), FALSE);
@@ -168,7 +169,13 @@
 	purple_conversation_manager_startup();
 	purple_whiteboard_manager_startup();
 	purple_blist_init();
-	purple_history_manager_startup();
+
+	/* Setup the history adapter. */
+	adapter = purple_ui_get_history_adapter(ui);
+	if(!purple_history_manager_startup(adapter, error)) {
+		return FALSE;
+	}
+
 	purple_network_init();
 	purple_proxy_init();
 	purple_xfers_init();
diff --git a/libpurple/purplehistorymanager.h b/libpurple/purplehistorymanager.h
--- a/libpurple/purplehistorymanager.h
+++ b/libpurple/purplehistorymanager.h
@@ -72,13 +72,19 @@
 
 /**
  * purple_history_manager_startup:
+ * @adapter: (transfer full) (nullable): The history adapter to use by default.
+ * @error: A return address for a #GError.
  *
- * Starts up the history manager by creating the default instance.
+ * Starts up the history manager by creating the default instance and setting
+ * @adapter as active if @adapter is non %NULL.
+ *
+ * Returns: %TRUE if startup was successful, otherwise %FALSE with @error
+ *          potentially set.
  *
  * Since: 3.0.0
  */
 PURPLE_AVAILABLE_IN_3_0
-void purple_history_manager_startup(void);
+gboolean purple_history_manager_startup(PurpleHistoryAdapter *adapter, GError **error);
 
 /**
  * purple_history_manager_shutdown:
diff --git a/libpurple/purplehistorymanager.c b/libpurple/purplehistorymanager.c
--- a/libpurple/purplehistorymanager.c
+++ b/libpurple/purplehistorymanager.c
@@ -138,38 +138,6 @@
 }
 
 /******************************************************************************
- * Private API
- *****************************************************************************/
-void
-purple_history_manager_startup(void) {
-	if(default_manager == NULL) {
-		default_manager = g_object_new(PURPLE_TYPE_HISTORY_MANAGER, NULL);
-	}
-}
-
-void
-purple_history_manager_shutdown(void) {
-	GError **error = NULL;
-
-	if(default_manager == NULL) {
-		return;
-	}
-
-	if(PURPLE_IS_HISTORY_ADAPTER(default_manager->active_adapter)) {
-		PurpleHistoryAdapter *adapter = NULL;
-
-		adapter = g_object_ref(default_manager->active_adapter);
-		purple_history_manager_set_active(default_manager, NULL, NULL);
-		purple_history_manager_unregister(default_manager,
-		                                  adapter, error);
-
-		g_clear_object(&adapter);
-	}
-
-	g_clear_object(&default_manager);
-}
-
-/******************************************************************************
  * Public API
  *****************************************************************************/
 PurpleHistoryManager *
@@ -397,3 +365,57 @@
 		func(PURPLE_HISTORY_ADAPTER(value), data);
 	}
 }
+
+gboolean
+purple_history_manager_startup(PurpleHistoryAdapter *adapter, GError **error) {
+	const char *id = NULL;
+
+	if(default_manager == NULL) {
+		default_manager = g_object_new(PURPLE_TYPE_HISTORY_MANAGER, NULL);
+		g_object_add_weak_pointer(G_OBJECT(default_manager),
+		                          (gpointer)&default_manager);
+	}
+
+	if(!PURPLE_IS_HISTORY_ADAPTER(adapter)) {
+		adapter = purple_sqlite_history_adapter_new(":memory:");
+	}
+
+	if(!purple_history_manager_register(default_manager, adapter, error)) {
+		g_clear_object(&adapter);
+
+		return FALSE;
+	}
+
+	id = purple_history_adapter_get_id(adapter);
+	if(!purple_history_manager_set_active(default_manager, id, error)) {
+		g_clear_object(&adapter);
+
+		return FALSE;
+	}
+
+	g_clear_object(&adapter);
+
+	return TRUE;
+}
+
+void
+purple_history_manager_shutdown(void) {
+	GError **error = NULL;
+
+	if(default_manager == NULL) {
+		return;
+	}
+
+	if(PURPLE_IS_HISTORY_ADAPTER(default_manager->active_adapter)) {
+		PurpleHistoryAdapter *adapter = NULL;
+
+		adapter = g_object_ref(default_manager->active_adapter);
+		purple_history_manager_set_active(default_manager, NULL, NULL);
+		purple_history_manager_unregister(default_manager,
+		                                  adapter, error);
+
+		g_clear_object(&adapter);
+	}
+
+	g_clear_object(&default_manager);
+}
diff --git a/libpurple/purpleui.h b/libpurple/purpleui.h
--- a/libpurple/purpleui.h
+++ b/libpurple/purpleui.h
@@ -26,6 +26,7 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include "purplehistoryadapter.h"
 #include "purpleversion.h"
 
 G_BEGIN_DECLS
@@ -71,6 +72,7 @@
 	void (*stop)(PurpleUi *ui);
 
 	gpointer (*get_settings_backend)(PurpleUi *ui);
+	PurpleHistoryAdapter *(*get_history_adapter)(PurpleUi *ui);
 
 	/*< private >*/
 	gpointer reserved[4];
@@ -215,6 +217,22 @@
 PURPLE_AVAILABLE_IN_3_0
 gpointer purple_ui_get_settings_backend(PurpleUi *ui);
 
+/**
+ * purple_ui_get_history_adapter:
+ * @ui: The instance:
+ *
+ * Gets the history adapter that the user interface wants to use.
+ *
+ * > Note: This should typically only be called by libpurple. If this returns
+ * %NULL, then libpurple will use an in-memory history adapter instead.
+ *
+ * Returns: (transfer full) (nullable): The [class@HistoryAdapter] to use or
+ *          %NULL.
+ *
+ * Since: 3.0.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+PurpleHistoryAdapter *purple_ui_get_history_adapter(PurpleUi *ui);
 
 G_END_DECLS
 
diff --git a/libpurple/purpleui.c b/libpurple/purpleui.c
--- a/libpurple/purpleui.c
+++ b/libpurple/purpleui.c
@@ -425,3 +425,17 @@
 
 	return NULL;
 }
+
+PurpleHistoryAdapter *
+purple_ui_get_history_adapter(PurpleUi *ui) {
+	PurpleUiClass *klass = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_UI(ui), NULL);
+
+	klass = PURPLE_UI_GET_CLASS(ui);
+	if(klass != NULL && klass->get_history_adapter != NULL) {
+		return klass->get_history_adapter(ui);
+	}
+
+	return NULL;
+}
diff --git a/libpurple/tests/test_ui.c b/libpurple/tests/test_ui.c
--- a/libpurple/tests/test_ui.c
+++ b/libpurple/tests/test_ui.c
@@ -107,31 +107,6 @@
 		NULL);
 }
 
-static gboolean
-test_ui_init_history(GError **error) {
-	PurpleHistoryManager *manager = NULL;
-	PurpleHistoryAdapter *adapter = NULL;
-	const gchar *id = NULL;
-
-	manager = purple_history_manager_get_default();
-
-	adapter = purple_sqlite_history_adapter_new(":memory:");
-	id = purple_history_adapter_get_id(adapter);
-
-	if(!purple_history_manager_register(manager, adapter, error)) {
-		g_clear_object(&adapter);
-
-		return FALSE;
-	}
-
-	/* The manager adds a ref to the adapter on registration, so we can remove
-	 * our reference.
-	 */
-	g_clear_object(&adapter);
-
-	return purple_history_manager_set_active(manager, id, error);
-}
-
 void
 test_ui_purple_init(void) {
 	PurpleUi *ui = NULL;
@@ -158,12 +133,6 @@
 	/* Make sure our configuration directory exists. */
 	g_mkdir_with_parents(purple_config_dir(), 0755);
 
-	if(!test_ui_init_history(&error)) {
-		g_critical("failed to initialize the history api: %s",
-		           error ? error->message : "unknown");
-		g_clear_error(&error);
-	}
-
 	/* Load the preferences. */
 	purple_prefs_load();
 
diff --git a/pidgin/pidginui.c b/pidgin/pidginui.c
--- a/pidgin/pidginui.c
+++ b/pidgin/pidginui.c
@@ -53,40 +53,6 @@
 /******************************************************************************
  * Helpers
  *****************************************************************************/
-static gboolean
-pidgin_history_init(GError **error) {
-	PurpleHistoryManager *manager = NULL;
-	PurpleHistoryAdapter *adapter = NULL;
-	gchar *filename = NULL;
-	const gchar *id = NULL;
-
-	manager = purple_history_manager_get_default();
-
-	/* Attempt to create the config_dir. We don't care about the result as the
-	 * logging adapter will fail with a better error than us failing to create
-	 * the directory.
-	 */
-	g_mkdir_with_parents(purple_config_dir(), 0700);
-
-	filename = g_build_filename(purple_config_dir(), "history.db", NULL);
-	adapter = purple_sqlite_history_adapter_new(filename);
-	g_free(filename);
-
-	id = purple_history_adapter_get_id(adapter);
-	if(!purple_history_manager_register(manager, adapter, error)) {
-		g_clear_object(&adapter);
-
-		return FALSE;
-	}
-
-	/* The manager adds a ref to the adapter on registration, so we can remove
-	 * our reference.
-	 */
-	g_clear_object(&adapter);
-
-	return purple_history_manager_set_active(manager, id, error);
-}
-
 static void
 pidgin_ui_add_protocol_theme_paths(PurpleProtocol *protocol) {
 	GdkDisplay *display = NULL;
@@ -134,7 +100,7 @@
 }
 
 static gboolean
-pidgin_ui_start(G_GNUC_UNUSED PurpleUi *ui, GError **error) {
+pidgin_ui_start(G_GNUC_UNUSED PurpleUi *ui, G_GNUC_UNUSED GError **error) {
 	PurpleProtocolManager *protocol_manager = NULL;
 	GdkDisplay *display = NULL;
 	GtkIconTheme *theme = NULL;
@@ -162,18 +128,6 @@
 	purple_protocol_manager_foreach(protocol_manager,
 	                                pidgin_ui_protocol_foreach_theme_cb, NULL);
 
-	if(!pidgin_history_init(error)) {
-		const char *error_message = "unknown";
-
-		if(error != NULL && *error != NULL) {
-			error_message = (*error)->message;
-		}
-
-		g_critical("failed to initialize the history api: %s", error_message);
-
-		return FALSE;
-	}
-
 	/* Set the UI operation structures. */
 	purple_xfers_set_ui_ops(pidgin_xfers_get_ui_ops());
 	purple_blist_set_ui(PIDGIN_TYPE_BUDDY_LIST);
@@ -223,6 +177,20 @@
 	return backend;
 }
 
+static PurpleHistoryAdapter *
+pidgin_ui_get_history_adapter(G_GNUC_UNUSED PurpleUi *ui) {
+	PurpleHistoryAdapter *adapter = NULL;
+	char *filename = NULL;
+
+	g_mkdir_with_parents(purple_config_dir(), 0700);
+
+	filename = g_build_filename(purple_config_dir(), "history.db", NULL);
+	adapter = purple_sqlite_history_adapter_new(filename);
+	g_free(filename);
+
+	return adapter;
+}
+
 /******************************************************************************
  * GObject Implementation
  *****************************************************************************/
@@ -238,6 +206,7 @@
 	ui_class->start = pidgin_ui_start;
 	ui_class->stop = pidgin_ui_stop;
 	ui_class->get_settings_backend = pidgin_ui_get_settings_backend;
+	ui_class->get_history_adapter = pidgin_ui_get_history_adapter;
 }
 
 /******************************************************************************
diff --git a/purple-history/purplehistorycore.c b/purple-history/purplehistorycore.c
--- a/purple-history/purplehistorycore.c
+++ b/purple-history/purplehistorycore.c
@@ -103,7 +103,7 @@
 		return EXIT_FAILURE;
 	}
 
-	purple_history_manager_startup();
+	purple_history_manager_startup(NULL, NULL);
 
 	for(gint i = 1; i < argc; i++) {
 		if(argv[i] == NULL || *argv[i] == '\0') {
