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/log/log.h>
26 #include <dpl/shared_ptr.h>
27 #include <CommonsJavaScript/Validator.h>
28 #include <JSTizenExceptionFactory.h>
29 #include <JSTizenException.h>
30 #include <SecurityExceptions.h>
31 #include "ContactFactory.h"
32 #include "plugin_config.h"
33 #include "ContactConverter.h"
35 #include <ArgumentValidator.h>
36 #include <JSWebAPIError.h>
37 #include <TimeTracer.h>
39 #define FILTER_CLASS_NAME "Person"
41 #define CONTACT_ATTR_ID "id"
42 #define CONTACT_ATTR_DISPLAY_NAME "displayName"
43 #define CONTACT_ATTR_CONTACT_COUNT "contactCount"
44 #define CONTACT_ATTR_HAS_PHONE_NUMBER "hasPhoneNumber"
45 #define CONTACT_ATTR_HAS_EMAIL "hasEmail"
46 #define CONTACT_ATTR_IS_FAVORITE "isFavorite"
47 #define CONTACT_ATTR_PHOTO_URI "photoURI"
48 #define CONTACT_ATTR_RINGTONE_URI "ringtoneURI"
49 #define CONTACT_ATTR_DISPLAY_CONTACT_ID "displayContactId"
50 #define CONTACT_FUNC_LINK "link"
51 #define CONTACT_FUNC_UNLINK "unlink"
56 using namespace DeviceAPI::Common;
57 using namespace WrtDeviceApis::Commons;
58 using namespace WrtDeviceApis::CommonsJavaScript;
60 JSClassDefinition JSPerson::m_classInfo =
63 kJSClassAttributeNone,
73 NULL, //DeleteProperty,
74 NULL, //getPropertyNames,
75 NULL, //CallAsFunction,
76 NULL, //CallAsConstructor,
77 hasInstance, //HasInstance,
78 NULL, //ConvertToType,
81 JSStaticValue JSPerson::m_property[] = {
82 { CONTACT_ATTR_ID, getId, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
83 { CONTACT_ATTR_DISPLAY_NAME, getDisplayName, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
84 { CONTACT_ATTR_CONTACT_COUNT, getContactCount, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
85 { CONTACT_ATTR_HAS_PHONE_NUMBER, getHasPhoneNumber, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
86 { CONTACT_ATTR_HAS_EMAIL, getHasEmail, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
87 { CONTACT_ATTR_IS_FAVORITE, getIsFavorite, setIsFavorite, kJSPropertyAttributeNone },
88 { CONTACT_ATTR_PHOTO_URI, getPhotoURI, setPhotoURI, kJSPropertyAttributeNone },
89 { CONTACT_ATTR_RINGTONE_URI, getRingtoneURI, setRingtoneURI, kJSPropertyAttributeNone },
90 { CONTACT_ATTR_DISPLAY_CONTACT_ID, getDisplayContactId, setDisplayContactId, kJSPropertyAttributeNone },
94 JSStaticFunction JSPerson::m_functions[] =
96 { CONTACT_FUNC_LINK, link, kJSPropertyAttributeNone },
97 { CONTACT_FUNC_UNLINK, unlink, kJSPropertyAttributeNone },
101 JSClassRef JSPerson::m_classRef = JSClassCreate(&m_classInfo);
103 JSClassRef JSPerson::getClassRef() {
105 m_classRef = JSClassCreate(&m_classInfo);
110 bool JSPerson::isObjectOfClass(JSContextRef context, JSValueRef value)
112 return JSValueIsObjectOfClass(context, value, getClassRef());
115 PersonPtr JSPerson::getPerson(JSContextRef context, JSValueRef value)
117 if (!isObjectOfClass(context, value)) {
118 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
120 JSObjectRef object = JSValueToObject(context, value, NULL);
122 Throw(WrtDeviceApis::Commons::InvalidArgumentException);
124 JSPersonPriv *priv = static_cast<JSPersonPriv*>(JSObjectGetPrivate(object));
126 Throw(WrtDeviceApis::Commons::NullPointerException);
128 return priv->getObject();
131 void JSPerson::Initialize(JSContextRef context, JSObjectRef object)
133 if (!JSObjectGetPrivate(object))
135 PersonPtr person = ContactFactory::getInstance().createPerson();
136 JSPersonPriv *priv = new JSPersonPriv(context, PersonPtr(person));
137 if (!JSObjectSetPrivate(object, priv)) {
143 void JSPerson::Finalize(JSObjectRef object)
145 JSPersonPriv *priv = static_cast<JSPersonPriv*>(JSObjectGetPrivate(object));
151 JSObjectRef JSPerson::createJSObject(JSContextRef context, PersonPtr person)
153 JSPersonPriv *priv = new JSPersonPriv(context, person);
154 JSObjectRef jsObjectRef = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
155 if (NULL == jsObjectRef) {
156 LogError("object creation error");
162 PersonPtr JSPerson::getPrivData(JSObjectRef object)
164 JSPersonPriv *priv = static_cast<JSPersonPriv*>(JSObjectGetPrivate(object));
166 ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is null");
168 PersonPtr result = priv->getObject();
170 ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is null.");
175 bool JSPerson::hasInstance(JSContextRef context,
176 JSObjectRef constructor,
177 JSValueRef possibleInstance,
178 JSValueRef* exception)
180 return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
183 JSValueRef JSPerson::getId(JSContextRef context,
185 JSStringRef propertyName,
186 JSValueRef* exception)
190 ContactConverterFactory::ConverterType converter =
191 ContactConverterFactory::getConverter(context);
192 PersonPtr person = getPrivData(object);
193 if(!person->getIdIsSet())
194 return JSValueMakeNull(context);
196 return converter->toJSValueRef(person->getId());
198 Catch(WrtDeviceApis::Commons::Exception)
200 LogWarning("trying to get incorrect value");
202 return JSValueMakeUndefined(context);
205 JSValueRef JSPerson::getDisplayName(JSContextRef context,
207 JSStringRef propertyName,
208 JSValueRef* exception)
212 ContactConverterFactory::ConverterType converter =
213 ContactConverterFactory::getConverter(context);
214 PersonPtr person = getPrivData(object);
215 if(!person->getIdIsSet())
216 return JSValueMakeNull(context);
218 return converter->toJSValueRef(person->getDisplayName());
220 Catch(WrtDeviceApis::Commons::Exception)
222 LogWarning("trying to get incorrect value");
224 return JSValueMakeUndefined(context);
227 JSValueRef JSPerson::getContactCount(JSContextRef context,
229 JSStringRef propertyName,
230 JSValueRef* exception)
234 ContactConverterFactory::ConverterType converter =
235 ContactConverterFactory::getConverter(context);
236 PersonPtr person = getPrivData(object);
237 if(!person->getIdIsSet())
238 return JSValueMakeNull(context);
240 return converter->toJSValueRefLong(person->getContactCount());
242 Catch(WrtDeviceApis::Commons::Exception)
244 LogWarning("trying to get incorrect value");
246 return JSValueMakeUndefined(context);
249 JSValueRef JSPerson::getHasPhoneNumber(JSContextRef context,
251 JSStringRef propertyName,
252 JSValueRef* exception)
256 ContactConverterFactory::ConverterType converter =
257 ContactConverterFactory::getConverter(context);
258 PersonPtr person = getPrivData(object);
259 if(!person->getIdIsSet())
260 return JSValueMakeNull(context);
262 return converter->toJSValueRef(person->getHasPhoneNumber());
264 Catch(WrtDeviceApis::Commons::Exception)
266 LogWarning("trying to get incorrect value");
268 return JSValueMakeUndefined(context);
271 JSValueRef JSPerson::getHasEmail(JSContextRef context,
273 JSStringRef propertyName,
274 JSValueRef* exception)
278 ContactConverterFactory::ConverterType converter =
279 ContactConverterFactory::getConverter(context);
280 PersonPtr person = getPrivData(object);
281 if(!person->getIdIsSet())
282 return JSValueMakeNull(context);
284 return converter->toJSValueRef(person->getHasEmail());
286 Catch(WrtDeviceApis::Commons::Exception)
288 LogWarning("trying to get incorrect value");
291 return JSValueMakeUndefined(context);
294 JSValueRef JSPerson::getIsFavorite(JSContextRef context,
296 JSStringRef propertyName,
297 JSValueRef* exception)
301 ContactConverterFactory::ConverterType converter =
302 ContactConverterFactory::getConverter(context);
303 PersonPtr person = getPrivData(object);
304 return converter->toJSValueRef(person->getIsFavorite());
306 Catch(WrtDeviceApis::Commons::Exception)
308 LogWarning("trying to get incorrect value");
311 return JSValueMakeUndefined(context);
314 bool JSPerson::setIsFavorite(JSContextRef context,
316 JSStringRef propertyName,
318 JSValueRef* exception)
322 PersonPtr person = getPrivData(object);
323 ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
324 person->setIsFavorite(converter->toBool(value));
326 Catch(WrtDeviceApis::Commons::Exception)
328 LogWarning("trying to set incorrect value");
329 JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
335 JSValueRef JSPerson::getPhotoURI(JSContextRef context,
337 JSStringRef propertyName,
338 JSValueRef* exception)
342 ContactConverterFactory::ConverterType converter =
343 ContactConverterFactory::getConverter(context);
344 PersonPtr person = getPrivData(object);
345 if(!person->getPhotoURIIsSet())
346 return JSValueMakeNull(context);
348 return converter->toJSValueRef(person->getPhotoURI());
350 Catch(WrtDeviceApis::Commons::Exception)
352 LogWarning("trying to get incorrect value");
355 return JSValueMakeUndefined(context);
358 bool JSPerson::setPhotoURI(JSContextRef context,
360 JSStringRef propertyName,
362 JSValueRef* exception)
366 PersonPtr person = getPrivData(object);
367 ContactConverterFactory::ConverterType converter =
368 ContactConverterFactory::getConverter(context);
369 BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
370 if(validator->isNullOrUndefined(value))
371 person->unsetPhotoURI();
373 person->setPhotoURI(converter->toString(value));
375 Catch(WrtDeviceApis::Commons::Exception)
377 LogWarning("trying to set incorrect value");
378 JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
384 JSValueRef JSPerson::getRingtoneURI(JSContextRef context,
386 JSStringRef propertyName,
387 JSValueRef* exception)
391 ContactConverterFactory::ConverterType converter =
392 ContactConverterFactory::getConverter(context);
393 PersonPtr person = getPrivData(object);
394 if(!person->getRingtoneURIIsSet())
395 return JSValueMakeNull(context);
397 return converter->toJSValueRef(person->getRingtoneURI());
399 Catch(WrtDeviceApis::Commons::Exception)
401 LogWarning("trying to get incorrect value");
404 return JSValueMakeUndefined(context);
407 bool JSPerson::setRingtoneURI(JSContextRef context,
409 JSStringRef propertyName,
411 JSValueRef* exception)
415 PersonPtr person = getPrivData(object);
416 ContactConverterFactory::ConverterType converter =
417 ContactConverterFactory::getConverter(context);
418 BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
419 if(validator->isNullOrUndefined(value))
420 person->unsetRingtoneURI();
422 person->setRingtoneURI(converter->toString(value));
424 Catch(WrtDeviceApis::Commons::Exception)
426 LogWarning("trying to set incorrect value");
427 JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
433 JSValueRef JSPerson::getDisplayContactId(JSContextRef context,
435 JSStringRef propertyName,
436 JSValueRef* exception)
440 ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
441 PersonPtr person = getPrivData(object);
442 if(!person->getDisplayContactIdIsSet())
443 return JSValueMakeNull(context);
445 return converter->toJSValueRef(person->getDisplayContactId());
447 Catch(WrtDeviceApis::Commons::Exception)
449 LogWarning("trying to get incorrect value");
452 return JSValueMakeUndefined(context);
455 bool JSPerson::setDisplayContactId(JSContextRef context,
457 JSStringRef propertyName,
459 JSValueRef* exception)
463 PersonPtr person = getPrivData(object);
464 ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
465 BasicValidator validator = BasicValidatorFactory::getValidator(context, exception);
466 if(validator->isNullOrUndefined(value))
467 person->unsetDisplayContactId();
469 person->setDisplayContactId(converter->toString(value));
471 Catch(WrtDeviceApis::Commons::Exception)
473 LogWarning("trying to set incorrect value");
474 JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "Type mismatch");
480 JSValueRef JSPerson::link(JSContextRef context,
482 JSObjectRef thisObject,
483 size_t argumentCount,
484 const JSValueRef arguments[],
485 JSValueRef* exception)
488 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
489 PersonPtr person(NULL);
493 person = getPrivData(thisObject);
495 ThrowMsg(InvalidArgumentException, "No private object.");
499 LogError("Argument type mismatch : " << _rethrown_exception.GetMessage());
500 return JSTizenExceptionFactory::postException(context, exception,
501 JSTizenException::TYPE_MISMATCH_ERROR, "Wrong object");
504 AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_PERSON_LINK);
505 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
507 ArgumentValidator validator(context, argumentCount, arguments);
508 std::string personId;
510 personId = validator.toString(0, false);
511 } catch (const TypeMismatchException& err ) {
512 return JSWebAPIError::throwException(context, exception, err);
513 } catch(const BasePlatformException& err) {
514 return JSWebAPIError::throwException(context, exception, err);
515 } catch(const ConversionException& err) {
516 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "");
517 } catch(const NullPointerException& err) {
518 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "");
521 EventPersonLinkPtr dplEvent(new EventPersonLink());
523 dplEvent->setPersonId(personId);
524 dplEvent->setForSynchronousCall();
528 person->link(dplEvent);
530 Catch(ConversionException)
532 LogError("Error on platform : " << _rethrown_exception.GetMessage());
533 return JSTizenExceptionFactory::postException(context, exception,
534 JSTizenException::TYPE_MISMATCH_ERROR, "1st argument must be 'PersonId'");
538 LogError("Error on platform : " << _rethrown_exception.GetMessage());
539 return JSTizenExceptionFactory::postException(context, exception,
540 JSTizenException::UNKNOWN_ERROR, "Internal error");
543 if (!dplEvent->getResult())
545 std::stringstream oss;
546 switch (dplEvent->getExceptionCode())
548 case ExceptionCodes::NotFoundException:
549 oss << "Person id (" << personId << ") is not exists.";
550 return JSTizenExceptionFactory::postException(context, exception,
551 JSTizenException::INVALID_VALUES_ERROR, oss.str());
553 case ExceptionCodes::InvalidArgumentException:
554 oss << "Person id (" << personId << ") is wrong.";
555 return JSTizenExceptionFactory::postException(context, exception,
556 JSTizenException::INVALID_VALUES_ERROR, oss.str());
558 case ExceptionCodes::PlatformException:
559 return JSTizenExceptionFactory::postException(context, exception,
560 JSTizenException::UNKNOWN_ERROR, "Internal error");
563 return JSTizenExceptionFactory::postException(context, exception,
564 JSTizenException::UNKNOWN_ERROR, "Internal error");
568 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
569 return JSValueMakeUndefined(context);
572 JSValueRef JSPerson::unlink(JSContextRef context,
574 JSObjectRef thisObject,
575 size_t argumentCount,
576 const JSValueRef arguments[],
577 JSValueRef* exception)
580 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
581 PersonPtr person(NULL);
585 person = getPrivData(thisObject);
587 ThrowMsg(InvalidArgumentException, "No private object.");
591 LogError("Argument type mismatch : " << _rethrown_exception.GetMessage());
592 return JSTizenExceptionFactory::postException(context, exception,
593 JSTizenException::TYPE_MISMATCH_ERROR, "Wrong object");
596 AceSecurityStatus status = CONTACT_CHECK_ACCESS(CONTACT_FUNCTION_API_PERSON_UNLINK);
597 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
599 ArgumentValidator validator(context, argumentCount, arguments);
600 std::string contactId;
602 contactId = validator.toString(0, false);
603 } catch (const TypeMismatchException& err ) {
604 return JSWebAPIError::throwException(context, exception, err);
605 } catch(const BasePlatformException& err) {
606 return JSWebAPIError::throwException(context, exception, err);
607 } catch(const ConversionException& err) {
608 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "");
609 } catch(const NullPointerException& err) {
610 return JSTizenExceptionFactory::postException(context, exception, JSTizenException::TYPE_MISMATCH_ERROR, "");
613 EventPersonUnlinkPtr dplEvent(new EventPersonUnlink());
615 dplEvent->setContactId(contactId);
616 dplEvent->setForSynchronousCall();
620 person->unlink(dplEvent);
622 Catch(ConversionException)
624 LogError("Error on platform : " << _rethrown_exception.GetMessage());
625 return JSTizenExceptionFactory::postException(context, exception,
626 JSTizenException::TYPE_MISMATCH_ERROR, "1st argument must be 'ContactId'");
630 LogError("Error on platform : " << _rethrown_exception.GetMessage());
631 return JSTizenExceptionFactory::postException(context, exception,
632 JSTizenException::UNKNOWN_ERROR, "Internal error");
635 if (!dplEvent->getResult())
637 std::stringstream oss;
638 switch (dplEvent->getExceptionCode())
640 case ExceptionCodes::InvalidArgumentException:
641 oss << "No Contact id is wrong : '" << contactId << "'";
642 return JSTizenExceptionFactory::postException(context, exception,
643 JSTizenException::INVALID_VALUES_ERROR, oss.str());
645 case ExceptionCodes::NotFoundException:
646 oss << "No Contact id '" << contactId << "'";
647 return JSTizenExceptionFactory::postException(context, exception,
648 JSTizenException::INVALID_VALUES_ERROR, oss.str());
650 case ExceptionCodes::OutOfRangeException:
651 oss << "Contact (id:'" << contactId << "') is not a member of person";
652 return JSTizenExceptionFactory::postException(context, exception,
653 JSTizenException::INVALID_VALUES_ERROR, oss.str());
655 case ExceptionCodes::PlatformException:
656 return JSTizenExceptionFactory::postException(context, exception,
657 JSTizenException::UNKNOWN_ERROR, "Internal error");
660 return JSTizenExceptionFactory::postException(context, exception,
661 JSTizenException::UNKNOWN_ERROR, "Internal error");
666 PersonPtr unlinkedPerson = dplEvent->getPerson();
667 ContactConverterFactory::ConverterType converter = ContactConverterFactory::getConverter(context);
672 result = converter->toJSValueRef(unlinkedPerson);
676 LogError("Error on conversion : " << _rethrown_exception.GetMessage());
677 return JSTizenExceptionFactory::postException(context, exception,
678 JSTizenException::UNKNOWN_ERROR, "Internal error");
680 TIME_TRACER_ITEM_END(__FUNCTION__, 0);