# HG changeset patch
# Node ID a71b044ff8e471781ecf4cc8b519df9095108c71
# Parent  ccd071e7cd830b2f34c510ce58612ea985b39ea5
diff --git a/libpurple/purpleconversation.c b/libpurple/purpleconversation.c
--- a/libpurple/purpleconversation.c
+++ b/libpurple/purpleconversation.c
@@ -1530,6 +1530,7 @@
 {
 	PurpleAccount *account = NULL;
 	PurpleProtocol *protocol = NULL;
+	PurpleProtocolConversation *protocol_conversation = NULL;
 	GTask *task = NULL;
 
 	g_return_if_fail(PURPLE_IS_CONVERSATION(conversation));
@@ -1555,6 +1556,18 @@
 		return;
 	}
 
+	protocol_conversation = PURPLE_PROTOCOL_CONVERSATION(protocol);
+	if(!purple_protocol_conversation_implements_send_message(protocol_conversation))
+	{
+		g_task_return_new_error(task, PURPLE_CONVERSATION_DOMAIN, 0,
+		                        "protocol does not implement "
+		                        "PurpleProtocolConversation.send_message");
+
+		g_clear_object(&task);
+
+		return;
+	}
+
 	purple_protocol_conversation_send_message_async(PURPLE_PROTOCOL_CONVERSATION(protocol),
 	                                                conversation,
 	                                                message,
diff --git a/libpurple/purpleprotocolconversation.c b/libpurple/purpleprotocolconversation.c
--- a/libpurple/purpleprotocolconversation.c
+++ b/libpurple/purpleprotocolconversation.c
@@ -39,13 +39,11 @@
 gboolean
 purple_protocol_conversation_implements_create_conversation(PurpleProtocolConversation *protocol)
 {
-	PurpleProtocolConversation *protocol_conversation = NULL;
 	PurpleProtocolConversationInterface *iface = NULL;
 
 	g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE);
 
-	protocol_conversation = PURPLE_PROTOCOL_CONVERSATION(protocol);
-	iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol_conversation);
+	iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol);
 
 	if(iface->get_create_conversation_details == NULL) {
 		return FALSE;
@@ -140,13 +138,11 @@
 gboolean
 purple_protocol_conversation_implements_leave_conversation(PurpleProtocolConversation *protocol)
 {
-	PurpleProtocolConversation *protocol_conversation = NULL;
 	PurpleProtocolConversationInterface *iface = NULL;
 
 	g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE);
 
-	protocol_conversation = PURPLE_PROTOCOL_CONVERSATION(protocol);
-	iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol_conversation);
+	iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol);
 
 	if(iface->leave_conversation_async == NULL) {
 		return FALSE;
@@ -213,6 +209,26 @@
 	return FALSE;
 }
 
+gboolean
+purple_protocol_conversation_implements_send_message(PurpleProtocolConversation *protocol)
+{
+	PurpleProtocolConversationInterface *iface = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_PROTOCOL_CONVERSATION(protocol), FALSE);
+
+	iface = PURPLE_PROTOCOL_CONVERSATION_GET_IFACE(protocol);
+
+	if(iface->send_message_async == NULL) {
+		return FALSE;
+	}
+
+	if(iface->send_message_finish == NULL) {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 void
 purple_protocol_conversation_send_message_async(PurpleProtocolConversation *protocol,
                                                 PurpleConversation *conversation,
diff --git a/libpurple/purpleprotocolconversation.h b/libpurple/purpleprotocolconversation.h
--- a/libpurple/purpleprotocolconversation.h
+++ b/libpurple/purpleprotocolconversation.h
@@ -228,6 +228,23 @@
 gboolean purple_protocol_conversation_leave_conversation_finish(PurpleProtocolConversation *protocol, GAsyncResult *result, GError **error);
 
 /**
+ * purple_protocol_conversation_implements_send_message:
+ * @protocol: The instance.
+ *
+ * Checks if a protocols implements all of the send message virtual functions.
+ *
+ * This checks if the [vfunc@ProtocolConversation.send_message_async] and
+ * [vfunc@ProtocolConversation.send_message_finish] functions are implemented.
+ *
+ * Returns: %TRUE if @protocol implements all of the virtual functions for
+ *          sending messages, otherwise %FALSE.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+gboolean purple_protocol_conversation_implements_send_message(PurpleProtocolConversation *protocol);
+
+/**
  * purple_protocol_conversation_send_message_async:
  * @protocol: The instance.
  * @conversation: The conversation to send a message to.
diff --git a/libpurple/tests/test_protocol_conversation.c b/libpurple/tests/test_protocol_conversation.c
--- a/libpurple/tests/test_protocol_conversation.c
+++ b/libpurple/tests/test_protocol_conversation.c
@@ -167,6 +167,18 @@
  * Empty Leave Conversation Tests
  *****************************************************************************/
 static void
+test_purple_protocol_conversation_empty_implements_leave_conversation(void) {
+	PurpleProtocolConversation *protocol = NULL;
+
+	protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(),
+	                        NULL);
+
+	g_assert_false(purple_protocol_conversation_implements_leave_conversation(protocol));
+
+	g_assert_finalize_object(protocol);
+}
+
+static void
 test_purple_protocol_conversation_empty_leave_conversation_async_cb(GObject *source,
                                                                     GAsyncResult *result,
                                                                     G_GNUC_UNUSED gpointer data)
@@ -230,6 +242,18 @@
 }
 
 static void
+test_purple_protocol_conversation_implementes_send_message(void) {
+	PurpleProtocolConversation *protocol = NULL;
+
+	protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(),
+	                        NULL);
+
+	g_assert_false(purple_protocol_conversation_implements_send_message(protocol));
+
+	g_assert_finalize_object(protocol);
+}
+
+static void
 test_purple_protocol_conversation_empty_send_message_async(void) {
 	PurpleAccount *account = NULL;
 	PurpleConversation *conversation = NULL;
@@ -414,6 +438,18 @@
 }
 
 static void
+test_purple_protocol_conversation_empty_implements_send_typing(void) {
+	PurpleProtocolConversation *protocol = NULL;
+
+	protocol = g_object_new(test_purple_protocol_conversation_empty_get_type(),
+	                        NULL);
+
+	g_assert_false(purple_protocol_conversation_implements_send_typing(protocol));
+
+	g_assert_finalize_object(protocol);
+}
+
+static void
 test_purple_protocol_conversation_empty_send_typing(void) {
 	if(g_test_subprocess()) {
 		PurpleAccount *account = NULL;
@@ -1084,6 +1120,18 @@
 }
 
 static void
+test_purple_protocol_conversation_implements_send_message(void) {
+	PurpleProtocolConversation *protocol = NULL;
+
+	protocol = g_object_new(test_purple_protocol_conversation_get_type(),
+	                        NULL);
+
+	g_assert_true(purple_protocol_conversation_implements_send_message(protocol));
+
+	g_assert_finalize_object(protocol);
+}
+
+static void
 test_purple_protocol_conversation_send_message_normal(gconstpointer data) {
 	TestPurpleProtocolConversation *protocol = NULL;
 
@@ -1360,6 +1408,18 @@
  * TestProtocolConversation Send Typing Tests
  ****************************************************************************/
 static void
+test_purple_protocol_conversation_implements_send_typing(void) {
+	PurpleProtocolConversation *protocol = NULL;
+
+	protocol = g_object_new(test_purple_protocol_conversation_get_type(),
+	                        NULL);
+
+	g_assert_true(purple_protocol_conversation_implements_send_typing(protocol));
+
+	g_assert_finalize_object(protocol);
+}
+
+static void
 test_purple_protocol_conversation_send_typing_normal(void) {
 	TestPurpleProtocolConversation *test_protocol = NULL;
 	PurpleAccount *account = NULL;
@@ -1413,12 +1473,17 @@
 	                test_purple_protocol_conversation_empty_create_conversation_async);
 
 	/* Empty leave conversation tests. */
+	g_test_add_func("/protocol-conversation/empty/implements-leave-conversation",
+	                test_purple_protocol_conversation_empty_implements_leave_conversation);
 	g_test_add_func("/protocol-conversation/empty/leave-conversation-async",
 	                test_purple_protocol_conversation_empty_leave_conversation_async);
 
 	/* Empty send message tests. */
+	g_test_add_func("/protocol-conversation/empty/implements-send-message",
+	                test_purple_protocol_conversation_implementes_send_message);
 	g_test_add_func("/protocol-conversation/empty/send-message-async",
 	                test_purple_protocol_conversation_empty_send_message_async);
+
 	g_test_add_func("/protocol-conversation/empty/set-topic-async",
 	                test_purple_protocol_conversation_empty_set_topic_async);
 	g_test_add_func("/protocol-conversation/empty/set-avatar-async",
@@ -1431,6 +1496,8 @@
 	                test_purple_protocol_conversation_empty_join_channel_async);
 
 	/* Empty send typing tests. */
+	g_test_add_func("/protocol-conversation/empty/implements-send-typing",
+	                test_purple_protocol_conversation_empty_implements_send_typing);
 	g_test_add_func("/protocol-conversation/empty/send-typing",
 	                test_purple_protocol_conversation_empty_send_typing);
 
@@ -1457,6 +1524,8 @@
 	                     test_purple_protocol_conversation_leave_conversation_normal);
 
 	/* Normal send message tests. */
+	g_test_add_func("/protocol-conversation/normal/implements-send-message",
+	                test_purple_protocol_conversation_implements_send_message);
 	g_test_add_data_func("/protocol-conversation/normal/send-message-normal",
 	                     GINT_TO_POINTER(FALSE),
 	                     test_purple_protocol_conversation_send_message_normal);
@@ -1491,6 +1560,8 @@
 	                     test_purple_protocol_conversation_set_avatar_normal);
 
 	/* Normal send typing tests. */
+	g_test_add_func("/protocol-conversation/normal/implements-send-typing",
+	                test_purple_protocol_conversation_implements_send_typing);
 	g_test_add_func("/protocol-conversation/normal/send-typing",
 	                test_purple_protocol_conversation_send_typing_normal);
 
