From: Jerzy Pabich Date: Tue, 16 Dec 2014 09:24:19 +0000 (+0100) Subject: [Messaging] Added DBus signal handling X-Git-Tag: submit/tizen_tv/20150603.064601~1^2~809^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3c67c33a6e604d15f32536d78e26db8849201b29;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Messaging] Added DBus signal handling Change-Id: I9241b4b3f11fd50b8d4bd0c4131da99f597529f7 Signed-off-by: Jerzy Pabich --- diff --git a/src/messaging/DBus/Connection.cpp b/src/messaging/DBus/Connection.cpp new file mode 100644 index 00000000..e1a49348 --- /dev/null +++ b/src/messaging/DBus/Connection.cpp @@ -0,0 +1,60 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "Connection.h" +#include "common/logger.h" +//#include +#include +#include +#include "../message_service.h" + +namespace extension { +namespace messaging { +namespace DBus { + +Connection& Connection::getInstance() +{ + LOGD("Entered"); + static Connection instance; + return instance; +} + +GDBusConnection* Connection::getDBus() +{ + return m_dbus; +} + +Connection::Connection() +{ + dbus_g_thread_init(); + g_type_init(); + + m_dbus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &m_error); + if (!m_dbus || m_error) { + LOGE("Could not get connection"); + } + LOGD("Connection set"); +} + +Connection::~Connection() +{ + g_object_unref(m_dbus); +} + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI diff --git a/src/messaging/DBus/Connection.h b/src/messaging/DBus/Connection.h new file mode 100644 index 00000000..07084e32 --- /dev/null +++ b/src/messaging/DBus/Connection.h @@ -0,0 +1,49 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef __TIZEN_DBUS_CONNECTION_H__ +#define __TIZEN_DBUS_CONNECTION_H__ + +#include +#include +#include + +namespace extension { +namespace messaging { +namespace DBus { + +class Connection { +public: + static Connection& getInstance(); + + GDBusConnection* getDBus(); + +private: + Connection(); + Connection(const Connection&); + void operator=(const Connection&); + virtual ~Connection(); + + GDBusConnection* m_dbus; + GError* m_error; +}; + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI + +#endif diff --git a/src/messaging/DBus/EmailSignalProxy.cpp b/src/messaging/DBus/EmailSignalProxy.cpp new file mode 100644 index 00000000..72149f17 --- /dev/null +++ b/src/messaging/DBus/EmailSignalProxy.cpp @@ -0,0 +1,85 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file EmailSignalProxy.cpp + */ + +#include "EmailSignalProxy.h" +#include "common/logger.h" +#include +//#include + +namespace extension { +namespace messaging { +namespace DBus { + +EmailSignalProxy::EmailSignalProxy(const std::string& proxy_path, + const std::string& proxy_iface) : + Proxy (proxy_path, + proxy_iface, + Proxy::DBUS_NAME_SIGNAL_EMAIL, //specify email signal details + DBUS_PATH_NETWORK_STATUS, + DBUS_IFACE_NETWORK_STATUS) +{ +} + +EmailSignalProxy::~EmailSignalProxy() +{ + +} + +void EmailSignalProxy::signalCallback(GDBusConnection* connection, + const gchar* sender_name, + const gchar* object_path, + const gchar* interface_name, + const gchar* signal_name, + GVariant* parameters) +{ + int status, mail_id, op_handle, error_code; + char* source = NULL; + + try { + g_variant_get(parameters, "(iisii)", + &status, + &mail_id, + &source, + &op_handle, + &error_code); + + //It is better to log this only when subclass is responsible of handling + //passed signal (usually determined by status value). + // + //LOGD("email:\n status: %d\n mail_id: %d\n " + // "source: %s\n op_handle: %d\n error_code: %d", + // status, mail_id, source, op_handle, error_code); + + handleEmailSignal(status, mail_id, source, op_handle, error_code); + +// } catch(const Common::BasePlatformException& exception) { +// LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(), +// (exception.getMessage()).c_str()); + } catch(...) { + LOGE("Unhandled exception!"); + } + + g_free(source); +} + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI diff --git a/src/messaging/DBus/EmailSignalProxy.h b/src/messaging/DBus/EmailSignalProxy.h new file mode 100644 index 00000000..74789815 --- /dev/null +++ b/src/messaging/DBus/EmailSignalProxy.h @@ -0,0 +1,64 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file EmailSignalProxy.h + */ + +#ifndef __TIZEN_DBUS_EMAIL_SIGNAL_PROXY_H__ +#define __TIZEN_DBUS_EMAIL_SIGNAL_PROXY_H__ + +#include "Proxy.h" + +namespace extension { +namespace messaging { +namespace DBus { + +class EmailSignalProxy; +typedef std::shared_ptr EmailSignalProxyPtr; + +class EmailSignalProxy : public Proxy { +public: + EmailSignalProxy(const std::string& proxy_path, + const std::string& proxy_iface); + virtual ~EmailSignalProxy(); + +protected: + /** + * Override this method in subclass to handle email signal + */ + virtual void handleEmailSignal(const int status, + const int mail_id, + const std::string& source, + const int op_handle, + const int error_code) = 0; + + virtual void signalCallback(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters); + +private: +}; + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI + +#endif // __TIZEN_DBUS_EMAIL_SIGNAL_PROXY_H__ diff --git a/src/messaging/DBus/LoadAttachmentProxy.cpp b/src/messaging/DBus/LoadAttachmentProxy.cpp new file mode 100644 index 00000000..55eac0bf --- /dev/null +++ b/src/messaging/DBus/LoadAttachmentProxy.cpp @@ -0,0 +1,231 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file LoadAttachmentProxy.cpp + */ + +#include "LoadAttachmentProxy.h" +#include +#include +#include +#include +#include "MessageService.h" +#include "Message.h" +#include "MessageBody.h" +#include "EmailManager.h" +#include "JSMessageAttachment.h" +#include +#include + +namespace DeviceAPI { +namespace Messaging { +namespace DBus { + +/** + * This method perform very specified task (see warning comment) so it should not be + * visible outside LoadAttachmentProxy class. + */ +void updateAttachmentDataWithEmailGetAttachmentData( + std::shared_ptr attachment) +{ + struct ScopedEmailAttachmentData { + ScopedEmailAttachmentData() : data(NULL) { } + ~ScopedEmailAttachmentData() { + if(data) { + email_free_attachment_data(&data, 1); + } + } + email_attachment_data_t* operator->() { return data; } + email_attachment_data_t* data; + } attachment_data_holder; + + LOGD("attachmentId = %d", attachment->getId()); + + /* + * WARNING: email_get_attachment_data seems to be getting NOT COMPLETE + * email_attachment_data_t object, observed that: + * mail_id is 0 + * account_id is 0 + * mailbox_id is 0 + * Thus currently only attachment_path and attachment_mime_type is used! + * + * To get COMPLETE data please use: Message::convertEmailToMessageAttachment + * mtehod which fetches all attachments from specified email. + */ + int err = email_get_attachment_data(attachment->getId(), &attachment_data_holder.data); + if (EMAIL_ERROR_NONE != err || + NULL == attachment_data_holder.data) { + LOGE("Couldn't get attachment data for attachmentId:%d", attachment->getId()); + throw Common::UnknownException("Couldn't get attachment."); + } + + LOGD("attachment name : %s", attachment_data_holder->attachment_name); + + if(attachment_data_holder->attachment_mime_type) { + attachment->setMimeType(attachment_data_holder->attachment_mime_type); + } + + bool isSaved = false; + if (attachment_data_holder->attachment_path) { + LOGD("set attachment path: %s", attachment_data_holder->attachment_path); + attachment->setFilePath(attachment_data_holder->attachment_path); + + LOGD("save_status: %d", attachment_data_holder->save_status); + LOGD("attachment_size : %d", attachment_data_holder->attachment_size); + } + isSaved = attachment_data_holder->save_status; + attachment->setIsSaved(isSaved); +} + +LoadAttachmentProxy::LoadAttachmentProxy(const std::string& path, + const std::string& iface) : + EmailSignalProxy(path, iface) +{ +} + +LoadAttachmentProxy::~LoadAttachmentProxy() +{ +} + +void LoadAttachmentProxy::addCallback(MessageAttachmentCallbackData* callbackOwned) +{ + if(callbackOwned->getMessageAttachment()) { + LOGD("Registered callback for attachment_id: %d mail_id:%d op_handle:%d nth:%d", + callbackOwned->getMessageAttachment()->getId(), + callbackOwned->getMessageAttachment()->getMessageId(), + callbackOwned->getOperationHandle(), + callbackOwned->getNth()); + } + + m_callback_set.insert(callbackOwned); +} + +void LoadAttachmentProxy::removeCallback(MessageAttachmentCallbackData* callback) +{ + if(callback->getMessageAttachment()) { + LOGD("Removed callback for attachment_id: %d mail_id:%d op_handle:%d nth:%d", + callback->getMessageAttachment()->getId(), + callback->getMessageAttachment()->getMessageId(), + callback->getOperationHandle(), + callback->getNth()); + } + + m_callback_set.erase(callback); +} + +MessageAttachmentCallbackData* LoadAttachmentProxy::findCallback(const int nth, + const int mail_id) +{ + CallbackSet::iterator it = m_callback_set.begin(); + for (; it != m_callback_set.end(); ++it) { + MessageAttachmentCallbackData* callback = *it; + if (nth == callback->getNth() && + mail_id == callback->getMessageAttachment()->getMessageId()) { + return callback; + } + } + + LOGW("Could not find callback with nth: %d and mail_id: %d", nth, mail_id); + return NULL; +} + +void LoadAttachmentProxy::handleEmailSignal(const int status, + const int mail_id, + const std::string& source, + const int op_handle, + const int error_code) +{ + if(NOTI_DOWNLOAD_ATTACH_FINISH != status && + NOTI_DOWNLOAD_ATTACH_FAIL != status) { + return; + } + + LOGD("received email signal with:\n status: %d\n mail_id: %d\n " + "source: %s\n op_handle(nth): %d\n error_code: %d", + status, mail_id, source.c_str(), op_handle, error_code); + + MessageAttachmentCallbackData* callback = NULL; + + //It seems that D-Bus signal op_handle is equal to nth in: + // int email_download_attachment(int mail_id, int nth, int *handle) + // and not handle returned from above call!! + const int nth = op_handle; + + try { + // From old implementation it looks that op_handle(nth) is is equal to + // index (1 based) of attachment inside email thus it is not globally unique! + // Therfore we need to test if mail_id match. + // For details see old implementation MailSync.cp line 461 + + callback = findCallback(nth, mail_id); + if(!callback) { + //We should not log not found pair since it could be requested by + //different application. + return; + } + + LOGD("Found callback for pair mailId:%d nth:%d", mail_id, nth); + + if(NOTI_DOWNLOAD_ATTACH_FINISH == status) { + LOGD("Message attachment downloaded!"); + + std::shared_ptr att = callback->getMessageAttachment(); + updateAttachmentDataWithEmailGetAttachmentData(att); + LOGD("Updated Message attachment object"); + + try { + JSContextRef context = callback->getContext(); + JSObjectRef jsMessageAtt = JSMessageAttachment::makeJSObject(context, att); + callback->callSuccessCallback(jsMessageAtt); + } catch (...) { + LOGW("Couldn't create JSMessageAttachment object!"); + throw Common::UnknownException( + "Couldn't create JSMessageAttachment object!"); + } + + } else if(NOTI_DOWNLOAD_ATTACH_FAIL) { + LOGD("Load message attachment failed!"); + JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject( + callback->getContext(), + callback->getErrorName(), + callback->getErrorMessage()); + callback->callErrorCallback(errobj); + } + } catch (const Common::BasePlatformException& e) { + LOGE("Exception in signal callback"); + JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject( + callback->getContext(), e); + callback->callErrorCallback(errobj); + } catch (...) { + LOGE("Exception in signal callback"); + JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject( + callback->getContext(), + Common::JSWebAPIErrorFactory::UNKNOWN_ERROR, + "Handling signal callback failed"); + callback->callErrorCallback(errobj); + } + + if(callback) { + removeCallback(callback); + delete callback; + } +} + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI diff --git a/src/messaging/DBus/LoadAttachmentProxy.h b/src/messaging/DBus/LoadAttachmentProxy.h new file mode 100644 index 00000000..06db27d0 --- /dev/null +++ b/src/messaging/DBus/LoadAttachmentProxy.h @@ -0,0 +1,69 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file LoadAttachmentProxy.h + */ + +#ifndef __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__ +#define __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__ + +#include "EmailSignalProxy.h" +#include + +namespace DeviceAPI { +namespace Messaging { + +class MessageAttachmentCallbackData; + +namespace DBus { + +class LoadAttachmentProxy; +typedef std::shared_ptr LoadAttachmentProxyPtr; + +class LoadAttachmentProxy : public EmailSignalProxy { +public: + + // Callback is owned by this set + typedef std::set CallbackSet; + + LoadAttachmentProxy(const std::string& path, + const std::string& iface); + virtual ~LoadAttachmentProxy(); + + //Passed callback will be owned by this proxy + void addCallback(MessageAttachmentCallbackData* callbackOwned); + void removeCallback(MessageAttachmentCallbackData* callback); + +protected: + virtual void handleEmailSignal(const int status, + const int mail_id, + const std::string& source, + const int op_handle, + const int error_code); + +private: + MessageAttachmentCallbackData* findCallback(const int nth, const int mail_id); + + CallbackSet m_callback_set; +}; + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI + +#endif // __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__ diff --git a/src/messaging/DBus/LoadBodyProxy.cpp b/src/messaging/DBus/LoadBodyProxy.cpp new file mode 100644 index 00000000..990d04f2 --- /dev/null +++ b/src/messaging/DBus/LoadBodyProxy.cpp @@ -0,0 +1,206 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file LoadBodyProxy.cpp + */ + +#include "LoadBodyProxy.h" +#include +#include +#include +#include +#include "MessageService.h" +#include "Message.h" +#include "MessageBody.h" +#include "EmailManager.h" +#include "JSMessage.h" +#include + +namespace DeviceAPI { +namespace Messaging { +namespace DBus { + +LoadBodyProxy::LoadBodyProxy(const std::string& path, + const std::string& iface) : + EmailSignalProxy(path, iface) +{ + +} + +LoadBodyProxy::~LoadBodyProxy() +{ + +} + +void LoadBodyProxy::addCallback(MessageBodyCallbackData* callbackOwned) +{ + m_callback_set.insert(callbackOwned); +} + +void LoadBodyProxy::removeCallback(MessageBodyCallbackData* callback) +{ + m_callback_set.erase(callback); +} + +MessageBodyCallbackData* LoadBodyProxy::findCallbackByOpHandle(const int op_handle) +{ + CallbackSet::iterator it = m_callback_set.begin(); + for (; it != m_callback_set.end(); ++it) { + + MessageBodyCallbackData* callback = *it; + if (op_handle == callback->getOperationHandle()) { + return callback; + } + } + + LOGW("Could not find callback with op_handle: %d", op_handle); + return NULL; +} + +void LoadBodyProxy::handleEmailSignal(const int status, + const int mail_id, + const std::string& source, + const int op_handle, + const int error_code) +{ + switch(status) { + //We should handle this signal since it is DOWNLOAD_BODY_* + case NOTI_DOWNLOAD_BODY_START: + case NOTI_DOWNLOAD_BODY_FINISH: + case NOTI_DOWNLOAD_BODY_FAIL: { + } break; + + // This values have not been explicitly handled in old implementation + // NOTI_DOWNLOAD_BODY_CANCEL + // NOTI_DOWNLOAD_MULTIPART_BODY + // + // 1. I assume that NOTI_DOWNLOAD_MULTIPART_BODY is called several times + // before final NOTI_DOWNLOAD_BODY_FINISH is called, thus we should not + // remove nor delete callback. + // + // 2. I assume that NOTI_DOWNLOAD_BODY_CANCEL is called before + // NOTI_DOWNLOAD_BODY_FAIL so we should do the same as in point 1. + case NOTI_DOWNLOAD_BODY_CANCEL: + case NOTI_DOWNLOAD_MULTIPART_BODY: + default: { + // This signal is not related with load message body or there is nothing + // to do so we can return now. + return; + } break; + } + + LOGD("received email signal with:\n status: %d\n mail_id: %d\n " + "source: %s\n op_handle: %d\n error_code: %d", + status, mail_id, source.c_str(), op_handle, error_code); + + if(NOTI_DOWNLOAD_BODY_START == status) { + LOGD("Download message body started ..."); + // There is nothing more to do so we can return now. + return; + } + + MessageBodyCallbackData* callback = NULL; + try { + callback = findCallbackByOpHandle(op_handle); + if (!callback) { + LOGE("Callback is null"); + } else { + if( (NOTI_DOWNLOAD_BODY_FINISH == status) || + (NOTI_DOWNLOAD_BODY_FAIL == status && + EMAIL_ERROR_MAIL_IS_ALREADY_DOWNLOADED == error_code)) { + + // Old implementation is not verifying whether message update failed, + // it just calls success callback. + if(callback->getMessage()) { + email_mail_data_t* mail_data = EmailManager::loadMessage( + callback->getMessage()->getId()); + if (mail_data) { + callback->getMessage()->updateEmailMessage(*mail_data); + EmailManager::freeMessage(mail_data); + mail_data = NULL; + } + + //TODO: this should be reviewed when attachments and + // loadAttachments have been completed. + //TODO: see old implementation lines 608-635 in MailSync.cpp + /* + * This is original Messaging implementation: + * + * std::vector attachments = mail->getAttachments(); + * std::vector inlineAttachments = mail->getInlineAttachments(); + * + * for (unsigned int idx = 0; idx < attachments.size() ; idx++ ) + * { + * LoggerD("set Attachment ID = " << attachments[idx]->getAttachmentID()); + * attachments[idx]->setMessage(event->m_message); + * + * } + * for (unsigned int idx = 0; idx < inlineAttachments.size() ; idx++ ) + * { + * LoggerD("set inline Attachment ID = " << inlineAttachments[idx]->getAttachmentID()); + * inlineAttachments[idx]->setMessage(event->m_message); + * } + */ + } + + LOGD("Message body downloaded!"); + try { + JSContextRef context = callback->getContext(); + JSObjectRef jsMessage = JSMessage::makeJSObject(context, + callback->getMessage()); + callback->callSuccessCallback(jsMessage); + } catch (...) { + LOGW("Couldn't create JSMessage object!"); + throw Common::UnknownException( + "Couldn't create JSMessage object!"); + } + + } else if(NOTI_DOWNLOAD_BODY_FAIL == status) { + LOGD("Load message body failed!"); + JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject( + callback->getContext(), + callback->getErrorName(), + callback->getErrorMessage()); + callback->callErrorCallback(errobj); + } + } + } + catch (const Common::BasePlatformException& e) { + LOGE("Exception in signal callback"); + JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject( + callback->getContext(), e); + callback->callErrorCallback(errobj); + } + catch (...) { + LOGE("Exception in signal callback"); + JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject( + callback->getContext(), + Common::JSWebAPIErrorFactory::UNKNOWN_ERROR, + "Handling signal callback failed"); + callback->callErrorCallback(errobj); + } + + if(callback) { + removeCallback(callback); + delete callback; + } +} + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI diff --git a/src/messaging/DBus/LoadBodyProxy.h b/src/messaging/DBus/LoadBodyProxy.h new file mode 100644 index 00000000..2fffa37c --- /dev/null +++ b/src/messaging/DBus/LoadBodyProxy.h @@ -0,0 +1,73 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file LoadBodyProxy.h + */ + +#ifndef __TIZEN_DBUS_LOAD_BODY_PROXY_H__ +#define __TIZEN_DBUS_LOAD_BODY_PROXY_H__ + +#include "EmailSignalProxy.h" +#include + +namespace DeviceAPI { +namespace Messaging { + +class MessageBodyCallbackData; + +namespace DBus { + +class LoadBodyProxy; +typedef std::shared_ptr LoadBodyProxyPtr; + +class LoadBodyProxy : public EmailSignalProxy { +public: + + // Callback is owned by this set + typedef std::set CallbackSet; + + LoadBodyProxy(const std::string& path, + const std::string& iface); + virtual ~LoadBodyProxy(); + + //Passed callback will be owned by this proxy + void addCallback(MessageBodyCallbackData* callbackOwned); + void removeCallback(MessageBodyCallbackData* callback); + +protected: + virtual void handleEmailSignal(const int status, + const int mail_id, + const std::string& source, + const int op_handle, + const int error_code); + +private: + /** + * Find callback by operation handle returned from: + * int email_download_body(..., int *handle); + */ + MessageBodyCallbackData* findCallbackByOpHandle(const int op_handle); + + CallbackSet m_callback_set; +}; + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI + +#endif // __TIZEN_DBUS_LOAD_BODY_PROXY_H__ diff --git a/src/messaging/DBus/MessageProxy.cpp b/src/messaging/DBus/MessageProxy.cpp new file mode 100644 index 00000000..32d47823 --- /dev/null +++ b/src/messaging/DBus/MessageProxy.cpp @@ -0,0 +1,290 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "MessageProxy.h" +#include "Connection.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace DeviceAPI { +namespace Messaging { +namespace DBus { + +MessageProxy::MessageProxy(): + Proxy(Proxy::DBUS_PATH_EMAIL_STORAGE_CHANGE, + Proxy::DBUS_IFACE_EMAIL_STORAGE_CHANGE, + Proxy::DBUS_NAME_SIGNAL_EMAIL, + Proxy::DBUS_PATH_EMAIL_STORAGE_CHANGE, + Proxy::DBUS_IFACE_EMAIL_STORAGE_CHANGE) +{ +} + +MessageProxy::~MessageProxy() +{ +} + +void MessageProxy::signalCallback(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters) +{ + LOGD("Enter"); + int status, account_id, object_id, thread_id; + char* name; + g_variant_get(parameters, "(iiisi)", + &status, + &account_id, + &object_id, + &name, + &thread_id); + LOGD("status: %d", status); + LOGD("account_id: %d", account_id); + LOGD("object_id: %d", object_id); + LOGD("name: %s", name); + LOGD("thread_id: %d", thread_id); + + try { + switch (status) { + case NOTI_MAIL_ADD: + case NOTI_MAIL_UPDATE: + handleEmailEvent(account_id, object_id, thread_id, status); + break; + case NOTI_MAIL_DELETE: + //ids of removing messages are sent with name in format: + //id1,id2,id3, + handleEmailRemoveEvent(account_id, name); + break; + case NOTI_MAIL_DELETE_FINISH: + case NOTI_MAIL_DELETE_FAIL: + //notify EmailManager, maybe it tries to delete mail + notifyEmailManager(name, static_cast(status)); + break; + case NOTI_THREAD_DELETE: + handleThreadRemoveEvent(account_id, object_id); + break; + case NOTI_MAILBOX_ADD: + case NOTI_MAILBOX_UPDATE: + case NOTI_MAILBOX_FIELD_UPDATE: + case NOTI_MAILBOX_RENAME: + case NOTI_MAILBOX_DELETE: + handleMailboxEvent(account_id, object_id, status); + break; + default: + LOGD("Unrecognized status: %d", status); + } + } catch (const Common::BasePlatformException& err) { + LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str()); + } catch (...) { + LOGE("Failed to call callback"); + } + g_free(name); +} + +void MessageProxy::handleEmailEvent(int account_id, int mail_id, int thread_id, int event) +{ + LOGD("Enter"); + + if(NOTI_MAIL_UPDATE == event) { + //getting thread_id from message + email_mail_data_t *mail_data = NULL; + + if(EMAIL_ERROR_NONE != email_get_mail_data(mail_id, &mail_data)) { + if (mail_data) email_free_mail_data(&mail_data, 1); + + LOGE("Failed to get mail data during setting conversation id in MessageProxy."); + return; + } + + thread_id = mail_data->thread_id; + + if(EMAIL_ERROR_NONE != email_free_mail_data(&mail_data,1)) { + LOGE("Failed to free mail data memory"); + } + } + + email_mail_data_t* mail_data = EmailManager::getInstance().loadMessage(mail_id); + if (mail_data == NULL) { + throw Common::UnknownException("Failed to load email"); + } + std::shared_ptr msg = Message::convertPlatformEmailToObject(*mail_data); + ConversationPtr conv = MessageConversation::convertEmailConversationToObject( + thread_id); + + EventMessages* eventMsg = new EventMessages(); + eventMsg->service_type = MessageType::EMAIL; + eventMsg->service_id = account_id; + eventMsg->items.push_back(msg); + EventConversations* eventConv = new EventConversations(); + eventConv->service_type = MessageType::EMAIL; + eventConv->service_id = account_id; + eventConv->items.push_back(conv); + switch (event) { + case NOTI_MAIL_ADD: + ChangeListenerContainer::getInstance().callMessageAdded(eventMsg); + if (conv->getMessageCount() == 1) { + LOGD("This thread is new, triggering conversationAdded"); + ChangeListenerContainer::getInstance().callConversationAdded(eventConv); + } else { + LOGD("This thread is not new, but it's updated"); + ChangeListenerContainer::getInstance().callConversationUpdated(eventConv); + } + break; + case NOTI_MAIL_UPDATE: + ChangeListenerContainer::getInstance().callMessageUpdated(eventMsg); + ChangeListenerContainer::getInstance().callConversationUpdated(eventConv); + break; + default: + LOGW("Unknown event type: %d", event); + break; + + } + delete eventMsg; + delete eventConv; + + EmailManager::getInstance().freeMessage(mail_data); +} + +std::vector getMailIds(const std::string& idsString) +{ + std::stringstream idsStream(idsString); + std::string item; + std::vector ids; + while (std::getline(idsStream, item, ',')) { + if (item.length() > 0) { + int id; + std::stringstream stream(item); + stream >> id; + if (stream) { + LOGD("Mail delete id: %d", id); + ids.push_back(id); + } + } + } + return ids; +} + +void MessageProxy::handleEmailRemoveEvent(int account_id, const std::string& idsString) +{ + LOGD("Enter"); + std::vector ids = getMailIds(idsString); + if (ids.empty()) { + LOGD("Mail id list is empty."); + return; + } + EventMessages* eventMsg = new EventMessages(); + eventMsg->service_type = MessageType::EMAIL; + eventMsg->service_id = account_id; + for (auto it = ids.begin(); it != ids.end(); ++it) { + //it turns out that this event is triggered after messages are removed + //so we just create empty messages with id and type + std::shared_ptr msg = std::make_shared(); + msg->setId(*it); + eventMsg->items.push_back(msg); + } + ChangeListenerContainer::getInstance().callMessageRemoved(eventMsg); + delete eventMsg; + eventMsg = NULL; +} + +void MessageProxy::notifyEmailManager(const std::string& idsString, + email_noti_on_storage_event status) +{ + LOGD("Enter"); + std::vector ids = getMailIds(idsString); + if (ids.empty()) { + LOGD("Mail id list is empty."); + return; + } + EmailManager::getInstance().removeStatusCallback(ids, status); +} + +void MessageProxy::handleThreadRemoveEvent(int account_id, int thread_id) +{ + LOGD("Enter"); + //event is called after thread is removed, so we just set thread id + ConversationPtr conv = std::make_shared(); + conv->setConversationId(thread_id); + + EventConversations* eventConv = new EventConversations(); + eventConv->service_type = MessageType::EMAIL; + eventConv->service_id = account_id; + eventConv->items.push_back(conv); + ChangeListenerContainer::getInstance().callConversationRemoved(eventConv); + delete eventConv; + eventConv = NULL; +} + +void MessageProxy::handleMailboxEvent(int account_id, int mailbox_id, int event) +{ + LOGD("Enter"); + + EventFolders* eventFolder = new EventFolders(); + eventFolder->service_type = MessageType::EMAIL; + eventFolder->service_id = account_id; + FolderPtr folder; + if (event == NOTI_MAILBOX_DELETE) { + //this event is triggered after mailbox is removed + //so we just create folder with id + folder.reset(new MessageFolder(std::to_string(mailbox_id), + "", //parent_id + "", //service_id + "", //content_type + "", //name + "", //path + MessageFolderType::MESSAGE_FOLDER_TYPE_NOTSTANDARD, + false)); + } else { + email_mailbox_t* mail_box = NULL; + if (EMAIL_ERROR_NONE != email_get_mailbox_by_mailbox_id(mailbox_id, &mail_box)) { + LOGE("Mailbox not retrieved"); + delete eventFolder; + throw Common::UnknownException("Failed to load mailbox"); + } + folder.reset(new MessageFolder(*mail_box)); + if (EMAIL_ERROR_NONE != email_free_mailbox(&mail_box, 1)) { + LOGD("Failed to free email_free_mailbox"); + } + } + eventFolder->items.push_back(folder); + switch (event) { + case NOTI_MAILBOX_ADD: + ChangeListenerContainer::getInstance().callFolderAdded(eventFolder); + break; + case NOTI_MAILBOX_UPDATE: + case NOTI_MAILBOX_FIELD_UPDATE: + ChangeListenerContainer::getInstance().callFolderUpdated(eventFolder); + break; + case NOTI_MAILBOX_DELETE: + ChangeListenerContainer::getInstance().callFolderRemoved(eventFolder); + break; + default: + LOGW("Unknown event type: %d", event); + } + delete eventFolder; +} + +} //DBus +} //Messaging +} //DeviceAPI diff --git a/src/messaging/DBus/MessageProxy.h b/src/messaging/DBus/MessageProxy.h new file mode 100644 index 00000000..7b6d456e --- /dev/null +++ b/src/messaging/DBus/MessageProxy.h @@ -0,0 +1,65 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef __TIZEN_MESSAGE_PROXY_H +#define __TIZEN_MESSAGE_PROXY_H + +#include +#include +#include +#include +#include +#include +#include "Proxy.h" + +namespace DeviceAPI { +namespace Messaging { +namespace DBus { + +class MessageProxy: public Proxy { +public: + MessageProxy(); + virtual ~MessageProxy(); +protected: + virtual void signalCallback(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters); + /** + * Handles e-mail add and update only. + * @param account_id + * @param mail_id + * @param thread_id + * @param event + */ + void handleEmailEvent(int account_id, int mail_id, int thread_id, int event); + void handleEmailRemoveEvent(int account_id, const std::string& idsString); + void notifyEmailManager(const std::string& idsString, email_noti_on_storage_event status); + void handleThreadRemoveEvent(int account_id, int thread_id); + void handleMailboxEvent(int account_id, int mailbox_id, int event); +}; + +typedef std::shared_ptr MessageProxyPtr; + +} //DBus +} //Messaging +} //DeviceAPI + +#endif /* __TIZEN_MESSAGE_PROXY_H */ + diff --git a/src/messaging/DBus/Proxy.cpp b/src/messaging/DBus/Proxy.cpp new file mode 100644 index 00000000..a6692a0c --- /dev/null +++ b/src/messaging/DBus/Proxy.cpp @@ -0,0 +1,163 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file Proxy.cpp + */ + +#include "Proxy.h" +#include "common/logger.h" +//#include +#include +#include +#include "../message_service.h" + +namespace extension { +namespace messaging { +namespace DBus { + +const char* Proxy::DBUS_PATH_NETWORK_STATUS = "/User/Email/NetworkStatus"; +const char* Proxy::DBUS_IFACE_NETWORK_STATUS = "User.Email.NetworkStatus"; +const char* Proxy::DBUS_PATH_EMAIL_STORAGE_CHANGE = "/User/Email/StorageChange"; +const char* Proxy::DBUS_IFACE_EMAIL_STORAGE_CHANGE = "User.Email.StorageChange"; +const char* Proxy::DBUS_NAME_SIGNAL_EMAIL = "email"; + +Proxy::Proxy(const std::string& proxy_path, + const std::string& proxy_iface, + const std::string& signal_name, + const std::string& signal_path, + const std::string& signal_iface) : + m_conn(Connection::getInstance()), + m_sub_id(0), + m_path(proxy_path), + m_iface(proxy_iface), + m_signal_name(signal_name), + m_signal_path(signal_path), + m_signal_iface(signal_iface), + m_error(NULL), + m_dbus_signal_subscribed(false) +{ + LOGD("Proxy:\n" + " proxy_path: %s\n proxy_iface: %s" + " signal_name: %s\n signal_path:%s\n signal_iface:%s", + m_path.c_str(), m_iface.c_str(), + m_signal_name.c_str(), m_signal_path.c_str(), m_signal_iface.c_str()); + + const gchar* unique_name = g_dbus_connection_get_unique_name(m_conn.getDBus()); + LOGD("Generated unique name: %d", unique_name); + + // path and interface are not obligatory to receive, but + // they should be set to send the signals. + m_proxy = g_dbus_proxy_new_sync(m_conn.getDBus(), + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, unique_name, m_path.c_str(), m_iface.c_str(), NULL, &m_error); + if (!m_proxy || m_error) { + LOGE("Could not get proxy"); + //TODO throw Common::UnknownException("Could not get proxy"); + } +} + +Proxy::~Proxy() +{ + signalUnsubscribe(); +} + +void Proxy::signalCallbackProxy(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + Proxy* this_ptr = static_cast(user_data); + if (!this_ptr) { + LOGW("Proxy is null, nothing to do"); + return; + } + + try { + //It is better to log this only when subclass is responsible of handling + //passed signal. If you need it put it into your signalCallback(...) method + //LOGD("signal: %s from: %s path: %s interface: %s", + // signal_name, sender_name, object_path, interface_name); + + this_ptr->signalCallback(connection, sender_name, object_path, interface_name, + signal_name, parameters); + +// } catch(const Common::BasePlatformException& exception) { +// LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(), +// (exception.getMessage()).c_str()); + } catch(...) { + LOGE("Unhandled exception!"); + } +} + +void Proxy::signalSubscribe() +{ + if(m_dbus_signal_subscribed) { + LOGW("Proxy has already subscribed for listening DBus signal"); + return; + } + + const char* sender = NULL; + m_sub_id = g_dbus_connection_signal_subscribe(m_conn.getDBus(), + sender, + m_signal_iface.c_str(), + m_signal_name.c_str(), + m_signal_path.c_str(), + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + signalCallbackProxy, + static_cast(this), + NULL); + LOGD("g_dbus_connection_signal_subscribe returned id: %d", m_sub_id); + + m_dbus_signal_subscribed = true; +} + +void Proxy::signalUnsubscribe() +{ + if (!m_dbus_signal_subscribed) { + LOGW("Proxy hasn't subscribed for listening DBus signal"); + return; + } + + g_dbus_connection_signal_unsubscribe(m_conn.getDBus(), m_sub_id); + LOGD("g_dbus_connection_signal_unsubscribe finished"); + + m_dbus_signal_subscribed = false; +} + +const std::string& Proxy::getSignalName() const +{ + return m_signal_name; +} + +const std::string& Proxy::getSignalPath() const +{ + return m_signal_path; +} + +const std::string& Proxy::getSignalInterfaceName() const +{ + return m_signal_iface; +} + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI diff --git a/src/messaging/DBus/Proxy.h b/src/messaging/DBus/Proxy.h new file mode 100644 index 00000000..75bab096 --- /dev/null +++ b/src/messaging/DBus/Proxy.h @@ -0,0 +1,125 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file Proxy.h + */ + +#ifndef __TIZEN_DBUS_PROXY_H__ +#define __TIZEN_DBUS_PROXY_H__ + +#include "Connection.h" +#include +#include +#include +#include +#include "common/callback_user_data.h" + +namespace extension { +namespace messaging { +namespace DBus { + + +class Proxy; +typedef std::shared_ptr ProxyPtr; + +/** + * This is generic dbus signal listener proxy. + */ +class Proxy { +public: + /** + * List of Tizen path and interface names: + */ + static const char* DBUS_PATH_NETWORK_STATUS; + static const char* DBUS_IFACE_NETWORK_STATUS; + static const char* DBUS_PATH_EMAIL_STORAGE_CHANGE; + static const char* DBUS_IFACE_EMAIL_STORAGE_CHANGE; + /** + * Name of email signal + */ + static const char* DBUS_NAME_SIGNAL_EMAIL; + + /** + * @param proxy_path - path of this proxy + * @param proxy_iface - interface name of this proxy + * + * @param signal_name - expected signal name + * @param signal_path - expected signal path + * @param signal_iface - expected signal interface name + */ + Proxy(const std::string& proxy_path, + const std::string& proxy_iface, + const std::string& signal_name, + const std::string& signal_path, + const std::string& signal_iface); + + virtual ~Proxy(); + + void signalSubscribe(); + void signalUnsubscribe(); + + const std::string& getSignalName() const; + const std::string& getSignalPath() const; + const std::string& getSignalInterfaceName() const; + +protected: + /** + * Please implement this method in subclass to handle signal. + * Executed by static void signalCallbackProxy(...). + */ + virtual void signalCallback(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters) = 0; + +private: + /** + * This method (registered with g_dbus_connection_signal_subscribe) is executed by + * DBus when signal is received. It calls + * (static_cast(user_data))->signalCallback(...) + */ + static void signalCallbackProxy(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data); + + Connection& m_conn; + guint m_sub_id; + + std::string m_path; + std::string m_iface; + + std::string m_signal_name; + std::string m_signal_path; + std::string m_signal_iface; + + GError* m_error; + GDBusProxy* m_proxy; + bool m_dbus_signal_subscribed; +}; + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI + +#endif // __TIZEN_DBUS_PROXY_H__ diff --git a/src/messaging/DBus/SendProxy.cpp b/src/messaging/DBus/SendProxy.cpp new file mode 100644 index 00000000..1e5a8364 --- /dev/null +++ b/src/messaging/DBus/SendProxy.cpp @@ -0,0 +1,64 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "SendProxy.h" + +#include +#include +#include + +namespace DeviceAPI { +namespace Messaging { +namespace DBus { + +SendProxy::SendProxy(): + EmailSignalProxy(Proxy::DBUS_PATH_NETWORK_STATUS, + Proxy::DBUS_IFACE_NETWORK_STATUS) +{ +} + +SendProxy::~SendProxy() +{ +} + +void SendProxy::handleEmailSignal(const int status, + const int account_id, + const std::string& source, + const int mail_id, + const int error_code) +{ + LOGD("Enter"); + switch (status) { + case NOTI_SEND_FINISH: + case NOTI_SEND_FAIL: + LOGD("Recognized status for email send"); + LOGD("received email signal with:\n status: %d\n account_id: %d\n " + "source: %s\n mail_id: %d\n error_code: %d", + status, account_id, source.c_str(), mail_id, error_code); + EmailManager::getInstance().sendStatusCallback(mail_id, + static_cast(status), + error_code); + break; + default: + LOGD("Unrecognized status %d, ignoring", status); + } +} + + +} //DBus +} //Messaging +} //DeviceAPI \ No newline at end of file diff --git a/src/messaging/DBus/SendProxy.h b/src/messaging/DBus/SendProxy.h new file mode 100644 index 00000000..1493c8ed --- /dev/null +++ b/src/messaging/DBus/SendProxy.h @@ -0,0 +1,47 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef __TIZEN_SEND_PROXY_H +#define __TIZEN_SEND_PROXY_H + +#include "EmailSignalProxy.h" + +namespace DeviceAPI { +namespace Messaging { +namespace DBus { + +class SendProxy: public EmailSignalProxy { +public: + SendProxy(); + virtual ~SendProxy(); +protected: + virtual void handleEmailSignal(const int status, + const int account_id, + const std::string& source, + const int op_handle, + const int error_code); + +}; + +typedef std::shared_ptr SendProxyPtr; + +} //DBus +} //Messaging +} //DeviceAPI + +#endif /* __TIZEN_SEND_PROXY_H */ + diff --git a/src/messaging/DBus/SyncProxy.cpp b/src/messaging/DBus/SyncProxy.cpp new file mode 100644 index 00000000..5c7f5fe4 --- /dev/null +++ b/src/messaging/DBus/SyncProxy.cpp @@ -0,0 +1,166 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file SyncProxy.cpp + */ + +#include "SyncProxy.h" +#include "common/logger.h" +//#include +#include +#include +#include "../message_service.h" + +namespace extension { +namespace messaging { +namespace DBus { + +SyncProxy::SyncProxy(const std::string& path, + const std::string& iface) : + EmailSignalProxy(path, iface) +{ + +} + +SyncProxy::~SyncProxy() +{ + +} + +void SyncProxy::addCallback(long op_id, common::CallbackUserData* callbackOwned) +{ + m_callback_map.insert(std::make_pair(op_id, callbackOwned)); +} + +common::CallbackUserData* SyncProxy::getCallback(long op_id) +{ + common::CallbackUserData* cb = NULL; + CallbackMap::iterator it = m_callback_map.find(op_id); + if (it != m_callback_map.end()) { + cb = it->second; + return cb; + } + LOGE("Could not find callback"); + //TODO throw Common::UnknownException("Could not find callback"); + return cb; +} + +void SyncProxy::removeCallback(long op_id){ + CallbackMap::iterator it = m_callback_map.find(op_id); + if (it != m_callback_map.end()) { + common::CallbackUserData* cb = it->second; + delete cb; + cb = NULL; + m_callback_map.erase(it); + } + else { + LOGE("Could not find callback"); + //TODO throw Common::UnknownException("Could not find callback"); + } +} + +void SyncProxy::handleEmailSignal(const int status, + const int mail_id, + const std::string& source, + const int op_handle, + const int error_code) +{ + if( NOTI_DOWNLOAD_START != status && + NOTI_DOWNLOAD_FINISH != status && + NOTI_DOWNLOAD_FAIL != status ) { + // Nothing to do: this status is not related to sync nor syncFolder request + return; + } + + LOGD("received email signal with:\n status: %d\n mail_id: %d\n " + "source: %s\n op_handle: %d\n error_code: %d", + status, mail_id, source.c_str(), op_handle, error_code); + + if (NOTI_DOWNLOAD_START == status) { + LOGD("Sync started..."); + // There is nothing more to do so we can return now. + return; + } + + common::CallbackUserData* callback = NULL; + CallbackMap::iterator callback_it; + + try { + callback_it = findSyncCallbackByOpHandle(op_handle); + callback = callback_it->second; + if (!callback) { + LOGE("Callback is null"); + //TODO throw Common::UnknownException("Callback is null"); + } + + switch (status) { + case NOTI_DOWNLOAD_FINISH: + LoggerD("Sync finished!"); + //TODO callback->callSuccessCallback(); + break; + + case NOTI_DOWNLOAD_FAIL: + LoggerD("Sync failed!"); + //TODO callback->callErrorCallback(); + break; + + default: + break; + } + } +// catch (const Common::BasePlatformException& e) { +// // this situation may occur when there is no callback in the +// // map with specified opId (for example stopSync() has +// // removed it), but sync() was already started - only +// // warning here: +// LOGE("Exception in signal callback"); +// } + catch(...) + { + LOGE("Exception in signal callback"); + } + + if(callback) { + delete callback; + m_callback_map.erase(callback_it); + } +} + +SyncProxy::CallbackMap::iterator SyncProxy::findSyncCallbackByOpHandle( + const int op_handle) +{ + CallbackMap::iterator it = m_callback_map.begin(); + for (; it != m_callback_map.end(); ++it) { + SyncCallbackData* cb = dynamic_cast(it->second); + if (!cb) continue; + + if (op_handle == cb->getOperationHandle()) { + return it; + } + } + // this situation may occur when there is no callback in the + // map with specified opId (for example stopSync() has + // removed it), but sync() was already started - only + // warning here: + LOGW("Could not find callback with op_handle: %d", op_handle); + //TODO throw Common::UnknownException("Could not find callback"); +} + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI diff --git a/src/messaging/DBus/SyncProxy.h b/src/messaging/DBus/SyncProxy.h new file mode 100644 index 00000000..eff69241 --- /dev/null +++ b/src/messaging/DBus/SyncProxy.h @@ -0,0 +1,70 @@ +// +// Tizen Web Device API +// Copyright (c) 2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file SyncProxy.h + */ + +#ifndef __TIZEN_DBUS_SYNC_PROXY_H__ +#define __TIZEN_DBUS_SYNC_PROXY_H__ + +#include "EmailSignalProxy.h" + +namespace extension { +namespace messaging { +namespace DBus { + +class SyncProxy; +typedef std::shared_ptr SyncProxyPtr; + +class SyncProxy : public EmailSignalProxy { +public: + + // Callback is owned by this map + typedef std::map CallbackMap; + + SyncProxy(const std::string& path, + const std::string& iface); + virtual ~SyncProxy(); + + //Passed callback will be owned by this proxy + void addCallback(long op_id, common::CallbackUserData* callbackOwned); + common::CallbackUserData* getCallback(long op_id); + void removeCallback(long op_id); + +protected: + virtual void handleEmailSignal(const int status, + const int mail_id, + const std::string& source, + const int op_handle, + const int error_code); + +private: + /** + * Find callback by operation handle returned from: + * int email_sync_header(..., int *handle); + */ + CallbackMap::iterator findSyncCallbackByOpHandle(const int op_handle); + + CallbackMap m_callback_map; +}; + +} //namespace DBus +} //namespace Messaging +} //namespace DeviceAPI + +#endif // __TIZEN_DBUS_SYNC_PROXY_H__ diff --git a/src/messaging/email_manager.cc b/src/messaging/email_manager.cc index 8afa325c..148a13cf 100644 --- a/src/messaging/email_manager.cc +++ b/src/messaging/email_manager.cc @@ -74,7 +74,7 @@ const std::string FIND_FOLDERS_ATTRIBUTE_ACCOUNTID_NAME = "serviceId"; EmailManager& EmailManager::getInstance() { - LOGD("Entered"); + LoggerD("Entered"); static EmailManager instance; return instance; @@ -82,7 +82,7 @@ EmailManager& EmailManager::getInstance() EmailManager::EmailManager() { - LOGD("Entered"); + LoggerD("Entered"); getUniqueOpId(); const int non_err = EMAIL_ERROR_NONE; @@ -101,15 +101,15 @@ EmailManager::EmailManager() m_slot_size = slot_size; } -// m_proxy_sync = std::make_shared( -// DBus::Proxy::DBUS_PATH_NETWORK_STATUS, -// DBus::Proxy::DBUS_IFACE_NETWORK_STATUS); -// if (!m_proxy_sync) { -// LOGE("Sync proxy is null"); -// throw Common::UnknownException("Sync proxy is null"); -// } -// m_proxy_sync->signalSubscribe(); -// + m_proxy_sync = std::make_shared( + DBus::Proxy::DBUS_PATH_NETWORK_STATUS, + DBus::Proxy::DBUS_IFACE_NETWORK_STATUS); + if (!m_proxy_sync) { + LOGE("Sync proxy is null"); + //TODO throw Common::UnknownException("Sync proxy is null"); + } + m_proxy_sync->signalSubscribe(); + // m_proxy_load_body = std::make_shared( // DBus::Proxy::DBUS_PATH_NETWORK_STATUS, // DBus::Proxy::DBUS_IFACE_NETWORK_STATUS); @@ -145,7 +145,7 @@ EmailManager::EmailManager() EmailManager::~EmailManager() { - LOGD("Entered"); + LoggerD("Entered"); } //void EmailManager::addDraftMessagePlatform(int account_id, @@ -646,7 +646,7 @@ EmailManager::~EmailManager() void EmailManager::sync(void* data) { - LOGD("Entered"); + LoggerD("Entered"); SyncCallbackData* callback = static_cast(data); if(!callback){ LOGE("Callback is null"); diff --git a/src/messaging/email_manager.h b/src/messaging/email_manager.h index 539610b4..fd553a7c 100644 --- a/src/messaging/email_manager.h +++ b/src/messaging/email_manager.h @@ -39,8 +39,8 @@ #include "messaging_util.h" #include "message_service.h" -//#include "DBus/Connection.h" -//#include "DBus/SyncProxy.h" +#include "DBus/Connection.h" +#include "DBus/SyncProxy.h" //#include "DBus/LoadBodyProxy.h" //#include "DBus/LoadAttachmentProxy.h" //#include "DBus/MessageProxy.h" @@ -120,7 +120,7 @@ private: int m_slot_size; -// DBus::SyncProxyPtr m_proxy_sync; + DBus::SyncProxyPtr m_proxy_sync; // DBus::LoadBodyProxyPtr m_proxy_load_body; // DBus::LoadAttachmentProxyPtr m_proxy_load_attachment; // DBus::MessageProxyPtr m_proxy_messageStorage; diff --git a/src/messaging/messaging.gyp b/src/messaging/messaging.gyp index 8fb0dc39..7ba46416 100644 --- a/src/messaging/messaging.gyp +++ b/src/messaging/messaging.gyp @@ -45,7 +45,23 @@ 'message_attachment.cc', 'message_attachment.h', 'message_body.cc', - 'message_body.h' + 'message_body.h', + 'DBus/Connection.cpp', + 'DBus/Connection.h', + 'DBus/EmailSignalProxy.cpp', + 'DBus/EmailSignalProxy.h', + #'DBus/LoadAttachmentProxy.cpp', + #'DBus/LoadAttachmentProxy.h', + #'DBus/LoadBodyProxy.cpp', + #'DBus/LoadBodyProxy.h', + #'DBus/MessageProxy.cpp', + #'DBus/MessageProxy.h', + 'DBus/Proxy.cpp', + 'DBus/Proxy.h', + #'DBus/SendProxy.cpp', + #'DBus/SendProxy.h', + 'DBus/SyncProxy.cpp', + 'DBus/SyncProxy.h', ], 'includes': [ '../common/pkg-config.gypi',