Update change log and spec for wrt-plugins-tizen_0.4.59
[framework/web/wrt-plugins-tizen.git] / src / Contact / JSContactManager.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        JSContactManager.cpp
20  * @author      Kisub Song (kisubs.song@samsung.com)
21  * @version     0.3
22  * @brief
23  */
24
25 #include "JSContactManager.h"
26
27 #include <string>
28 #include <CommonsJavaScript/JSCallbackManager.h>
29 #include <CommonsJavaScript/Validator.h>
30 #include <CommonsJavaScript/Converter.h>
31 #include <CommonsJavaScript/JSUtils.h>
32 #include <CommonsJavaScript/JSPendingOperation.h>
33 #include <SecurityExceptions.h>
34 #include <FilterConverter.h>
35 #include "ContactFactory.h"
36 #include "ContactTypes.h"
37 #include "plugin_config.h"
38 #include "ContactManagerController.h"
39 #include "ContactAsyncCallbackManager.h"
40 #include "ContactListenerManager.h"
41 #include "ContactConverter.h"
42 #include "JSPerson.h"
43 #include "JSContactManagerChangeCallbackManager.h"
44 #include "ContactFilterConverter.h"
45 #include <ArgumentValidator.h>
46 #include <JSWebAPIErrorFactory.h>
47 #include <TimeTracer.h>
48 #include <Logger.h>
49 #include <Export.h>
50 #include "ContactUtility.h"
51
52 namespace DeviceAPI {
53 namespace Contact {
54
55 using namespace DeviceAPI::Common;
56 using namespace DeviceAPI::Tizen;
57 using namespace WrtDeviceApis::Commons;
58 using namespace WrtDeviceApis::CommonsJavaScript;
59
60 JSClassDefinition JSContactManager::m_classInfo = {
61         0,
62         kJSClassAttributeNone,
63         "ContactManager",
64         0,
65         m_property,
66         m_function,
67         Initialize,
68         Finalize,
69         NULL, //HasProperty,
70         NULL, //GetProperty,
71         NULL, //SetProperty,
72         NULL, //DeleteProperty,
73         NULL, //GetPropertyNames,
74         NULL, //CallAsFunction,
75         NULL, //CallAsConstructor,
76         NULL, //HasInstance,
77         NULL, //ConvertToType,
78 };
79
80 const JSClassDefinition* JSContactManager::getClassInfo()
81 {
82         return &m_classInfo;
83 }
84
85 JSStaticValue JSContactManager::m_property[] = {
86         { 0, 0, 0, 0 }
87 };
88
89 JSStaticFunction JSContactManager::m_function[] = {
90         { "getAddressBooks", getAddressBooks, kJSPropertyAttributeNone },
91         { "getDefaultAddressBook", getDefaultAddressBook, kJSPropertyAttributeNone },
92         { "getUnifiedAddressBook", getUnifiedAddressBook, kJSPropertyAttributeNone },
93         { "getAddressBook", getAddressBook, kJSPropertyAttributeNone },
94         { "get", get, kJSPropertyAttributeNone },
95         { "update", update, kJSPropertyAttributeNone },
96         { "updateBatch", updateBatch, kJSPropertyAttributeNone },
97         { "remove", remove, kJSPropertyAttributeNone },
98         { "removeBatch", removeBatch, kJSPropertyAttributeNone },
99         { "find", find, kJSPropertyAttributeNone },
100         { "addChangeListener", addChangeListener, kJSPropertyAttributeNone },
101         { "removeChangeListener", removeChangeListener, kJSPropertyAttributeNone },
102         { 0, 0, 0 }
103 };
104
105 JSClassRef DLL_EXPORT JSContactManager::getClassRef()
106 {
107         if (!m_classRef) {
108                 m_classRef = JSClassCreate(&m_classInfo);
109         }
110         return m_classRef;
111 }
112
113 JSClassRef JSContactManager::m_classRef = JSClassCreate(JSContactManager::getClassInfo());
114
115 void JSContactManager::Initialize(JSContextRef context,
116                 JSObjectRef object)
117 {
118         LoggerD("Entered");
119         ContactManagerPtr contactManager = ContactFactory::getInstance().createContactManager();
120
121         ContactManagerController *priv = new ContactManagerController(context, contactManager);
122
123         JSObjectSetPrivate(object, static_cast<void*>(priv));
124 }
125
126 void JSContactManager::Finalize(JSObjectRef object)
127 {
128         LoggerD("entered");
129         ContactManagerController *priv = static_cast<ContactManagerController*>(JSObjectGetPrivate(object));
130         LoggerI("Delete address book manager");
131         delete priv;
132 }
133
134 JSValueRef JSContactManager::getAddressBooks(JSContextRef context,
135                 JSObjectRef object,
136                 JSObjectRef thisObject,
137                 size_t argumentCount,
138                 const JSValueRef arguments[],
139                 JSValueRef* exception)
140 {
141         LoggerD("Entered");
142         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
143         ContactManagerPtr contactManager;
144         JSContextRef gContext;
145         ContactManagerController *controller;
146
147         bool js2ndParamIsFunction = false;
148
149         Try     {
150                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
151                 if (!controller) {
152                         ThrowMsg(InvalidArgumentException, "No private object.");
153                 }
154                 contactManager = controller->getObject();
155                 gContext = controller->getContext();
156         } Catch(Exception) {
157                 LoggerE("No private object");
158                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
159         }
160
161         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOKS);
162         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
163
164         BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
165         try {
166                 ArgumentValidator validator(context, argumentCount, arguments);
167                 validator.toFunction(0, false);
168                 JSObjectRef errorObj = validator.toFunction(1, true);
169                 if(errorObj)
170                         js2ndParamIsFunction = true;
171         } catch (const TypeMismatchException& err ) {
172                 return JSWebAPIErrorFactory::postException(context, exception, err);
173         } catch(const BasePlatformException& err) {
174                 return JSWebAPIErrorFactory::postException(context, exception, err);
175         } catch(const ConversionException& err) {
176                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
177         } catch(const NullPointerException& err) {
178                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
179         }
180
181         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
182
183         callbackManager->setOnSuccess(arguments[0]);
184
185         if(js2ndParamIsFunction)
186                 callbackManager->setOnError(arguments[1]);
187
188         callbackManager->setObject(thisObject);
189
190         EventContactManagerGetAddressBooksPtr dplEvent(new EventContactManagerGetAddressBooks());
191
192         // set event handler's data
193         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
194         dplEvent->setForAsynchronousCall(controller);
195
196 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
197 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
198
199         Try {
200                 contactManager->getAddressBooks(dplEvent);
201                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
202         } Catch(Exception) {
203                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
204                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
205         }
206
207         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
208 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
209         return JSValueMakeUndefined(context);
210 }
211
212 JSValueRef JSContactManager::getDefaultAddressBook(JSContextRef context,
213                 JSObjectRef object,
214                 JSObjectRef thisObject,
215                 size_t argumentCount,
216                 const JSValueRef arguments[],
217                 JSValueRef* exception)
218 {
219         LoggerD("Entered");
220         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
221         ContactManagerController *priv =
222                 static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
223         if (!priv) {
224                 LoggerE("private object is null");
225                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
226         }
227
228         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_DEFAULT_ADDRESS_BOOK);
229         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
230
231         ContactManagerPtr contactManager;
232         JSContextRef gContext;
233         Try {
234                 contactManager = priv->getObject();
235                 gContext = priv->getContext();
236         } Catch(Exception) {
237                 LoggerE("contact manager or context is null");
238                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
239         }
240
241         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
242
243         EventContactManagerGetDefaultAddressBookPtr dplEvent(new EventContactManagerGetDefaultAddressBook());
244
245     dplEvent->setForSynchronousCall();
246
247         Try {
248                 contactManager->getDefaultAddressBook(dplEvent);
249         } Catch(Exception) {
250                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
251                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
252         }
253
254         if (!dplEvent->getResult() || !dplEvent->getDefaultAddressBookIsSet())
255         {
256                 std::stringstream oss;
257                 switch (dplEvent->getExceptionCode())
258                 {
259                 case ExceptionCodes::NotFoundException:
260                 case ExceptionCodes::InvalidArgumentException:
261                         LoggerE("Not Found error");
262                         oss << "No default address book";
263                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
264                         break;
265                 case ExceptionCodes::PlatformException:
266                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
267                         break;
268                 default:
269                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
270                         break;
271                 }
272         }
273
274         AddressBookPtr defaultAddressBook = dplEvent->getDefaultAddressBook();
275
276         JSValueRef resultValue;
277         Try {
278                 resultValue = converter->toJSValueRef(defaultAddressBook);
279         } Catch(Exception){
280                 LoggerE("Conversion error.");
281                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
282         }
283
284         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
285         return resultValue;
286 }
287
288 JSValueRef JSContactManager::getUnifiedAddressBook(JSContextRef context,
289                 JSObjectRef object,
290                 JSObjectRef thisObject,
291                 size_t argumentCount,
292                 const JSValueRef arguments[],
293                 JSValueRef* exception)
294 {
295         LoggerD("Entered");
296         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
297         ContactManagerController *priv =
298                 static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
299         if (!priv) {
300                 LoggerE("private object is null");
301                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
302         }
303
304         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_UNIFIED_ADDRESS_BOOK);
305         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
306
307         ContactManagerPtr contactManager;
308         JSContextRef gContext;
309         Try {
310                 contactManager = priv->getObject();
311                 gContext = priv->getContext();
312         } Catch(Exception) {
313                 LoggerE("contact manager or context is null");
314                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
315         }
316
317         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
318
319         EventContactManagerGetUnifiedAddressBookPtr dplEvent(new EventContactManagerGetUnifiedAddressBook());
320
321     dplEvent->setForSynchronousCall();
322
323         Try {
324                 contactManager->getUnifiedAddressBook(dplEvent);
325         } Catch(Exception) {
326                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
327                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
328         }
329
330         if (!dplEvent->getResult() || !dplEvent->getUnifiedAddressBookIsSet())
331         {
332                 std::stringstream oss;
333                 switch (dplEvent->getExceptionCode())
334                 {
335                 case ExceptionCodes::NotFoundException:
336                 case ExceptionCodes::InvalidArgumentException:
337                         LoggerE("Not Found error");
338                         oss << "No default address book";
339                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
340                         break;
341                 case ExceptionCodes::PlatformException:
342                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
343                         break;
344                 default:
345                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
346                         break;
347                 }
348         }
349
350         AddressBookPtr unifiedAddressBook = dplEvent->getUnifiedAddressBook();
351
352         JSValueRef resultValue;
353         Try {
354                 resultValue = converter->toJSValueRef(unifiedAddressBook);
355         } Catch(Exception){
356                 LoggerE("Conversion error.");
357                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
358         }
359
360         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
361         return resultValue;
362 }
363
364 JSValueRef JSContactManager::getAddressBook(JSContextRef context,
365                 JSObjectRef object,
366                 JSObjectRef thisObject,
367                 size_t argumentCount,
368                 const JSValueRef arguments[],
369                 JSValueRef* exception)
370 {
371         LoggerD("Entered");
372         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
373         ContactManagerController *priv =
374                 static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
375         if (!priv) {
376                 LoggerE("private object is null");
377                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
378         }
379
380         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOK);
381         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
382
383         ContactManagerPtr contactManager;
384         JSContextRef gContext;
385         Try {
386                 contactManager = priv->getObject();
387                 gContext = priv->getContext();
388         } Catch(Exception) {
389                 LoggerE("contact manager or context is null");
390                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
391         }
392
393         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
394
395         std::string addressBookId;
396         try {
397                 ArgumentValidator validator(context, argumentCount, arguments);
398                 addressBookId = validator.toString(0, false);
399         } catch (const TypeMismatchException& err ) {
400                 return JSWebAPIErrorFactory::postException(context, exception, err);
401         } catch(const BasePlatformException& err) {
402                 return JSWebAPIErrorFactory::postException(context, exception, err);
403         } catch(const ConversionException& err) {
404                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
405         } catch(const NullPointerException& err) {
406                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
407         }
408
409         EventContactManagerGetAddressBookPtr dplEvent(new EventContactManagerGetAddressBook());
410
411         dplEvent->setAddressBookId(addressBookId);
412     dplEvent->setForSynchronousCall();
413
414         Try {
415                 contactManager->getAddressBook(dplEvent);
416         } Catch(Exception) {
417                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
418                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
419         }
420
421         if (!dplEvent->getResult() || !dplEvent->getAddressBookIsSet())
422         {
423                 std::stringstream oss;
424                 switch (dplEvent->getExceptionCode())
425                 {
426                 case ExceptionCodes::NotFoundException:
427                 case ExceptionCodes::InvalidArgumentException:
428                         LoggerE("Not Found error : " << addressBookId);
429                         oss << "No addressBookId id '" << addressBookId << "'";
430                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
431                         break;
432                 case ExceptionCodes::PlatformException:
433                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
434                         break;
435                 default:
436                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
437                         break;
438                 }
439         }
440
441         AddressBookPtr addressBook = dplEvent->getAddressBook();
442
443         JSValueRef resultValue;
444         Try {
445                 resultValue = converter->toJSValueRef(addressBook);
446         } Catch(Exception){
447                 LoggerE("Conversion error.");
448                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
449         }
450
451         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
452         return resultValue;
453 }
454
455 JSValueRef JSContactManager::get(JSContextRef context,
456                 JSObjectRef object,
457                 JSObjectRef thisObject,
458                 size_t argumentCount,
459                 const JSValueRef arguments[],
460                 JSValueRef* exception)
461 {
462         LoggerD("entered");
463         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
464         ContactManagerPtr addressBook;
465         ContactManagerController *controller;
466
467         Try     {
468                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
469                 if (!controller) {
470                         ThrowMsg(InvalidArgumentException, "No private object.");
471                 }
472                 addressBook = controller->getObject();
473         } Catch(Exception) {
474                 LoggerE("No private object");
475                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
476         }
477
478         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET);
479         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
480
481         std::string id;
482
483         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
484         try     {
485                 ArgumentValidator validator(context, argumentCount, arguments);
486                 id = validator.toString(0, false);
487         } catch (const TypeMismatchException& err ) {
488                 return JSWebAPIErrorFactory::postException(context, exception, err);
489         } catch(const BasePlatformException& err) {
490                 return JSWebAPIErrorFactory::postException(context, exception, err);
491         } catch(const ConversionException& err) {
492                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
493         } catch(const NullPointerException& err) {
494                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
495         }
496
497         if(!ContactUtility::checkStrIsUInt(id))
498                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "");
499
500         EventContactManagerGetPtr dplEvent(new EventContactManagerGet());
501
502         dplEvent->setId(id);
503     dplEvent->setForSynchronousCall();
504
505         Try {
506                 addressBook->get(dplEvent);
507         } Catch(Exception) {
508                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
509                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
510         }
511
512         if (!dplEvent->getResult() || !dplEvent->getPersonIsSet())
513         {
514                 std::stringstream oss;
515                 switch (dplEvent->getExceptionCode())
516                 {
517                 case ExceptionCodes::NotFoundException:
518                 case ExceptionCodes::InvalidArgumentException:
519                         LoggerE("Not Found error : " << id);
520                         oss << "No Person id '" << id << "'";
521                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
522                         break;
523                 case ExceptionCodes::PlatformException:
524                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
525                         break;
526                 default:
527                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
528                         break;
529                 }
530         }
531
532         PersonPtr person = dplEvent->getPerson();
533
534         JSValueRef result;
535         Try {
536                 result = converter->toJSValueRef(person);
537         } Catch(Exception) {
538                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
539                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
540         }
541
542         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
543         return result;
544 }
545
546 JSValueRef JSContactManager::update(JSContextRef context,
547                 JSObjectRef object,
548                 JSObjectRef thisObject,
549                 size_t argumentCount,
550                 const JSValueRef arguments[],
551                 JSValueRef* exception)
552 {
553         LoggerD("entered");
554         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
555         ContactManagerPtr addressBook;
556         ContactManagerController *controller;
557
558         Try     {
559                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
560                 if (!controller) {
561                         ThrowMsg(InvalidArgumentException, "No private object.");
562                 }
563                 addressBook = controller->getObject();
564         } Catch(Exception) {
565                 LoggerE("No private object");
566                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
567         }
568
569         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE);
570         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
571
572         try {
573                 ArgumentValidator validator(context, argumentCount, arguments);
574                 validator.toObject(0, false);
575         } catch (const TypeMismatchException& err ) {
576                 return JSWebAPIErrorFactory::postException(context, exception, err);
577         } catch(const BasePlatformException& err) {
578                 return JSWebAPIErrorFactory::postException(context, exception, err);
579         } catch(const ConversionException& err) {
580                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
581         } catch(const NullPointerException& err) {
582                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
583         }
584
585         PersonPtr person(NULL);
586
587         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
588         Try     {
589                 if (!JSPerson::isObjectOfClass(context, arguments[0]))
590                         ThrowMsg(InvalidArgumentException, "1st argument is not a 'Contact object'.");
591                 person = converter->toPerson(arguments[0]);
592         } Catch(Exception) {
593                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
594                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument is not a 'Contact object'");
595         }
596
597         EventContactManagerUpdatePtr dplEvent(new EventContactManagerUpdate());
598
599         dplEvent->setPerson(person);
600     dplEvent->setForSynchronousCall();
601
602         Try {
603                 addressBook->update(dplEvent);
604         } Catch(Exception) {
605                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
606                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
607         }
608
609         if (!dplEvent->getResult())
610         {
611                 std::stringstream oss;
612                 switch (dplEvent->getExceptionCode())
613                 {
614                 case ExceptionCodes::NotFoundException:
615                 case ExceptionCodes::InvalidArgumentException:
616                         oss << "No id '" << person->getId() << "'";
617                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
618                         break;
619                 case ExceptionCodes::PlatformException:
620                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
621                         break;
622                 default:
623                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
624                         break;
625                 }
626         }
627
628         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
629         return JSValueMakeUndefined(context);
630 }
631
632 JSValueRef JSContactManager::updateBatch(JSContextRef context,
633                 JSObjectRef object,
634                 JSObjectRef thisObject,
635                 size_t argumentCount,
636                 const JSValueRef arguments[],
637                 JSValueRef* exception)
638 {
639         LoggerD("entered");
640         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
641         ContactManagerPtr addressBook;
642         JSContextRef gContext;
643         ContactManagerController *controller;
644
645         bool js2ndParamIsFunction = false;
646         bool js3rdParamIsFunction = false;
647
648         Try     {
649                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
650                 if (!controller) {
651                         ThrowMsg(InvalidArgumentException, "No private object.");
652                 }
653                 addressBook = controller->getObject();
654                 gContext = controller->getContext();
655         } Catch(Exception) {
656                 LoggerE("No private object");
657                 return JSWebAPIErrorFactory::postException(context, exception,
658                                 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
659         }
660
661         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE_BATCH);
662         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
663
664         try {
665                 ArgumentValidator validator(context, argumentCount, arguments);
666
667                 validator.toObject(0, false);
668                 JSObjectRef successObj = validator.toFunction(1, true);
669                 if(successObj)
670                         js2ndParamIsFunction = true;
671
672                 JSObjectRef errorObj = validator.toFunction(2, true);
673                 if(errorObj)
674                         js3rdParamIsFunction = true;
675         } catch (const TypeMismatchException& err ) {
676                 return JSWebAPIErrorFactory::postException(context, exception, err);
677         } catch(const BasePlatformException& err) {
678                 return JSWebAPIErrorFactory::postException(context, exception, err);
679         } catch(const ConversionException& err) {
680                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
681         } catch(const NullPointerException& err) {
682                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
683         }
684
685         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
686
687         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
688
689         if(js2ndParamIsFunction)
690                 callbackManager->setOnSuccess(arguments[1]);
691
692         if(js3rdParamIsFunction)
693                 callbackManager->setOnError(arguments[2]);
694
695         callbackManager->setObject(thisObject);
696
697         EventContactManagerUpdateBatchPtr dplEvent(new EventContactManagerUpdateBatch());
698         Try {
699                 dplEvent->setPersons(converter->toPersonArray(arguments[0]));
700         } Catch(ConversionException) {
701                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
702                 return JSWebAPIErrorFactory::postException(context, exception,
703                                 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "3rd argument must be a 'function' or a 'null'");
704         }
705
706         // set event handler's data
707         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
708         dplEvent->setForAsynchronousCall(controller);
709
710 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
711 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
712
713         Try {
714                 addressBook->updateBatch(dplEvent);
715                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
716         } Catch(Exception) {
717                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
718                 return JSWebAPIErrorFactory::postException(context, exception,
719                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
720         }
721
722         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
723 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
724         return JSValueMakeUndefined(context);
725 }
726
727 JSValueRef JSContactManager::remove(JSContextRef context,
728                 JSObjectRef object,
729                 JSObjectRef thisObject,
730                 size_t argumentCount,
731                 const JSValueRef arguments[],
732                 JSValueRef* exception)
733 {
734         LoggerD("entered");
735         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
736         ContactManagerPtr addressBook;
737         ContactManagerController *controller;
738
739         Try     {
740                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
741                 if (!controller) {
742                         ThrowMsg(InvalidArgumentException, "No private object.");
743                 }
744                 addressBook = controller->getObject();
745         } Catch(Exception) {
746                 LoggerE("No private object");
747                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
748         }
749
750         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE);
751         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
752
753         std::string personId;
754
755         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
756         try     {
757                 ArgumentValidator validator(context, argumentCount, arguments);
758                 personId = validator.toString(0, false);
759         } catch (const TypeMismatchException& err ) {
760                 return JSWebAPIErrorFactory::postException(context, exception, err);
761         } catch(const BasePlatformException& err) {
762                 return JSWebAPIErrorFactory::postException(context, exception, err);
763         } catch(const ConversionException& err) {
764                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
765         } catch(const NullPointerException& err) {
766                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
767         }
768         if(!ContactUtility::checkStrIsUInt(personId))
769                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "");
770
771         EventContactManagerRemovePtr dplEvent(new EventContactManagerRemove());
772
773         dplEvent->setPersonId(personId);
774     dplEvent->setForSynchronousCall();
775
776         Try {
777                 addressBook->remove(dplEvent);
778         } Catch(Exception) {
779                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
780                 return JSWebAPIErrorFactory::postException(context, exception,
781                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
782         }
783
784         if (!dplEvent->getResult())
785         {
786                 std::stringstream oss;
787                 switch (dplEvent->getExceptionCode())
788                 {
789                 case ExceptionCodes::NotFoundException:
790                 case ExceptionCodes::InvalidArgumentException:
791                         LoggerE("Not Found error : " << personId);
792                         oss << "No id '" << personId << "'";
793                         return JSWebAPIErrorFactory::postException(context, exception,
794                                         JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
795                         break;
796                 case ExceptionCodes::PlatformException:
797                         return JSWebAPIErrorFactory::postException(context, exception,
798                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
799                         break;
800                 default:
801                         return JSWebAPIErrorFactory::postException(context, exception,
802                                         JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
803                         break;
804                 }
805         }
806
807         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
808         return JSValueMakeUndefined(context);
809 }
810
811 JSValueRef JSContactManager::removeBatch(JSContextRef context,
812                 JSObjectRef object,
813                 JSObjectRef thisObject,
814                 size_t argumentCount,
815                 const JSValueRef arguments[],
816                 JSValueRef* exception)
817 {
818         LoggerD("entered");
819         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
820         ContactManagerPtr addressBook;
821         JSContextRef gContext;
822         ContactManagerController *controller;
823
824         bool js2ndParamIsFunction = false;
825         bool js3rdParamIsFunction = false;
826
827         Try     {
828                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
829                 if (!controller) {
830                         ThrowMsg(InvalidArgumentException, "No private object.");
831                 }
832                 addressBook = controller->getObject();
833                 gContext = controller->getContext();
834         } Catch(Exception) {
835                 LoggerE("No private object");
836                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
837         }
838
839         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_BATCH);
840         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
841
842         try {
843                 ArgumentValidator validator(context, argumentCount, arguments);
844
845                 validator.toObject(0, false);
846                 JSObjectRef successObj = validator.toFunction(1, true);
847                 if(successObj)
848                         js2ndParamIsFunction = true;
849
850                 JSObjectRef errorObj = validator.toFunction(2, true);
851                 if(errorObj)
852                         js3rdParamIsFunction = true;
853         } catch (const TypeMismatchException& err ) {
854                 return JSWebAPIErrorFactory::postException(context, exception, err);
855         } catch(const BasePlatformException& err) {
856                 return JSWebAPIErrorFactory::postException(context, exception, err);
857         } catch(const ConversionException& err) {
858                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
859         } catch(const NullPointerException& err) {
860                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
861         }
862
863         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
864
865         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
866
867         if(js2ndParamIsFunction)
868                 callbackManager->setOnSuccess(arguments[1]);
869
870         if(js3rdParamIsFunction)
871                 callbackManager->setOnError(arguments[2]);
872
873         callbackManager->setObject(thisObject);
874
875         EventContactManagerRemoveBatchPtr dplEvent(new EventContactManagerRemoveBatch());
876         Try {
877                 dplEvent->setPersonIds(converter->toStringArray(arguments[0]));
878         } Catch(ConversionException) {
879                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
880                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "3rd argument must be an array of 'Contact id'");
881         }
882
883         // set event handler's data
884         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
885         dplEvent->setForAsynchronousCall(controller);
886
887 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
888 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
889
890         Try {
891                 addressBook->removeBatch(dplEvent);
892                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
893         } Catch(Exception) {
894                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
895                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
896         }
897
898         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
899 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
900         return JSValueMakeUndefined(context);
901 }
902
903 JSValueRef JSContactManager::find(JSContextRef context,
904                 JSObjectRef object,
905                 JSObjectRef thisObject,
906                 size_t argumentCount,
907                 const JSValueRef arguments[],
908                 JSValueRef* exception)
909 {
910         LoggerD("entered");
911         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
912         ContactManagerPtr addressBook;
913         JSContextRef gContext;
914         ContactManagerController *controller;
915
916         bool js2ndParamIsFunction = false;
917         bool js3rdParamIsObject = false;
918         bool js4thParamIsObject = false;
919
920         Try     {
921                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
922                 if (!controller) {
923                         ThrowMsg(InvalidArgumentException, "No private object.");
924                 }
925                 addressBook = controller->getObject();
926                 gContext = controller->getContext();
927         } Catch(Exception) {
928                 LoggerE("No private object");
929                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
930         }
931
932         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_FIND);
933         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
934
935         try {
936                 ArgumentValidator validator(context, argumentCount, arguments);
937
938                 validator.toFunction(0, false);
939                 JSObjectRef errorObj = validator.toFunction(1, true);
940                 if(errorObj)
941                         js2ndParamIsFunction = true;
942
943                 JSObjectRef filterObj = validator.toObject(2, true);
944                 if(filterObj)
945                         js3rdParamIsObject = true;
946
947                 JSObjectRef sortObj = validator.toObject(3, true);
948                 if(sortObj)
949                         js4thParamIsObject = true;
950
951         } catch (const TypeMismatchException& err ) {
952                 return JSWebAPIErrorFactory::postException(context, exception, err);
953         } catch(const BasePlatformException& err) {
954                 return JSWebAPIErrorFactory::postException(context, exception, err);
955         } catch(const ConversionException& err) {
956                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
957         } catch(const NullPointerException& err) {
958                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
959         }
960
961         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
962
963         callbackManager->setOnSuccess(arguments[0]);
964
965         if (js2ndParamIsFunction)
966                 callbackManager->setOnError(arguments[1]);
967
968         callbackManager->setObject(thisObject);
969
970         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
971         PersonFilterConverterFactory::ConverterType filterConverter = PersonFilterConverterFactory::getConverter(context);
972
973         EventContactManagerFindPtr dplEvent(new EventContactManagerFind());
974         Try {
975                 if (js3rdParamIsObject){
976                         FilterPtr filter = filterConverter->toFilter(arguments[2]);
977                         if(filter)
978                                 dplEvent->setFilter(filter);
979                         else
980                                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "3rd argument must be an Correct 'Filter object' or 'null'");
981                 }
982         } Catch(Exception) {
983                 LoggerE("Error on 3rd parameter conversion : " << _rethrown_exception.GetMessage());
984                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "3rd argument must be an 'Filter object' or 'null'");
985         }
986
987         Try {
988                 if (js4thParamIsObject){
989                         SortModePtr sortMode = filterConverter->toSortMode(arguments[3]);
990                         dplEvent->setSortMode(sortMode);
991                 }
992         } Catch(Exception) {
993                 LoggerE("Error on 4th parameter conversion : " << _rethrown_exception.GetMessage());
994                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "4th argument must be an 'SortMode object' or 'null'");
995         }
996
997         // set event handler's data
998         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
999         dplEvent->setForAsynchronousCall(controller);
1000
1001 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
1002 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
1003
1004         Try {
1005                 addressBook->find(dplEvent);
1006                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
1007         } Catch(Exception) {
1008                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1009                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1010         }
1011
1012         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1013 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
1014         return JSValueMakeUndefined(context);
1015 }
1016
1017 JSValueRef JSContactManager::addChangeListener(JSContextRef context,
1018                 JSObjectRef object,
1019                 JSObjectRef thisObject,
1020                 size_t argumentCount,
1021                 const JSValueRef arguments[],
1022                 JSValueRef* exception)
1023 {
1024         LoggerD("entered");
1025         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1026         ContactManagerPtr addressBook;
1027         JSContextRef gContext;
1028         ContactManagerController *controller;
1029
1030         bool js2ndParamIsFunction = false;
1031
1032         Try     {
1033                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
1034                 if (!controller) {
1035                         ThrowMsg(InvalidArgumentException, "No private object.");
1036                 }
1037                 addressBook = controller->getObject();
1038                 gContext = controller->getContext();
1039         } Catch(Exception) {
1040                 LoggerE("No private object");
1041                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1042         }
1043
1044         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_CHANGE_LISTENER);
1045         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
1046
1047         BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
1048         try {
1049                 ArgumentValidator Argvalidator(context, argumentCount, arguments);
1050
1051                 Argvalidator.toObject(0, false);
1052                 JSObjectRef errorObj = Argvalidator.toFunction(1, true);
1053                 if(errorObj)
1054                         js2ndParamIsFunction = true;
1055
1056         } catch (const TypeMismatchException& err ) {
1057                 return JSWebAPIErrorFactory::postException(context, exception, err);
1058         } catch(const BasePlatformException& err) {
1059                 return JSWebAPIErrorFactory::postException(context, exception, err);
1060         } catch(const ConversionException& err) {
1061                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1062         } catch(const NullPointerException& err) {
1063                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1064         }
1065
1066         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
1067
1068         JSValueRef onpersonsadded;
1069         JSValueRef onpersonsupdated;
1070         JSValueRef onpersonsdeleted;
1071         Try {
1072                 JSObjectRef callbackObject = converter->toJSObjectRef(arguments[0]);
1073
1074                 onpersonsadded = JSUtils::getJSPropertyOrUndefined(context, callbackObject, "onpersonsadded");
1075                 if (validator->isNullOrUndefined(onpersonsadded))
1076                         onpersonsadded = NULL;
1077                 else if (!validator->isCallback(onpersonsadded)) {
1078                         ThrowMsg(ConversionException, "2nd argument's onpersonsadded attribute is not a 'function'");
1079                 }
1080
1081                 onpersonsupdated = JSUtils::getJSPropertyOrUndefined(context, callbackObject, "onpersonsupdated");
1082                 if (validator->isNullOrUndefined(onpersonsupdated))
1083                         onpersonsupdated = NULL;
1084                 else if (!validator->isCallback(onpersonsupdated)) {
1085                         ThrowMsg(ConversionException, "2nd argument's onpersonsupdated attribute is not a 'function'");
1086                 }
1087
1088                 onpersonsdeleted = JSUtils::getJSPropertyOrUndefined(context, callbackObject, "onpersonsremoved");
1089                 if (validator->isNullOrUndefined(onpersonsdeleted))
1090                         onpersonsdeleted = NULL;
1091                 else if (!validator->isCallback(onpersonsdeleted)) {
1092                         ThrowMsg(ConversionException, "2nd argument's onpersonsremoved attribute is not a 'function'");
1093                 }
1094
1095                 if (onpersonsadded == NULL && onpersonsupdated == NULL && onpersonsdeleted == NULL)
1096                         ThrowMsg(ConversionException, "invalid 2nd argument");
1097
1098         } Catch(ConversionException) {
1099                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
1100                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
1101         }
1102
1103         JSContactManagerChangeCallbackManagerPtr callbackManager = JSContactManagerChangeCallbackManager::createObject(gContext);
1104
1105         callbackManager->setOnPersonsAdded(onpersonsadded);
1106         callbackManager->setOnPersonsUpdated(onpersonsupdated);
1107         callbackManager->setOnPersonsDeleted(onpersonsdeleted);
1108         if(js2ndParamIsFunction)
1109                 callbackManager->setOnError(arguments[1]);
1110
1111         EventContactManagerChangeListenerEmitterPtr emitter(new EventContactManagerChangeListenerEmitter());
1112
1113         emitter->setEventPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
1114         emitter->setListener(controller);
1115
1116         EventContactManagerAddChangeListenerPtr dplEvent(new EventContactManagerAddChangeListener());
1117
1118         dplEvent->setEmitter(emitter);
1119     dplEvent->setForSynchronousCall();
1120
1121         Try {
1122                 addressBook->addChangeListener(dplEvent);
1123         } Catch(Exception) {
1124                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1125                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1126         }
1127
1128         if (!dplEvent->getResult() || !dplEvent->getIdIsSet())
1129         {
1130                 switch (dplEvent->getExceptionCode())
1131                 {
1132                 case ExceptionCodes::InvalidArgumentException:
1133                 case ExceptionCodes::PlatformException:
1134                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1135                         break;
1136                 default:
1137                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1138                         break;
1139                 }
1140         }
1141
1142         long watchId = dplEvent->getId();
1143
1144         PersonsChangeListenerCancellerPtr canceller = PersonsChangeListenerCancellerPtr(new PersonsChangeListenerCanceller(gContext, thisObject, watchId));
1145         DeviceAPI::Common::IListenerItemPtr listenerItem = DPL::StaticPointerCast<DeviceAPI::Common::IListenerItem>(canceller);
1146         ContactListenerManagerSingleton::Instance().registerListener(listenerItem, gContext);
1147
1148         JSValueRef result;
1149         Try {
1150                 result = converter->toJSValueRefLong(watchId);
1151         } Catch(Exception) {
1152                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
1153                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1154         }
1155         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1156         return result;
1157 }
1158
1159 JSValueRef JSContactManager::removeChangeListener(JSContextRef context,
1160                 JSObjectRef object,
1161                 JSObjectRef thisObject,
1162                 size_t argumentCount,
1163                 const JSValueRef arguments[],
1164                 JSValueRef* exception)
1165 {
1166         LoggerD("entered");
1167         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
1168         ContactManagerPtr addressBook;
1169         JSContextRef gContext;
1170         ContactManagerController *controller;
1171
1172         Try     {
1173                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
1174                 if (!controller) {
1175                         ThrowMsg(InvalidArgumentException, "No private object.");
1176                 }
1177                 addressBook = controller->getObject();
1178                 gContext = controller->getContext();
1179         } Catch(Exception) {
1180                 LoggerE("No private object");
1181                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
1182         }
1183
1184         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_CHANGE_LISTENER);
1185         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
1186
1187         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
1188
1189         long watchId = 0;
1190         std::string id;
1191
1192         try {
1193                 ArgumentValidator validator(context, argumentCount, arguments);
1194                 watchId = validator.toLong(0, false, 0);
1195                 id = validator.toString(0, false);
1196         } catch (const TypeMismatchException& err ) {
1197                 return JSWebAPIErrorFactory::postException(context, exception, err);
1198         } catch(const BasePlatformException& err) {
1199                 return JSWebAPIErrorFactory::postException(context, exception, err);
1200         } catch(const ConversionException& err) {
1201                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1202         } catch(const NullPointerException& err) {
1203                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1204         }
1205         if(!ContactUtility::checkStrIsUInt(id))
1206                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "");
1207
1208         EventContactManagerRemoveChangeListenerPtr dplEvent(new EventContactManagerRemoveChangeListener());
1209
1210         dplEvent->setId(watchId);
1211     dplEvent->setForSynchronousCall();
1212
1213         Try {
1214                 addressBook->removeChangeListener(dplEvent);
1215         } Catch(Exception) {
1216                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1217                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1218         }
1219
1220         PersonsChangeListenerCancellerPtr canceller = PersonsChangeListenerCancellerPtr(new PersonsChangeListenerCanceller(gContext, thisObject, watchId));
1221         DeviceAPI::Common::IListenerItemPtr listenerItem = DPL::StaticPointerCast<DeviceAPI::Common::IListenerItem>(canceller);
1222         ContactListenerManagerSingleton::Instance().unregisterListener(listenerItem);
1223
1224         if (!dplEvent->getResult())
1225         {
1226                 switch (dplEvent->getExceptionCode())
1227                 {
1228                 case ExceptionCodes::InvalidArgumentException:
1229                 case ExceptionCodes::NotFoundException:
1230                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, "Watch id not found");
1231                         break;
1232                 default:
1233                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1234                         break;
1235                 }
1236         }
1237         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1238         return JSValueMakeUndefined(context);
1239 }
1240
1241 } // Contact
1242 } // DeviceAPI