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