[Libreoffice-commits] .: Branch 'feature/tubes2' - 3 commits - tubes/inc tubes/qa tubes/source
Will Thompson
wjt at kemper.freedesktop.org
Fri Mar 23 02:00:12 PDT 2012
tubes/inc/tubes/conference.hxx | 2
tubes/inc/tubes/file-transfer-helper.h | 3
tubes/inc/tubes/manager.hxx | 9 ++
tubes/qa/test_manager.cxx | 30 ++++++
tubes/source/conference.cxx | 5 -
tubes/source/file-transfer-helper.c | 29 +++++-
tubes/source/manager.cxx | 148 +++++++++++++++++++++++++++++++--
7 files changed, 212 insertions(+), 14 deletions(-)
New commits:
commit 7b662a91f6452f22265fb99ff782539f43dd2095
Author: Will Thompson <will.thompson at collabora.co.uk>
Date: Fri Mar 23 08:57:52 2012 +0000
tubes: remove "account without account??" warning
It's completely kosher for Telepathy accounts not to have a parameter
called 'account' (which really means 'username'): Salut (link-local
XMPP) accounts do not, for example, because you don't need to specify a
username.
tp_account_get_normalized_name() gets your contact ID for an account,
which is really what we're looking for here.
diff --git a/tubes/source/manager.cxx b/tubes/source/manager.cxx
index b479d5d..cb9e5d7 100644
--- a/tubes/source/manager.cxx
+++ b/tubes/source/manager.cxx
@@ -668,9 +668,7 @@ TpAccount* TeleManager::getAccount( const rtl::OString& rAccountID )
for (GList* pA = pAccounts; pA; pA = pA->next)
{
TpAccount* pAcc = TP_ACCOUNT( pA->data);
- const GHashTable* pPar = tp_account_get_parameters( pAcc);
- const gchar* pID = tp_asv_get_string( pPar, "account");
- SAL_WARN_IF( !pID, "tubes", "TeleManager::getMyAccount: account without account??");
+ const gchar* pID = tp_account_get_normalized_name( pAcc);
if (pID && rAccountID == pID)
{
pAccount = pAcc;
commit 25c39927fd338283d2441694eb00b7e595b68f4c
Author: Will Thompson <will.thompson at collabora.co.uk>
Date: Fri Mar 23 08:53:21 2012 +0000
tubes: implement receiving files.
diff --git a/tubes/inc/tubes/conference.hxx b/tubes/inc/tubes/conference.hxx
index 7428bcb..7c5fd30 100644
--- a/tubes/inc/tubes/conference.hxx
+++ b/tubes/inc/tubes/conference.hxx
@@ -94,6 +94,8 @@ public:
{ return mbTubeChannelStateChangedHandlerInvoked; }
void setTubeChannelState( TpTubeChannelState eState ) { meTubeChannelState = eState; }
+ static void FTReady( EmpathyFTHandler *handler, GError *error, gpointer user_data);
+
private:
rtl::OString maSessionId;
diff --git a/tubes/inc/tubes/file-transfer-helper.h b/tubes/inc/tubes/file-transfer-helper.h
index fe0678f..8960d14 100644
--- a/tubes/inc/tubes/file-transfer-helper.h
+++ b/tubes/inc/tubes/file-transfer-helper.h
@@ -90,6 +90,9 @@ void empathy_ft_handler_new_outgoing (
gint64 action_time,
EmpathyFTHandlerReadyCallback callback,
gpointer user_data);
+void empathy_ft_handler_set_service_name (
+ EmpathyFTHandler *self,
+ const gchar *service_name);
void empathy_ft_handler_new_incoming (TpFileTransferChannel *channel,
EmpathyFTHandlerReadyCallback callback,
diff --git a/tubes/inc/tubes/manager.hxx b/tubes/inc/tubes/manager.hxx
index 97f5de8..0d2ef3e 100644
--- a/tubes/inc/tubes/manager.hxx
+++ b/tubes/inc/tubes/manager.hxx
@@ -140,6 +140,9 @@ public:
void sendFile( rtl::OUString &localUri, TeleConference::FileSentCallback pCallback, void* pUserData);
+ typedef void (*FileReceivedCallback)( rtl::OUString &localUri, void* pUserData );
+ void setFileReceivedCallback( FileReceivedCallback callback, void* pUserData );
+
/// Only for use with MainLoopFlusher
GMainLoop* getMainLoop() const;
@@ -197,6 +200,9 @@ public:
TpAccount* getAccount( const rtl::OString& rAccountID );
+/* Callbacks; not for use outside this class. */
+ static void TransferDone( EmpathyFTHandler *handler, TpFileTransferChannel *, gpointer user_data);
+
private:
TeleConferenceVector maConferences;
@@ -207,6 +213,9 @@ private:
static sal_uInt32 nRefCount;
static rtl::OString aNameSuffix;
+ FileReceivedCallback mpFileReceivedCallback;
+ void *mpFileReceivedCallbackData;
+
friend class TeleManagerImpl; // access to mutex
TUBES_DLLPRIVATE static ::osl::Mutex& GetMutex();
diff --git a/tubes/qa/test_manager.cxx b/tubes/qa/test_manager.cxx
index d08190d..540728a 100644
--- a/tubes/qa/test_manager.cxx
+++ b/tubes/qa/test_manager.cxx
@@ -70,6 +70,7 @@ public:
void spinMainLoop();
static void FileSent( bool success, void *user_data);
+ static void FileReceived( rtl::OUString& aUri, void *user_data);
// Order is significant.
CPPUNIT_TEST_SUITE( TestTeleTubes );
@@ -102,6 +103,7 @@ private:
rtl::OString maAccepterIdentifier;
bool maFileSentSuccess;
+ rtl::OUString maFileReceivedUri;
};
// static, not members, so they actually survive cppunit test iteration
@@ -299,17 +301,33 @@ void TestTeleTubes::FileSent( bool success, void *user_data)
g_main_loop_quit (self->mpMainLoop);
}
+void TestTeleTubes::FileReceived( rtl::OUString& aUri, void *user_data)
+{
+ TestTeleTubes *self = reinterpret_cast<TestTeleTubes *>(user_data);
+
+ self->maFileReceivedUri = aUri;
+ g_main_loop_quit (self->mpMainLoop);
+}
+
void TestTeleTubes::testSendFile()
{
TpAccount *pAcc1 = mpManager1->getAccount(maOffererIdentifier);
CPPUNIT_ASSERT( pAcc1 != 0);
/* This has to run after testContactList has run successfully. */
CPPUNIT_ASSERT( mpAccepterContact != 0);
+
+ mpManager1->setFileReceivedCallback(&TestTeleTubes::FileReceived, this);
+
mpManager1->sendFile( maTestConfigIniURL,
&TestTeleTubes::FileSent, this);
+ /* Waiting for two events: FileSent and FileReceived both quit the mainloop */
+ spinMainLoop();
spinMainLoop();
CPPUNIT_ASSERT( maFileSentSuccess);
+ CPPUNIT_ASSERT_MESSAGE(
+ OUStringToOString( maFileReceivedUri, RTL_TEXTENCODING_UTF8).getStr(),
+ maFileReceivedUri == "file:///tmp/fixme.ods");
}
void TestTeleTubes::testFlushLoops()
diff --git a/tubes/source/conference.cxx b/tubes/source/conference.cxx
index 9a35c70..88ec817 100644
--- a/tubes/source/conference.cxx
+++ b/tubes/source/conference.cxx
@@ -479,7 +479,7 @@ static void TeleConference_TransferError( EmpathyFTHandler *handler, const GErro
g_object_unref (handler);
}
-static void TeleConference_FTReady( EmpathyFTHandler *handler, GError *error, gpointer user_data)
+void TeleConference::FTReady( EmpathyFTHandler *handler, GError *error, gpointer user_data)
{
SendFileRequest *request = reinterpret_cast<SendFileRequest *>(user_data);
@@ -495,6 +495,7 @@ static void TeleConference_FTReady( EmpathyFTHandler *handler, GError *error, gp
G_CALLBACK (TeleConference_TransferDone), request);
g_signal_connect(handler, "transfer-error",
G_CALLBACK (TeleConference_TransferError), request);
+ empathy_ft_handler_set_service_name(handler, request->mpSelf->mpManager->getFullServiceName().getStr());
empathy_ft_handler_start_transfer(handler);
}
}
@@ -517,7 +518,7 @@ void TeleConference::sendFile( rtl::OUString &localUri, FileSentCallback pCallba
tp_channel_get_target_contact( mpChannel),
pSource,
0,
- &TeleConference_FTReady, pReq);
+ &TeleConference::FTReady, pReq);
}
diff --git a/tubes/source/file-transfer-helper.c b/tubes/source/file-transfer-helper.c
index ca1a70b..15e3dfd 100644
--- a/tubes/source/file-transfer-helper.c
+++ b/tubes/source/file-transfer-helper.c
@@ -134,6 +134,7 @@ struct _EmpathyFTHandlerPriv {
guint64 mtime;
gchar *content_hash;
TpFileHashType content_hash_type;
+ gchar *service_name;
gint64 user_action_time;
@@ -260,6 +261,11 @@ do_dispose (GObject *object)
priv->dispose_run = TRUE;
+ if (priv->account != NULL) {
+ g_object_unref (priv->account);
+ priv->account = NULL;
+ }
+
if (priv->contact != NULL) {
g_object_unref (priv->contact);
priv->contact = NULL;
@@ -310,6 +316,9 @@ do_finalize (GObject *object)
g_free (priv->content_hash);
priv->content_hash = NULL;
+ g_free (priv->service_name);
+ priv->service_name = NULL;
+
G_OBJECT_CLASS (empathy_ft_handler_parent_class)->finalize (object);
}
@@ -907,6 +916,9 @@ ft_handler_populate_outgoing_request (EmpathyFTHandler *handler)
TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_URI, G_TYPE_STRING, uri,
NULL);
+ if (priv->service_name != NULL)
+ tp_asv_set_string (priv->request, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, priv->service_name);
+
g_free (uri);
}
@@ -1358,11 +1370,11 @@ channel_prepared_cb (
properties = tp_channel_borrow_immutable_properties (TP_CHANNEL (channel));
- priv->content_hash = g_value_dup_string (
- g_hash_table_lookup (properties, "ContentHash"));
+ priv->content_hash = g_strdup (
+ tp_asv_get_string (properties, "ContentHash"));
- priv->content_hash_type = g_value_get_uint (
- g_hash_table_lookup (properties, "ContentHashType"));
+ priv->content_hash_type = tp_asv_get_uint32 (
+ properties, "ContentHashType", NULL);
priv->contact = g_object_ref (tp_channel_get_target_contact (TP_CHANNEL (channel)));
@@ -1426,6 +1438,15 @@ empathy_ft_handler_new_outgoing (
NULL, (GAsyncReadyCallback) ft_handler_gfile_ready_cb, data);
}
+void
+empathy_ft_handler_set_service_name (
+ EmpathyFTHandler *self,
+ const gchar *service_name)
+{
+ g_free (self->priv->service_name);
+ self->priv->service_name = g_strdup (service_name);
+}
+
/**
* empathy_ft_handler_new_incoming:
* @channel: the #TpFileTransferChannel proxy to the incoming channel
diff --git a/tubes/source/manager.cxx b/tubes/source/manager.cxx
index 8403270..b479d5d 100644
--- a/tubes/source/manager.cxx
+++ b/tubes/source/manager.cxx
@@ -31,6 +31,7 @@
#include <rtl/strbuf.hxx>
#include <rtl/uuid.h>
#include <osl/mutex.hxx>
+#include <cstring>
#if defined SAL_LOG_INFO
@@ -77,6 +78,7 @@ public:
GMainLoop* mpLoop;
TpDBusDaemon* mpDBus;
TpBaseClient* mpClient;
+ TpBaseClient* mpFileTransferClient;
TpAccountManager* mpAccountManager;
TeleManager::AccountManagerStatus meAccountManagerStatus;
bool mbAccountManagerReadyHandlerInvoked;
@@ -172,6 +174,102 @@ static void TeleManager_DBusChannelHandler(
}
}
+void TeleManager::TransferDone( EmpathyFTHandler *handler, TpFileTransferChannel *, gpointer pUserData)
+{
+ TeleManager* pManager = reinterpret_cast<TeleManager*>(pUserData);
+
+ SAL_INFO( "tubes", "TeleConference_TransferDone: hooray!");
+ GFile *gfile = empathy_ft_handler_get_gfile( handler);
+ char *uri = g_file_get_uri( gfile);
+ rtl::OUString aUri( uri, strlen( uri), RTL_TEXTENCODING_UTF8);
+ g_free( uri);
+
+ pManager->mpFileReceivedCallback( aUri, pManager->mpFileReceivedCallbackData);
+
+ //g_object_unref( handler);
+}
+
+static void TeleManager_TransferError( EmpathyFTHandler *handler, const GError *error, void*)
+{
+ SAL_INFO( "tubes", "TeleConference_TransferError: " << error->message);
+
+ //g_object_unref( handler);
+}
+
+static void
+TeleManager_IncomingHandlerReady (
+ EmpathyFTHandler* pHandler,
+ GError* pError,
+ void* pUserData)
+{
+ TeleManager* pManager = reinterpret_cast<TeleManager*>(pUserData);
+
+ if (pError)
+ {
+ SAL_INFO ("tubes", "failed to prepare incoming transfer: " << pError->message);
+ g_object_unref( pHandler);
+ return;
+ }
+
+ GFile *pDestination = g_file_new_for_uri( "file:///tmp/fixme.ods");
+
+ empathy_ft_handler_incoming_set_destination( pHandler, pDestination);
+ g_object_unref( pDestination);
+
+ g_signal_connect( pHandler, "transfer-done", G_CALLBACK (&TeleManager::TransferDone), pManager);
+ g_signal_connect( pHandler, "transfer-error", G_CALLBACK (TeleManager_TransferError), pManager);
+ empathy_ft_handler_start_transfer( pHandler);
+}
+
+static void TeleManager_FileTransferHandler(
+ TpSimpleHandler* /*handler*/,
+ TpAccount* /*Account*/,
+ TpConnection* /*connection*/,
+ GList* pChannels,
+ GList* /*requests_satisfied*/,
+ gint64 /*user_action_time*/,
+ TpHandleChannelsContext* pContext,
+ gpointer pUserData)
+{
+ bool aAccepted = false;
+ INFO_LOGGER_F( "TeleManager_FileTransferHandler");
+
+ TeleManager* pManager = reinterpret_cast<TeleManager*>(pUserData);
+ SAL_WARN_IF( !pManager, "tubes", "TeleManager_FileTransferHandler: no manager");
+ if (!pManager)
+ return;
+
+ for (GList* p = pChannels; p; p = p->next)
+ {
+ TpChannel* pChannel = TP_CHANNEL(p->data);
+
+ SAL_INFO( "tubes", "TeleManager_FileTransferHandler: incoming dbus channel: "
+ << tp_channel_get_identifier( pChannel));
+
+ if (TP_IS_FILE_TRANSFER_CHANNEL( pChannel))
+ {
+ SAL_INFO( "tubes", "accepting file transfer");
+ empathy_ft_handler_new_incoming( TP_FILE_TRANSFER_CHANNEL( pChannel),
+ TeleManager_IncomingHandlerReady, pManager);
+ aAccepted = true;
+ }
+ else
+ {
+ SAL_INFO( "tubes", "ignored");
+ }
+ }
+
+ if (aAccepted)
+ tp_handle_channels_context_accept( pContext);
+ else
+ {
+ GError *pError = g_error_new_literal( TP_ERRORS, TP_ERROR_CONFUSED,
+ "None of these channels were file transfers; "
+ "why did the Channel Dispatcher give them to us?");
+ tp_handle_channels_context_fail( pContext, pError);
+ g_clear_error (&pError);
+ }
+}
static void TeleManager_ChannelReadyHandler(
GObject* pSourceObject,
@@ -296,13 +394,13 @@ bool TeleManager::connect()
return false;
}
- TpSimpleClientFactory* pFactory = tp_simple_client_factory_new( pImpl->mpDBus);
+ TpAutomaticClientFactory* pFactory = tp_automatic_client_factory_new( pImpl->mpDBus);
SAL_WARN_IF( !pFactory, "tubes", "TeleManager::connect: no client factory");
if (!pFactory)
return false;
pImpl->mpClient = tp_simple_handler_new_with_factory(
- pFactory, // factory
+ TP_SIMPLE_CLIENT_FACTORY (pFactory), // factory
FALSE, // bypass_approval
FALSE, // requests
getFullClientName().getStr(), // name
@@ -346,6 +444,36 @@ bool TeleManager::connect()
SAL_INFO( "tubes", "TeleManager::connect: bus name: " << tp_base_client_get_bus_name( pImpl->mpClient));
SAL_INFO( "tubes", "TeleManager::connect: object path: " << tp_base_client_get_object_path( pImpl->mpClient));
+ /* Register a second "head" for incoming file transfers. This uses a more
+ * specific filter than Empathy's handler by matching on the file
+ * transfer's ServiceName property, and uses bypass_approval to ensure the
+ * user isn't prompted before the channel gets passed to us.
+ */
+ pImpl->mpFileTransferClient = tp_simple_handler_new_with_factory (
+ TP_SIMPLE_CLIENT_FACTORY( pFactory), // factory
+ TRUE, // bypass_approval
+ FALSE, // requests
+ getFullClientName().getStr(), // name
+ TRUE, // uniquify to get a different bus name to the main client, above
+ TeleManager_FileTransferHandler, // callback
+ this, // user_data
+ NULL // destroy
+ );
+ tp_base_client_take_handler_filter( pImpl->mpFileTransferClient,
+ tp_asv_new(
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
+ TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, G_TYPE_STRING, getFullServiceName().getStr(),
+ NULL));
+
+ if (!tp_base_client_register( pImpl->mpFileTransferClient, &pError))
+ {
+ /* This shouldn't fail if registering the main handler succeeded */
+ SAL_WARN( "tubes", "TeleManager::connect: error registering file transfer handler: " << pError->message);
+ g_error_free( pError);
+ return false;
+ }
+
return true;
}
@@ -603,6 +731,12 @@ void TeleManager::sendFile( rtl::OUString &localUri, TeleConference::FileSentCal
}
}
+void TeleManager::setFileReceivedCallback( TeleManager::FileReceivedCallback callback, void* pUserData )
+{
+ mpFileReceivedCallback = callback;
+ mpFileReceivedCallbackData = pUserData;
+}
+
void TeleManager::unregisterConference( TeleConferencePtr pConference )
{
INFO_LOGGER( "TeleManager::unregisterConference");
@@ -625,6 +759,9 @@ void TeleManager::disconnect()
tp_base_client_unregister( pImpl->mpClient);
pImpl->mpClient = NULL;
+ tp_base_client_unregister( pImpl->mpFileTransferClient);
+ pImpl->mpFileTransferClient = NULL;
+
size_t nSize = maConferences.size();
for (size_t i=0; i < nSize; /*nop*/)
{
@@ -798,6 +935,7 @@ TeleManagerImpl::TeleManagerImpl()
mpLoop( NULL),
mpDBus( NULL),
mpClient( NULL),
+ mpFileTransferClient( NULL),
mpAccountManager( NULL),
meAccountManagerStatus( TeleManager::AMS_UNINITIALIZED),
mbAccountManagerReadyHandlerInvoked( false)
@@ -809,6 +947,8 @@ TeleManagerImpl::~TeleManagerImpl()
{
if (mpClient)
g_object_unref( mpClient);
+ if (mpFileTransferClient)
+ g_object_unref( mpFileTransferClient);
if (mpDBus)
g_object_unref( mpDBus);
if (mpAccountManager)
commit 50280f414ffac039e225ed2aa4340ae4e1805611
Author: Will Thompson <will.thompson at collabora.co.uk>
Date: Fri Mar 23 08:50:44 2012 +0000
tubes test: fix stack corruption on test failure
We can't use CPPUNIT_ASSERT() from a callback called by C code (such as
the FileSent callback), or we'll trash the stack if it fails.
diff --git a/tubes/qa/test_manager.cxx b/tubes/qa/test_manager.cxx
index ce9a2d0..d08190d 100644
--- a/tubes/qa/test_manager.cxx
+++ b/tubes/qa/test_manager.cxx
@@ -69,6 +69,8 @@ public:
GMainLoop* mpMainLoop;
void spinMainLoop();
+ static void FileSent( bool success, void *user_data);
+
// Order is significant.
CPPUNIT_TEST_SUITE( TestTeleTubes );
CPPUNIT_TEST( testSetupManager1 );
@@ -98,6 +100,8 @@ private:
rtl::OString maOffererIdentifier;
rtl::OString maAccepterIdentifier;
+
+ bool maFileSentSuccess;
};
// static, not members, so they actually survive cppunit test iteration
@@ -287,11 +291,11 @@ void TestTeleTubes::testReceivePacket()
CPPUNIT_ASSERT( nReceivedPackets == nSentPackets);
}
-static void TestTeleTubes_FileSent( bool success, void *user_data)
+void TestTeleTubes::FileSent( bool success, void *user_data)
{
TestTeleTubes *self = reinterpret_cast<TestTeleTubes *>(user_data);
- CPPUNIT_ASSERT( success);
+ self->maFileSentSuccess = success;
g_main_loop_quit (self->mpMainLoop);
}
@@ -302,8 +306,10 @@ void TestTeleTubes::testSendFile()
/* This has to run after testContactList has run successfully. */
CPPUNIT_ASSERT( mpAccepterContact != 0);
mpManager1->sendFile( maTestConfigIniURL,
- TestTeleTubes_FileSent, this);
+ &TestTeleTubes::FileSent, this);
spinMainLoop();
+
+ CPPUNIT_ASSERT( maFileSentSuccess);
}
void TestTeleTubes::testFlushLoops()
More information about the Libreoffice-commits
mailing list