#include "MessageProxy.h"
#include "Connection.h"
-#include <Logger.h>
-#include <Message.h>
-#include <MessageEmail.h>
-#include <MessageConversation.h>
-#include <MessageFolder.h>
-#include <ChangeListenerContainer.h>
-#include <EmailManager.h>
-#include <PlatformException.h>
-namespace DeviceAPI {
-namespace Messaging {
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "../message.h"
+#include "../message_email.h"
+
+//#include <MessageConversation.h>
+//#include <MessageFolder.h>
+
+#include "../change_listener_container.h"
+
+#include "../email_manager.h"
+
+namespace extension {
+namespace messaging {
namespace DBus {
MessageProxy::MessageProxy():
const gchar *signal_name,
GVariant *parameters)
{
- LOGD("Enter");
+ LoggerD("Enter");
int status, account_id, object_id, thread_id;
char* name;
g_variant_get(parameters, "(iiisi)",
&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);
+ LoggerD("status: %d", status);
+ LoggerD("account_id: %d", account_id);
+ LoggerD("object_id: %d", object_id);
+ LoggerD("name: %s", name);
+ LoggerD("thread_id: %d", thread_id);
try {
switch (status) {
handleMailboxEvent(account_id, object_id, status);
break;
default:
- LOGD("Unrecognized status: %d", status);
+ LoggerD("Unrecognized status: %d", status);
}
- } catch (const Common::BasePlatformException& err) {
- LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+ } catch (const common::PlatformException& err) {
+ LoggerE("%s (%s)", (err.name()).c_str(), (err.message()).c_str());
} catch (...) {
- LOGE("Failed to call callback");
+ LoggerE("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<Message> 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);
+/*
+ * LoggerD("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);
+ *
+ * LoggerE("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)) {
+ * LoggerE("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<Message> 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) {
+ * LoggerD("This thread is new, triggering conversationAdded");
+ * ChangeListenerContainer::getInstance().callConversationAdded(eventConv);
+ * } else {
+ * LoggerD("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:
+ * LoggerW("Unknown event type: %d", event);
+ * break;
+ *
+ * }
+ * delete eventMsg;
+ * delete eventConv;
+ *
+ * EmailManager::getInstance().freeMessage(mail_data);
+ */
}
std::vector<int> getMailIds(const std::string& idsString)
std::stringstream stream(item);
stream >> id;
if (stream) {
- LOGD("Mail delete id: %d", id);
+ LoggerD("Mail delete id: %d", id);
ids.push_back(id);
}
}
void MessageProxy::handleEmailRemoveEvent(int account_id, const std::string& idsString)
{
- LOGD("Enter");
+ LoggerD("Enter");
std::vector<int> ids = getMailIds(idsString);
if (ids.empty()) {
- LOGD("Mail id list is empty.");
+ LoggerD("Mail id list is empty.");
return;
}
EventMessages* eventMsg = new EventMessages();
void MessageProxy::notifyEmailManager(const std::string& idsString,
email_noti_on_storage_event status)
{
- LOGD("Enter");
+ LoggerD("Enter");
std::vector<int> ids = getMailIds(idsString);
if (ids.empty()) {
- LOGD("Mail id list is empty.");
+ LoggerD("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<MessageConversation>();
- 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;
+/*
+ * LoggerD("Enter");
+ * //event is called after thread is removed, so we just set thread id
+ * ConversationPtr conv = std::make_shared<MessageConversation>();
+ * 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;
+/*
+ * LoggerD("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)) {
+ * LoggerE("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)) {
+ * LoggerD("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:
+ * LoggerW("Unknown event type: %d", event);
+ * }
+ * delete eventFolder;
+ */
}
-} //DBus
-} //Messaging
-} //DeviceAPI
+} //namespace DBus
+} //namespace messaging
+} //namespace extension
#include <gio/gio.h>
#include <memory>
#include <string>
+#include <sstream>
#include <email-types.h>
#include "Proxy.h"
-namespace DeviceAPI {
-namespace Messaging {
+namespace extension {
+namespace messaging {
namespace DBus {
class MessageProxy: public Proxy {
typedef std::shared_ptr<MessageProxy> MessageProxyPtr;
-} //DBus
-} //Messaging
-} //DeviceAPI
+} //namespace DBus
+} //namespace messaging
+} //namespace extension
#endif /* __TIZEN_MESSAGE_PROXY_H */
--- /dev/null
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "change_listener_container.h"
+
+#include "email_manager.h"
+//#include "ShortMsgManager.h"
+
+namespace extension {
+namespace messaging {
+
+ChangeListenerContainer& ChangeListenerContainer::getInstance()
+{
+ EmailManager::getInstance(); //make sure that callbacks are registered in email-service
+ //ShortMsgManager::getInstance(); //make sure that callbacks are registered in msg-service
+ static ChangeListenerContainer clc;
+ return clc;
+}
+
+ChangeListenerContainer::ChangeListenerContainer():
+ m_current_id(0)
+{
+ LoggerD("Entered");
+ // call getNextId() function to properly initialize static mutex inside
+ getNextId();
+}
+
+// --- Listeners registration functions ---
+/*
+ *long ChangeListenerContainer::addMessageChangeListener(
+ * std::shared_ptr<MessagesChangeCallback> callback)
+ *{
+ * LoggerD("Entered");
+ * // Check type of service for which listener should be registered
+ * // and lock appropriate mutex
+ * MessageType mtype = callback->getServiceType();
+ * if (MessageType(SMS) == mtype || MessageType(MMS) == mtype)
+ * {
+ * std::lock_guard<std::mutex> lock(m_short_lock);
+ * int new_id = getNextId();
+ * m_short_message_callbacks.insert(std::make_pair(new_id, callback));
+ * LoggerD("Added callback for ShortMessage, watchId: %d", new_id);
+ * return new_id;
+ * }
+ * else if (MessageType(EMAIL) == mtype) {
+ * std::lock_guard<std::mutex> lock(m_email_lock);
+ * int new_id = getNextId();
+ * m_email_message_callbacks.insert(std::make_pair(new_id, callback));
+ * LoggerD("Added callback for Email, watchId: %d", new_id);
+ * return new_id;
+ * }
+ * LoggerE("Listener with invalid MessageService type - failed to register");
+ * return -1;
+ *}
+ */
+
+/*
+ *long ChangeListenerContainer::addConversationChangeListener(
+ * std::shared_ptr<ConversationsChangeCallback> callback)
+ *{
+ * LoggerD("Entered");
+ * // Check type of service for which listener should be registered
+ * // and lock appropriate mutex
+ * MessageType mtype = callback->getServiceType();
+ * if (MessageType(SMS) == mtype || MessageType(MMS) == mtype)
+ * {
+ * std::lock_guard<std::mutex> lock(m_short_lock);
+ * int new_id = getNextId();
+ * m_short_conversation_callbacks.insert(std::make_pair(new_id, callback));
+ * LoggerD("Added callback for ShortMessage, watchId: %d", new_id);
+ * return new_id;
+ * }
+ * else if (MessageType(EMAIL) == mtype) {
+ * std::lock_guard<std::mutex> lock(m_email_lock);
+ * int new_id = getNextId();
+ * m_email_conversation_callbacks.insert(std::make_pair(new_id, callback));
+ * LoggerD("Added callback for Email, watchId: %d", new_id);
+ * return new_id;
+ * }
+ * LoggerE("Listener with invalid MessageService type - failed to register");
+ * return -1;
+ *}
+ */
+
+/*
+ *long ChangeListenerContainer::addFolderChangeListener(
+ * std::shared_ptr<FoldersChangeCallback> callback)
+ *{
+ * LoggerD("Entered");
+ * // Check type of service for which listener should be registered
+ * // and lock appropriate mutex
+ * MessageType mtype = callback->getServiceType();
+ * if (MessageType(SMS) == mtype || MessageType(MMS) == mtype)
+ * {
+ * std::lock_guard<std::mutex> lock(m_short_lock);
+ * int new_id = getNextId();
+ * m_short_folder_callbacks.insert(std::make_pair(new_id, callback));
+ * LoggerD("Added callback for ShortMessage, watchId: %d", new_id);
+ * return new_id;
+ * }
+ * else if (MessageType(EMAIL) == mtype) {
+ * std::lock_guard<std::mutex> lock(m_email_lock);
+ * int new_id = getNextId();
+ * m_email_folder_callbacks.insert(std::make_pair(new_id, callback));
+ * LoggerD("Added callback for Email, watchId: %d", new_id);
+ * return new_id;
+ * }
+ * LoggerE("Listener with invalid MessageService type - failed to register");
+ * return -1;
+ *}
+ */
+
+// --- listeners removal ---
+void ChangeListenerContainer::removeChangeListener(long id)
+{
+ LoggerD("Entered");
+ // Lock both types of collections - id does not indicate service type
+ // TODO: consider additional map<listener_id, service_type> or
+ // map<lister_id, map<>&> to provide faster and less complicated removal
+ std::lock_guard<std::mutex> shortlock(m_short_lock);
+ std::lock_guard<std::mutex> maillock(m_email_lock);
+ LoggerD("Locks done");
+ if(id<0 || id > m_current_id) {
+ LoggerE("Invalid id %d given.", id);
+ return;
+ }
+ /*
+ *if (removeCallbackIfExists<MessagesChangeCallback>(
+ * context, m_short_message_callbacks,id)) {
+ * LoggerD("ShortMessage message listener with id: %d removed", id);
+ *}
+ *else if (removeCallbackIfExists<ConversationsChangeCallback>(
+ * context, m_short_conversation_callbacks, id)) {
+ * LoggerD("ShortMessage conversation listener with id: %d removed", id);
+ *}
+ *else if (removeCallbackIfExists<FoldersChangeCallback>(
+ * context, m_short_folder_callbacks, id)) {
+ * LoggerD("ShortMessage folder listener with id: %d removed", id);
+ *}
+ */
+ /*else*/ if (removeCallbackIfExists<MessagesChangeCallback>(
+ m_email_message_callbacks, id)) {
+ LoggerD("Email message listener with id: %d removed", id);
+ }
+ /*
+ *else if (removeCallbackIfExists<ConversationsChangeCallback>(
+ * context, m_email_conversation_callbacks, id)) {
+ * LoggerD("Email conversation listener with id: %d removed", id);
+ *}
+ *else if (removeCallbackIfExists<FoldersChangeCallback>(
+ * context, m_email_folder_callbacks,id)) {
+ * LoggerD("Email folder listener with id: %d removed", id);
+ *}
+ */
+ else {
+ LoggerW("WatchId %d not found", id);
+ }
+}
+
+// --- Callback invoking functions ---
+// -- for message --
+/*
+ *void ChangeListenerContainer::callMessageAdded(EventMessages* event)
+ *{
+ * LoggerD("Entered");
+ *
+ * if(MessageType(SMS) == event->service_type ||
+ * MessageType(MMS) == event->service_type) {
+ * LoggerD("Calling messageadded for ShortMessage");
+ * MCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * callbacksCopy = m_short_message_callbacks;
+ * }
+ * callAdded<MessagesChangeCallback, EventMessages>(
+ * callbacksCopy, event);
+ * }
+ * else if(MessageType(EMAIL) == event->service_type) {
+ * LoggerD("Calling messageadded for Email");
+ * MCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> maillock(m_email_lock);
+ * callbacksCopy = m_email_message_callbacks;
+ * }
+ * callAdded<MessagesChangeCallback, EventMessages>(
+ * callbacksCopy, event);
+ * }
+ * else {
+ * LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ * }
+ *}
+ */
+
+/*
+ *void ChangeListenerContainer::callMessageUpdated(EventMessages* event)
+ *{
+ * LoggerD("Entered");
+ *
+ * if(MessageType(SMS) == event->service_type ||
+ * MessageType(MMS) == event->service_type) {
+ * LoggerD("Calling messageupdated for ShortMessage");
+ * MCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * callbacksCopy = m_short_message_callbacks;
+ * }
+ * callUpdated<MessagesChangeCallback, EventMessages>(
+ * callbacksCopy, event);
+ * }
+ * else if(MessageType(EMAIL) == event->service_type) {
+ * LoggerD("Calling messageupdated for Email");
+ * MCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> maillock(m_email_lock);
+ * callbacksCopy = m_email_message_callbacks;
+ * }
+ * callUpdated<MessagesChangeCallback, EventMessages>(
+ * callbacksCopy, event);
+ * }
+ * else {
+ * LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ * }
+ *}
+ */
+
+void ChangeListenerContainer::callMessageRemoved(EventMessages* event)
+{
+ LoggerD("Entered");
+
+ if(MessageType(SMS) == event->service_type ||
+ MessageType(MMS) == event->service_type) {
+ /*
+ *LoggerD("Calling messageremoved for ShortMessage");
+ *MCLmap callbacksCopy;
+ *{
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * callbacksCopy = m_short_message_callbacks;
+ *}
+ *callRemoved<MessagesChangeCallback, EventMessages>(
+ * callbacksCopy, event);
+ */
+ }
+ else if(MessageType(EMAIL) == event->service_type) {
+ LoggerD("Calling messageremoved for Email");
+ MCLmap callbacksCopy;
+ {
+ std::lock_guard<std::mutex> maillock(m_email_lock);
+ callbacksCopy = m_email_message_callbacks;
+ }
+ callRemoved<MessagesChangeCallback, EventMessages>(
+ callbacksCopy, event);
+ }
+ else {
+ LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ }
+}
+
+// -- for conversation --
+/*
+ *void ChangeListenerContainer::callConversationAdded(EventConversations* event)
+ *{
+ * LoggerD("Entered");
+ *
+ * if(MessageType(SMS) == event->service_type ||
+ * MessageType(MMS) == event->service_type) {
+ * LoggerD("Calling converationadded for ShortMessage");
+ * CCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * callbacksCopy = m_short_conversation_callbacks;
+ * }
+ * callAdded<ConversationsChangeCallback, EventConversations>(
+ * callbacksCopy, event);
+ * }
+ * else if(MessageType(EMAIL) == event->service_type) {
+ * LoggerD("Calling conversationadded for Email");
+ * CCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> maillock(m_email_lock);
+ * callbacksCopy = m_email_conversation_callbacks;
+ * }
+ * callAdded<ConversationsChangeCallback, EventConversations>(
+ * callbacksCopy, event);
+ * }
+ * else {
+ * LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ * }
+ *}
+ */
+
+/*
+ *void ChangeListenerContainer::callConversationUpdated(EventConversations* event)
+ *{
+ * LoggerD("Entered");
+ *
+ * if(MessageType(SMS) == event->service_type ||
+ * MessageType(MMS) == event->service_type) {
+ * LoggerD("Calling conversationupdated for ShortConversation");
+ * CCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * callbacksCopy = m_short_conversation_callbacks;
+ * }
+ * callUpdated<ConversationsChangeCallback, EventConversations>(
+ * callbacksCopy, event);
+ * }
+ * else if(MessageType(EMAIL) == event->service_type) {
+ * LoggerD("Calling conversationupdated for Email");
+ * CCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> maillock(m_email_lock);
+ * callbacksCopy = m_email_conversation_callbacks;
+ * }
+ * callUpdated<ConversationsChangeCallback, EventConversations>(
+ * callbacksCopy, event);
+ * }
+ * else {
+ * LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ * }
+ *}
+ */
+
+/*
+ *void ChangeListenerContainer::callConversationRemoved(EventConversations* event)
+ *{
+ * LoggerD("Entered");
+ *
+ * if(MessageType(SMS) == event->service_type ||
+ * MessageType(MMS) == event->service_type) {
+ * LoggerD("Calling conversationremoved for ShortConversation");
+ * CCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * LoggerD("m_short_conversation_callbacks.size() = %d",
+ * m_short_conversation_callbacks.size());
+ *
+ * callbacksCopy = m_short_conversation_callbacks;
+ * }
+ * callRemoved<ConversationsChangeCallback, EventConversations>(
+ * callbacksCopy, event);
+ * }
+ * else if(MessageType(EMAIL) == event->service_type) {
+ * LoggerD("Calling conversationremoved for Email");
+ * CCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> maillock(m_email_lock);
+ * LoggerD("m_email_conversation_callbacks.size() = %d",
+ * m_email_conversation_callbacks.size());
+ *
+ * callbacksCopy = m_email_conversation_callbacks;
+ * }
+ * callRemoved<ConversationsChangeCallback, EventConversations>(
+ * callbacksCopy, event);
+ * }
+ * else {
+ * LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ * }
+ *}
+ */
+
+// -- for folder --
+/*
+ *void ChangeListenerContainer::callFolderAdded(EventFolders* event)
+ *{
+ * LoggerD("Entered");
+ *
+ * if(MessageType(SMS) == event->service_type ||
+ * MessageType(MMS) == event->service_type) {
+ * LoggerD("Calling folderadded for ShortMessage");
+ * FCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * callbacksCopy = m_short_folder_callbacks;
+ * }
+ * callAdded<FoldersChangeCallback, EventFolders>(
+ * m_short_folder_callbacks, event);
+ * }
+ * else if(MessageType(EMAIL) == event->service_type) {
+ * LoggerD("Calling folderadded for Email");
+ * FCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> maillock(m_email_lock);
+ * callbacksCopy = m_email_folder_callbacks;
+ * }
+ * callAdded<FoldersChangeCallback, EventFolders>(
+ * callbacksCopy, event);
+ * }
+ * else {
+ * LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ * }
+ *}
+ */
+
+
+/*
+ *void ChangeListenerContainer::callFolderUpdated(EventFolders* event)
+ *{
+ * LoggerD("Entered");
+ *
+ * if(MessageType(SMS) == event->service_type ||
+ * MessageType(MMS) == event->service_type) {
+ * LoggerD("Calling folderupdated for ShortFolder");
+ * FCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * callbacksCopy = m_short_folder_callbacks;
+ * }
+ * callUpdated<FoldersChangeCallback, EventFolders>(
+ * callbacksCopy, event);
+ * }
+ * else if(MessageType(EMAIL) == event->service_type) {
+ * LoggerD("Calling folderupdated for Email");
+ * FCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> maillock(m_email_lock);
+ * callbacksCopy = m_email_folder_callbacks;
+ * }
+ * callUpdated<FoldersChangeCallback, EventFolders>(
+ * callbacksCopy, event);
+ * }
+ * else {
+ * LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ * }
+ *}
+ */
+
+/*
+ *void ChangeListenerContainer::callFolderRemoved(EventFolders* event)
+ *{
+ * LoggerD("Entered");
+ *
+ * if(MessageType(SMS) == event->service_type ||
+ * MessageType(MMS) == event->service_type) {
+ * LoggerD("Calling folderremoved for ShortFolder");
+ * FCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> shortlock(m_short_lock);
+ * callbacksCopy = m_short_folder_callbacks;
+ * }
+ * callRemoved<FoldersChangeCallback, EventFolders>(
+ * callbacksCopy, event);
+ * }
+ * else if(MessageType(EMAIL) == event->service_type) {
+ * LoggerD("Calling folderremoved for Email");
+ * FCLmap callbacksCopy;
+ * {
+ * std::lock_guard<std::mutex> maillock(m_email_lock);
+ * callbacksCopy = m_email_folder_callbacks;
+ * }
+ * callRemoved<FoldersChangeCallback, EventFolders>(
+ * callbacksCopy, event);
+ * }
+ * else {
+ * LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+ * }
+ *}
+ */
+
+int ChangeListenerContainer::getNextId() {
+ // mutex is created only on first call (first call added to constructor
+ // to initialize mutex correctly
+ static std::mutex id_mutex;
+ std::lock_guard<std::mutex> idlock(id_mutex);
+
+ return m_current_id++;
+}
+
+} //namespace messaging
+} //namespace extension
--- /dev/null
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef __TIZEN_CHANGE_LISTENER_CONTAINER_H__
+#define __TIZEN_CHANGE_LISTENER_CONTAINER_H__
+
+#include <memory>
+#include <mutex>
+#include <vector>
+#include <map>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "message.h"
+
+//#include "MessageConversation.h"
+//#include "MessageFolder.h"
+
+#include "messaging_util.h"
+#include "messages_change_callback.h"
+
+//#include "ConversationsChangeCallback.h"
+//#include "FoldersChangeCallback.h"
+
+namespace extension {
+namespace messaging {
+
+//! Data related to MessageChange event passed to add/update/remove callbacks
+struct EventMessages {
+ int service_id;
+ MessageType service_type;
+ MessagePtrVector items;
+ // TODO Uncomment when removing conversations
+ // ConversationPtrVector removed_conversations;
+ // TODO: Filtering support
+};
+
+//! Data related to ConversationChange event passed to add/update/remove callbacks
+/*
+ *struct EventConversations {
+ * int service_id;
+ * MessageType service_type;
+ * ConversationPtrVector items;
+ * // TODO: Filtering support
+ *};
+ */
+
+//! Data related to FolderChange event passed to add/update/remove callbacks
+/*
+ *struct EventFolders {
+ * int service_id;
+ * MessageType service_type;
+ * FolderPtrVector items;
+ * // TODO: Filtering support
+ *};
+ */
+
+template <class T > struct CallbackDataHolder {
+ std::shared_ptr<T> ptr;
+ int operation_type;
+};
+
+//! Map that stores MessageChangeListeners
+typedef std::map<long, std::shared_ptr<MessagesChangeCallback>> MCLmap;
+//! Map that stores ConversationsChangeListeners
+//typedef std::map<long, std::shared_ptr<ConversationsChangeCallback>> CCLmap;
+//! Map that stores FoldersChangeListeners
+//typedef std::map<long, std::shared_ptr<FoldersChangeCallback>> FCLmap;
+
+
+/**
+ * Singleton class for managing (storing and calling) ChangeListeners for
+ * short message (SMS/MMS) service and email service.
+ *
+ * Two mutexes used to lock separately addition and searching of Short and
+ * Email message related listeners. Listeneres removal functions locks access
+ * to both types of listeners (havind listener id only it is not possible
+ * to determine message (service) type.
+ */
+class ChangeListenerContainer {
+ public:
+ static ChangeListenerContainer& getInstance();
+
+
+ // Interface for listener's manipulation (registration and removal).
+ //long addMessageChangeListener(std::shared_ptr<MessagesChangeCallback> callback);
+ //long addConversationChangeListener(std::shared_ptr<ConversationsChangeCallback> callback);
+ //long addFolderChangeListener(std::shared_ptr<FoldersChangeCallback> callback);
+ void removeChangeListener(long id);
+
+ // Methods used to invoke registered listeners
+ //void callMessageAdded(EventMessages* event);
+ //void callMessageUpdated(EventMessages* event);
+ void callMessageRemoved(EventMessages* event);
+ //void callConversationAdded(EventConversations* event);
+ //void callConversationUpdated(EventConversations* event);
+ //void callConversationRemoved(EventConversations* event);
+ //void callFolderAdded(EventFolders* event);
+ //void callFolderUpdated(EventFolders* event);
+ //void callFolderRemoved(EventFolders* event);
+
+ private:
+ //! Highest used id (in most cases id of last registered listener)
+ long m_current_id;
+ //! Mutex for preventing race conditions on SMS/MMS callbacks collection
+ std::mutex m_short_lock;
+ //! Mutex for preventing race conditions on email callbacks collection
+ std::mutex m_email_lock;
+
+ //! Functions for listener id incrementation with thread safe mutex locking
+ int getNextId();
+
+ /* Callbacks for emails and short messages should be stored in separate
+ * collections to simplyfy adding ang searching on call */
+
+ // Callbacks for short messages service
+ //MCLmap m_short_message_callbacks;
+ //CCLmap m_short_conversation_callbacks;
+ //FCLmap m_short_folder_callbacks;
+
+ // Callbacks for email service
+ MCLmap m_email_message_callbacks;
+ //CCLmap m_email_conversation_callbacks;
+ //FCLmap m_email_folder_callbacks;
+
+ ChangeListenerContainer();
+
+ template<class T> static bool removeCallbackIfExists(
+ std::map<long,std::shared_ptr<T>>& collection, long id ) {
+ LoggerD("Entered");
+
+ auto itr = collection.find(id);
+ if ( itr != collection.end()) {
+ itr->second->setActive(false);
+ collection.erase(id);
+ return true;
+ } else {
+ LoggerE("Removing callback which does not belong to the current context is not allowed.");
+ throw common::NotFoundException(
+ "Removing callback which does not belong to the current context is not allowed.");
+ }
+ return false;
+ }
+
+ /* Templates below written for code reusage (each template is used
+ * 2 times in each callXxxx[Added | Removed | Updated] function. */
+
+ /**
+ * Template function for calling "added" callback for all listeners
+ * from given collection with given event.
+ * */
+ /*
+ *template<class T, class U> void callAdded(
+ * std::map<long,std::shared_ptr<T>>& collection,
+ * U* event) {
+ * typename std::map<long,std::shared_ptr<T>>::iterator itstart = collection.begin();
+ * typename std::map<long,std::shared_ptr<T>>::iterator itend = collection.end();
+ * try {
+ * for (; itstart != itend; ++itstart) {
+ * auto callback = (*itstart).second;
+ * if (callback->getServiceType() == event->service_type
+ * && callback->getServiceId() == event->service_id) {
+ * LoggerD("Found callback for given service id (%d) and type (%d)",
+ * event->service_id, event->service_type);
+ * //@todo filter msgs
+ * callback->added(event->items);
+ * }
+ * }
+ * }catch (const Common::BasePlatformException &err) {
+ * LoggerE("callAdded failed, %s: %s", err.getName().c_str(),
+ * err.getMessage().c_str());
+ * }
+ * catch (...) {
+ * LoggerE("callAdded failed");
+ * }
+ *}
+ */
+
+ /**
+ * Template function for calling "updated" callback for all listeners
+ * from given collection with given event.
+ * */
+ /*
+ *template<class T, class U> void callUpdated(
+ * std::map<long,std::shared_ptr<T>>& collection,
+ * U* event) {
+ * typename std::map<long,std::shared_ptr<T>>::iterator itstart = collection.begin();
+ * typename std::map<long,std::shared_ptr<T>>::iterator itend = collection.end();
+ * try {
+ * for (; itstart != itend; ++itstart) {
+ * auto callback = (*itstart).second;
+ * if (callback->getServiceType() == event->service_type
+ * && callback->getServiceId() == event->service_id) {
+ * LoggerD("Found callback for given service id (%d) and type (%d)",
+ * event->service_id, event->service_type);
+ * //@todo filter msgs
+ * callback->updated(event->items);
+ * }
+ * }
+ * }catch (const Common::BasePlatformException &err) {
+ * LoggerE("callUpdated failed, %s: %s", err.getName().c_str(),
+ * err.getMessage().c_str());
+ * }
+ * catch (...) {
+ * LoggerE("callUpdated failed");
+ * }
+ *}
+ */
+
+ /**
+ * Template function for calling "removed" callback for all listeners
+ * from given collection with given event.
+ * */
+
+ template<class T, class U> void callRemoved(
+ std::map<long,std::shared_ptr<T>>& collection,
+ U* event) {
+ typename std::map<long,std::shared_ptr<T>>::iterator itstart = collection.begin();
+ typename std::map<long,std::shared_ptr<T>>::iterator itend = collection.end();
+ try {
+ for (; itstart != itend; ++itstart) {
+ auto callback = (*itstart).second;
+ if (callback->getServiceType() == event->service_type
+ && callback->getServiceId() == event->service_id) {
+ LoggerD("Found callback for given service id (%d) and type (%d)",
+ event->service_id, event->service_type);
+ //@todo filter msgs
+ callback->removed(event->items);
+ }
+ }
+ }catch (const common::PlatformException &err) {
+ LoggerE("callRemoved failed, %s: %s", err.name().c_str(),
+ err.message().c_str());
+ }
+ catch (...) {
+ LoggerE("callRemoved failed");
+ }
+ }
+};
+
+
+} //namespace messaging
+} //namespace extension
+
+#endif // __TIZEN_CHANGE_LISTENER_CONTAINER_H__
DBus::Proxy::DBUS_IFACE_NETWORK_STATUS);
if (!m_proxy_load_body) {
LoggerE("Load body proxy is null");
- throw common::UnknownException("Load body proxy is null");
+ throw UnknownException("Load body proxy is null");
}
m_proxy_load_body->signalSubscribe();
// throw Common::UnknownException("Load attachment proxy is null");
// }
// m_proxy_load_attachment->signalSubscribe();
-//
-// m_proxy_messageStorage = std::make_shared<DBus::MessageProxy>();
-// if (!m_proxy_messageStorage) {
-// LoggerE("Message proxy is null");
-// throw Common::UnknownException("Message proxy is null");
-// }
-// m_proxy_messageStorage->signalSubscribe();
+
+ m_proxy_messageStorage = std::make_shared<DBus::MessageProxy>();
+ if (!m_proxy_messageStorage) {
+ LoggerE("Message proxy is null");
+ throw UnknownException("Message proxy is null");
+ }
+ m_proxy_messageStorage->signalSubscribe();
m_proxy_send = std::make_shared<DBus::SendProxy>();
if (!m_proxy_send) {
LoggerE("Send proxy is null");
- throw common::UnknownException("Send proxy is null");
+ throw UnknownException("Send proxy is null");
}
m_proxy_send->signalSubscribe();
}
//################################## ^stopSync #################################
-//void removeEmailCompleteCB(MessagesCallbackUserData* callback)
-//{
-// LoggerD("Entered");
-// if (!callback) {
-// LoggerE("Callback is null");
-// return;
-// }
-//
-// JSContextRef context = callback->getContext();
-// if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
-// LoggerE("context was closed");
-// delete callback;
-// callback = NULL;
-// return;
-// }
-//
-// try {
-// if (callback->isError()) {
-// LoggerD("Calling error callback");
-// JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
-// callback->getErrorName(),
-// callback->getErrorMessage());
-// callback->callErrorCallback(errobj);
-// } else {
-// LoggerD("Calling success callback");
-// callback->callSuccessCallback();
-// }
-// } catch (const BasePlatformException& err) {
-// LoggerE("Error while calling removeEmail callback: %s (%s)",
-// (err.getName()).c_str(), (err.getMessage()).c_str());
-// } catch (...) {
-// LoggerE("Unknown error when calling removeEmail callback.");
-// }
-//
-// delete callback;
-// callback = NULL;
-//}
-//
-//EmailManager::DeleteReqVector::iterator EmailManager::getDeleteRequest(
-// const std::vector<int> &ids)
-//{
-// for (auto idIt = ids.begin(); idIt != ids.end(); ++idIt) {
-// for (auto reqIt = m_deleteRequests.begin(); reqIt != m_deleteRequests.end(); ++reqIt) {
-// MessagePtrVector msgs = reqIt->callback->getMessages();
-// for (auto msgIt = msgs.begin(); msgIt != msgs.end(); ++msgIt) {
-// if ((*msgIt)->getId() == *idIt) {
-// return reqIt;
-// }
-// }
-// }
-// }
-// return m_deleteRequests.end();
-//}
-//
-//void EmailManager::removeStatusCallback(const std::vector<int> &ids,
-// email_noti_on_storage_event status)
-//{
-// LoggerD("Enter");
-// std::lock_guard<std::mutex> lock(m_mutex);
-// DeleteReqVector::iterator it = getDeleteRequest(ids);
-// if (it != m_deleteRequests.end()) {
-// LoggerD("Found request");
-// if (NOTI_MAIL_DELETE_FINISH == status) {
-// LoggerD("Successfully removed %d mails", ids.size());
-// it->messagesDeleted += ids.size();
-// }
-// MessagesCallbackUserData* callback = it->callback;
-// if (NOTI_MAIL_DELETE_FAIL == status) {
-// LoggerD("Failed to remove mail");
-// callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages remove failed");
-// }
-// //if one of mails failed, call error callback
-// //if all mails are deleted, call success.
-// // >= is used in case of duplicated dbus messages
-// if (NOTI_MAIL_DELETE_FAIL == status ||
-// static_cast<unsigned int>(it->messagesDeleted) >= it->callback->getMessages().size()) {
-// LoggerD("Calling callback");
-// m_deleteRequests.erase(it);
-// m_mutex.unlock();
-// removeEmailCompleteCB(callback);
-// } else {
-// LoggerD("Not all messages are removed, waiting for next callback");
-// }
-// } else {
-// LoggerD("Request not found, ignoring");
-// }
-//}
-//
-//void EmailManager::removeMessages(MessagesCallbackUserData* callback)
-//{
-// LoggerD("Entered");
-//
-// if (!callback){
-// LoggerE("Callback is null");
-// return;
-// }
-//
-// int error;
-// email_mail_data_t *mail = NULL;
-//
-// try {
-// std::lock_guard<std::mutex> lock(m_mutex);
-// std::vector<std::shared_ptr<Message>> messages = callback->getMessages();
-// MessageType type = callback->getMessageServiceType();
-// for(auto it = messages.begin() ; it != messages.end(); ++it) {
-// if((*it)->getType() != type) {
-// LoggerE("Invalid message type");
-// throw TypeMismatchException("Error while deleting email");
-// }
-// }
-// for (auto it = messages.begin() ; it != messages.end(); ++it) {
-// error = email_get_mail_data((*it)->getId(), &mail);
-// if (EMAIL_ERROR_NONE != error) {
-// LoggerE("Couldn't retrieve mail data");
-// throw UnknownException("Error while deleting mail");
-// }
-//
-// //This task (_EMAIL_API_DELETE_MAIL) is for async
-// error = email_delete_mail(mail->mailbox_id, &mail->mail_id, 1, 0);
-// if (EMAIL_ERROR_NONE != error) {
-// email_free_mail_data(&mail, 1);
-// LoggerE("Error while deleting mail");
-// throw UnknownException("Error while deleting mail");
-// }
-// email_free_mail_data(&mail, 1);
-// }
-// //store delete request and wait for dbus response
-// DeleteReq request;
-// request.callback = callback;
-// request.messagesDeleted = 0;
-// m_deleteRequests.push_back(request);
-// } catch (const BasePlatformException& err) {
-// LoggerE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
-// callback->setError(err.getName(), err.getMessage());
-// removeEmailCompleteCB(callback);
-// } catch (...) {
-// LoggerE("Messages remove failed");
-// callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages remove failed");
-// removeEmailCompleteCB(callback);
-// }
-//}
-//
+void removeEmailCompleteCB(MessagesCallbackUserData* callback)
+{
+ LoggerD("Entered");
+ if (!callback) {
+ LoggerE("Callback is null");
+ return;
+ }
+
+ try {
+ if (callback->isError()) {
+ LoggerD("Calling error callback");
+ MessagingInstance::getInstance().PostMessage(
+ callback->getJson()->serialize().c_str());
+ } else {
+ LoggerD("Calling success callback");
+
+ auto json = callback->getJson();
+ picojson::object& obj = json->get<picojson::object>();
+ obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+ MessagingInstance::getInstance().PostMessage(json->serialize().c_str());
+ }
+ } catch (const PlatformException& err) {
+ LoggerE("Error while calling removeEmail callback: %s (%s)",
+ (err.name()).c_str(), (err.message()).c_str());
+ } catch (...) {
+ LoggerE("Unknown error when calling removeEmail callback.");
+ }
+
+ delete callback;
+ callback = NULL;
+}
+
+EmailManager::DeleteReqVector::iterator EmailManager::getDeleteRequest(
+ const std::vector<int> &ids)
+{
+ for (auto idIt = ids.begin(); idIt != ids.end(); ++idIt) {
+ for (auto reqIt = m_deleteRequests.begin(); reqIt != m_deleteRequests.end(); ++reqIt) {
+ MessagePtrVector msgs = reqIt->callback->getMessages();
+ for (auto msgIt = msgs.begin(); msgIt != msgs.end(); ++msgIt) {
+ if ((*msgIt)->getId() == *idIt) {
+ return reqIt;
+ }
+ }
+ }
+ }
+ return m_deleteRequests.end();
+}
+
+void EmailManager::removeStatusCallback(const std::vector<int> &ids,
+ email_noti_on_storage_event status)
+{
+ LoggerD("Enter");
+ std::lock_guard<std::mutex> lock(m_mutex);
+ DeleteReqVector::iterator it = getDeleteRequest(ids);
+ if (it != m_deleteRequests.end()) {
+ LoggerD("Found request");
+ if (NOTI_MAIL_DELETE_FINISH == status) {
+ LoggerD("Successfully removed %d mails", ids.size());
+ it->messagesDeleted += ids.size();
+ }
+ MessagesCallbackUserData* callback = it->callback;
+ if (NOTI_MAIL_DELETE_FAIL == status) {
+ LoggerD("Failed to remove mail");
+ UnknownException e("Messages remove failed");
+ callback->setError(e.name(), e.message());
+ }
+ //if one of mails failed, call error callback
+ //if all mails are deleted, call success.
+ // >= is used in case of duplicated dbus messages
+ if (NOTI_MAIL_DELETE_FAIL == status ||
+ static_cast<unsigned int>(it->messagesDeleted) >= it->callback->getMessages().size()) {
+ LoggerD("Calling callback");
+ m_deleteRequests.erase(it);
+ m_mutex.unlock();
+ removeEmailCompleteCB(callback);
+ } else {
+ LoggerD("Not all messages are removed, waiting for next callback");
+ }
+ } else {
+ LoggerD("Request not found, ignoring");
+ }
+}
+
+void EmailManager::removeMessages(MessagesCallbackUserData* callback)
+{
+ LoggerD("Entered");
+
+ if (!callback){
+ LoggerE("Callback is null");
+ return;
+ }
+
+ int error;
+ email_mail_data_t *mail = NULL;
+
+ try {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ std::vector<std::shared_ptr<Message>> messages = callback->getMessages();
+ MessageType type = callback->getMessageServiceType();
+ for(auto it = messages.begin() ; it != messages.end(); ++it) {
+ if((*it)->getType() != type) {
+ LoggerE("Invalid message type");
+ throw TypeMismatchException("Error while deleting email");
+ }
+ }
+ for (auto it = messages.begin() ; it != messages.end(); ++it) {
+ error = email_get_mail_data((*it)->getId(), &mail);
+ if (EMAIL_ERROR_NONE != error) {
+ LoggerE("Couldn't retrieve mail data");
+ throw UnknownException("Error while deleting mail");
+ }
+
+ //This task (_EMAIL_API_DELETE_MAIL) is for async
+ error = email_delete_mail(mail->mailbox_id, &mail->mail_id, 1, 0);
+ if (EMAIL_ERROR_NONE != error) {
+ email_free_mail_data(&mail, 1);
+ LoggerE("Error while deleting mail");
+ throw UnknownException("Error while deleting mail");
+ }
+ email_free_mail_data(&mail, 1);
+ }
+ //store delete request and wait for dbus response
+ DeleteReq request;
+ request.callback = callback;
+ request.messagesDeleted = 0;
+ m_deleteRequests.push_back(request);
+ } catch (const PlatformException& err) {
+ LoggerE("%s (%s)", (err.name()).c_str(), (err.message()).c_str());
+ callback->setError(err.name(), err.message());
+ removeEmailCompleteCB(callback);
+ } catch (...) {
+ LoggerE("Messages remove failed");
+ UnknownException e("Messages remove failed");
+ callback->setError(e.name(), e.message());
+ removeEmailCompleteCB(callback);
+ }
+}
+
//void EmailManager::updateMessages(MessagesCallbackUserData* callback)
//{
// LoggerD("Entered");
#include "DBus/SyncProxy.h"
#include "DBus/LoadBodyProxy.h"
//#include "DBus/LoadAttachmentProxy.h"
-//#include "DBus/MessageProxy.h"
+#include "DBus/MessageProxy.h"
#include "DBus/SendProxy.h"
namespace extension {
static EmailManager& getInstance();
void addDraftMessage(MessageCallbackUserData* callback);
-// void removeMessages(MessagesCallbackUserData* callback);
+ void removeMessages(MessagesCallbackUserData* callback);
// void updateMessages(MessagesCallbackUserData* callback);
void findMessages(FindMsgCallbackUserData* callback);
// void findConversations(ConversationCallbackData* callback);
void sendMessage(MessageRecipientsCallbackData* callback);
void sendStatusCallback(int mail_id, email_noti_on_network_event status,
int error_code);
-// void removeStatusCallback(const std::vector<int> &ids,
-// email_noti_on_storage_event status);
-//
+ void removeStatusCallback(const std::vector<int> &ids,
+ email_noti_on_storage_event status);
+
void loadMessageBody(MessageBodyCallbackData* callback);
// void loadMessageAttachment(MessageAttachmentCallbackData* callback);
typedef SendReqMap::iterator SendReqMapIterator;
SendReqMapIterator getSendRequest(int mail_id);
SendReqMap m_sendRequests;
-// struct DeleteReq {
-// MessagesCallbackUserData* callback;
-// int messagesDeleted;
-// };
-// typedef std::vector<DeleteReq> DeleteReqVector;
-// /**
-// * Find first request containing at least one message id
-// * @param ids
-// * @return
-// */
-// DeleteReqVector::iterator getDeleteRequest(const std::vector<int> &ids);
-// DeleteReqVector m_deleteRequests;
+ struct DeleteReq {
+ MessagesCallbackUserData* callback;
+ int messagesDeleted;
+ };
+ typedef std::vector<DeleteReq> DeleteReqVector;
+ /**
+ * Find first request containing at least one message id
+ * @param ids
+ * @return
+ */
+ DeleteReqVector::iterator getDeleteRequest(const std::vector<int> &ids);
+ DeleteReqVector m_deleteRequests;
int m_slot_size;
DBus::SyncProxyPtr m_proxy_sync;
DBus::LoadBodyProxyPtr m_proxy_load_body;
// DBus::LoadAttachmentProxyPtr m_proxy_load_attachment;
-// DBus::MessageProxyPtr m_proxy_messageStorage;
+ DBus::MessageProxyPtr m_proxy_messageStorage;
DBus::SendProxyPtr m_proxy_send;
std::mutex m_mutex;
#include "messaging_util.h"
#include "message_callback_user_data.h"
+#include "messages_callback_user_data.h"
namespace extension {
namespace messaging {
virtual MessageType getMsgServiceType() const;
virtual void addDraftMessage(MessageCallbackUserData* callback) = 0;
- virtual void removeMessages() = 0;
+ virtual void removeMessages(MessagesCallbackUserData* callback) = 0;
virtual void updateMessages() = 0;
virtual void findMessages() = 0;
virtual void findConversations() = 0;
}
}
-void MessageStorageEmail::removeMessages()
+static gboolean removeMessagesTask(void* data)
{
LoggerD("Entered");
- //TODO add implementation
+
+ MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+ EmailManager::getInstance().removeMessages(callback);
+
+ return FALSE;
+}
+
+void MessageStorageEmail::removeMessages(MessagesCallbackUserData* callback)
+{
+ LoggerD("Entered");
+
+ if (!callback) {
+ LoggerE("Callback is null");
+ throw common::UnknownException("Callback is null");
+ }
+
+ callback->setMessageServiceType(m_msg_type);
+
+ guint id = g_idle_add(removeMessagesTask, static_cast<void*>(callback));
+ if (!id) {
+ LoggerE("g_idle_add failed");
+ delete callback;
+ callback = NULL;
+ }
}
void MessageStorageEmail::updateMessages()
virtual ~MessageStorageEmail();
virtual void addDraftMessage(MessageCallbackUserData* callback);
- virtual void removeMessages();
+ virtual void removeMessages(MessagesCallbackUserData* callback);
virtual void updateMessages();
virtual void findMessages();
virtual void findConversations();
--- /dev/null
+
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "messages_callback_user_data.h"
+
+namespace extension {
+namespace messaging {
+
+MessagesCallbackUserData::MessagesCallbackUserData():
+ common::CallbackUserData(),
+ m_is_error(false),
+ m_service_type(MessageType::UNDEFINED)
+{
+}
+
+MessagesCallbackUserData::~MessagesCallbackUserData() {
+}
+
+void MessagesCallbackUserData::addMessage(std::shared_ptr<Message> msg)
+{
+ m_messages.push_back(msg);
+}
+
+std::vector<std::shared_ptr<Message>> MessagesCallbackUserData::getMessages() const
+{
+ return m_messages;
+}
+
+void MessagesCallbackUserData::setError(const std::string& err_name,
+ const std::string& err_message)
+{
+ // keep only first error in chain
+ if (!m_is_error) {
+ picojson::object& obj = m_json->get<picojson::object>();
+ obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+ auto objData = picojson::object();
+
+ objData[JSON_ERROR_NAME] = picojson::value(err_name);
+ objData[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+
+ obj[JSON_DATA] = picojson::value(objData);
+
+ m_is_error = true;
+ m_err_name = err_name;
+ m_err_message = err_message;
+ }
+}
+
+bool MessagesCallbackUserData::isError() const
+{
+ return m_is_error;
+}
+
+std::string MessagesCallbackUserData::getErrorName() const
+{
+ return m_err_name;
+}
+
+std::string MessagesCallbackUserData::getErrorMessage() const
+{
+ return m_err_message;
+}
+
+void MessagesCallbackUserData::setMessageServiceType(MessageType m_msg_type)
+{
+ m_service_type = m_msg_type;
+}
+
+MessageType MessagesCallbackUserData::getMessageServiceType() const
+{
+ return m_service_type;
+}
+
+}//messaging
+}//extension
--- /dev/null
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MESSAGING_MESSAGES_CALLBACK_USER_DATA_H_
+#define MESSAGING_MESSAGES_CALLBACK_USER_DATA_H_
+
+#include "common/callback_user_data.h"
+#include "messaging_util.h"
+
+#include <memory>
+#include <string>
+
+namespace extension {
+namespace messaging {
+
+class Message;
+
+class MessagesCallbackUserData: public common::CallbackUserData {
+public:
+ MessagesCallbackUserData();
+ virtual ~MessagesCallbackUserData();
+
+ void addMessage(std::shared_ptr<Message> msg);
+ std::vector<std::shared_ptr<Message>> getMessages() const;
+
+ void setError(const std::string& err_name,
+ const std::string& err_message);
+ bool isError() const;
+ std::string getErrorName() const;
+ std::string getErrorMessage() const;
+
+ void setMessageServiceType(MessageType m_msg_type);
+ MessageType getMessageServiceType() const;
+
+private:
+ std::vector<std::shared_ptr<Message>> m_messages;
+ bool m_is_error;
+ std::string m_err_name;
+ std::string m_err_message;
+ MessageType m_service_type;
+};
+
+}//messaging
+}//extension
+
+#endif /* MESSAGING_MESSAGES_CALLBACK_USER_DATA_H_ */
+
--- /dev/null
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//#include <JSWebAPIErrorFactory.h>
+//#include <JSUtil.h>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "messages_change_callback.h"
+//#include "JSMessage.h"
+//#include "AbstractFilter.h"
+//#include "MessagingUtil.h"
+
+namespace extension {
+namespace messaging {
+
+namespace {
+
+std::string limitedString(const std::string& src,
+ const size_t max_len = 40)
+{
+ if(src.length() > max_len) {
+ return src.substr(0,max_len);
+ } else {
+ return src;
+ }
+}
+
+} //Anonymous namespace
+
+const char* MESSAGESADDED = "messagesadded";
+const char* MESSAGESUPDATED = "messagesupdated";
+const char* MESSAGESREMOVED = "messagesremoved";
+
+MessagesChangeCallback::MessagesChangeCallback(/*JSContextRef global_ctx,
+ JSObjectRef on_added_obj,
+ JSObjectRef on_updated_obj,
+ JSObjectRef on_removed_obj,*/
+ int service_id,
+ MessageType service_type) :
+ /*m_callback_data(global_ctx),*/
+ m_service_id(service_id),
+ m_msg_type(service_type),
+ m_is_act(true)
+{
+ LOGD("Entered");
+
+ //m_callback_data.setCallback(MESSAGESADDED, on_added_obj);
+ //m_callback_data.setCallback(MESSAGESUPDATED, on_updated_obj);
+ //m_callback_data.setCallback(MESSAGESREMOVED, on_removed_obj);
+}
+
+MessagesChangeCallback::~MessagesChangeCallback()
+{
+ LOGD("Entered");
+}
+
+/*
+ *MessagePtrVector MessagesChangeCallback::filterMessages(
+ * AbstractFilterPtr filter,
+ * const MessagePtrVector& source_messages,
+ * const int service_id)
+ *{
+ * LOGD("Entered sourceMessages.size():%d filter:%s", source_messages.size(),
+ * (filter ? "PRESENT" : "NULL"));
+ *
+ * if (filter) {
+ * MessagePtrVector filtered_messages;
+ * MessagePtrVector::const_iterator it = source_messages.begin();
+ * MessagePtrVector::const_iterator end_it = source_messages.end();
+ *
+ * for(int i = 0; it != end_it ; ++i, ++it) {
+ * const MessagePtr& message = *it;
+ * message->setServiceId(service_id);
+ *
+ * const bool matched = filter->isMatching(message.get());
+ * if(matched) {
+ * filtered_messages.push_back(message);
+ * }
+ *
+ * LOGD("[%d] is Message(%p) {", i, message.get());
+ * LOGD("[%d] messageId: %d", i, message->getId());
+ * LOGD("[%d] message subject: %s", i, message->getSubject().c_str());
+ * LOGD("[%d] from: %s", i, message->getFrom().c_str());
+ *
+ * if(message->getBody()) {
+ * const std::string& pBody = message->getBody()->getPlainBody();
+ * LOGD("[%d] message plainBody: %s", i, limitedString(pBody).c_str());
+ * }
+ *
+ * LOGD("[%d] matched filter: %s", i, matched ? "YES" : "NO");
+ * LOGD("[%d] }");
+ * }
+ *
+ * LOGD("returning matching %d of %d messages", filtered_messages.size(),
+ * source_messages.size());
+ * return filtered_messages;
+ * }
+ * else {
+ * return source_messages;
+ * }
+ *}
+ */
+
+/*
+ *void MessagesChangeCallback::added(const MessagePtrVector& msgs)
+ *{
+ * LOGD("Entered num messages: %d", msgs.size());
+ * if (!m_is_act) {
+ * return;
+ * }
+ * JSContextRef ctx = m_callback_data.getContext();
+ * CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+ * MessagePtrVector filtered_msgs = filterMessages(m_filter, msgs, m_service_id);
+ * //cancel callback only if filter did remove all messages
+ * //if callback was called with empty msgs list, call it
+ * if (msgs.size() > 0 && filtered_msgs.size() == 0) {
+ * LOGD("All messages were filtered out, not calling callback");
+ * return;
+ * }
+ * JSObjectRef js_obj = JSMessage::messageVectorToJSObjectArray(
+ * ctx, filtered_msgs);
+ *
+ * LOGD("Calling:%s with:%d added messages", MESSAGESADDED,
+ * filtered_msgs.size());
+ * m_callback_data.invokeCallback(MESSAGESADDED, js_obj);
+ *}
+ *
+ *void MessagesChangeCallback::updated(const MessagePtrVector& msgs)
+ *{
+ * LOGD("Entered num messages: %d", msgs.size());
+ * if (!m_is_act) {
+ * return;
+ * }
+ * JSContextRef ctx = m_callback_data.getContext();
+ * CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+ * MessagePtrVector filtered_msgs = filterMessages(m_filter, msgs, m_service_id);
+ * //cancel callback only if filter did remove all messages
+ * //if callback was called with empty msgs list, call it
+ * if (msgs.size() > 0 && filtered_msgs.size() == 0) {
+ * LOGD("All messages were filtered out, not calling callback");
+ * return;
+ * }
+ * JSObjectRef js_obj = JSMessage::messageVectorToJSObjectArray(
+ * ctx, filtered_msgs);
+ *
+ * LOGD("Calling:%s with:%d updated messages", MESSAGESUPDATED,
+ * filtered_msgs.size());
+ * m_callback_data.invokeCallback(MESSAGESUPDATED, js_obj);
+ *}
+ */
+
+void MessagesChangeCallback::removed(const MessagePtrVector& msgs)
+{
+/*
+ * LOGD("Enter event: msgs.size() = %d", msgs.size());
+ * if (!m_is_act) {
+ * return;
+ * }
+ *
+ * MessagePtrVector filtered_msgs = filterMessages(m_filter, msgs, m_service_id);
+ * //cancel callback only if filter did remove all messages
+ * //if callback was called with empty msgs list, call it
+ * if (msgs.size() > 0 && filtered_msgs.size() == 0) {
+ * LOGD("All messages were filtered out, not calling callback");
+ * return;
+ * }
+ * JSObjectRef js_obj = JSMessage::messageVectorToJSObjectArray(
+ * ctx, filtered_msgs);
+ *
+ * LOGD("Calling:%s with:%d removed messages", MESSAGESREMOVED,
+ * filtered_msgs.size());
+ * m_callback_data.invokeCallback(MESSAGESREMOVED, js_obj);
+ */
+}
+
+/*
+ *void MessagesChangeCallback::setFilter(AbstractFilterPtr filter)
+ *{
+ * m_filter = filter;
+ *}
+ */
+
+/*
+ *AbstractFilterPtr MessagesChangeCallback::getFilter() const
+ *{
+ * return m_filter;
+ *}
+ */
+
+int MessagesChangeCallback::getServiceId() const
+{
+ return m_service_id;
+}
+
+MessageType MessagesChangeCallback::getServiceType() const
+{
+ return m_msg_type;
+}
+
+void MessagesChangeCallback::setActive(bool act) {
+ m_is_act = act;
+}
+
+bool MessagesChangeCallback::isActive() {
+ return m_is_act;
+}
+
+void MessagesChangeCallback::setItems(MessagePtrVector& items)
+{
+ m_items = items;
+}
+MessagePtrVector MessagesChangeCallback::getItems()
+{
+ return m_items;
+}
+
+
+} //namespace messaging
+} //namespace extension
--- /dev/null
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef __TIZEN_MESSAGES_CHANGE_CALLBACK_H__
+#define __TIZEN_MESSAGES_CHANGE_CALLBACK_H__
+
+//#include <JavaScriptCore/JavaScript.h>
+
+//#include <MultiCallbackUserData.h>
+
+//#include <AbstractFilter.h>
+
+#include "message.h"
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+extern const char* MESSAGESADDED;
+extern const char* MESSAGESUPDATED;
+extern const char* MESSAGESREMOVED;
+
+class MessagesChangeCallback {
+public:
+ MessagesChangeCallback(
+ int service_id,
+ MessageType service_type);
+ virtual ~MessagesChangeCallback();
+
+ //void added(const MessagePtrVector& messages);
+ //void updated(const MessagePtrVector& messages);
+ void removed(const MessagePtrVector& messages);
+
+ //void setFilter(DeviceAPI::Tizen::AbstractFilterPtr filter);
+ //DeviceAPI::Tizen::AbstractFilterPtr getFilter() const;
+
+ int getServiceId() const;
+ MessageType getServiceType() const;
+ /*
+ *static MessagePtrVector filterMessages(
+ * DeviceAPI::Tizen::AbstractFilterPtr a_filter,
+ * const MessagePtrVector& a_sourceMessages,
+ * const int service_id);
+ */
+
+ void setActive(bool act);
+ bool isActive();
+
+ void setItems(MessagePtrVector& items);
+ MessagePtrVector getItems();
+private:
+ //Common::MultiCallbackUserData m_callback_data;
+ //DeviceAPI::Tizen::AbstractFilterPtr m_filter;
+ int m_service_id;
+ MessageType m_msg_type;
+ bool m_is_act;
+ MessagePtrVector m_items;
+};
+
+} //namespace messaging
+} //namespace extension
+
+
+#endif // __TIZEN_MESSAGES_CHANGE_CALLBACK_H__
#'DBus/LoadAttachmentProxy.h',
'DBus/LoadBodyProxy.cpp',
'DBus/LoadBodyProxy.h',
- #'DBus/MessageProxy.cpp',
- #'DBus/MessageProxy.h',
+ 'DBus/MessageProxy.cpp',
+ 'DBus/MessageProxy.h',
'DBus/Proxy.cpp',
'DBus/Proxy.h',
'DBus/SendProxy.cpp',
'MsgCommon/CompositeFilter.h',
'MsgCommon/FilterIterator.cpp',
'MsgCommon/FilterIterator.h',
+ 'message_callback_user_data.cc',
+ 'message_callback_user_data.h',
+ 'messages_callback_user_data.cc',
+ 'messages_callback_user_data.h',
+ 'change_listener_container.cc',
+ 'change_listener_container.h',
+ 'messages_change_callback.cc',
+ 'messages_change_callback.h'
],
'includes': [
'../common/pkg-config.gypi',
{name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
]);
+ var self = this;
+
bridge.async({
cmd: 'MessageStorage_removeMessages',
args: {
- messages: args.messages
+ messages: args.messages,
+ serviceId: self.service.id,
+ type: self.service.type
}
}).then({
success: function () {
picojson::object& out)
{
LoggerD("Entered");
+ picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+ picojson::array messages = data.at(REMOVE_MESSAGES_ARGS_MESSAGES).get<picojson::array>();
+ const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+ MessagesCallbackUserData* callback = new MessagesCallbackUserData();
+
+ auto each = [callback] (picojson::value& v)->void {
+ callback->addMessage(MessagingUtil::jsonToMessage(v));
+ };
+
+ for_each(messages.begin(), messages.end(), each);
+
+ auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+ picojson::object& obj = json->get<picojson::object>();
+ obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+ callback->setJson(json);
+
+ int serviceId = static_cast<int>(data.at(FUNCTIONS_HIDDEN_ARGS_SERVICE_ID).get<double>());
+ auto service = MessagingManager::getInstance().getMessageServiceEmail(serviceId);
+
+ service->getMsgStorage()->removeMessages(callback);
}
void MessagingInstance::MessageStorageUpdateMessages(const picojson::value& args,