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.
19 #include <CommonsJavaScript/PrivateObject.h>
20 #include <CommonsJavaScript/Converter.h>
21 #include <CommonsJavaScript/JSUtils.h>
22 #include <CommonsJavaScript/Utils.h>
23 #include <CommonsJavaScript/Validator.h>
24 #include <CommonsJavaScript/JSCallbackManager.h>
26 #include "JSCalendarEvent.h"
27 #include "JSCalendarItemProperties.h"
28 #include "CalendarConverter.h"
29 #include "JSCalendarEventId.h"
30 #include "JSCalendarRecurrenceRule.h"
31 #include "plugin_config.h"
32 #include "CalendarResponseDispatcher.h"
33 #include <TimeUtilConverter.h>
35 #include <JSWebAPIErrorFactory.h>
36 #include <SecurityExceptions.h>
37 #include <GlobalContextManager.h>
38 #include <TimeTracer.h>
42 using namespace WrtDeviceApis::Commons;
43 using namespace WrtDeviceApis::CommonsJavaScript;
44 using namespace DeviceAPI::Common;
45 using namespace DeviceAPI::Time;
50 using WrtDeviceApis::Commons::UnknownException;
51 using WrtDeviceApis::Commons::NotFoundException;
53 JSClassDefinition JSCalendarEvent::m_classInfo = {
55 kJSClassAttributeNone,
56 TIZEN_INTERFACE_CALENDAR_EVENT,
57 JSCalendarItemProperties::getClassRef(),
65 NULL, //DeleteProperty,
66 NULL, //GetPropertyNames,
67 NULL, //CallAsFunction,
73 JSStaticValue JSCalendarEvent::m_property[] = {
74 { TIZEN_CALENDAR_EVENT_ID, getPropertyId, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
75 { TIZEN_CALENDAR_EVENT_IS_DETACHED, getPropertyIsDetached, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
76 { TIZEN_CALENDAR_EVENT_RECURRENCE_RULE, getPropertyRecurrenceRule, setPropertyRecurrenceRule, kJSPropertyAttributeNone | kJSPropertyAttributeDontDelete },
81 JSStaticFunction JSCalendarEvent::m_function[] = {
82 { CALENDAR_FUNCTION_API_EXPAND_RECURRENCE, expandRecurrence, kJSPropertyAttributeNone },
87 JSClassRef JSCalendarEvent::m_jsClassRef = JSClassCreate(JSCalendarEvent::getClassInfo());
89 ICalendarPtr JSCalendarEvent::m_calendar;
91 void JSCalendarEvent::initialize(JSContextRef context,
94 if (!JSObjectGetPrivate(object)) {
95 LoggerD("Create calendar event private object.");
96 CalendarEventPtr event( new CalendarEvent() );
97 CalendarEventPrivObject *priv = new CalendarEventPrivObject(context, event);
98 if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
102 LoggerD("Private object already set.");
105 if (NULL==m_calendar) {
106 m_calendar = CalendarFactory::getInstance().createCalendarObject();
107 LoggerD("Static calendar for event created.");
111 m_calendar->setType(CalendarEvent::EVENT_TYPE);
112 LoggerD("Calendar object type is set to event.");
116 void JSCalendarEvent::finalize(JSObjectRef object)
118 CalendarEventPrivObject* priv = static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
121 JSObjectSetPrivate(object, NULL);
125 JSObjectRef DLL_EXPORT JSCalendarEvent::constructor(JSContextRef context,
126 JSObjectRef constructor,
127 size_t argumentCount,
128 const JSValueRef arguments[],
129 JSValueRef* exception)
133 JSContextRef globalContext = GlobalContextManager::getInstance()->getGlobalContext(context);
135 CalendarConverter converter(globalContext);
136 CalendarEventPtr event;
138 if (argumentCount==0) {
139 CalendarEventPtr result(new CalendarEvent());
141 } else if (argumentCount==1) {
142 LoggerI("eventInitDict case");
143 if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0])) {
144 CalendarEventPtr result(new CalendarEvent());
146 } else if (JSValueIsObject(context, arguments[0])) {
147 event = converter.toItem(arguments[0], false);
149 ThrowMsg(ConversionException, "Parameter conversion failed.");
152 ThrowMsg(ConversionException, "Parameter conversion failed.");
154 } else if (argumentCount>=2) {
155 LoggerI("event stringRepresentation case");
156 std::string eventStr;
157 CalendarEvent::VObjectFormat format = CalendarEvent::UNDEFINED_FORMAT;
158 eventStr = converter.toString(arguments[0]);
159 format = converter.toVObjectFormat(converter.toString(arguments[1]));
161 IEventCreateEventFromStringPtr dplEvent(new IEventCreateEventFromString());
162 dplEvent->setEventString(eventStr);
163 dplEvent->setFormat(format);
164 dplEvent->setForSynchronousCall();
165 m_calendar->createEventFromString(dplEvent);
167 // Process the returned object.
168 if (dplEvent->getResult()) {
169 LoggerI("Successfully created an event.");
170 event = dplEvent->getEvent();
172 if (dplEvent->getExceptionCode()==ExceptionCodes::InvalidArgumentException) {
173 ThrowMsg(InvalidArgumentException, "Wrong string to convert.");
175 ThrowMsg(UnknownException, "Converting string failed.");
180 return createJSCalendarEvent(globalContext, event);
182 Catch(UnsupportedException)
184 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
185 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
187 Catch(InvalidArgumentException)
189 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
190 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
192 Catch(ConversionException)
194 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
195 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
199 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
200 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
204 JSObjectRef JSCalendarEvent::createJSCalendarEvent(JSContextRef context, CalendarEventPtr event)
206 CalendarEventPrivObject *priv = new CalendarEventPrivObject(context, event);
207 return JSObjectMake(context, getClassRef(), priv);
210 const JSClassRef DLL_EXPORT JSCalendarEvent::getClassRef()
213 m_jsClassRef = JSClassCreate(&m_classInfo);
218 const JSClassDefinition* JSCalendarEvent::getClassInfo()
223 CalendarEventPtr JSCalendarEvent::getPrivateObject(JSObjectRef object)
225 CalendarEventPrivObject *priv =
226 static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
228 ThrowMsg(NullPointerException, "Private object is null");
230 CalendarEventPtr result = priv->getObject();
232 ThrowMsg(NullPointerException, "Private object is null");
237 void JSCalendarEvent::setPrivateObject(const CalendarEventPtr &event,
239 const JSObjectRef object)
243 CalendarEventPrivObject *priv =
244 static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
246 priv = new CalendarEventPrivObject(ctx, event);
247 if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
253 LoggerE("Error during replacing event object");
257 JSValueRef JSCalendarEvent::expandRecurrence(JSContextRef context,
259 JSObjectRef thisObject,
260 size_t argumentCount,
261 const JSValueRef arguments[],
262 JSValueRef* exception)
264 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
265 CalendarEventPrivObject *privateObject =
266 static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(thisObject));
268 AceSecurityStatus status = CALENDAR_CHECK_ACCESS(CALENDAR_FUNCTION_API_EXPAND_RECURRENCE);
270 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
274 if (!privateObject) {
275 ThrowMsg(ConversionException, "Object is null.");
278 CalendarEventPtr event = privateObject->getObject();
280 ThrowMsg(ConversionException, "Parameter conversion failed.");
283 JSContextRef globalContext = GlobalContextManager::getInstance()->getGlobalContext(context);
284 CalendarConverter converter(context);
286 std::time_t startDate = 0;
287 std::time_t endDate = INT_MAX; // about 60 years in 4 bytes system.
288 TimeUtilConverter timeConverter(context);
289 if (argumentCount>=1) {
290 if (JSValueIsObjectOfClass(context, arguments[0], JSTZDate::getClassRef())) {
291 startDate = (long long int) (timeConverter.getTimeInMilliseconds(arguments[0])/1000);
292 LoggerI("startDate: "<<startDate);
294 ThrowMsg(ConversionException, "Wrong first parameter type.");
297 if (argumentCount>=2) {
298 if (JSValueIsObjectOfClass(context, arguments[1], JSTZDate::getClassRef())) {
299 endDate = (long long int) (timeConverter.getTimeInMilliseconds(arguments[1])/1000);
300 LoggerI("endDate: "<<endDate);
302 ThrowMsg(ConversionException, "Wrong second parameter type.");
306 JSValueRef onError = argumentCount > 3 ? converter.toFunctionOrNull(arguments[3]) : NULL;
308 JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext, NULL, onError);
310 Validator validator(context);
311 if (validator.isCallback(arguments[2])) {
312 cbm->setOnSuccess(arguments[2]);
314 ThrowMsg(ConversionException, "Wrong third parameter type.");
317 cbm->setObject(thisObject);
319 LoggerD("Proceed the expand event to the platform.");
321 IEventExpandEventRecurrencePtr dplEvent(new IEventExpandEventRecurrence());
322 dplEvent->setPrivateData(DPL::StaticPointerCast<IEventPrivateData>(cbm));
323 dplEvent->setForAsynchronousCall(&CalendarResponseDispatcher::getInstance());
324 dplEvent->setEvent(event);
325 dplEvent->setStartDate(startDate);
326 dplEvent->setEndDate(endDate);
327 m_calendar->expandEventRecurrence(dplEvent);
329 TIME_TRACER_ITEM_END(__FUNCTION__, 0);
330 return JSValueMakeUndefined(context);
332 Catch(UnsupportedException)
334 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
335 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
337 Catch(InvalidArgumentException)
339 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
340 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
342 Catch(ConversionException)
344 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
345 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
347 Catch (NotFoundException)
349 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
350 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, _rethrown_exception.GetMessage());
354 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
355 return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
359 JSValueRef JSCalendarEvent::getPropertyId(JSContextRef context,
361 JSStringRef propertyName,
362 JSValueRef* exception)
366 CalendarEventPrivObject *privateObject = static_cast<CalendarEventPrivObject*>(JSObjectGetPrivate(object));
367 CalendarEventPtr event = privateObject->getObject();
369 EventIdPtr eventId( new EventId() );
371 if (UNDEFINED_ITEM_ID==event->getId()) {
372 return JSValueMakeNull(context);
374 eventId->setUId(event->getUId());
377 std::stringstream ss;
378 std::time_t rid = event->getRecurrenceId();
380 eventId->setRecurrenceId(ss.str());
381 return JSCalendarEventId::createJSCalendarEventId(context, eventId);
385 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
387 return JSValueMakeUndefined(context);
390 JSValueRef JSCalendarEvent::getPropertyIsDetached(JSContextRef context,
392 JSStringRef propertyName,
393 JSValueRef* exception)
397 CalendarEventPtr event = getPrivateObject(object);
398 if(CalendarEvent::EVENT_TYPE != event->getCalendarType()) {
399 return JSValueMakeUndefined(context);
402 Converter converter(context);
403 return converter.toJSValueRef(event->getIsDetached());
407 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
409 return JSValueMakeUndefined(context);
412 JSValueRef JSCalendarEvent::getPropertyRecurrenceRule(JSContextRef context,
414 JSStringRef propertyName,
415 JSValueRef* exception)
419 CalendarItemPropertiesPrivObject *priv = static_cast<CalendarItemPropertiesPrivObject*>(JSObjectGetPrivate(object));
421 CalendarEventPtr event = getPrivateObject(object);
422 EventRecurrenceRulePtr rrule;
423 if (event->getIsDetached()) {
424 LoggerD("This is a detached event.");
425 return JSValueMakeUndefined(context);
427 rrule = event->getRecurrenceRule();
431 return JSValueMakeNull(context);
432 } else if (EventRecurrenceRule::NO_RECURRENCE==rrule->getFrequency()) {
433 return JSValueMakeUndefined(context);
435 return JSCalendarRecurrenceRule::createJSCalendarRecurrenceRule(priv->getContext(), rrule);
440 LoggerW("Exception: "<<_rethrown_exception.GetMessage());
442 return JSValueMakeUndefined(context);
445 bool JSCalendarEvent::setPropertyRecurrenceRule(JSContextRef context,
447 JSStringRef propertyName,
449 JSValueRef* exception)
451 CalendarEventPtr event(NULL);
454 event = getPrivateObject(object);
455 if (event->getIsDetached()) {
456 LoggerW("Can't set the recurrenceRule of a detached event!");
457 DeviceAPI::Common::JSWebAPIErrorFactory::postException(context, exception, DeviceAPI::Common::JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR);
460 if (JSValueIsNull(context, value)) {
461 EventRecurrenceRulePtr rrule(NULL);
462 event->setRecurrenceRule(rrule);
463 } else if (JSValueIsUndefined(context, value)) {
464 EventRecurrenceRulePtr rrule( new EventRecurrenceRule() );
465 event->setRecurrenceRule(rrule);
467 event->setRecurrenceRule(JSCalendarRecurrenceRule::getPrivateObject(JSValueToObject(context, value, NULL)));
473 LoggerW("Exception: "<<_rethrown_exception.GetMessage());