Update change log and spec for wrt-plugins-tizen_0.4.50
[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
51 namespace DeviceAPI {
52 namespace Contact {
53
54 using namespace DeviceAPI::Common;
55 using namespace DeviceAPI::Tizen;
56 using namespace WrtDeviceApis::Commons;
57 using namespace WrtDeviceApis::CommonsJavaScript;
58
59 JSClassDefinition JSContactManager::m_classInfo = {
60         0,
61         kJSClassAttributeNone,
62         "ContactManager",
63         0,
64         m_property,
65         m_function,
66         Initialize,
67         Finalize,
68         NULL, //HasProperty,
69         NULL, //GetProperty,
70         NULL, //SetProperty,
71         NULL, //DeleteProperty,
72         NULL, //GetPropertyNames,
73         NULL, //CallAsFunction,
74         NULL, //CallAsConstructor,
75         NULL, //HasInstance,
76         NULL, //ConvertToType,
77 };
78
79 const JSClassDefinition* JSContactManager::getClassInfo()
80 {
81         return &m_classInfo;
82 }
83
84 JSStaticValue JSContactManager::m_property[] = {
85         { 0, 0, 0, 0 }
86 };
87
88 JSStaticFunction JSContactManager::m_function[] = {
89         { "getAddressBooks", getAddressBooks, kJSPropertyAttributeNone },
90         { "getDefaultAddressBook", getDefaultAddressBook, kJSPropertyAttributeNone },
91         { "getUnifiedAddressBook", getUnifiedAddressBook, kJSPropertyAttributeNone },
92         { "getAddressBook", getAddressBook, kJSPropertyAttributeNone },
93         { "get", get, kJSPropertyAttributeNone },
94         { "update", update, kJSPropertyAttributeNone },
95         { "updateBatch", updateBatch, kJSPropertyAttributeNone },
96         { "remove", remove, kJSPropertyAttributeNone },
97         { "removeBatch", removeBatch, kJSPropertyAttributeNone },
98         { "find", find, kJSPropertyAttributeNone },
99         { "addChangeListener", addChangeListener, kJSPropertyAttributeNone },
100         { "removeChangeListener", removeChangeListener, kJSPropertyAttributeNone },
101         { 0, 0, 0 }
102 };
103
104 JSClassRef DLL_EXPORT JSContactManager::getClassRef()
105 {
106         if (!m_classRef) {
107                 m_classRef = JSClassCreate(&m_classInfo);
108         }
109         return m_classRef;
110 }
111
112 JSClassRef JSContactManager::m_classRef = JSClassCreate(JSContactManager::getClassInfo());
113
114 void JSContactManager::Initialize(JSContextRef context,
115                 JSObjectRef object)
116 {
117         LoggerD("Entered");
118         ContactManagerPtr contactManager = ContactFactory::getInstance().createContactManager();
119
120         ContactManagerController *priv = new ContactManagerController(context, contactManager);
121
122         JSObjectSetPrivate(object, static_cast<void*>(priv));
123 }
124
125 void JSContactManager::Finalize(JSObjectRef object)
126 {
127         LoggerD("entered");
128         ContactManagerController *priv = static_cast<ContactManagerController*>(JSObjectGetPrivate(object));
129         LoggerI("Delete address book manager");
130         delete priv;
131 }
132
133 JSValueRef JSContactManager::getAddressBooks(JSContextRef context,
134                 JSObjectRef object,
135                 JSObjectRef thisObject,
136                 size_t argumentCount,
137                 const JSValueRef arguments[],
138                 JSValueRef* exception)
139 {
140         LoggerD("Entered");
141         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
142         ContactManagerPtr contactManager;
143         JSContextRef gContext;
144         ContactManagerController *controller;
145
146         bool js2ndParamIsFunction = false;
147
148         Try     {
149                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
150                 if (!controller) {
151                         ThrowMsg(InvalidArgumentException, "No private object.");
152                 }
153                 contactManager = controller->getObject();
154                 gContext = controller->getContext();
155         } Catch(Exception) {
156                 LoggerE("No private object");
157                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
158         }
159
160         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOKS);
161         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
162
163         BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
164         try {
165                 ArgumentValidator validator(context, argumentCount, arguments);
166                 validator.toFunction(0, false);
167                 JSObjectRef errorObj = validator.toFunction(1, true);
168                 if(errorObj)
169                         js2ndParamIsFunction = true;
170         } catch (const TypeMismatchException& err ) {
171                 return JSWebAPIErrorFactory::postException(context, exception, err);
172         } catch(const BasePlatformException& err) {
173                 return JSWebAPIErrorFactory::postException(context, exception, err);
174         } catch(const ConversionException& err) {
175                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
176         } catch(const NullPointerException& err) {
177                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
178         }
179
180         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
181
182         callbackManager->setOnSuccess(arguments[0]);
183
184         if(js2ndParamIsFunction)
185                 callbackManager->setOnError(arguments[1]);
186
187         callbackManager->setObject(thisObject);
188
189         EventContactManagerGetAddressBooksPtr dplEvent(new EventContactManagerGetAddressBooks());
190
191         // set event handler's data
192         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
193         dplEvent->setForAsynchronousCall(controller);
194
195 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
196 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
197
198         Try {
199                 contactManager->getAddressBooks(dplEvent);
200                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
201         } Catch(Exception) {
202                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
203                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
204         }
205
206         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
207 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
208         return JSValueMakeUndefined(context);
209 }
210
211 JSValueRef JSContactManager::getDefaultAddressBook(JSContextRef context,
212                 JSObjectRef object,
213                 JSObjectRef thisObject,
214                 size_t argumentCount,
215                 const JSValueRef arguments[],
216                 JSValueRef* exception)
217 {
218         LoggerD("Entered");
219         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
220         ContactManagerController *priv =
221                 static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
222         if (!priv) {
223                 LoggerE("private object is null");
224                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
225         }
226
227         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_DEFAULT_ADDRESS_BOOK);
228         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
229
230         ContactManagerPtr contactManager;
231         JSContextRef gContext;
232         Try {
233                 contactManager = priv->getObject();
234                 gContext = priv->getContext();
235         } Catch(Exception) {
236                 LoggerE("contact manager or context is null");
237                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
238         }
239
240         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
241
242         EventContactManagerGetDefaultAddressBookPtr dplEvent(new EventContactManagerGetDefaultAddressBook());
243
244     dplEvent->setForSynchronousCall();
245
246         Try {
247                 contactManager->getDefaultAddressBook(dplEvent);
248         } Catch(Exception) {
249                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
250                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
251         }
252
253         if (!dplEvent->getResult() || !dplEvent->getDefaultAddressBookIsSet())
254         {
255                 std::stringstream oss;
256                 switch (dplEvent->getExceptionCode())
257                 {
258                 case ExceptionCodes::NotFoundException:
259                 case ExceptionCodes::InvalidArgumentException:
260                         LoggerE("Not Found error");
261                         oss << "No default address book";
262                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
263                         break;
264                 case ExceptionCodes::PlatformException:
265                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
266                         break;
267                 default:
268                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
269                         break;
270                 }
271         }
272
273         AddressBookPtr defaultAddressBook = dplEvent->getDefaultAddressBook();
274
275         JSValueRef resultValue;
276         Try {
277                 resultValue = converter->toJSValueRef(defaultAddressBook);
278         } Catch(Exception){
279                 LoggerE("Conversion error.");
280                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
281         }
282
283         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
284         return resultValue;
285 }
286
287 JSValueRef JSContactManager::getUnifiedAddressBook(JSContextRef context,
288                 JSObjectRef object,
289                 JSObjectRef thisObject,
290                 size_t argumentCount,
291                 const JSValueRef arguments[],
292                 JSValueRef* exception)
293 {
294         LoggerD("Entered");
295         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
296         ContactManagerController *priv =
297                 static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
298         if (!priv) {
299                 LoggerE("private object is null");
300                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
301         }
302
303         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_UNIFIED_ADDRESS_BOOK);
304         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
305
306         ContactManagerPtr contactManager;
307         JSContextRef gContext;
308         Try {
309                 contactManager = priv->getObject();
310                 gContext = priv->getContext();
311         } Catch(Exception) {
312                 LoggerE("contact manager or context is null");
313                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
314         }
315
316         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
317
318         EventContactManagerGetUnifiedAddressBookPtr dplEvent(new EventContactManagerGetUnifiedAddressBook());
319
320     dplEvent->setForSynchronousCall();
321
322         Try {
323                 contactManager->getUnifiedAddressBook(dplEvent);
324         } Catch(Exception) {
325                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
326                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
327         }
328
329         if (!dplEvent->getResult() || !dplEvent->getUnifiedAddressBookIsSet())
330         {
331                 std::stringstream oss;
332                 switch (dplEvent->getExceptionCode())
333                 {
334                 case ExceptionCodes::NotFoundException:
335                 case ExceptionCodes::InvalidArgumentException:
336                         LoggerE("Not Found error");
337                         oss << "No default address book";
338                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
339                         break;
340                 case ExceptionCodes::PlatformException:
341                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
342                         break;
343                 default:
344                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
345                         break;
346                 }
347         }
348
349         AddressBookPtr unifiedAddressBook = dplEvent->getUnifiedAddressBook();
350
351         JSValueRef resultValue;
352         Try {
353                 resultValue = converter->toJSValueRef(unifiedAddressBook);
354         } Catch(Exception){
355                 LoggerE("Conversion error.");
356                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
357         }
358
359         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
360         return resultValue;
361 }
362
363 JSValueRef JSContactManager::getAddressBook(JSContextRef context,
364                 JSObjectRef object,
365                 JSObjectRef thisObject,
366                 size_t argumentCount,
367                 const JSValueRef arguments[],
368                 JSValueRef* exception)
369 {
370         LoggerD("Entered");
371         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
372         ContactManagerController *priv =
373                 static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
374         if (!priv) {
375                 LoggerE("private object is null");
376                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
377         }
378
379         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOK);
380         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
381
382         ContactManagerPtr contactManager;
383         JSContextRef gContext;
384         Try {
385                 contactManager = priv->getObject();
386                 gContext = priv->getContext();
387         } Catch(Exception) {
388                 LoggerE("contact manager or context is null");
389                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
390         }
391
392         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(gContext);
393
394         std::string addressBookId;
395         try {
396                 ArgumentValidator validator(context, argumentCount, arguments);
397                 addressBookId = validator.toString(0, false);
398         } catch (const TypeMismatchException& err ) {
399                 return JSWebAPIErrorFactory::postException(context, exception, err);
400         } catch(const BasePlatformException& err) {
401                 return JSWebAPIErrorFactory::postException(context, exception, err);
402         } catch(const ConversionException& err) {
403                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
404         } catch(const NullPointerException& err) {
405                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
406         }
407
408         EventContactManagerGetAddressBookPtr dplEvent(new EventContactManagerGetAddressBook());
409
410         dplEvent->setAddressBookId(addressBookId);
411     dplEvent->setForSynchronousCall();
412
413         Try {
414                 contactManager->getAddressBook(dplEvent);
415         } Catch(Exception) {
416                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
417                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
418         }
419
420         if (!dplEvent->getResult() || !dplEvent->getAddressBookIsSet())
421         {
422                 std::stringstream oss;
423                 switch (dplEvent->getExceptionCode())
424                 {
425                 case ExceptionCodes::NotFoundException:
426                 case ExceptionCodes::InvalidArgumentException:
427                         LoggerE("Not Found error : " << addressBookId);
428                         oss << "No addressBookId id '" << addressBookId << "'";
429                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
430                         break;
431                 case ExceptionCodes::PlatformException:
432                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
433                         break;
434                 default:
435                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
436                         break;
437                 }
438         }
439
440         AddressBookPtr addressBook = dplEvent->getAddressBook();
441
442         JSValueRef resultValue;
443         Try {
444                 resultValue = converter->toJSValueRef(addressBook);
445         } Catch(Exception){
446                 LoggerE("Conversion error.");
447                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
448         }
449
450         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
451         return resultValue;
452 }
453
454 JSValueRef JSContactManager::get(JSContextRef context,
455                 JSObjectRef object,
456                 JSObjectRef thisObject,
457                 size_t argumentCount,
458                 const JSValueRef arguments[],
459                 JSValueRef* exception)
460 {
461         LoggerD("entered");
462         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
463         ContactManagerPtr addressBook;
464         ContactManagerController *controller;
465
466         Try     {
467                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
468                 if (!controller) {
469                         ThrowMsg(InvalidArgumentException, "No private object.");
470                 }
471                 addressBook = controller->getObject();
472         } Catch(Exception) {
473                 LoggerE("No private object");
474                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
475         }
476
477         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_GET);
478         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
479
480         if (argumentCount < 1) {
481                 /* 1st Argument must be string. */
482                 LoggerE("1st argument must not be undefined.");
483                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, "No id 'undefined'");
484         }
485
486         std::string id;
487
488         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
489         try     {
490                 ArgumentValidator validator(context, argumentCount, arguments);
491                 id = validator.toString(0, false);
492         } catch (const TypeMismatchException& err ) {
493                 return JSWebAPIErrorFactory::postException(context, exception, err);
494         } catch(const BasePlatformException& err) {
495                 return JSWebAPIErrorFactory::postException(context, exception, err);
496         } catch(const ConversionException& err) {
497                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
498         } catch(const NullPointerException& err) {
499                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
500         }
501
502         EventContactManagerGetPtr dplEvent(new EventContactManagerGet());
503
504         dplEvent->setId(id);
505     dplEvent->setForSynchronousCall();
506
507         Try {
508                 addressBook->get(dplEvent);
509         } Catch(Exception) {
510                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
511                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
512         }
513
514         if (!dplEvent->getResult() || !dplEvent->getPersonIsSet())
515         {
516                 std::stringstream oss;
517                 switch (dplEvent->getExceptionCode())
518                 {
519                 case ExceptionCodes::NotFoundException:
520                 case ExceptionCodes::InvalidArgumentException:
521                         LoggerE("Not Found error : " << id);
522                         oss << "No Person id '" << id << "'";
523                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
524                         break;
525                 case ExceptionCodes::PlatformException:
526                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
527                         break;
528                 default:
529                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
530                         break;
531                 }
532         }
533
534         PersonPtr person = dplEvent->getPerson();
535
536         JSValueRef result;
537         Try {
538                 result = converter->toJSValueRef(person);
539         } Catch(Exception) {
540                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
541                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
542         }
543
544         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
545         return result;
546 }
547
548 JSValueRef JSContactManager::update(JSContextRef context,
549                 JSObjectRef object,
550                 JSObjectRef thisObject,
551                 size_t argumentCount,
552                 const JSValueRef arguments[],
553                 JSValueRef* exception)
554 {
555         LoggerD("entered");
556         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
557         ContactManagerPtr addressBook;
558         ContactManagerController *controller;
559
560         Try     {
561                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
562                 if (!controller) {
563                         ThrowMsg(InvalidArgumentException, "No private object.");
564                 }
565                 addressBook = controller->getObject();
566         } Catch(Exception) {
567                 LoggerE("No private object");
568                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
569         }
570
571         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE);
572         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
573
574         try {
575                 ArgumentValidator validator(context, argumentCount, arguments);
576                 validator.toObject(0, false);
577         } catch (const TypeMismatchException& err ) {
578                 return JSWebAPIErrorFactory::postException(context, exception, err);
579         } catch(const BasePlatformException& err) {
580                 return JSWebAPIErrorFactory::postException(context, exception, err);
581         } catch(const ConversionException& err) {
582                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
583         } catch(const NullPointerException& err) {
584                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
585         }
586
587         PersonPtr person(NULL);
588
589         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
590         Try     {
591                 if (!JSPerson::isObjectOfClass(context, arguments[0]))
592                         ThrowMsg(InvalidArgumentException, "1st argument is not a 'Contact object'.");
593                 person = converter->toPerson(arguments[0]);
594         } Catch(Exception) {
595                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
596                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument is not a 'Contact object'");
597         }
598
599         EventContactManagerUpdatePtr dplEvent(new EventContactManagerUpdate());
600
601         dplEvent->setPerson(person);
602     dplEvent->setForSynchronousCall();
603
604         Try {
605                 addressBook->update(dplEvent);
606         } Catch(Exception) {
607                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
608                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
609         }
610
611         if (!dplEvent->getResult())
612         {
613                 std::stringstream oss;
614                 switch (dplEvent->getExceptionCode())
615                 {
616                 case ExceptionCodes::NotFoundException:
617                 case ExceptionCodes::InvalidArgumentException:
618                         oss << "No id '" << person->getId() << "'";
619                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, oss.str());
620                         break;
621                 case ExceptionCodes::PlatformException:
622                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
623                         break;
624                 default:
625                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
626                         break;
627                 }
628         }
629
630         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
631         return JSValueMakeUndefined(context);
632 }
633
634 JSValueRef JSContactManager::updateBatch(JSContextRef context,
635                 JSObjectRef object,
636                 JSObjectRef thisObject,
637                 size_t argumentCount,
638                 const JSValueRef arguments[],
639                 JSValueRef* exception)
640 {
641         LoggerD("entered");
642         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
643         ContactManagerPtr addressBook;
644         JSContextRef gContext;
645         ContactManagerController *controller;
646
647         bool js2ndParamIsFunction = false;
648         bool js3rdParamIsFunction = false;
649
650         Try     {
651                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
652                 if (!controller) {
653                         ThrowMsg(InvalidArgumentException, "No private object.");
654                 }
655                 addressBook = controller->getObject();
656                 gContext = controller->getContext();
657         } Catch(Exception) {
658                 LoggerE("No private object");
659                 return JSWebAPIErrorFactory::postException(context, exception,
660                                 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
661         }
662
663         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE_BATCH);
664         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
665
666         try {
667                 ArgumentValidator validator(context, argumentCount, arguments);
668
669                 validator.toObject(0, false);
670                 JSObjectRef successObj = validator.toFunction(1, true);
671                 if(successObj)
672                         js2ndParamIsFunction = true;
673
674                 JSObjectRef errorObj = validator.toFunction(2, true);
675                 if(errorObj)
676                         js3rdParamIsFunction = true;
677         } catch (const TypeMismatchException& err ) {
678                 return JSWebAPIErrorFactory::postException(context, exception, err);
679         } catch(const BasePlatformException& err) {
680                 return JSWebAPIErrorFactory::postException(context, exception, err);
681         } catch(const ConversionException& err) {
682                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
683         } catch(const NullPointerException& err) {
684                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
685         }
686
687         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
688
689         JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
690
691         if(js2ndParamIsFunction)
692                 callbackManager->setOnSuccess(arguments[1]);
693
694         if(js3rdParamIsFunction)
695                 callbackManager->setOnError(arguments[2]);
696
697         callbackManager->setObject(thisObject);
698
699         EventContactManagerUpdateBatchPtr dplEvent(new EventContactManagerUpdateBatch());
700         Try {
701                 dplEvent->setPersons(converter->toPersonArray(arguments[0]));
702         } Catch(ConversionException) {
703                 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
704                 return JSWebAPIErrorFactory::postException(context, exception,
705                                 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "3rd argument must be a 'function' or a 'null'");
706         }
707
708         // set event handler's data
709         dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(callbackManager));
710         dplEvent->setForAsynchronousCall(controller);
711
712 //      DPL::SharedPtr<IEventController> eventContr = DPL::StaticPointerCast< IEventController>(dplEvent);
713 //      IJSPendingOperationPrivateObject *gcPendingOperation = new IJSPendingOperationPrivateObject(eventContr);
714
715         Try {
716                 addressBook->updateBatch(dplEvent);
717                 ContactAsyncCallbackManagerSingleton::Instance().registerCallbackManager(callbackManager, gContext);
718         } Catch(Exception) {
719                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
720                 return JSWebAPIErrorFactory::postException(context, exception,
721                                 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
722         }
723
724         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
725 //      return JSObjectMake(gContext, JSPendingOperation::getClassRef(), gcPendingOperation);
726         return JSValueMakeUndefined(context);
727 }
728
729 JSValueRef JSContactManager::remove(JSContextRef context,
730                 JSObjectRef object,
731                 JSObjectRef thisObject,
732                 size_t argumentCount,
733                 const JSValueRef arguments[],
734                 JSValueRef* exception)
735 {
736         LoggerD("entered");
737         TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
738         ContactManagerPtr addressBook;
739         ContactManagerController *controller;
740
741         Try     {
742                 controller = static_cast<ContactManagerController*>(JSObjectGetPrivate(thisObject));
743                 if (!controller) {
744                         ThrowMsg(InvalidArgumentException, "No private object.");
745                 }
746                 addressBook = controller->getObject();
747         } Catch(Exception) {
748                 LoggerE("No private object");
749                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
750         }
751
752         AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE);
753         TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
754
755         std::string personId;
756
757         ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
758         try     {
759                 ArgumentValidator validator(context, argumentCount, arguments);
760                 personId = validator.toString(0, false);
761         } catch (const TypeMismatchException& err ) {
762                 return JSWebAPIErrorFactory::postException(context, exception, err);
763         } catch(const BasePlatformException& err) {
764                 return JSWebAPIErrorFactory::postException(context, exception, err);
765         } catch(const ConversionException& err) {
766                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
767         } catch(const NullPointerException& err) {
768                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
769         }
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         try {
1191                 ArgumentValidator validator(context, argumentCount, arguments);
1192                 watchId = validator.toLong(0, false, 0);
1193         } catch (const TypeMismatchException& err ) {
1194                 return JSWebAPIErrorFactory::postException(context, exception, err);
1195         } catch(const BasePlatformException& err) {
1196                 return JSWebAPIErrorFactory::postException(context, exception, err);
1197         } catch(const ConversionException& err) {
1198                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1199         } catch(const NullPointerException& err) {
1200                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
1201         }
1202
1203         EventContactManagerRemoveChangeListenerPtr dplEvent(new EventContactManagerRemoveChangeListener());
1204
1205         dplEvent->setId(watchId);
1206     dplEvent->setForSynchronousCall();
1207
1208         Try {
1209                 addressBook->removeChangeListener(dplEvent);
1210         } Catch(Exception) {
1211                 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
1212                 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1213         }
1214
1215         PersonsChangeListenerCancellerPtr canceller = PersonsChangeListenerCancellerPtr(new PersonsChangeListenerCanceller(gContext, thisObject, watchId));
1216         DeviceAPI::Common::IListenerItemPtr listenerItem = DPL::StaticPointerCast<DeviceAPI::Common::IListenerItem>(canceller);
1217         ContactListenerManagerSingleton::Instance().unregisterListener(listenerItem);
1218
1219         if (!dplEvent->getResult())
1220         {
1221                 switch (dplEvent->getExceptionCode())
1222                 {
1223                 case ExceptionCodes::InvalidArgumentException:
1224                 case ExceptionCodes::NotFoundException:
1225                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, "Watch id not found");
1226                         break;
1227                 default:
1228                         return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
1229                         break;
1230                 }
1231         }
1232         TIME_TRACER_ITEM_END(__FUNCTION__, 0);
1233         return JSValueMakeUndefined(context);
1234 }
1235
1236 } // Contact
1237 } // DeviceAPI