Add Purple.Protocol.generate_account_name

Tue, 28 Jan 2025 10:56:12 -0600

author
Gary Kramlich <grim@reaperworld.com>
date
Tue, 28 Jan 2025 10:56:12 -0600
changeset 43161
920605926071
parent 43160
a9cc7d8325ba
child 43162
b6b96199a068

Add Purple.Protocol.generate_account_name

This is the first step in allowing users to assign names to their accounts.

I also did a bunch of house keeping in the existing unit tests.

Testing Done:
Ran the tests under valgrind and called in the turtles.

Bugs closed: PIDGIN-17997

Reviewed at https://reviews.imfreedom.org/r/3787/

libpurple/purpleprotocol.c file | annotate | diff | comparison | revisions
libpurple/purpleprotocol.h file | annotate | diff | comparison | revisions
libpurple/tests/test_protocol.c file | annotate | diff | comparison | revisions
--- a/libpurple/purpleprotocol.c	Tue Jan 28 10:53:46 2025 -0600
+++ b/libpurple/purpleprotocol.c	Tue Jan 28 10:56:12 2025 -0600
@@ -163,6 +163,20 @@
 		NULL);
 }
 
+static char *
+purple_protocol_default_generate_account_name(PurpleProtocol *protocol,
+                                              G_GNUC_UNUSED PurpleAccount *account,
+                                              guint n_accounts)
+{
+	PurpleProtocolPrivate *priv = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL);
+
+	priv = purple_protocol_get_instance_private(protocol);
+
+	return g_strdup_printf("%s %u", priv->name, n_accounts + 1);
+}
+
 /******************************************************************************
  * GObject Implementation
  *****************************************************************************/
@@ -270,6 +284,7 @@
 	obj_class->finalize = purple_protocol_finalize;
 
 	klass->create_connection = purple_protocol_default_create_connection;
+	klass->generate_account_name = purple_protocol_default_generate_account_name;
 
 	/**
 	 * PurpleProtocol:id:
@@ -367,6 +382,24 @@
 /******************************************************************************
  * Public API
  *****************************************************************************/
+char *
+purple_protocol_generate_account_name(PurpleProtocol *protocol,
+                                      PurpleAccount *account,
+                                      guint n_accounts)
+{
+	PurpleProtocolClass *klass = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL);
+	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
+
+	klass = PURPLE_PROTOCOL_GET_CLASS(protocol);
+	if(klass != NULL && klass->generate_account_name != NULL) {
+		return klass->generate_account_name(protocol, account, n_accounts);
+	}
+
+	return NULL;
+}
+
 BirbActionMenu *
 purple_protocol_get_action_menu(PurpleProtocol *protocol,
                                 PurpleAccount *account)
--- a/libpurple/purpleprotocol.h	Tue Jan 28 10:53:46 2025 -0600
+++ b/libpurple/purpleprotocol.h	Tue Jan 28 10:56:12 2025 -0600
@@ -143,6 +143,8 @@
 	GList *(*get_account_options)(PurpleProtocol *protocol);
 	PurpleWhiteboardOps *(*get_whiteboard_ops)(PurpleProtocol *protocol);
 
+	char *(*generate_account_name)(PurpleProtocol *protocol, PurpleAccount *account, guint n_accounts);
+
 	void (*can_connect_async)(PurpleProtocol *protocol, PurpleAccount *account, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data);
 	gboolean (*can_connect_finish)(PurpleProtocol *protocol, GAsyncResult *result, GError **error);
 
@@ -175,6 +177,29 @@
 G_BEGIN_DECLS
 
 /**
+ * purple_protocol_generate_account_name:
+ * @account: the account whose name to generate
+ * @n_accounts: the number of accounts
+ *
+ * Generates a name for an account.
+ *
+ * This is used to attempt to generate a simple name for an account. Something
+ * like "IRC 1".
+ *
+ * The @n_accounts parameter is the number of existing accounts with the same
+ * protocol.
+ *
+ * This may be called multiple times for the same account if a duplicate
+ * account name is found.
+ *
+ * Returns: (transfer full): The new account name.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+char *purple_protocol_generate_account_name(PurpleProtocol *protocol, PurpleAccount *account, guint n_accounts);
+
+/**
  * purple_protocol_get_id:
  * @protocol: The #PurpleProtocol instance.
  *
--- a/libpurple/tests/test_protocol.c	Tue Jan 28 10:53:46 2025 -0600
+++ b/libpurple/tests/test_protocol.c	Tue Jan 28 10:56:12 2025 -0600
@@ -39,8 +39,10 @@
 	gboolean result;
 	GError *error;
 
-	gboolean can_connect_async;
-	gboolean can_connect_finish;
+	guint can_connect_async;
+	guint can_connect_finish;
+
+	guint generate_account_name;
 };
 
 G_DEFINE_FINAL_TYPE(TestPurpleProtocol, test_purple_protocol,
@@ -64,7 +66,7 @@
 	}
 	g_clear_object(&task);
 
-	test_protocol->can_connect_async = TRUE;
+	test_protocol->can_connect_async += 1;
 }
 
 static gboolean
@@ -74,11 +76,27 @@
 {
 	TestPurpleProtocol *test_protocol = TEST_PURPLE_PROTOCOL(protocol);
 
-	test_protocol->can_connect_finish = TRUE;
+	test_protocol->can_connect_finish += 1;
 
 	return g_task_propagate_boolean(G_TASK(result), error);
 }
 
+static char *
+test_purple_protocol_generate_account_name(PurpleProtocol *protocol,
+                                           PurpleAccount *account,
+                                           guint n_accounts)
+{
+	TestPurpleProtocol *test_protocol = NULL;
+
+	birb_assert_type(protocol, TEST_PURPLE_TYPE_PROTOCOL);
+	birb_assert_type(account, PURPLE_TYPE_ACCOUNT);
+
+	test_protocol = TEST_PURPLE_PROTOCOL(protocol);
+	test_protocol->generate_account_name += 1;
+
+	return g_strdup_printf("override %u", n_accounts + 1);
+}
+
 static BirbActionMenu *
 test_purple_protocol_get_action_menu(PurpleProtocol *protocol,
                                      PurpleAccount *account)
@@ -99,7 +117,7 @@
 }
 
 static void
-test_purple_protocol_init(G_GNUC_UNUSED TestPurpleProtocol *provider) {
+test_purple_protocol_init(G_GNUC_UNUSED TestPurpleProtocol *protocol) {
 }
 
 static void
@@ -112,23 +130,17 @@
 
 	protocol_class->can_connect_async = test_purple_protocol_can_connect_async;
 	protocol_class->can_connect_finish = test_purple_protocol_can_connect_finish;
+	protocol_class->generate_account_name = test_purple_protocol_generate_account_name;
 	protocol_class->get_action_menu = test_purple_protocol_get_action_menu;
 }
 
-static TestPurpleProtocol *
-test_purple_protocol_new(gboolean result, GError *error) {
-	TestPurpleProtocol *test_protocol = NULL;
-
-	test_protocol = g_object_new(
+static PurpleProtocol *
+test_purple_protocol_new(void) {
+	return g_object_new(
 		TEST_PURPLE_TYPE_PROTOCOL,
-		"id", "test-provider",
-		"name", "Test Provider",
+		"id", "test-protocol",
+		"name", "Test Protocol",
 		NULL);
-
-	test_protocol->result = result;
-	test_protocol->error = error;
-
-	return test_protocol;
 }
 
 /******************************************************************************
@@ -157,12 +169,15 @@
 
 static void
 test_purple_protocol_can_connect_error(void) {
-	TestPurpleProtocol *protocol = NULL;
+	TestPurpleProtocol *test_protocol = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleAccount *account = NULL;
 	GError *error = NULL;
 
 	error = g_error_new(TEST_PROTOCOL_DOMAIN, 0, "no network");
-	protocol = test_purple_protocol_new(FALSE, error);
+	protocol = test_purple_protocol_new();
+	test_protocol = TEST_PURPLE_PROTOCOL(protocol);
+	test_protocol->error = error;
 
 	account = purple_account_new("test", "test");
 
@@ -172,8 +187,8 @@
 
 	g_main_context_iteration(NULL, FALSE);
 
-	g_assert_true(protocol->can_connect_async);
-	g_assert_true(protocol->can_connect_finish);
+	g_assert_cmpuint(test_protocol->can_connect_async, ==, 1);
+	g_assert_cmpuint(test_protocol->can_connect_finish, ==, 1);
 
 	g_assert_finalize_object(protocol);
 	g_clear_object(&account);
@@ -181,10 +196,36 @@
 
 static void
 test_purple_protocol_can_connect_false(void) {
-	TestPurpleProtocol *protocol = NULL;
+	TestPurpleProtocol *test_protocol = NULL;
+	PurpleProtocol *protocol = NULL;
 	PurpleAccount *account = NULL;
 
-	protocol = test_purple_protocol_new(FALSE, NULL);
+	protocol = test_purple_protocol_new();
+	test_protocol = TEST_PURPLE_PROTOCOL(protocol);
+	account = purple_account_new("test", "test");
+
+	purple_protocol_can_connect_async(PURPLE_PROTOCOL(protocol), account, NULL,
+	                                  test_purple_protocol_can_connect_cb,
+	                                  NULL);
+
+	g_main_context_iteration(NULL, FALSE);
+
+	g_assert_cmpuint(test_protocol->can_connect_async, ==, 1);
+	g_assert_cmpuint(test_protocol->can_connect_finish, ==, 1);
+
+	g_assert_finalize_object(protocol);
+	g_clear_object(&account);
+}
+
+static void
+test_purple_protocol_can_connect_true(void) {
+	TestPurpleProtocol *test_protocol = NULL;
+	PurpleProtocol *protocol = NULL;
+	PurpleAccount *account = NULL;
+
+	protocol = test_purple_protocol_new();
+	test_protocol = TEST_PURPLE_PROTOCOL(protocol);
+	test_protocol->result = TRUE;
 	account = purple_account_new("test", "test");
 
 	purple_protocol_can_connect_async(PURPLE_PROTOCOL(protocol), account, NULL,
@@ -193,32 +234,66 @@
 
 	g_main_context_iteration(NULL, FALSE);
 
-	g_assert_true(protocol->can_connect_async);
-	g_assert_true(protocol->can_connect_finish);
+	g_assert_cmpuint(test_protocol->can_connect_async, ==, 1);
+	g_assert_cmpuint(test_protocol->can_connect_finish, ==, 1);
 
 	g_assert_finalize_object(protocol);
 	g_clear_object(&account);
 }
 
 static void
-test_purple_protocol_can_connect_true(void) {
-	TestPurpleProtocol *protocol = NULL;
+test_purple_protocol_generate_account_name_default(void) {
+	TestPurpleProtocol *test_protocol = NULL;
 	PurpleAccount *account = NULL;
+	PurpleProtocol *protocol = NULL;
+	PurpleProtocolClass *klass = NULL;
+	char *name = NULL;
 
-	protocol = test_purple_protocol_new(TRUE, NULL);
+	protocol = test_purple_protocol_new();
+	test_protocol = TEST_PURPLE_PROTOCOL(protocol);
+	klass = PURPLE_PROTOCOL_GET_CLASS(protocol);
+	klass->generate_account_name = PURPLE_PROTOCOL_CLASS(test_purple_protocol_parent_class)->generate_account_name;
+
 	account = purple_account_new("test", "test");
 
-	purple_protocol_can_connect_async(PURPLE_PROTOCOL(protocol), account, NULL,
-	                                  test_purple_protocol_can_connect_cb,
-	                                  NULL);
+	name = purple_protocol_generate_account_name(protocol, account, 0);
+	g_assert_cmpstr(name, ==, "Test Protocol 1");
+	g_clear_pointer(&name, g_free);
 
-	g_main_context_iteration(NULL, FALSE);
+	name = purple_protocol_generate_account_name(protocol, account, 9);
+	g_assert_cmpstr(name, ==, "Test Protocol 10");
+	g_clear_pointer(&name, g_free);
+
+	g_assert_cmpuint(test_protocol->generate_account_name, ==, 0);
+
+	g_assert_finalize_object(account);
+	g_assert_finalize_object(protocol);
+}
 
-	g_assert_true(protocol->can_connect_async);
-	g_assert_true(protocol->can_connect_finish);
+static void
+test_purple_protocol_generate_account_name_override(void) {
+	TestPurpleProtocol *test_protocol = NULL;
+	PurpleAccount *account = NULL;
+	PurpleProtocol *protocol = NULL;
+	char *name = NULL;
+
+	protocol = test_purple_protocol_new();
+	test_protocol = TEST_PURPLE_PROTOCOL(protocol);
+
+	account = purple_account_new("test", "test");
 
+	name = purple_protocol_generate_account_name(protocol, account, 0);
+	g_assert_cmpstr(name, ==, "override 1");
+	g_clear_pointer(&name, g_free);
+
+	name = purple_protocol_generate_account_name(protocol, account, 9);
+	g_assert_cmpstr(name, ==, "override 10");
+	g_clear_pointer(&name, g_free);
+
+	g_assert_cmpuint(test_protocol->generate_account_name, ==, 2);
+
+	g_assert_finalize_object(account);
 	g_assert_finalize_object(protocol);
-	g_clear_object(&account);
 }
 
 static void
@@ -227,12 +302,7 @@
 	PurpleAccount *account = NULL;
 	BirbActionMenu *action_menu = NULL;
 
-	protocol = g_object_new(
-		TEST_PURPLE_TYPE_PROTOCOL,
-		"id", "test-provider",
-		"name", "Test Provider",
-		NULL);
-
+	protocol = test_purple_protocol_new();
 	account = purple_account_new("test", "test");
 
 	action_menu = purple_protocol_get_action_menu(protocol, account);
@@ -257,6 +327,12 @@
 	                test_purple_protocol_can_connect_false);
 	g_test_add_func("/protocol/can-connect/true",
 	                test_purple_protocol_can_connect_true);
+
+	g_test_add_func("/protocol/generate-account-name/override",
+	                test_purple_protocol_generate_account_name_override);
+	g_test_add_func("/protocol/generate-account-name/default",
+	                test_purple_protocol_generate_account_name_default);
+
 	g_test_add_func("/protocol/get-action-menu/valid",
 	                test_purple_protocol_get_action_menu_valid);
 

mercurial