[messaging] Make MessageFolder.attributes a picojson::value.
[platform/core/api/webapi-plugins.git] / src / messaging / messaging_instance.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include "messaging_instance.h"
18
19 #include <system_info.h>
20 #include <sstream>
21 #include <stdexcept>
22
23 #include "common/filesystem/filesystem_provider.h"
24 #include "common/logger.h"
25 #include "common/tools.h"
26
27 #include "MsgCommon/AbstractFilter.h"
28 #include "conversations_change_callback.h"
29 #include "email_manager.h"
30 #include "find_msg_callback_user_data.h"
31 #include "folders_change_callback.h"
32 #include "message.h"
33 #include "message_storage.h"
34 #include "messages_callback_user_data.h"
35 #include "messages_change_callback.h"
36 #include "messaging_manager.h"
37 #include "messaging_util.h"
38 #include "short_message_manager.h"
39
40 using common::ErrorCode;
41 using common::TypeMismatchException;
42 using common::PlatformResult;
43 using common::tools::ReportError;
44
45 namespace extension {
46 namespace messaging {
47
48 namespace {
49 const char* GET_MESSAGE_SERVICES_ARGS_MESSAGE_SERVICE_TYPE = "messageServiceType";
50 const char* SEND_MESSAGE_ARGS_MESSAGE = "message";
51 const char* SEND_MESSAGE_ARGS_SIMINDEX = "simIndex";
52 const char* LOAD_MESSAGE_ATTACHMENT_ARGS_ATTACHMENT = "attachment";
53 const char* SYNC_ARGS_ID = "id";
54 const char* SYNC_ARGS_LIMIT = "limit";
55 const char* SYNC_FOLDER_ARGS_ID = "id";
56 const char* SYNC_FOLDER_ARGS_FOLDER = "folder";
57 const char* SYNC_FOLDER_ARGS_LIMIT = "limit";
58 const char* STOP_SYNC_ARGS_ID = "id";
59 const char* STOP_SYNC_ARGS_OPID = "opId";
60 const char* ADD_DRAFT_MESSAGE_ARGS_MESSAGE = "message";
61 const char* REMOVE_MESSAGES_ARGS_MESSAGES = "messages";
62 const char* UPDATE_MESSAGES_ARGS_MESSAGES = "messages";
63 const char* FIND_CONVERSATIONS_ARGS_LIMIT = "limit";
64 const char* FIND_CONVERSATIONS_ARGS_OFFSET = "offset";
65 const char* REMOVE_CONVERSATIONS_ARGS_CONVERSATIONS = "conversations";
66 const char* FIND_FOLDERS_ARGS_LIMIT = "limit";
67 const char* FIND_FOLDERS_ARGS_OFFSET = "offset";
68 const char* REMOVE_CHANGE_LISTENER_ARGS_WATCHID = "watchId";
69 const char* FUNCTIONS_HIDDEN_ARGS_SERVICE_ID = "serviceId";
70 const char* FUN_MESSAGE_MESSAGING_EMAIL = "messaging.email";
71
72 int getServiceIdFromJSON(const picojson::object& data) {
73   try {
74     return std::stoi(
75         MessagingUtil::getValueFromJSONObject<std::string>(data, FUNCTIONS_HIDDEN_ARGS_SERVICE_ID));
76   } catch (...) {
77     return -1;
78   }
79 };
80
81 const std::string kPrivilegeMessagingRead = "http://tizen.org/privilege/messaging.read";
82 const std::string kPrivilegeMessagingWrite = "http://tizen.org/privilege/messaging.write";
83
84 const long kDumbCallbackId = -1;
85 }
86
87 MessagingInstance::MessagingInstance() : manager_(*this), queue_(*this) {
88   ScopeLogger();
89   using std::placeholders::_1;
90   using std::placeholders::_2;
91
92 #define REGISTER_METHOD(M) RegisterSyncHandler(#M, std::bind(&MessagingInstance::M, this, _1, _2))
93   REGISTER_METHOD(GetMessageServices);
94   REGISTER_METHOD(MessageServiceSendMessage);
95   REGISTER_METHOD(MessageServiceLoadMessageBody);
96   REGISTER_METHOD(MessageServiceLoadMessageAttachment);
97   REGISTER_METHOD(MessageStorageAddDraftMessage);
98   REGISTER_METHOD(MessageStorageFindMessages);
99   REGISTER_METHOD(MessageStorageRemoveMessages);
100   REGISTER_METHOD(MessageStorageUpdateMessages);
101   REGISTER_METHOD(MessageStorageFindConversations);
102   REGISTER_METHOD(MessageStorageRemoveConversations);
103   REGISTER_METHOD(MessageStorageFindFolders);
104
105   REGISTER_METHOD(MessageServiceSync);
106   REGISTER_METHOD(MessageServiceStopSync);
107   REGISTER_METHOD(MessageServiceSyncFolder);
108   REGISTER_METHOD(MessageStorageAddMessagesChangeListener);
109   REGISTER_METHOD(MessageStorageAddConversationsChangeListener);
110   REGISTER_METHOD(MessageStorageAddFolderChangeListener);
111   REGISTER_METHOD(MessageStorageRemoveChangeListener);
112   REGISTER_METHOD(MessageGetMessageStatus);
113 #undef REGISTER_METHOD
114 }
115
116 MessagingInstance::~MessagingInstance() {
117   ScopeLogger();
118 }
119
120 #define POST_AND_RETURN(ret, json, obj)                                            \
121   LogAndReportError(ret, &obj);                                                    \
122   queue_.addAndResolve(obj.at(JSON_CALLBACK_ID).get<double>(), PostPriority::HIGH, \
123                        json->serialize());                                         \
124   return;
125
126 #define CHECK_EXIST(args, name, out)                                                \
127   if (!args.contains(name)) {                                                       \
128     std::string message = std::string(name) + " is required argument";              \
129     LogAndReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, message), &out); \
130     return;                                                                         \
131   }
132
133 EmailManager& MessagingInstance::getEmailManager() {
134   return email_manager_;
135 }
136
137 ShortMsgManager& MessagingInstance::getShortMsgManager() {
138   return short_msg_manager_;
139 }
140
141 void MessagingInstance::GetMessageServices(const picojson::value& args, picojson::object& out) {
142   ScopeLogger();
143
144   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
145
146   picojson::value serviceTag =
147       args.get<picojson::object>().at(GET_MESSAGE_SERVICES_ARGS_MESSAGE_SERVICE_TYPE);
148   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
149   // above values should be validated in js
150   manager_.getMessageServices(serviceTag.to_str(), callbackId);
151 }
152
153 void MessagingInstance::MessageServiceSendMessage(const picojson::value& args,
154                                                   picojson::object& out) {
155   ScopeLogger();
156
157   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
158   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
159
160   picojson::object data = args.get<picojson::object>();
161   picojson::value v_message = data.at(SEND_MESSAGE_ARGS_MESSAGE);
162
163   bool has_attachments = v_message.get("hasAttachment").get<bool>();
164   if (has_attachments) {
165     const auto& attachments = v_message.get("attachments").get<std::vector<picojson::value>>();
166     for (const auto& att : attachments) {
167       const auto& attachment_path = att.get("filePath").get<std::string>();
168       const auto& attachment_real_path =
169           common::FilesystemProvider::Create().GetRealPath(attachment_path);
170       CHECK_STORAGE_ACCESS(attachment_real_path, &out);
171     }
172   }
173
174   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
175
176   auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
177   picojson::object& obj = json->get<picojson::object>();
178   obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
179
180   std::shared_ptr<Message> message;
181   PlatformResult ret = MessagingUtil::jsonToMessage(v_message, &message, *this);
182   if (ret.IsError()) {
183     POST_AND_RETURN(ret, json, obj)
184   }
185
186   MessageRecipientsCallbackData* callback =
187       new MessageRecipientsCallbackData(queue_, callbackId, *this);
188   long simIndex = 0;
189   int serviceId = 0;
190
191   callback->setMessage(message);
192   serviceId = getServiceIdFromJSON(data);
193   callback->setAccountId(serviceId);
194   simIndex = static_cast<long>(
195       MessagingUtil::getValueFromJSONObject<double>(data, SEND_MESSAGE_ARGS_SIMINDEX));
196
197   bool cell_support = false;
198   system_info_get_platform_bool("http://tizen.org/feature/network.telephony", &cell_support);
199   if (cell_support) {
200     LoggerD("cell_support is true");
201     if (!callback->setSimIndex(simIndex)) {
202       delete callback;
203       callback = nullptr;
204       POST_AND_RETURN(PlatformResult(ErrorCode::UNKNOWN_ERR, "set sim index failed"), json, obj)
205     }
206   } else {
207     LoggerD("cell_support is false");
208   }
209
210   callback->AddToQueue();
211   auto service = manager_.getMessageService(serviceId);
212
213   ret = service->sendMessage(callback);
214   if (!ret) {
215     POST_AND_RETURN(ret, json, obj)
216   }
217 }
218
219 void MessagingInstance::MessageServiceLoadMessageBody(const picojson::value& args,
220                                                       picojson::object& out) {
221   ScopeLogger();
222
223   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
224   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
225
226   picojson::object data = args.get<picojson::object>();
227
228   picojson::value json_message = data.at(ADD_DRAFT_MESSAGE_ARGS_MESSAGE);
229   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
230
231   auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
232   picojson::object& obj = json->get<picojson::object>();
233   obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
234
235   std::shared_ptr<Message> message;
236   PlatformResult ret = MessagingUtil::jsonToMessage(json_message, &message, *this);
237   if (ret.IsError()) {
238     POST_AND_RETURN(ret, json, obj)
239   }
240
241   MessageBodyCallbackData* callback = new MessageBodyCallbackData(queue_, callbackId, *this);
242
243   callback->setMessage(message);
244
245   callback->AddToQueue();
246   auto service = manager_.getMessageService(getServiceIdFromJSON(data));
247   ret = service->loadMessageBody(callback);
248   if (ret.IsError()) {
249     POST_AND_RETURN(ret, json, obj)
250   }
251 }
252
253 void MessagingInstance::MessageServiceLoadMessageAttachment(const picojson::value& args,
254                                                             picojson::object& out) {
255   ScopeLogger();
256
257   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
258   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
259
260   picojson::object data = args.get<picojson::object>();
261   picojson::value attachment = data.at(LOAD_MESSAGE_ATTACHMENT_ARGS_ATTACHMENT);
262   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
263
264   MessageAttachmentCallbackData* callback =
265       new MessageAttachmentCallbackData(queue_, callbackId, *this);
266   callback->setMessageAttachment(MessagingUtil::jsonToMessageAttachment(attachment));
267
268   callback->AddToQueue();
269   auto service = manager_.getMessageService(getServiceIdFromJSON(data));
270   const auto result = service->loadMessageAttachment(callback);
271   if (result.IsError()) {
272     auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
273     picojson::object& obj = json->get<picojson::object>();
274     obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
275     POST_AND_RETURN(result, json, obj)
276   }
277 }
278
279 void MessagingInstance::MessageServiceSync(const picojson::value& args, picojson::object& out) {
280   ScopeLogger();
281
282   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
283   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
284
285   picojson::object data = args.get<picojson::object>();
286   picojson::value v_id = data.at(SYNC_ARGS_ID);
287   picojson::value v_limit = data.at(SYNC_ARGS_LIMIT);
288   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
289
290   int id = -1;
291   try {
292     id = std::stoi(v_id.get<std::string>());
293   } catch (...) {
294     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &out,
295                       ("Problem with MessageService"));
296     return;
297   }
298   long limit = 0;
299   if (v_limit.is<double>()) {
300     limit = static_cast<long>(v_limit.get<double>());
301   }
302
303   SyncCallbackData* callback = new SyncCallbackData(queue_, callbackId, *this);
304   callback->setAccountId(id);
305   callback->setLimit(limit);
306
307   callback->AddToQueue();
308   long op_id = -1;
309
310   const auto result = manager_.getMessageService(id)->sync(callback, &op_id);
311
312   if (result) {
313     ReportSuccess(picojson::value(static_cast<double>(op_id)), out);
314   } else {
315     LogAndReportError(result, &out);
316   }
317 }
318
319 void MessagingInstance::MessageServiceSyncFolder(const picojson::value& args,
320                                                  picojson::object& out) {
321   ScopeLogger();
322
323   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
324   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
325
326   picojson::object data = args.get<picojson::object>();
327   picojson::value v_id = data.at(SYNC_FOLDER_ARGS_ID);
328   picojson::value v_folder = data.at(SYNC_FOLDER_ARGS_FOLDER);
329   picojson::value v_limit = data.at(SYNC_FOLDER_ARGS_LIMIT);
330   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
331
332   int id = -1;
333   try {
334     id = std::stoi(v_id.get<std::string>());
335   } catch (...) {
336     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &out,
337                       ("Problem with MessageService"));
338     return;
339   }
340
341   long limit = 0;
342   if (v_limit.is<double>()) {
343     limit = static_cast<long>(v_limit.get<double>());
344   }
345
346   SyncFolderCallbackData* callback = new SyncFolderCallbackData(queue_, callbackId, *this);
347   callback->setAccountId(id);
348   auto folder_ptr = std::make_shared<MessageFolder>();
349   folder_ptr->attributes = v_folder;
350   callback->setMessageFolder(folder_ptr);
351   callback->setLimit(limit);
352
353   callback->AddToQueue();
354   long op_id = -1;
355
356   const auto result = manager_.getMessageService(id)->syncFolder(callback, &op_id);
357   if (result) {
358     ReportSuccess(picojson::value(static_cast<double>(op_id)), out);
359   } else {
360     LogAndReportError(result, &out);
361   }
362 }
363
364 void MessagingInstance::MessageServiceStopSync(const picojson::value& args, picojson::object& out) {
365   ScopeLogger();
366   CHECK_EXIST(args, STOP_SYNC_ARGS_OPID, out);
367
368   picojson::object data = args.get<picojson::object>();
369
370   if (data.find(STOP_SYNC_ARGS_ID) != data.end()) {
371     picojson::value v_id = data.at(STOP_SYNC_ARGS_ID);
372     picojson::value v_op_id = data.at(STOP_SYNC_ARGS_OPID);
373
374     int id = -1;
375     try {
376       id = std::stoi(v_id.get<std::string>());
377     } catch (...) {
378       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &out,
379                         ("Problem with MessageService"));
380       return;
381     }
382
383     long op_id = 0;
384     if (v_op_id.is<double>()) {
385       op_id = static_cast<long>(v_op_id.get<double>());
386     }
387
388     const auto result = manager_.getMessageService(id)->stopSync(op_id);
389
390     if (result) {
391       ReportSuccess(out);
392     } else {
393       LogAndReportError(result, &out);
394     }
395   } else {
396     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &out, ("Unknown error"));
397   }
398 }
399
400 void MessagingInstance::MessageStorageAddDraftMessage(const picojson::value& args,
401                                                       picojson::object& out) {
402   ScopeLogger();
403
404   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
405   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
406
407   picojson::object data = args.get<picojson::object>();
408   picojson::value v_message = data.at(ADD_DRAFT_MESSAGE_ARGS_MESSAGE);
409   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
410
411   auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
412   picojson::object& obj = json->get<picojson::object>();
413   obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
414
415   std::shared_ptr<Message> message;
416   PlatformResult ret = MessagingUtil::jsonToMessage(v_message, &message, *this);
417   if (ret.IsError()) {
418     POST_AND_RETURN(ret, json, obj)
419   }
420
421   MessageCallbackUserData* callback = new MessageCallbackUserData(queue_, callbackId, *this);
422   callback->setMessage(message);
423
424   int serviceId = getServiceIdFromJSON(data);
425   callback->setAccountId(serviceId);
426
427   callback->AddToQueue();
428   auto service = manager_.getMessageService(serviceId);
429   service->getMsgStorage()->addDraftMessage(callback);
430 }
431
432 void MessagingInstance::MessageStorageFindMessages(const picojson::value& args,
433                                                    picojson::object& out) {
434   ScopeLogger();
435
436   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingRead, &out);
437   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
438
439   picojson::object data = args.get<picojson::object>();
440   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
441
442   auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
443   picojson::object& obj = json->get<picojson::object>();
444   obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
445
446   AbstractFilterPtr filter;
447   PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
448   if (ret.IsError()) {
449     POST_AND_RETURN(ret, json, obj)
450   }
451   auto sortMode = MessagingUtil::jsonToSortMode(data);
452
453   long limit = static_cast<long>(
454       MessagingUtil::getValueFromJSONObject<double>(data, FIND_FOLDERS_ARGS_LIMIT));
455
456   long offset = static_cast<long>(
457       MessagingUtil::getValueFromJSONObject<double>(data, FIND_FOLDERS_ARGS_OFFSET));
458
459   int serviceId = getServiceIdFromJSON(data);
460   auto storage = manager_.getMessageService(serviceId)->getMsgStorage();
461
462   FindMsgCallbackUserData* callback = new FindMsgCallbackUserData(queue_, callbackId, *this);
463   callback->setFilter(filter);
464   callback->setLimit(limit);
465   callback->setOffset(offset);
466   callback->setAccountId(serviceId);
467   callback->setSortMode(sortMode);
468
469   callback->AddToQueue();
470   storage->findMessages(callback);
471 }
472
473 void MessagingInstance::MessageStorageRemoveMessages(const picojson::value& args,
474                                                      picojson::object& out) {
475   ScopeLogger();
476
477   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
478   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
479
480   picojson::object data = args.get<picojson::object>();
481   picojson::array messages = data.at(REMOVE_MESSAGES_ARGS_MESSAGES).get<picojson::array>();
482   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
483
484   MessagesCallbackUserData* callback = new MessagesCallbackUserData(queue_, callbackId, *this);
485
486   auto each = [callback, this](picojson::value& v) -> void {
487     std::shared_ptr<Message> message;
488     PlatformResult ret = MessagingUtil::jsonToMessage(v, &message, *this);
489     if (ret.IsSuccess()) {
490       callback->addMessage(message);
491     }
492   };
493
494   for_each(messages.begin(), messages.end(), each);
495
496   auto service = manager_.getMessageService(getServiceIdFromJSON(data));
497
498   callback->AddToQueue();
499   service->getMsgStorage()->removeMessages(callback);
500 }
501
502 void MessagingInstance::MessageStorageUpdateMessages(const picojson::value& args,
503                                                      picojson::object& out) {
504   ScopeLogger();
505
506   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
507   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
508
509   picojson::object data = args.get<picojson::object>();
510   picojson::value pico_messages = data.at(UPDATE_MESSAGES_ARGS_MESSAGES);
511   auto pico_array = pico_messages.get<picojson::array>();
512   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
513
514   auto callback = new MessagesCallbackUserData(queue_, callbackId, *this);
515
516   std::for_each(pico_array.begin(), pico_array.end(),
517                 [&callback, this](picojson::value& v) -> void {
518                   std::shared_ptr<Message> message;
519                   PlatformResult ret = MessagingUtil::jsonToMessage(v, &message, *this);
520                   if (ret.IsSuccess()) {
521                     callback->addMessage(message);
522                   }
523                 });
524
525   auto service = manager_.getMessageService(getServiceIdFromJSON(data));
526
527   callback->AddToQueue();
528   service->getMsgStorage()->updateMessages(callback);
529 }
530
531 void MessagingInstance::MessageStorageFindConversations(const picojson::value& args,
532                                                         picojson::object& out) {
533   ScopeLogger();
534
535   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingRead, &out);
536   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
537
538   picojson::object data = args.get<picojson::object>();
539   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
540
541   auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
542   picojson::object& obj = json->get<picojson::object>();
543   obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
544
545   AbstractFilterPtr filter;
546   PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
547   if (ret.IsError()) {
548     POST_AND_RETURN(ret, json, obj)
549   }
550   auto sortMode = MessagingUtil::jsonToSortMode(data);
551   long limit = static_cast<long>(
552       MessagingUtil::getValueFromJSONObject<double>(data, FIND_CONVERSATIONS_ARGS_LIMIT));
553   long offset = static_cast<long>(
554       MessagingUtil::getValueFromJSONObject<double>(data, FIND_CONVERSATIONS_ARGS_OFFSET));
555
556   int serviceId = getServiceIdFromJSON(data);
557
558   ConversationCallbackData* callback = new ConversationCallbackData(queue_, callbackId, *this);
559   callback->setFilter(filter);
560   callback->setLimit(limit);
561   callback->setOffset(offset);
562   callback->setAccountId(serviceId);
563   callback->setSortMode(sortMode);
564
565   callback->AddToQueue();
566   auto storage = manager_.getMessageService(serviceId)->getMsgStorage();
567   storage->findConversations(callback);
568 }
569
570 void MessagingInstance::MessageStorageRemoveConversations(const picojson::value& args,
571                                                           picojson::object& out) {
572   ScopeLogger();
573
574   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingWrite, &out);
575   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
576
577   picojson::object data = args.get<picojson::object>();
578   picojson::array conversations =
579       data.at(REMOVE_CONVERSATIONS_ARGS_CONVERSATIONS).get<picojson::array>();
580   const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
581
582   auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
583   picojson::object& obj = json->get<picojson::object>();
584   obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
585
586   ConversationCallbackData* callback = new ConversationCallbackData(queue_, callbackId, *this);
587
588   PlatformResult ret(ErrorCode::NO_ERROR);
589   for (auto it = conversations.begin(); it != conversations.end(); ++it) {
590     std::shared_ptr<MessageConversation> conversation;
591     ret = MessagingUtil::jsonToMessageConversation(*it, &conversation);
592     if (ret.IsError()) {
593       delete callback;
594       POST_AND_RETURN(ret, json, obj)
595     }
596     callback->addConversation(conversation);
597   }
598
599   auto service = manager_.getMessageService(getServiceIdFromJSON(data));
600
601   callback->AddToQueue();
602   service->getMsgStorage()->removeConversations(callback);
603 }
604
605 void MessagingInstance::MessageStorageFindFolders(const picojson::value& args,
606                                                   picojson::object& out) {
607   ScopeLogger();
608
609   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingRead, &out);
610   CHECK_EXIST(args, JSON_CALLBACK_ID, out);
611
612   const auto& data = args.get<picojson::object>();
613   auto service = manager_.getMessageService(getServiceIdFromJSON(data));
614
615   auto task_params = new FindFoldersTaskParams();
616   task_params->instance = this;
617   task_params->callback_id = args.get(JSON_CALLBACK_ID).get<double>();
618   task_params->account_id = service->getMsgServiceId();
619   task_params->message_type = service->getMsgServiceTypeString();
620
621   PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &(task_params->filter));
622   if (ret.IsError()) {
623     LoggerE("Cannot convert json to AbstractFilter: %s", args.serialize().c_str());
624     ReportError(ret, &out);
625     delete task_params;
626     return;
627   }
628
629   service->getMsgStorage()->findFolders(task_params);
630 }
631
632 void MessagingInstance::MessageStorageAddMessagesChangeListener(const picojson::value& args,
633                                                                 picojson::object& out) {
634   ScopeLogger();
635
636   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingRead, &out);
637
638   picojson::object data = args.get<picojson::object>();
639
640   AbstractFilterPtr filter;
641   PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
642   if (ret.IsError()) {
643     ReportError(ret, &out);
644     return;
645   }
646
647   int serviceId = getServiceIdFromJSON(data);
648
649   auto service = manager_.getMessageService(serviceId);
650
651   std::shared_ptr<MessagesChangeCallback> callback(new MessagesChangeCallback(
652       kDumbCallbackId, serviceId, service->getMsgServiceType(), queue_, *this));
653
654   callback->setFilter(filter);
655
656   long op_id = service->getMsgStorage()->addMessagesChangeListener(callback);
657
658   picojson::value v(static_cast<double>(op_id));
659   ReportSuccess(v, out);
660 }
661
662 void MessagingInstance::MessageStorageAddConversationsChangeListener(const picojson::value& args,
663                                                                      picojson::object& out) {
664   ScopeLogger();
665
666   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingRead, &out);
667
668   picojson::object data = args.get<picojson::object>();
669
670   AbstractFilterPtr filter;
671   PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
672   if (ret.IsError()) {
673     ReportError(ret, &out);
674     return;
675   }
676
677   int serviceId = getServiceIdFromJSON(data);
678
679   auto service = manager_.getMessageService(serviceId);
680
681   std::shared_ptr<ConversationsChangeCallback> callback(new ConversationsChangeCallback(
682       static_cast<long>(-1), serviceId, service->getMsgServiceType(), queue_, *this));
683
684   callback->setFilter(filter);
685
686   long op_id = service->getMsgStorage()->addConversationsChangeListener(callback);
687
688   picojson::value v(static_cast<double>(op_id));
689   ReportSuccess(v, out);
690 }
691
692 void MessagingInstance::MessageStorageAddFolderChangeListener(const picojson::value& args,
693                                                               picojson::object& out) {
694   ScopeLogger();
695
696   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingRead, &out);
697
698   picojson::object data = args.get<picojson::object>();
699
700   AbstractFilterPtr filter;
701   PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
702   if (ret.IsError()) {
703     ReportError(ret, &out);
704     return;
705   }
706
707   int serviceId = getServiceIdFromJSON(data);
708
709   auto service = manager_.getMessageService(serviceId);
710
711   std::shared_ptr<FoldersChangeCallback> callback(
712       new FoldersChangeCallback(serviceId, service->getMsgServiceType(), *this));
713
714   callback->setFilter(filter);
715
716   long op_id = service->getMsgStorage()->addFoldersChangeListener(callback);
717
718   picojson::value v(static_cast<double>(op_id));
719   ReportSuccess(v, out);
720 }
721
722 void MessagingInstance::MessageStorageRemoveChangeListener(const picojson::value& args,
723                                                            picojson::object& out) {
724   ScopeLogger();
725
726   CHECK_PRIVILEGE_ACCESS(kPrivilegeMessagingRead, &out);
727
728   picojson::object data = args.get<picojson::object>();
729   const long watchId =
730       static_cast<long>(data.at(REMOVE_CHANGE_LISTENER_ARGS_WATCHID).get<double>());
731
732   auto service = manager_.getMessageService(getServiceIdFromJSON(data));
733
734   service->getMsgStorage()->removeChangeListener(watchId);
735   ReportSuccess(out);
736 }
737
738 void MessagingInstance::MessageGetMessageStatus(const picojson::value& args,
739                                                 picojson::object& out) {
740   ScopeLogger();
741
742   picojson::object data = args.get<picojson::object>();
743   const int id = stoi(data.at("id").get<std::string>());
744   const std::string& type = data.at("type").get<std::string>();
745
746   std::string status;
747   if (FUN_MESSAGE_MESSAGING_EMAIL == type) {
748     status = email_manager_.getMessageStatus(id);
749   } else {
750     status = short_msg_manager_.getMessageStatus(id);
751   }
752
753   ReportSuccess(picojson::value(status), out);
754 }
755
756 }  // namespace messaging
757 }  // namespace extension