2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
20 * @author Kisub Song (kisubs.song@samsung.com)
22 * @brief Implementation of the JSPerson class
25 #include <dpl/shared_ptr.h>
26 #include <CommonsJavaScript/Validator.h>
27 #include <SecurityExceptions.h>
28 #include "ContactFactory.h"
29 #include "plugin_config.h"
30 #include "ContactConverter.h"
32 #include <ArgumentValidator.h>
33 #include <JSWebAPIErrorFactory.h>
34 #include <TimeTracer.h>
38 #define FILTER_CLASS_NAME "Person"
40 #define CONTACT_ATTR_ID "id"
41 #define CONTACT_ATTR_DISPLAY_NAME "displayName"
42 #define CONTACT_ATTR_CONTACT_COUNT "contactCount"
43 #define CONTACT_ATTR_HAS_PHONE_NUMBER "hasPhoneNumber"
44 #define CONTACT_ATTR_HAS_EMAIL "hasEmail"
45 #define CONTACT_ATTR_IS_FAVORITE "isFavorite"
46 #define CONTACT_ATTR_PHOTO_URI "photoURI"
47 #define CONTACT_ATTR_RINGTONE_URI "ringtoneURI"
48 #define CONTACT_ATTR_DISPLAY_CONTACT_ID "displayContactId"
49 #define CONTACT_FUNC_LINK "link"
50 #define CONTACT_FUNC_UNLINK "unlink"
55 using namespace DeviceAPI::Common;
56 using namespace WrtDeviceApis::Commons;
57 using namespace WrtDeviceApis::CommonsJavaScript;
59 JSClassDefinition JSPerson::m_classInfo =
62 kJSClassAttributeNone,
72 NULL, //DeleteProperty,
73 NULL, //getPropertyNames,
74 NULL, //CallAsFunction,
75 NULL, //CallAsConstructor,
76 hasInstance, //HasInstance,
77 NULL, //ConvertToType,
80 JSStaticValue JSPerson::m_property[] = {
81 { CONTACT_ATTR_ID, getId, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
82 { CONTACT_ATTR_DISPLAY_NAME, getDisplayName, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
83 { CONTACT_ATTR_CONTACT_COUNT, getContactCount, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
84 { CONTACT_ATTR_HAS_PHONE_NUMBER, getHasPhoneNumber, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
85 { CONTACT_ATTR_HAS_EMAIL, getHasEmail, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
86 { CONTACT_ATTR_IS_FAVORITE, getIsFavorite, setIsFavorite, kJSPropertyAttributeNone },
87 { CONTACT_ATTR_PHOTO_URI, getPhotoURI, setPhotoURI, kJSPropertyAttributeNone },
88 { CONTACT_ATTR_RINGTONE_URI, getRingtoneURI, setRingtoneURI, kJSPropertyAttributeNone },
89 { CONTACT_ATTR_DISPLAY_CONTACT_ID, getDisplayContactId, setDisplayContactId, kJSPropertyAttributeNone },
93 JSStaticFunction JSPerson::m_functions[] =
95 { CONTACT_FUNC_LINK, link, kJSPropertyAttributeNone },
96 { CONTACT_FUNC_UNLINK, unlink, kJSPropertyAttributeNone },
100 JSClassRef JSPerson::m_classRef = JSClassCreate(&m_classInfo);
102 JSClassRef DLL_EXPORT JSPerson::getClassRef() {
104 m_classRef = JSClassCreate(&m_classInfo);
109 bool JSPerson::isObjectOfClass(JSContextRef context, JSValueRef value)
111 return JSValueIsObjectOfClass(context, value, getClassRef());
114 PersonPtr JSPerson::getPerson(JSContextRef context, JSValueRef value)
116 if (!isObjectOfClass(context, value)) {
117 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
119 JSObjectRef object = JSValueToObject(context, value, NULL);
121 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
123 JSPersonPriv *priv = static_cast<JSPersonPriv*>(JSObjectGetPrivate(object));
125 Throw(WrtDeviceApis::Commons::NullPointerException);
127 return priv->getObject();
130 void JSPerson::Initialize(JSContextRef context, JSObjectRef object)
132 if (!JSObjectGetPrivate(object))
134 PersonPtr person = ContactFactory::getInstance().createPerson();
135 JSPersonPriv *priv = new JSPersonPriv(context, PersonPtr(person));
136 if (!JSObjectSetPrivate(object, priv)) {
142 void JSPerson::Finalize(JSObjectRef object)
144 JSPersonPriv *priv = static_cast<JSPersonPriv*>(JSObjectGetPrivate(object));
150 JSObjectRef JSPerson::createJSObject(JSContextRef context, PersonPtr person)
152 JSPersonPriv *priv = new JSPersonPriv(context, person);
153 JSObjectRef jsObjectRef = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
154 if (NULL == jsObjectRef) {
155 LoggerE("object creation error");
161 PersonPtr JSPerson::getPrivData(JSObjectRef object)
163 JSPersonPriv *priv = static_cast<JSPersonPriv*>(JSObjectGetPrivate(object));
165 ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is null");
167 PersonPtr result = priv->getObject();
169 ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is null.");
174 bool JSPerson::hasInstance(JSContextRef context,
175 JSObjectRef constructor,
176 JSValueRef possibleInstance,
177 JSValueRef* exception)
179 return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
182 JSValueRef JSPerson::getId(JSContextRef context,
184 JSStringRef propertyName,
185 JSValueRef* exception)
189 ContactConverterFactory::ConverterType converter =
190 ContactConverterFactory::getConverter(context);
191 PersonPtr person = getPrivData(object);
192 if(!person->getIdIsSet())
193 return JSValueMakeNull(context);
195 return converter->toJSValueRef(person->getId());
197 Catch(WrtDeviceApis::Commons::Exception)
199 LoggerW("trying to get incorrect value");
201 return JSValueMakeUndefined(context);
204 JSValueRef JSPerson::getDisplayName(JSContextRef context,
206 JSStringRef propertyName,
207 JSValueRef* exception)
211 ContactConverterFactory::ConverterType converter =
212 ContactConverterFactory::getConverter(context);
213 PersonPtr person = getPrivData(object);
214 if(!person->getIdIsSet())
215 return JSValueMakeNull(context);
217 return converter->toJSValueRef(person->getDisplayName());
219 Catch(WrtDeviceApis::Commons::Exception)
221 LoggerW("trying to get incorrect value");
223 return JSValueMakeUndefined(context);
226 JSValueRef JSPerson::getContactCount(JSContextRef context,
228 JSStringRef propertyName,
229 JSValueRef* exception)
233 ContactConverterFactory::ConverterType converter =
234 ContactConverterFactory::getConverter(context);
235 PersonPtr person = getPrivData(object);
236 if(!person->getIdIsSet())
237 return JSValueMakeNull(context);
239 return converter->toJSValueRefLong(person->getContactCount());
241 Catch(WrtDeviceApis::Commons::Exception)
243 LoggerW("trying to get incorrect value");
245 return JSValueMakeUndefined(context);
248 JSValueRef JSPerson::getHasPhoneNumber(JSContextRef context,
250 JSStringRef propertyName,
251 JSValueRef* exception)
255 ContactConverterFactory::ConverterType converter =
256 ContactConverterFactory::getConverter(context);
257 PersonPtr person = getPrivData(object);
258 if(!person->getIdIsSet())
259 return JSValueMakeNull(context);
261 return converter->toJSValueRef(person->getHasPhoneNumber());
263 Catch(WrtDeviceApis::Commons::Exception)
265 LoggerW("trying to get incorrect value");
267 return JSValueMakeUndefined(context);
270 JSValueRef JSPerson::getHasEmail(JSContextRef context,
272 JSStringRef propertyName,
273 JSValueRef* exception)
277 ContactConverterFactory::ConverterType converter =
278 ContactConverterFactory::getConverter(context);
279 PersonPtr person = getPrivData(object);
280 if(!person->getIdIsSet())
281 return JSValueMakeNull(context);
283 return converter->toJSValueRef(person->getHasEmail());
285 Catch(WrtDeviceApis::Commons::Exception)
287 LoggerW("trying to get incorrect value");
290 return JSValueMakeUndefined(context);
293 JSValueRef JSPerson::getIsFavorite(JSContextRef context,
295 JSStringRef propertyName,
296 JSValueRef* exception)
300 ContactConverterFactory::ConverterType converter =
301 ContactConverterFactory::getConverter(context);
302 PersonPtr person = getPrivData(object);
303 return converter->toJSValueRef(person->getIsFavorite());
305 Catch(WrtDeviceApis::Commons::Exception)
307 LoggerW("trying to get incorrect value");
310 return JSValueMakeUndefined(context);
313 bool JSPerson::setIsFavorite(JSContextRef context,
315 JSStringRef propertyName,
317 JSValueRef* exception)
321 PersonPtr person = getPrivData(object);
322 ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
323 person->setIsFavorite(converter->toBool(value));
325 Catch(WrtDeviceApis::Commons::Exception)
327 LoggerW("trying to set incorrect value");
328 JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch");
334 JSValueRef JSPerson::getPhotoURI(JSContextRef context,
336 JSStringRef propertyName,
337 JSValueRef* exception)
341 ContactConverterFactory::ConverterType converter =
342 ContactConverterFactory::getConverter(context);
343 PersonPtr person = getPrivData(object);
344 if(!person->getPhotoURIIsSet())
345 return JSValueMakeNull(context);
347 return converter->toJSValueRef(person->getPhotoURI());
349 Catch(WrtDeviceApis::Commons::Exception)
351 LoggerW("trying to get incorrect value");
354 return JSValueMakeUndefined(context);
357 bool JSPerson::setPhotoURI(JSContextRef context,
359 JSStringRef propertyName,
361 JSValueRef* exception)
365 PersonPtr person = getPrivData(object);
366 ContactConverterFactory::ConverterType converter =
367 ContactConverterFactory::getConverter(context);
368 BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
369 if(validator->isNullOrUndefined(value))
370 person->unsetPhotoURI();
372 person->setPhotoURI(converter->toString(value));
374 Catch(WrtDeviceApis::Commons::Exception)
376 LoggerW("trying to set incorrect value");
377 JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch");
383 JSValueRef JSPerson::getRingtoneURI(JSContextRef context,
385 JSStringRef propertyName,
386 JSValueRef* exception)
390 ContactConverterFactory::ConverterType converter =
391 ContactConverterFactory::getConverter(context);
392 PersonPtr person = getPrivData(object);
393 if(!person->getRingtoneURIIsSet())
394 return JSValueMakeNull(context);
396 return converter->toJSValueRef(person->getRingtoneURI());
398 Catch(WrtDeviceApis::Commons::Exception)
400 LoggerW("trying to get incorrect value");
403 return JSValueMakeUndefined(context);
406 bool JSPerson::setRingtoneURI(JSContextRef context,
408 JSStringRef propertyName,
410 JSValueRef* exception)
414 PersonPtr person = getPrivData(object);
415 ContactConverterFactory::ConverterType converter =
416 ContactConverterFactory::getConverter(context);
417 BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
418 if(validator->isNullOrUndefined(value))
419 person->unsetRingtoneURI();
421 person->setRingtoneURI(converter->toString(value));
423 Catch(WrtDeviceApis::Commons::Exception)
425 LoggerW("trying to set incorrect value");
426 JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch");
432 JSValueRef JSPerson::getDisplayContactId(JSContextRef context,
434 JSStringRef propertyName,
435 JSValueRef* exception)
439 ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
440 PersonPtr person = getPrivData(object);
441 if(!person->getDisplayContactIdIsSet())
442 return JSValueMakeNull(context);
444 return converter->toJSValueRef(person->getDisplayContactId());
446 Catch(WrtDeviceApis::Commons::Exception)
448 LoggerW("trying to get incorrect value");
451 return JSValueMakeUndefined(context);
454 bool JSPerson::setDisplayContactId(JSContextRef context,
456 JSStringRef propertyName,
458 JSValueRef* exception)
462 PersonPtr person = getPrivData(object);
463 ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
464 BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
465 if(validator->isNullOrUndefined(value))
466 person->unsetDisplayContactId();
468 person->setDisplayContactId(converter->toString(value));
470 Catch(WrtDeviceApis::Commons::Exception)
472 LoggerW("trying to set incorrect value");
473 JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch");
479 JSValueRef JSPerson::link(JSContextRef context,
481 JSObjectRef thisObject,
482 size_t argumentCount,
483 const JSValueRef arguments[],
484 JSValueRef* exception)
487 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
488 PersonPtr person(NULL);
492 person = getPrivData(thisObject);
494 ThrowMsg(InvalidArgumentException, "No private object.");
498 LoggerE("Argument type mismatch : " << _rethrown_exception.GetMessage());
499 return JSWebAPIErrorFactory::postException(context, exception,
500 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
503 AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_PERSON_LINK);
504 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
506 ArgumentValidator validator(context, argumentCount, arguments);
507 std::string personId;
509 personId = validator.toString(0, false);
510 } catch (const TypeMismatchException& err ) {
511 return JSWebAPIErrorFactory::postException(context, exception, err);
512 } catch(const BasePlatformException& err) {
513 return JSWebAPIErrorFactory::postException(context, exception, err);
514 } catch(const ConversionException& err) {
515 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
516 } catch(const NullPointerException& err) {
517 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
520 EventPersonLinkPtr dplEvent(new EventPersonLink());
522 dplEvent->setPersonId(personId);
523 dplEvent->setForSynchronousCall();
527 person->link(dplEvent);
529 Catch(ConversionException)
531 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
532 return JSWebAPIErrorFactory::postException(context, exception,
533 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument must be 'PersonId'");
537 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
538 return JSWebAPIErrorFactory::postException(context, exception,
539 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
542 if (!dplEvent->getResult())
544 std::stringstream oss;
545 switch (dplEvent->getExceptionCode())
547 case ExceptionCodes::NotFoundException:
548 oss << "Person id (" << personId << ") is not exists.";
549 return JSWebAPIErrorFactory::postException(context, exception,
550 JSWebAPIErrorFactory::INVALID_VALUES_ERROR, oss.str());
552 case ExceptionCodes::InvalidArgumentException:
553 oss << "Person id (" << personId << ") is wrong.";
554 return JSWebAPIErrorFactory::postException(context, exception,
555 JSWebAPIErrorFactory::INVALID_VALUES_ERROR, oss.str());
557 case ExceptionCodes::PlatformException:
558 return JSWebAPIErrorFactory::postException(context, exception,
559 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
562 return JSWebAPIErrorFactory::postException(context, exception,
563 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
567 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
568 return JSValueMakeUndefined(context);
571 JSValueRef JSPerson::unlink(JSContextRef context,
573 JSObjectRef thisObject,
574 size_t argumentCount,
575 const JSValueRef arguments[],
576 JSValueRef* exception)
579 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
580 PersonPtr person(NULL);
584 person = getPrivData(thisObject);
586 ThrowMsg(InvalidArgumentException, "No private object.");
590 LoggerE("Argument type mismatch : " << _rethrown_exception.GetMessage());
591 return JSWebAPIErrorFactory::postException(context, exception,
592 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
595 AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_PERSON_UNLINK);
596 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
598 ArgumentValidator validator(context, argumentCount, arguments);
599 std::string contactId;
601 contactId = validator.toString(0, false);
602 } catch (const TypeMismatchException& err ) {
603 return JSWebAPIErrorFactory::postException(context, exception, err);
604 } catch(const BasePlatformException& err) {
605 return JSWebAPIErrorFactory::postException(context, exception, err);
606 } catch(const ConversionException& err) {
607 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
608 } catch(const NullPointerException& err) {
609 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
612 EventPersonUnlinkPtr dplEvent(new EventPersonUnlink());
614 dplEvent->setContactId(contactId);
615 dplEvent->setForSynchronousCall();
619 person->unlink(dplEvent);
621 Catch(ConversionException)
623 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
624 return JSWebAPIErrorFactory::postException(context, exception,
625 JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "1st argument must be 'ContactId'");
629 LoggerE("Error on platform : " << _rethrown_exception.GetMessage());
630 return JSWebAPIErrorFactory::postException(context, exception,
631 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
634 if (!dplEvent->getResult())
636 std::stringstream oss;
637 switch (dplEvent->getExceptionCode())
639 case ExceptionCodes::InvalidArgumentException:
640 oss << "No Contact id is wrong : '" << contactId << "'";
641 return JSWebAPIErrorFactory::postException(context, exception,
642 JSWebAPIErrorFactory::INVALID_VALUES_ERROR, oss.str());
644 case ExceptionCodes::NotFoundException:
645 oss << "No Contact id '" << contactId << "'";
646 return JSWebAPIErrorFactory::postException(context, exception,
647 JSWebAPIErrorFactory::INVALID_VALUES_ERROR, oss.str());
649 case ExceptionCodes::OutOfRangeException:
650 oss << "Contact (id:'" << contactId << "') is not a member of person";
651 return JSWebAPIErrorFactory::postException(context, exception,
652 JSWebAPIErrorFactory::INVALID_VALUES_ERROR, oss.str());
654 case ExceptionCodes::PlatformException:
655 return JSWebAPIErrorFactory::postException(context, exception,
656 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
659 return JSWebAPIErrorFactory::postException(context, exception,
660 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
665 PersonPtr unlinkedPerson = dplEvent->getPerson();
666 ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
671 result = converter->toJSValueRef(unlinkedPerson);
675 LoggerE("Error on conversion : " << _rethrown_exception.GetMessage());
676 return JSWebAPIErrorFactory::postException(context, exception,
677 JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
679 TIME_TRACER_ITEM_END(__FUNCTION__, 0);